云
4 天以前 ccdebc5369c108e6616550bfbe1cd47ec1e05813
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/feedback/MesProFeedbackServiceImpl.java
@@ -4,11 +4,14 @@
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmProcessDefinitionService;
import org.flowable.engine.repository.ProcessDefinition;
import cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo.*;
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
@@ -76,6 +79,7 @@
import java.util.List;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -90,6 +94,8 @@
@Validated
@lombok.extern.slf4j.Slf4j
public class MesProFeedbackServiceImpl implements MesProFeedbackService {
    private static final String FEEDBACK_APPROVE_CATEGORY_CODE = "mes_pro_feedback_audit";
    @Resource
    private MesProFeedbackEquipmentService equipmentService;
@@ -147,6 +153,8 @@
    private MdmItemBatchConfigApi itemBatchConfigApi;
    @Resource
    private cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi processInstanceApi;
    @Resource
    private BpmProcessDefinitionService bpmProcessDefinitionService;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -267,16 +275,28 @@
        }
        MesProWorkOrderDO workOrder = workOrderService.getWorkOrder(feedback.getWorkOrderId());
        if (workOrder != null && Boolean.TRUE.equals(workOrder.getFeedbackApprove())
                && StrUtil.isBlank(workOrder.getProcessDefinitionKey())) {
            throw exception(PRO_FEEDBACK_APPROVAL_PROCESS_KEY_REQUIRED);
        }
        // 1.2 报工与质检分离:提交报工不再自动生成过程检验单,质检由质检部门手工建单
        if (!processInstanceApi.isGlobalAutoApprove() && workOrder != null
                && Boolean.TRUE.equals(workOrder.getFeedbackApprove())
                && cn.hutool.core.util.StrUtil.isNotBlank(workOrder.getProcessDefinitionKey())) {
                && StrUtil.isNotBlank(workOrder.getProcessDefinitionKey())) {
            ProcessDefinition processDefinition = bpmProcessDefinitionService
                    .getActiveProcessDefinition(workOrder.getProcessDefinitionKey());
            if (processDefinition == null || bpmProcessDefinitionService
                    .getProcessDefinitionInfoListByCategory(FEEDBACK_APPROVE_CATEGORY_CODE).stream()
                    .noneMatch(info -> Objects.equals(info.getProcessDefinitionId(), processDefinition.getId()))) {
                throw exception(PRO_FEEDBACK_APPROVAL_PROCESS_KEY_INVALID);
            }
            // 2. 更新状态为审批中,并启动流程
            String processInstanceId = processInstanceApi.createProcessInstance(cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId(),
                    new cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO()
                            .setProcessDefinitionKey(workOrder.getProcessDefinitionKey())
                            .setBusinessKey(String.valueOf(id)));
                            .setBusinessKey(String.valueOf(id))
                            .setVariables(Map.of("businessNo", feedback.getCode())));
            feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
                    .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus())
@@ -292,8 +312,11 @@
            }
            // 3. 更新状态为审批中,然后直接通过审批
            feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
                    .setStatus(MesProFeedbackStatusEnum.APPROVING.getStatus()));
            feedbackMapper.update(null, new LambdaUpdateWrapper<MesProFeedbackDO>()
                    .eq(MesProFeedbackDO::getId, id)
                    .set(MesProFeedbackDO::getStatus, MesProFeedbackStatusEnum.APPROVING.getStatus())
                    .set(MesProFeedbackDO::getProcessInstanceId, null)
                    .set(MesProFeedbackDO::getProcessDefinitionKey, null));
            MesProFeedbackApproveReqVO approveReqVO = cn.iocoder.yudao.framework.common.util.object.BeanUtils.toBean(reqVO, MesProFeedbackApproveReqVO.class);
            // 自动审批:过程检验单刚生成尚未填写,不做质检工资前置校验(质量调整留空)
            approveFeedback(approveReqVO, false);
@@ -329,21 +352,29 @@
                 reqVO.setLotNumber(reason);
               }
            }
            approveFeedback(reqVO);
            // BPM 回调时流程实例仍在运行,必须走内部方法,不能被「已发起流程」的校验拦住
            doApproveFeedback(reqVO, feedback, true);
        } else if (cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum.REJECT.getStatus().equals(bpmResult) ||
                   cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum.CANCEL.getStatus().equals(bpmResult)) {
            rejectFeedback(id);
            doRejectFeedback(id);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void rejectFeedback(Long id) {
        equipmentService.lock();
        // 1. 校验存在 + 审批中状态
        validateFeedbackStatusApproving(id);
        MesProFeedbackDO feedback = validateFeedbackStatusApproving(id);
        // 1.1 已发起审批流程的报工单只能由审批人通过「待办任务」处理,避免业务接口绕过流程
        if (StrUtil.isNotBlank(feedback.getProcessInstanceId())) {
            throw exception(PRO_FEEDBACK_APPROVAL_HANDLE_IN_BPM);
        }
        doRejectFeedback(id);
    }
        // 2. 更新状态为草稿
    private void doRejectFeedback(Long id) {
        equipmentService.lock();
        // 1. 更新状态为草稿
        feedbackMapper.updateById(new MesProFeedbackDO().setId(id)
                .setStatus(MesProFeedbackStatusEnum.PREPARE.getStatus()));
    }
@@ -355,9 +386,18 @@
    }
    private boolean approveFeedback(MesProFeedbackApproveReqVO reqVO, boolean enforceQualityGate) {
        equipmentService.lock();
        // 1.1 校验存在 + 审批中状态
        MesProFeedbackDO feedback = validateFeedbackStatusApproving(reqVO.getId());
        // 1.2 已发起审批流程的报工单只能由审批人通过「待办任务」处理,避免业务接口绕过流程
        if (StrUtil.isNotBlank(feedback.getProcessInstanceId())) {
            throw exception(PRO_FEEDBACK_APPROVAL_HANDLE_IN_BPM);
        }
        return doApproveFeedback(reqVO, feedback, enforceQualityGate);
    }
    private boolean doApproveFeedback(MesProFeedbackApproveReqVO reqVO, MesProFeedbackDO feedback,
                                      boolean enforceQualityGate) {
        equipmentService.lock();
        equipmentService.validateApproval(feedback);
        try (var equipmentScope = equipmentService.beginApproval(feedback)) {
            return approveValidatedFeedback(reqVO, feedback, enforceQualityGate);