364 lines
14 KiB
Java
364 lines
14 KiB
Java
package com.klp.service.impl;
|
|
|
|
import cn.hutool.core.bean.BeanUtil;
|
|
import cn.hutool.core.io.IoUtil;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
import com.klp.common.core.domain.PageQuery;
|
|
import com.klp.common.core.domain.entity.SysUser;
|
|
import com.klp.common.core.page.TableDataInfo;
|
|
import com.klp.common.exception.ServiceException;
|
|
import com.klp.config.StampProperties;
|
|
import com.klp.domain.WmsApproval;
|
|
import com.klp.domain.WmsApprovalTask;
|
|
import com.klp.domain.WmsDept;
|
|
import com.klp.domain.WmsSealReq;
|
|
import com.klp.domain.bo.WmsSealReqBo;
|
|
import com.klp.domain.bo.WmsSealStampBo;
|
|
import com.klp.domain.vo.WmsSealReqVo;
|
|
import com.klp.mapper.WmsApprovalMapper;
|
|
import com.klp.mapper.WmsApprovalTaskMapper;
|
|
import com.klp.mapper.WmsDeptMapper;
|
|
import com.klp.mapper.WmsSealReqMapper;
|
|
import com.klp.oss.core.OssClient;
|
|
import com.klp.oss.entity.UploadResult;
|
|
import com.klp.oss.factory.OssFactory;
|
|
import com.klp.service.IWmsSealReqService;
|
|
import com.klp.system.mapper.SysUserMapper;
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
import org.apache.pdfbox.pdmodel.PDPage;
|
|
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
|
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
|
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.InputStream;
|
|
import java.util.Collection;
|
|
import java.util.Date;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* 用印申请 服务实现
|
|
*/
|
|
@Slf4j
|
|
@RequiredArgsConstructor
|
|
@Service
|
|
public class WmsSealReqServiceImpl implements IWmsSealReqService {
|
|
|
|
private final WmsSealReqMapper baseMapper;
|
|
private final WmsDeptMapper wmsDeptMapper;
|
|
private final SysUserMapper sysUserMapper;
|
|
private final WmsApprovalMapper approvalMapper;
|
|
private final WmsApprovalTaskMapper approvalTaskMapper;
|
|
private final StampProperties stampProperties;
|
|
|
|
@Override
|
|
public WmsSealReqVo queryById(Long bizId) {
|
|
return baseMapper.selectVoById(bizId);
|
|
}
|
|
|
|
@Override
|
|
public TableDataInfo<WmsSealReqVo> queryPageList(WmsSealReqBo bo, PageQuery pageQuery) {
|
|
LambdaQueryWrapper<WmsSealReq> lqw = buildQueryWrapper(bo);
|
|
Page<WmsSealReqVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
|
|
return TableDataInfo.build(result);
|
|
}
|
|
|
|
@Override
|
|
public List<WmsSealReqVo> queryList(WmsSealReqBo bo) {
|
|
LambdaQueryWrapper<WmsSealReq> lqw = buildQueryWrapper(bo);
|
|
return baseMapper.selectVoList(lqw);
|
|
}
|
|
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public Boolean insertByBo(WmsSealReqBo bo) {
|
|
WmsSealReq add = BeanUtil.toBean(bo, WmsSealReq.class);
|
|
add.setStatus(defaultStatus(add.getStatus()));
|
|
validEntityBeforeSave(add);
|
|
boolean ok = baseMapper.insert(add) > 0;
|
|
if (ok) {
|
|
createDeptLeaderApproval(add, bo.getDeptId());
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public Boolean updateByBo(WmsSealReqBo bo) {
|
|
if (bo.getBizId() == null) {
|
|
throw new ServiceException("bizId不能为空");
|
|
}
|
|
WmsSealReq update = BeanUtil.toBean(bo, WmsSealReq.class);
|
|
validEntityBeforeSave(update);
|
|
return baseMapper.updateById(update) > 0;
|
|
}
|
|
|
|
@Override
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
if (isValid) {
|
|
// 可添加业务校验
|
|
}
|
|
return baseMapper.deleteBatchIds(ids) > 0;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public Boolean approveByDeptLeader(Long bizId, String approvalOpinion) {
|
|
WmsSealReq req = baseMapper.selectById(bizId);
|
|
if (req == null) {
|
|
throw new ServiceException("用印申请不存在");
|
|
}
|
|
WmsApproval approval = getApprovalByApplyId(bizId);
|
|
if (approval == null) {
|
|
throw new ServiceException("审批记录不存在");
|
|
}
|
|
WmsApprovalTask task = getPendingTaskForCurrentLeader(approval.getApprovalId(), req.getDeptId());
|
|
if (task == null) {
|
|
throw new ServiceException("当前用户不是该部门负责人或审批任务不存在");
|
|
}
|
|
|
|
task.setTaskStatus("approved");
|
|
task.setApprovalOpinion(approvalOpinion);
|
|
task.setApprovalTime(new Date());
|
|
approvalTaskMapper.updateById(task);
|
|
|
|
approval.setApprovalStatus("已同意");
|
|
approval.setFinalStatus("all_approved");
|
|
approval.setApprovalOpinion(approvalOpinion);
|
|
approval.setApprovalTime(new Date());
|
|
approvalMapper.updateById(approval);
|
|
|
|
updateStatus(bizId, "approved");
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public Boolean rejectByDeptLeader(Long bizId, String approvalOpinion) {
|
|
WmsSealReq req = baseMapper.selectById(bizId);
|
|
if (req == null) {
|
|
throw new ServiceException("用印申请不存在");
|
|
}
|
|
WmsApproval approval = getApprovalByApplyId(bizId);
|
|
if (approval == null) {
|
|
throw new ServiceException("审批记录不存在");
|
|
}
|
|
WmsApprovalTask task = getPendingTaskForCurrentLeader(approval.getApprovalId(), req.getDeptId());
|
|
if (task == null) {
|
|
throw new ServiceException("当前用户不是该部门负责人或审批任务不存在");
|
|
}
|
|
|
|
task.setTaskStatus("rejected");
|
|
task.setApprovalOpinion(approvalOpinion);
|
|
task.setApprovalTime(new Date());
|
|
approvalTaskMapper.updateById(task);
|
|
|
|
approval.setApprovalStatus("已驳回");
|
|
approval.setFinalStatus("rejected");
|
|
approval.setApprovalOpinion(approvalOpinion);
|
|
approval.setApprovalTime(new Date());
|
|
approvalMapper.updateById(approval);
|
|
|
|
updateStatus(bizId, "rejected");
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public Boolean updateStatus(Long bizId, String status) {
|
|
WmsSealReq req = new WmsSealReq();
|
|
req.setBizId(bizId);
|
|
req.setStatus(status);
|
|
return baseMapper.updateById(req) > 0;
|
|
}
|
|
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public String stampWithJava(Long bizId, WmsSealStampBo cmd) {
|
|
if (!Boolean.TRUE.equals(stampProperties.getJavaService().isEnabled())) {
|
|
throw new ServiceException("Java盖章未启用");
|
|
}
|
|
String resultUrl = doPdfStamp(cmd);
|
|
WmsSealReq update = new WmsSealReq();
|
|
update.setBizId(bizId);
|
|
update.setReceiptStatus("done");
|
|
update.setReceiptFileIds(resultUrl);
|
|
baseMapper.updateById(update);
|
|
return resultUrl;
|
|
}
|
|
|
|
@Override
|
|
public String stampWithPython(Long bizId, WmsSealStampBo cmd) {
|
|
if (!Boolean.TRUE.equals(stampProperties.getPythonService().isEnabled())) {
|
|
throw new ServiceException("Python盖章未启用");
|
|
}
|
|
throw new ServiceException("Python盖章接口未实现");
|
|
}
|
|
|
|
private LambdaQueryWrapper<WmsSealReq> buildQueryWrapper(WmsSealReqBo bo) {
|
|
LambdaQueryWrapper<WmsSealReq> lqw = Wrappers.lambdaQuery();
|
|
lqw.eq(bo.getBizId() != null, WmsSealReq::getBizId, bo.getBizId());
|
|
lqw.eq(bo.getEmpId() != null, WmsSealReq::getEmpId, bo.getEmpId());
|
|
lqw.eq(bo.getSealType() != null, WmsSealReq::getSealType, bo.getSealType());
|
|
lqw.eq(bo.getStatus() != null, WmsSealReq::getStatus, bo.getStatus());
|
|
lqw.orderByDesc(WmsSealReq::getCreateTime);
|
|
return lqw;
|
|
}
|
|
|
|
private void validEntityBeforeSave(WmsSealReq entity) {
|
|
// 预留数据校验,如唯一约束
|
|
}
|
|
|
|
private String defaultStatus(String status) {
|
|
return status == null ? "draft" : status;
|
|
}
|
|
|
|
private void createDeptLeaderApproval(WmsSealReq req, Long deptId) {
|
|
if (deptId == null) {
|
|
return;
|
|
}
|
|
WmsDept dept = wmsDeptMapper.selectById(deptId);
|
|
if (dept == null || dept.getLeader() == null) {
|
|
return;
|
|
}
|
|
SysUser leader = sysUserMapper.selectById(dept.getLeader());
|
|
if (leader == null) {
|
|
return;
|
|
}
|
|
|
|
WmsApproval approval = new WmsApproval();
|
|
approval.setApplyType("seal");
|
|
approval.setApplyId(req.getBizId());
|
|
approval.setApproverName(leader.getNickName());
|
|
approval.setApprovalStatus("待审批");
|
|
approval.setApprovalType("single");
|
|
approval.setRequiredApprovers(1);
|
|
approval.setCurrentApprovers(0);
|
|
approval.setFinalStatus("pending");
|
|
approval.setCreateBy(req.getCreateBy());
|
|
approval.setCreateTime(req.getCreateTime());
|
|
approvalMapper.insert(approval);
|
|
|
|
WmsApprovalTask task = new WmsApprovalTask();
|
|
task.setApprovalId(approval.getApprovalId());
|
|
task.setApproverId(leader.getUserId());
|
|
task.setApproverName(leader.getNickName());
|
|
task.setTaskStatus("pending");
|
|
task.setCreateBy(req.getCreateBy());
|
|
task.setCreateTime(req.getCreateTime());
|
|
approvalTaskMapper.insert(task);
|
|
|
|
updateStatus(req.getBizId(), "running");
|
|
}
|
|
|
|
private WmsApproval getApprovalByApplyId(Long applyId) {
|
|
return approvalMapper.selectOne(Wrappers.<WmsApproval>lambdaQuery()
|
|
.eq(WmsApproval::getApplyType, "seal")
|
|
.eq(WmsApproval::getApplyId, applyId)
|
|
.eq(WmsApproval::getDelFlag, 0));
|
|
}
|
|
|
|
private WmsApprovalTask getPendingTaskForCurrentLeader(Long approvalId, Long deptId) {
|
|
if (approvalId == null || deptId == null) {
|
|
return null;
|
|
}
|
|
WmsDept dept = wmsDeptMapper.selectById(deptId);
|
|
if (dept == null || dept.getLeader() == null) {
|
|
return null;
|
|
}
|
|
Long leaderId = dept.getLeader();
|
|
return approvalTaskMapper.selectOne(Wrappers.<WmsApprovalTask>lambdaQuery()
|
|
.eq(WmsApprovalTask::getApprovalId, approvalId)
|
|
.eq(WmsApprovalTask::getApproverId, leaderId)
|
|
.eq(WmsApprovalTask::getTaskStatus, "pending")
|
|
.eq(WmsApprovalTask::getDelFlag, 0));
|
|
}
|
|
|
|
private String doPdfStamp(WmsSealStampBo cmd) {
|
|
try (InputStream pdfIn = getObject(cmd.getTargetFileUrl());
|
|
InputStream imgIn = getObject(cmd.getStampImageUrl());
|
|
PDDocument document = PDDocument.load(pdfIn);
|
|
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
|
|
|
|
int pageIndex = cmd.getPageNo() - 1;
|
|
if (pageIndex < 0 || pageIndex >= document.getNumberOfPages()) {
|
|
throw new ServiceException("页码超出范围");
|
|
}
|
|
PDPage page = document.getPage(pageIndex);
|
|
PDRectangle mediaBox = page.getMediaBox();
|
|
|
|
byte[] imgBytes = IoUtil.readBytes(imgIn);
|
|
PDImageXObject image = PDImageXObject.createFromByteArray(document, imgBytes, "stamp");
|
|
|
|
float stampW = image.getWidth();
|
|
float stampH = image.getHeight();
|
|
|
|
float pdfW = mediaBox.getWidth();
|
|
float pdfH = mediaBox.getHeight();
|
|
|
|
float x;
|
|
float y;
|
|
if (cmd.getViewportWidth() != null && cmd.getViewportHeight() != null
|
|
&& cmd.getViewportWidth() > 0 && cmd.getViewportHeight() > 0) {
|
|
float ratioX = pdfW / cmd.getViewportWidth();
|
|
float ratioY = pdfH / cmd.getViewportHeight();
|
|
x = cmd.getXPx() * ratioX;
|
|
y = cmd.getYPx() * ratioY;
|
|
} else {
|
|
x = cmd.getXPx();
|
|
y = cmd.getYPx();
|
|
}
|
|
|
|
final float maxCm = 4.0f;
|
|
final float maxPt = maxCm * 72.0f / 2.54f;
|
|
float scale = Math.min(maxPt / stampW, maxPt / stampH);
|
|
scale = Math.min(scale, 1.0f);
|
|
|
|
float width = stampW * scale;
|
|
float height = stampH * scale;
|
|
|
|
log.info("[stamp] pdfW={},pdfH={}, viewportW={},viewportH={}, ratioX={},ratioY={}, xPx={},yPx={}, x={},y={}, stampW={},stampH={}, drawW={},drawH={}",
|
|
pdfW, pdfH,
|
|
cmd.getViewportWidth(), cmd.getViewportHeight(),
|
|
(cmd.getViewportWidth() != null && cmd.getViewportWidth() > 0) ? (pdfW / cmd.getViewportWidth()) : null,
|
|
(cmd.getViewportHeight() != null && cmd.getViewportHeight() > 0) ? (pdfH / cmd.getViewportHeight()) : null,
|
|
cmd.getXPx(), cmd.getYPx(),
|
|
x, y,
|
|
stampW, stampH,
|
|
width, height);
|
|
|
|
if (x + width > mediaBox.getWidth()) {
|
|
x = Math.max(0, mediaBox.getWidth() - width);
|
|
}
|
|
if (y + height > mediaBox.getHeight()) {
|
|
y = Math.max(0, mediaBox.getHeight() - height);
|
|
}
|
|
|
|
try (PDPageContentStream contentStream = new PDPageContentStream(document, page,
|
|
PDPageContentStream.AppendMode.APPEND, true, true)) {
|
|
contentStream.drawImage(image, x, y, width, height);
|
|
}
|
|
|
|
document.save(bos);
|
|
|
|
OssClient storage = OssFactory.instance();
|
|
UploadResult uploadResult = storage.uploadSuffix(bos.toByteArray(), ".pdf", "application/pdf");
|
|
return uploadResult.getUrl();
|
|
} catch (Exception e) {
|
|
log.error("PDF盖章失败", e);
|
|
throw new ServiceException("PDF盖章失败: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
private InputStream getObject(String url) {
|
|
OssClient storage = OssFactory.instance();
|
|
return storage.getObjectContent(url);
|
|
}
|
|
}
|