package com.ruoyi.approve.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.ruoyi.approve.bean.dto.ApprovalInstanceDto;
|
import com.ruoyi.approve.bean.vo.ApprovalInstanceVo;
|
import com.ruoyi.approve.mapper.ApprovalInstanceMapper;
|
import com.ruoyi.approve.mapper.ApprovalTemplateNodeApproverMapper;
|
import com.ruoyi.approve.mapper.FinReimbursementMapper;
|
import com.ruoyi.approve.pojo.*;
|
import com.ruoyi.approve.service.*;
|
import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils;
|
import com.ruoyi.basic.enums.ApplicationTypeEnum;
|
import com.ruoyi.basic.enums.RecordTypeEnum;
|
import com.ruoyi.basic.utils.FileUtil;
|
import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsMapper;
|
import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeDeptMapper;
|
import com.ruoyi.collaborativeApproval.mapper.EnterpriseNewsScopeUserMapper;
|
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNews;
|
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept;
|
import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser;
|
import com.ruoyi.common.enums.*;
|
import com.ruoyi.common.utils.OrderUtils;
|
import com.ruoyi.common.utils.SecurityUtils;
|
import com.ruoyi.framework.security.LoginUser;
|
import com.ruoyi.framework.web.domain.R;
|
import com.ruoyi.procurementrecord.utils.StockUtils;
|
import com.ruoyi.project.system.domain.SysDept;
|
import com.ruoyi.project.system.domain.SysUser;
|
import com.ruoyi.project.system.mapper.SysDeptMapper;
|
import com.ruoyi.project.system.mapper.SysUserDeptMapper;
|
import com.ruoyi.project.system.mapper.SysUserMapper;
|
import com.ruoyi.project.system.service.ISysNoticeService;
|
import com.ruoyi.purchase.mapper.PurchaseLedgerMapper;
|
import com.ruoyi.purchase.pojo.PurchaseLedger;
|
import com.ruoyi.quality.utils.QualityInspectHelper;
|
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
|
import com.ruoyi.sales.mapper.SalesQuotationMapper;
|
import com.ruoyi.sales.mapper.ShippingInfoMapper;
|
import com.ruoyi.sales.pojo.SalesLedgerProduct;
|
import com.ruoyi.sales.pojo.SalesQuotation;
|
import com.ruoyi.sales.pojo.ShippingInfo;
|
import com.ruoyi.staff.mapper.HolidayApplicationMapper;
|
import com.ruoyi.staff.pojo.HolidayApplication;
|
import lombok.RequiredArgsConstructor;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.StringUtils;
|
|
import java.time.LocalDateTime;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* <p>
|
* 审批实例服务实现类
|
* </p>
|
*
|
* @since 2026-05-18 03:27:46
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class ApprovalInstanceServiceImpl extends ServiceImpl<ApprovalInstanceMapper, ApprovalInstance> implements ApprovalInstanceService {
|
|
private static final String ENTERPRISE_NEWS_STATUS_PUBLISHED = "PUBLISHED";
|
private static final String ENTERPRISE_NEWS_STATUS_REJECTED = "REJECTED";
|
|
private final ApprovalInstanceMapper approvalInstanceMapper;
|
private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils;
|
private final ApprovalInstanceNodeService approvalInstanceNodeService;
|
private final ApprovalTaskService approvalTaskService;
|
private final ApprovalRecordService approvalRecordService;
|
private final ApprovalTemplateNodeService approvalTemplateNodeService;
|
private final FinReimbursementMapper finReimbursementMapper;
|
private final FileUtil fileUtil;
|
private final ISysNoticeService sysNoticeService;
|
private final PurchaseLedgerMapper purchaseLedgerMapper;
|
private final SalesLedgerProductMapper salesLedgerProductMapper;
|
private final StockUtils stockUtils;
|
private final SalesQuotationMapper salesQuotationMapper;
|
private final ShippingInfoMapper shippingInfoMapper;
|
private final QualityInspectHelper qualityInspectHelper;
|
private final EnterpriseNewsScopeUserMapper enterpriseNewsScopeUserMapper;
|
private final SysUserMapper sysUserMapper;
|
private final SysUserDeptMapper sysUserDeptMapper;
|
private final SysDeptMapper sysDeptMapper;
|
private final HolidayApplicationMapper holidayApplicationMapper;
|
private final EnterpriseNewsMapper enterpriseNewsMapper;
|
private final EnterpriseNewsScopeDeptMapper enterpriseNewsScopeDeptMapper;
|
private final ApprovalTemplateNodeApproverMapper approvalTemplateNodeApproverMapper;
|
|
@Override
|
public R listPage(Page<ApprovalInstanceVo> page, ApprovalInstanceDto approvalInstanceDto) {
|
IPage<ApprovalInstanceVo> approvalInstanceVoIPage = approvalInstanceMapper.listPage(page, approvalInstanceDto);
|
|
List<ApprovalInstanceVo> records = approvalInstanceVoIPage.getRecords();
|
if (records == null || records.isEmpty()) {
|
return R.ok(approvalInstanceVoIPage);
|
}
|
records.forEach(vo -> {
|
vo.setBusinessName(TypeEnums.getLabelByValue(vo.getBusinessType()));
|
});
|
Long currentUserId = SecurityUtils.getUserId();
|
|
List<Long> instanceIds = records.stream()
|
.map(ApprovalInstanceVo::getId)
|
.filter(id -> id != null)
|
.distinct()
|
.collect(Collectors.toList());
|
|
if (!instanceIds.isEmpty()) {
|
Map<Long, List<ApprovalRecord>> recordMap = approvalRecordService.list(
|
Wrappers.<ApprovalRecord>lambdaQuery()
|
.in(ApprovalRecord::getInstanceId, instanceIds)
|
.eq(ApprovalRecord::getDeleted, 0)
|
).stream().collect(Collectors.groupingBy(ApprovalRecord::getInstanceId));
|
Map<Long, List<ApprovalTask>> taskMap = approvalTaskService.list(
|
Wrappers.<ApprovalTask>lambdaQuery()
|
.in(ApprovalTask::getInstanceId, instanceIds)
|
.eq(ApprovalTask::getDeleted, 0)
|
).stream().collect(Collectors.groupingBy(ApprovalTask::getInstanceId));
|
|
for (ApprovalInstanceVo vo : records) {
|
vo.setIsApprove(approveProcessConfigNodeUtils.isCurrentApprover(vo.getId(), currentUserId));
|
vo.setRecords(recordMap.getOrDefault(vo.getId(), new ArrayList<>()));
|
vo.setTasks(taskMap.getOrDefault(vo.getId(), new ArrayList<>()));
|
vo.setStorageBlobVOList(fileUtil.getStorageBlobVOsByRecordTypeAndRecordId(RecordTypeEnum.APPROVAL_INSTANCE, vo.getId()));
|
}
|
|
}
|
return R.ok(approvalInstanceVoIPage);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean add(ApprovalInstanceDto approvalInstanceDto) {
|
String instanceNo = OrderUtils.countTodayByCreateTime(approvalInstanceMapper, "SP", "instance_no");
|
approvalInstanceDto.setInstanceNo(instanceNo);
|
approvalInstanceDto.setStatus("PENDING");
|
approvalInstanceDto.setCurrentLevel(1);
|
boolean saved = this.save(approvalInstanceDto);
|
if (!saved) {
|
return false;
|
}
|
approveProcessConfigNodeUtils.createCurrentNodeAndTasks(approvalInstanceDto);
|
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, approvalInstanceDto.getId(), approvalInstanceDto.getStorageBlobDTOs());
|
sendApproveNotice(approvalInstanceDto, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean update(ApprovalInstanceDto approvalInstanceDto) {
|
if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) {
|
return false;
|
}
|
boolean updated = this.updateById(approvalInstanceDto);
|
if (!updated) {
|
return false;
|
}
|
fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, approvalInstanceDto.getId(), approvalInstanceDto.getStorageBlobDTOs());
|
return true;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Boolean delete(List<Long> ids) {
|
if (ids == null || ids.isEmpty()) {
|
return false;
|
}
|
fileUtil.deleteStorageAttachmentsByApplicationAndRecordTypeAndRecordIds(ApplicationTypeEnum.FILE, RecordTypeEnum.APPROVAL_INSTANCE, ids);
|
|
int instanceRows = approvalInstanceMapper.update(
|
null,
|
Wrappers.<ApprovalInstance>lambdaUpdate()
|
.in(ApprovalInstance::getId, ids)
|
.eq(ApprovalInstance::getDeleted, 0)
|
.set(ApprovalInstance::getDeleted, (byte) 1)
|
);
|
|
LambdaUpdateWrapper<ApprovalInstanceNode> nodeUpdateWrapper = Wrappers.lambdaUpdate();
|
nodeUpdateWrapper.in(ApprovalInstanceNode::getInstanceId, ids)
|
.eq(ApprovalInstanceNode::getDeleted, 0)
|
.set(ApprovalInstanceNode::getDeleted, (byte) 1);
|
approvalInstanceNodeService.update(nodeUpdateWrapper);
|
|
LambdaUpdateWrapper<ApprovalTask> taskUpdateWrapper = Wrappers.lambdaUpdate();
|
taskUpdateWrapper.in(ApprovalTask::getInstanceId, ids)
|
.eq(ApprovalTask::getDeleted, 0)
|
.set(ApprovalTask::getDeleted, (byte) 1);
|
approvalTaskService.update(taskUpdateWrapper);
|
|
LambdaUpdateWrapper<ApprovalRecord> recordUpdateWrapper = Wrappers.lambdaUpdate();
|
recordUpdateWrapper.in(ApprovalRecord::getInstanceId, ids)
|
.eq(ApprovalRecord::getDeleted, 0)
|
.set(ApprovalRecord::getDeleted, (byte) 1);
|
approvalRecordService.update(recordUpdateWrapper);
|
|
return instanceRows > 0;
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public R approve(ApprovalInstanceDto approvalInstanceDto) {
|
if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) {
|
return R.fail("审批实例 ID 不能为空");
|
}
|
String approveAction = normalizeApproveAction(approvalInstanceDto.getApproveAction());
|
if (approveAction == null) {
|
return R.fail("审批动作只支持 APPROVED 或 REJECTED");
|
}
|
|
ApprovalInstance instance = getPendingApprovalInstance(approvalInstanceDto.getId());
|
if (instance == null) {
|
return R.fail("审批实例不存在");
|
}
|
|
ApprovalInstanceNode currentNode = approveProcessConfigNodeUtils.getCurrentNode(instance.getId());
|
if (currentNode == null) {
|
return R.fail("当前没有待处理的审批节点");
|
}
|
|
Long currentUserId = SecurityUtils.getUserId();
|
ApprovalTask currentTask = approveProcessConfigNodeUtils.getCurrentUserTask(instance.getId(), currentUserId);
|
if (currentTask == null) {
|
return R.fail("当前用户没有可审批任务");
|
}
|
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
String operatorName = loginUser.getUser() != null ? loginUser.getUser().getNickName() : SecurityUtils.getUsername();
|
LocalDateTime now = LocalDateTime.now();
|
|
if (!updateCurrentTask(approvalInstanceDto, approveAction, currentTask, now)) {
|
return R.fail("当前任务已被处理,请刷新后重试");
|
}
|
|
saveApprovalRecord(
|
instance.getId(),
|
currentNode.getId(),
|
currentTask.getId(),
|
currentUserId,
|
operatorName,
|
approveAction,
|
approvalInstanceDto.getApproveComment()
|
);
|
//审批拒绝的处理
|
if ("REJECTED".equals(approveAction)) {
|
return rejectCurrentNode(instance, currentNode, now);
|
}
|
if (!approveProcessConfigNodeUtils.canProceedToNextLevel(instance.getId(), currentNode.getApproveType())) {
|
return R.ok("审批成功,等待其他审批人处理");
|
}
|
|
return approveAndMoveNext(instance, currentNode, approvalInstanceDto, now);
|
}
|
|
private String normalizeApproveAction(String approveAction) {
|
if (!StringUtils.hasText(approveAction)) {
|
return null;
|
}
|
String normalizedAction = approveAction.trim().toUpperCase(Locale.ROOT);
|
return "APPROVED".equals(normalizedAction) || "REJECTED".equals(normalizedAction)
|
? normalizedAction
|
: null;
|
}
|
|
private ApprovalInstance getPendingApprovalInstance(Long instanceId) {
|
return this.getOne(
|
new LambdaQueryWrapper<ApprovalInstance>()
|
.eq(ApprovalInstance::getId, instanceId)
|
.eq(ApprovalInstance::getDeleted, 0)
|
.last("LIMIT 1")
|
);
|
}
|
|
private boolean updateCurrentTask(ApprovalInstanceDto approvalInstanceDto,
|
String approveAction,
|
ApprovalTask currentTask,
|
LocalDateTime now) {
|
// 仅允许待审批任务被成功处理一次,避免并发下重复审批成功。
|
return approvalTaskService.update(
|
Wrappers.<ApprovalTask>lambdaUpdate()
|
.eq(ApprovalTask::getId, currentTask.getId())
|
.eq(ApprovalTask::getTaskStatus, "PENDING")
|
.eq(ApprovalTask::getDeleted, 0)
|
.set(ApprovalTask::getTaskStatus, approveAction)
|
.set(ApprovalTask::getComment, approvalInstanceDto.getApproveComment())
|
.set(ApprovalTask::getApproveTime, now)
|
.set(ApprovalTask::getIsRead, (byte) 1)
|
);
|
}
|
|
private R rejectCurrentNode(ApprovalInstance instance, ApprovalInstanceNode currentNode, LocalDateTime now) {
|
if (!updateCurrentNodeStatus(currentNode.getId(), "REJECTED", now)) {
|
return R.ok("当前节点已处理完成");
|
}
|
|
closePendingTasks(instance.getId(), currentNode.getId());
|
instance.setStatus("REJECTED");
|
instance.setFinishTime(now);
|
this.updateById(instance);
|
// 驳回对应的企业新闻, 差旅报销
|
if (instance.getBusinessType().equals(TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode())) {
|
enterpriseNewsMapper.update(
|
new LambdaUpdateWrapper<EnterpriseNews>()
|
.eq(EnterpriseNews::getId, instance.getBusinessId())
|
.set(EnterpriseNews::getStatus, "REJECTED")
|
);
|
}else if (instance.getBusinessType().equals(TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode())||instance.getBusinessType().equals(TypeEnums.EXPENSE_APPROVAL.getCode())) {
|
finReimbursementMapper.update(
|
new LambdaUpdateWrapper<FinReimbursement>()
|
.eq(FinReimbursement::getId, instance.getBusinessId())
|
.set(FinReimbursement::getBillStatus, "REJECTED")
|
);
|
}
|
return R.ok("审批已驳回");
|
}
|
|
private R approveAndMoveNext(ApprovalInstance instance,
|
ApprovalInstanceNode currentNode,
|
ApprovalInstanceDto approvalInstanceDto,
|
LocalDateTime now) {
|
if (!updateCurrentNodeStatus(currentNode.getId(), "APPROVED", now)) {
|
return R.ok("当前节点已处理完成");
|
}
|
|
closePendingTasks(instance.getId(), currentNode.getId());
|
|
int nextLevel = currentNode.getLevelNo() + 1;
|
ApprovalInstanceNode nextInstanceNode = approvalInstanceNodeService.getOne(
|
new LambdaQueryWrapper<ApprovalInstanceNode>()
|
.eq(ApprovalInstanceNode::getInstanceId, instance.getId())
|
.eq(ApprovalInstanceNode::getLevelNo, nextLevel)
|
.eq(ApprovalInstanceNode::getDeleted, 0)
|
.orderByAsc(ApprovalInstanceNode::getId)
|
.last("LIMIT 1")
|
);
|
|
if (nextInstanceNode != null) {
|
if (!activateNextInstanceNode(nextInstanceNode.getId(), now)) {
|
return R.ok("下一审批节点已被激活,请刷新后重试");
|
}
|
instance.setCurrentLevel(nextLevel);
|
instance.setStatus("PENDING");
|
this.updateById(instance);
|
List<ApprovalTask> nextTasks = approvalTaskService.list(
|
Wrappers.<ApprovalTask>lambdaQuery()
|
.eq(ApprovalTask::getInstanceId, instance.getId())
|
.eq(ApprovalTask::getNodeId, nextInstanceNode.getId())
|
.eq(ApprovalTask::getTaskStatus, "PENDING")
|
.eq(ApprovalTask::getDeleted, 0)
|
);
|
sendApproveNotice(instance, nextTasks);
|
return R.ok("审批成功,已流转到下一节点");
|
}
|
|
ApprovalTemplateNode nextTemplateNode = approvalTemplateNodeService.getOne(
|
new LambdaQueryWrapper<ApprovalTemplateNode>()
|
.eq(ApprovalTemplateNode::getTemplateId, instance.getTemplateId())
|
.eq(ApprovalTemplateNode::getLevelNo, nextLevel)
|
.orderByAsc(ApprovalTemplateNode::getId)
|
.last("LIMIT 1")
|
);
|
|
if (nextTemplateNode == null) {
|
instance.setStatus("APPROVED");
|
instance.setFinishTime(now);
|
this.updateById(instance);
|
handleBusinessAfterApprovalFinished(instance);
|
return R.ok("审批已完成");
|
}
|
|
instance.setCurrentLevel(nextLevel);
|
instance.setStatus("PENDING");
|
this.updateById(instance);
|
approveProcessConfigNodeUtils.createCurrentNodeAndTasks(instance, false);
|
sendApproveNotice(instance, approveProcessConfigNodeUtils.getCurrentPendingTasks(approvalInstanceDto.getId()));
|
return R.ok("审批成功,已流转到下一节点");
|
}
|
|
private boolean activateNextInstanceNode(Long nodeId, LocalDateTime now) {
|
return approvalInstanceNodeService.update(
|
Wrappers.<ApprovalInstanceNode>lambdaUpdate()
|
.eq(ApprovalInstanceNode::getId, nodeId)
|
.eq(ApprovalInstanceNode::getStatus, "WAITING")
|
.eq(ApprovalInstanceNode::getDeleted, 0)
|
.set(ApprovalInstanceNode::getStatus, "PENDING")
|
.set(ApprovalInstanceNode::getStartTime, now)
|
);
|
}
|
|
private boolean updateCurrentNodeStatus(Long nodeId, String targetStatus, LocalDateTime now) {
|
// 仅允许一个请求将当前节点从待处理推进到目标状态,避免重复流转。
|
return approvalInstanceNodeService.update(
|
Wrappers.<ApprovalInstanceNode>lambdaUpdate()
|
.eq(ApprovalInstanceNode::getId, nodeId)
|
.eq(ApprovalInstanceNode::getStatus, "PENDING")
|
.eq(ApprovalInstanceNode::getDeleted, 0)
|
.set(ApprovalInstanceNode::getStatus, targetStatus)
|
.set(ApprovalInstanceNode::getFinishTime, now)
|
);
|
}
|
|
private void handleBusinessAfterApprovalFinished(ApprovalInstance instance) {
|
String status = instance.getStatus();
|
Long businessType = instance.getBusinessType();
|
if (TypeEnums.PURCHASE_APPROVAL.getCode().equals(businessType)) {
|
handlePurchaseApprovalFinished(instance, status);
|
return;
|
}
|
if (TypeEnums.QUOTATION_APPROVAL.getCode().equals(businessType)) {
|
handleSalesQuotationApprovalFinished(instance, status);
|
return;
|
}
|
if (TypeEnums.SHIPPING_APPROVAL.getCode().equals(businessType)) {
|
handleShippingApprovalFinished(instance, status);
|
return;
|
}
|
if (TypeEnums.TRAVEL_REIMBURSEMENT_APPROVAL.getCode().equals(businessType)
|
|| TypeEnums.EXPENSE_APPROVAL.getCode().equals(businessType)) {
|
handleReimbursementApprovalFinished(instance, status);
|
return;
|
}
|
// 驳回对应的企业新闻、加班申请、请假申请可以重新再提交
|
if (TypeEnums.LEAVE_APPROVAL.getCode().equals(businessType)
|
|| TypeEnums.OVERTIME_APPROVAL.getCode().equals(businessType)) {
|
handleHolidayApplicationApprovalFinished(instance, status);
|
return;
|
}
|
if (TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode().equals(businessType)) {
|
handleNewsApprovalFinished(instance, status);
|
}
|
}
|
|
private void handleReimbursementApprovalFinished(ApprovalInstance instance, String status) {
|
if (instance == null || instance.getBusinessId() == null) {
|
return;
|
}
|
|
FinReimbursement reimbursement = new FinReimbursement();
|
reimbursement.setId(instance.getBusinessId());
|
if ("APPROVED".equals(status)) {
|
reimbursement.setBillStatus("APPROVED");
|
reimbursement.setApprovedTime(instance.getFinishTime());
|
} else if ("REJECTED".equals(status)) {
|
reimbursement.setBillStatus("REJECTED");
|
} else if ("PENDING".equals(status)) {
|
reimbursement.setBillStatus("IN_APPROVAL");
|
} else {
|
return;
|
}
|
finReimbursementMapper.updateById(reimbursement);
|
}
|
|
private void handleNewsApprovalFinished(ApprovalInstance instance, String status) {
|
if (instance == null || instance.getBusinessId() == null) {
|
return;
|
}
|
EnterpriseNews enterpriseNews = new EnterpriseNews();
|
enterpriseNews.setId(instance.getBusinessId());
|
if ("APPROVED".equals(status)) {
|
enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_PUBLISHED);
|
enterpriseNewsMapper.updateById(enterpriseNews);
|
sendEnterpriseNewsNotice(instance.getBusinessId());
|
return;
|
}
|
if ("REJECTED".equals(status)) {
|
enterpriseNews.setStatus(ENTERPRISE_NEWS_STATUS_REJECTED);
|
enterpriseNewsMapper.updateById(enterpriseNews);
|
}
|
}
|
|
private void handleHolidayApplicationApprovalFinished(ApprovalInstance instance, String status) {
|
if (instance == null || instance.getBusinessId() == null) {
|
return;
|
}
|
HolidayApplication holidayApplication = new HolidayApplication();
|
holidayApplication.setId(instance.getBusinessId());
|
if ("APPROVED".equals(status)) {
|
holidayApplication.setStatus("APPROVED");
|
} else if ("REJECTED".equals(status)) {
|
holidayApplication.setStatus("REJECTED");
|
} else if ("PENDING".equals(status)) {
|
holidayApplication.setStatus("PENDING");
|
} else {
|
return;
|
}
|
holidayApplicationMapper.updateById(holidayApplication);
|
}
|
|
private void handlePurchaseApprovalFinished(ApprovalInstance instance, String status) {
|
PurchaseLedger purchaseLedger = purchaseLedgerMapper.selectOne(
|
new LambdaQueryWrapper<PurchaseLedger>()
|
.eq(PurchaseLedger::getPurchaseContractNumber, instance.getTitle())
|
.last("limit 1")
|
);
|
if (purchaseLedger == null) {
|
return;
|
}
|
|
if ("APPROVED".equals(status)) {
|
purchaseLedger.setApprovalStatus(ApprovalStatusEnum.APPROVED.getCode());
|
List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(
|
new QueryWrapper<SalesLedgerProduct>().lambda()
|
.eq(SalesLedgerProduct::getSalesLedgerId, purchaseLedger.getId())
|
.eq(SalesLedgerProduct::getType, 2)
|
);
|
for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
|
if (salesLedgerProduct.getIsChecked()) {
|
qualityInspectHelper.addQualityInspect(purchaseLedger, salesLedgerProduct);
|
} else {
|
stockUtils.addStockWithBatchNo(
|
salesLedgerProduct.getProductModelId(),
|
salesLedgerProduct.getQuantity(),
|
StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
|
purchaseLedger.getId(),
|
purchaseLedger.getPurchaseContractNumber() + "-" + salesLedgerProduct.getId()
|
);
|
}
|
}
|
} else if ("REJECTED".equals(status)) {
|
purchaseLedger.setApprovalStatus(ApprovalStatusEnum.REJECTED.getCode());
|
} else if ("PENDING".equals(status)) {
|
purchaseLedger.setApprovalStatus(ApprovalStatusEnum.IN_PROGRESS.getCode());
|
}
|
purchaseLedgerMapper.updateById(purchaseLedger);
|
}
|
|
private void handleSalesQuotationApprovalFinished(ApprovalInstance instance, String status) {
|
SalesQuotation salesQuote = salesQuotationMapper.selectOne(
|
new LambdaQueryWrapper<SalesQuotation>()
|
.eq(SalesQuotation::getQuotationNo, instance.getTitle())
|
.last("limit 1")
|
);
|
if (salesQuote == null) {
|
return;
|
}
|
|
if ("APPROVED".equals(status)) {
|
salesQuote.setStatus(SalesQuotationStatusEnum.APPROVED.getCode());
|
} else if ("REJECTED".equals(status)) {
|
salesQuote.setStatus(SalesQuotationStatusEnum.REJECTED.getCode());
|
} else if ("PENDING".equals(status)) {
|
salesQuote.setStatus(SalesQuotationStatusEnum.IN_PROGRESS.getCode());
|
}
|
salesQuotationMapper.updateById(salesQuote);
|
}
|
|
private void handleShippingApprovalFinished(ApprovalInstance instance, String status) {
|
ShippingInfo shippingInfo = shippingInfoMapper.selectOne(
|
new LambdaQueryWrapper<ShippingInfo>()
|
.eq(ShippingInfo::getShippingNo, instance.getTitle())
|
.orderByDesc(ShippingInfo::getCreateTime)
|
.last("limit 1")
|
);
|
if (shippingInfo == null) {
|
return;
|
}
|
|
if ("APPROVED".equals(status)) {
|
shippingInfo.setStatus(ShippingStatusEnum.APPROVED.getCode());
|
shippingInfo.setShippingDate(new Date());
|
stockUtils.shipmentStatus(StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), shippingInfo.getId());
|
} else if ("REJECTED".equals(status)) {
|
stockUtils.deleteStockOutRecord(shippingInfo.getId(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode());
|
shippingInfo.setStatus(ShippingStatusEnum.REJECTED.getCode());
|
} else if ("PENDING".equals(status)) {
|
shippingInfo.setStatus(ShippingStatusEnum.IN_PROGRESS.getCode());
|
}
|
shippingInfoMapper.updateById(shippingInfo);
|
}
|
|
private List<ApprovalTask> createNodeAndTasks(ApprovalInstance instance, ApprovalTemplateNode templateNode) {
|
List<ApprovalTemplateNodeApprover> approvers = approvalTemplateNodeApproverMapper.selectList(
|
new LambdaQueryWrapper<ApprovalTemplateNodeApprover>()
|
.eq(ApprovalTemplateNodeApprover::getTemplateId, instance.getTemplateId())
|
.eq(ApprovalTemplateNodeApprover::getNodeId, templateNode.getId())
|
.eq(ApprovalTemplateNodeApprover::getDeleted, 0L)
|
.orderByAsc(ApprovalTemplateNodeApprover::getSortNo)
|
);
|
if (approvers == null || approvers.isEmpty()) {
|
throw new RuntimeException("下一审批节点未配置审批人");
|
}
|
|
ApprovalInstanceNode instanceNode = new ApprovalInstanceNode();
|
instanceNode.setInstanceId(instance.getId());
|
instanceNode.setLevelNo(templateNode.getLevelNo());
|
instanceNode.setApproveType(templateNode.getApproveType());
|
instanceNode.setStatus("PENDING");
|
instanceNode.setStartTime(LocalDateTime.now());
|
instanceNode.setDeleted((byte) 0);
|
approvalInstanceNodeService.save(instanceNode);
|
|
List<ApprovalTask> taskList = new ArrayList<>(approvers.size());
|
for (ApprovalTemplateNodeApprover approver : approvers) {
|
ApprovalTask task = new ApprovalTask();
|
task.setInstanceId(instance.getId());
|
task.setNodeId(instanceNode.getId());
|
task.setLevelNo(instanceNode.getLevelNo());
|
task.setApproverId(approver.getApproverId());
|
task.setApproverName(approver.getApproverName());
|
task.setTaskStatus("PENDING");
|
task.setIsRead((byte) 0);
|
task.setDeleted((byte) 0);
|
taskList.add(task);
|
}
|
approvalTaskService.saveBatch(taskList);
|
return taskList;
|
}
|
|
private void sendApproveNotice(ApprovalInstance instance, List<ApprovalTask> tasks) {
|
if (instance == null || tasks == null || tasks.isEmpty()) {
|
return;
|
}
|
|
List<Long> approverIds = tasks.stream()
|
.map(ApprovalTask::getApproverId)
|
.filter(id -> id != null && id > 0)
|
.distinct()
|
.collect(Collectors.toList());
|
if (approverIds.isEmpty()) {
|
return;
|
}
|
|
String title = StringUtils.hasText(instance.getTemplateName()) ? instance.getTemplateName() : "审批提醒";
|
String message = "审批单号 " + instance.getInstanceNo() + " 需要您审批";
|
String jumpPath = "/approvalInstance?id=" + instance.getId();
|
sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath);
|
}
|
|
private void sendEnterpriseNewsNotice(Long newsId) {
|
EnterpriseNews enterpriseNews = enterpriseNewsMapper.selectById(newsId);
|
if (enterpriseNews == null) {
|
return;
|
}
|
List<Long> userIds = getEnterpriseNewsNoticeUserIds(enterpriseNews);
|
if (userIds == null || userIds.isEmpty()) {
|
return;
|
}
|
String title = "企业新闻";
|
String message = "您有新的企业新闻《" + enterpriseNews.getTitle() + "》请及时查阅";
|
String jumpPath = "/enterpriseNews?id=" + newsId;
|
sysNoticeService.simpleNoticeByUser(title, message, userIds, jumpPath);
|
}
|
|
private List<Long> getEnterpriseNewsNoticeUserIds(EnterpriseNews enterpriseNews) {
|
if (enterpriseNews == null || !org.springframework.util.StringUtils.hasText(enterpriseNews.getReadScope())) {
|
return Collections.emptyList();
|
}
|
String readScope = enterpriseNews.getReadScope().trim();
|
if ("all".equals(readScope)) {
|
return sysUserMapper.selectList(new LambdaQueryWrapper<SysUser>()
|
.select(SysUser::getUserId)
|
.eq(SysUser::getDelFlag, "0"))
|
.stream()
|
.map(SysUser::getUserId)
|
.filter(id -> id != null && id > 0)
|
.distinct()
|
.collect(Collectors.toList());
|
}
|
if ("dept".equals(readScope)) {
|
List<Long> deptIds = enterpriseNewsScopeDeptMapper.selectList(
|
new LambdaQueryWrapper<EnterpriseNewsScopeDept>()
|
.eq(EnterpriseNewsScopeDept::getNewsId, enterpriseNews.getId()))
|
.stream()
|
.map(EnterpriseNewsScopeDept::getDeptId)
|
.filter(id -> id != null && id > 0)
|
.distinct()
|
.collect(Collectors.toList());
|
if (deptIds.isEmpty()) {
|
return Collections.emptyList();
|
}
|
return sysUserDeptMapper.selectDistinctUserIdsByDeptIds(collectDeptIdsWithChildren(deptIds));
|
}
|
if ("custom".equals(readScope)) {
|
return enterpriseNewsScopeUserMapper.selectList(
|
new LambdaQueryWrapper<EnterpriseNewsScopeUser>()
|
.eq(EnterpriseNewsScopeUser::getNewsId, enterpriseNews.getId()))
|
.stream()
|
.map(EnterpriseNewsScopeUser::getUserId)
|
.filter(id -> id != null && id > 0)
|
.distinct()
|
.collect(Collectors.toList());
|
}
|
return Collections.emptyList();
|
}
|
|
private List<Long> collectDeptIdsWithChildren(List<Long> deptIds) {
|
Set<Long> allDeptIds = new LinkedHashSet<>();
|
for (Long deptId : deptIds) {
|
if (deptId == null) {
|
continue;
|
}
|
allDeptIds.add(deptId);
|
List<SysDept> children = sysDeptMapper.selectChildrenDeptById(deptId);
|
if (children != null && !children.isEmpty()) {
|
for (SysDept child : children) {
|
if (child != null && child.getDeptId() != null) {
|
allDeptIds.add(child.getDeptId());
|
}
|
}
|
}
|
}
|
return new ArrayList<>(allDeptIds);
|
}
|
|
private void closePendingTasks(Long instanceId, Long nodeId) {
|
LambdaUpdateWrapper<ApprovalTask> updateWrapper = Wrappers.lambdaUpdate();
|
updateWrapper.eq(ApprovalTask::getInstanceId, instanceId)
|
.eq(ApprovalTask::getNodeId, nodeId)
|
.eq(ApprovalTask::getTaskStatus, "PENDING")
|
.eq(ApprovalTask::getDeleted, 0)
|
.set(ApprovalTask::getDeleted, (byte) 1);
|
approvalTaskService.update(updateWrapper);
|
}
|
|
private void saveApprovalRecord(Long instanceId,
|
Long nodeId,
|
Long taskId,
|
Long operatorId,
|
String operatorName,
|
String action,
|
String comment) {
|
ApprovalRecord record = new ApprovalRecord();
|
record.setInstanceId(instanceId);
|
record.setNodeId(nodeId);
|
record.setTaskId(taskId);
|
record.setOperatorId(operatorId);
|
record.setOperatorName(operatorName);
|
record.setAction(action);
|
record.setComment(comment);
|
record.setDeleted((byte) 0);
|
approvalRecordService.save(record);
|
}
|
|
|
}
|