昨天 eccad5a129106377a275be4f7cdc58e99e9b95d4
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/mps/MesProMpsServiceImpl.java
@@ -12,7 +12,10 @@
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.mps.MesProMpsMergeItemDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.mps.MesProMpsMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.mps.MesProMpsMergeItemMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO;
import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
@@ -61,6 +64,8 @@
    private MesMdAutoCodeRecordService autoCodeRecordService;
    @Resource
    private CrmCustomerApi customerApi;
    @Resource
    private MesProFeedbackMapper feedbackMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -331,6 +336,94 @@
        mpsMapper.updateProducedQuantity(id, incrQuantity);
    }
    @Override
    public Boolean checkSaleOrderProductionFinished(Long saleOrderId) {
        if (saleOrderId == null) {
            return false;
        }
        // 1. 查询该销售订单所有 MPS(通过 saleOrderId 关联)
        List<MesProMpsDO> mpsList = mpsMapper.selectList(
                MesProMpsDO::getSaleOrderId, saleOrderId);
        if (CollUtil.isEmpty(mpsList)) {
            // 无 MPS 关联,视为完成
            return true;
        }
        // 2. 检查每个 MPS 是否完成
        for (MesProMpsDO mps : mpsList) {
            if (!isMpsFinished(mps)) {
                return false;
            }
        }
        return true;
    }
    @Override
    public MesProMpsDO getMpsByWorkOrderId(Long workOrderId) {
        if (workOrderId == null) {
            return null;
        }
        return mpsMapper.selectOne(MesProMpsDO::getWorkOrderId, workOrderId);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean checkAndFinishMps(Long mpsId) {
        if (mpsId == null) {
            log.warn("[checkAndFinishMps] mpsId is null");
            return false;
        }
        MesProMpsDO mps = mpsMapper.selectById(mpsId);
        if (mps == null) {
            log.warn("[checkAndFinishMps] MPS not found, mpsId={}", mpsId);
            return false;
        }
        // 已完成或已取消,直接返回 true
        if (MesProMpsStatusEnum.FINISHED.getStatus().equals(mps.getStatus())
                || MesProMpsStatusEnum.CANCELED.getStatus().equals(mps.getStatus())) {
            log.info("[checkAndFinishMps] MPS {} already finished or canceled, status={}", mpsId, mps.getStatus());
            return true;
        }
        // 检查是否满足完成条件
        boolean finished = isMpsFinished(mps);
        log.info("[checkAndFinishMps] MPS {} check result: {}, quantity={}, produced={}, workOrderId={}",
                mpsId, finished, mps.getQuantity(), mps.getQuantityProduced(), mps.getWorkOrderId());
        if (finished) {
            // 自动完成 MPS
            mpsMapper.updateById(new MesProMpsDO()
                    .setId(mpsId)
                    .setStatus(MesProMpsStatusEnum.FINISHED.getStatus())
                    .setFinishDate(LocalDateTime.now()));
            log.info("[checkAndFinishMps] MPS {} auto finished", mpsId);
            return true;
        }
        return false;
    }
    /**
     * 判断单个 MPS 是否完成
     */
    private boolean isMpsFinished(MesProMpsDO mps) {
        // 1. 已生产数量 >= 计划数量
        BigDecimal quantityProduced = ObjUtil.defaultIfNull(mps.getQuantityProduced(), BigDecimal.ZERO);
        if (quantityProduced.compareTo(mps.getQuantity()) < 0) {
            log.debug("[isMpsFinished] MPS {} quantity not enough: produced={}, required={}",
                    mps.getId(), quantityProduced, mps.getQuantity());
            return false;
        }
        // 2. 检查工单下所有报工是否完成(确保质检完成)
        if (mps.getWorkOrderId() != null) {
            Long unfinishedCount = feedbackMapper.selectCount(
                    new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MesProFeedbackDO>()
                            .eq(MesProFeedbackDO::getWorkOrderId, mps.getWorkOrderId())
                            .ne(MesProFeedbackDO::getStatus, MesProFeedbackStatusEnum.FINISHED.getStatus()));
            log.debug("[isMpsFinished] MPS {} unfinished feedback count: {}", mps.getId(), unfinishedCount);
            if (unfinishedCount > 0) {
                return false;
            }
        }
        return true;
    }
    // ========== 私有方法 ==========
    /**