云
2026-10-27 ffca46b39d25439a06a27cafda2ec523a3fb67cf
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/wm/batch/MesWmBatchServiceImpl.java
@@ -6,9 +6,14 @@
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchProcessTraceRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchPurchaseSourceRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.wm.batch.vo.MesWmBatchSalesTargetRespVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.mdm.MesMdmItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.batch.MesWmBatchDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.sn.MesWmSnDO;
import cn.iocoder.yudao.module.mes.dal.mysql.wm.batch.MesWmBatchMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.wm.sn.MesWmSnMapper;
import cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
@@ -24,6 +29,7 @@
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -34,7 +40,7 @@
/**
 * 批次管理 Service 实现类
 *
 * @author 芋道源码
 * @author 超级管理员
 */
@Service
@Validated
@@ -52,6 +58,8 @@
    @Resource
    private MesMdmItemService mdmItemService;
    @Resource
    private MesWmSnMapper snMapper;
    @Resource
    private MdmItemBatchConfigApi itemBatchConfigApi;
    @Resource
    private MesMdAutoCodeRecordService autoCodeRecordService;
@@ -62,9 +70,7 @@
    @Override
    public PageResult<MesWmBatchDO> getBatchPage(MesWmBatchPageReqVO pageReqVO) {
        // 获取用户有权限的客户 ID 列表
        List<Long> permittedClientIds = customerApi.getPermittedCustomerIds();
        return batchMapper.selectPage(pageReqVO, permittedClientIds);
        return batchMapper.selectPage(pageReqVO, (List<Long>) null);
    }
    @Override
@@ -78,11 +84,16 @@
    }
    @Override
    public List<MesWmBatchDO> getBatchList(java.util.Collection<Long> ids) {
        return CollUtil.isEmpty(ids) ? java.util.Collections.emptyList() : batchMapper.selectByIds(ids);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public MesWmBatchDO getOrGenerateBatchCode(MesWmBatchGenerateReqVO reqVO) {
        // 1.1 查询物料信息,检查是否启用批次管理
        MesMdmItemDO item = mdmItemService.validateItemExists(reqVO.getItemId());
        if (Boolean.FALSE.equals(item.getIsBatchManaged())) {
        if (Boolean.FALSE.equals(item.getIsBatchManaged()) && StrUtil.isBlank(reqVO.getReelNo())) {
            // 未启用批次管理,返回 null
            return null;
        }
@@ -95,7 +106,8 @@
        MdmItemBatchConfigRespDTO config = itemBatchConfigApi.getItemBatchConfig(reqVO.getItemId());
        // 2. 根据配置校验必填参数并清空不需要的参数
        MesWmBatchDO batch = MesWmBatchDO.builder().itemId(reqVO.getItemId()).build();
        String reelNo = StrUtil.isBlank(reqVO.getReelNo()) ? null : reqVO.getReelNo();
        MesWmBatchDO batch = MesWmBatchDO.builder().itemId(reqVO.getItemId()).reelNo(reelNo).build();
        if (config != null) {
            // ========== 必填校验(flag=true 表示该字段为必填) ==========
            // 生产日期
@@ -207,6 +219,15 @@
                // 校验物料是否匹配
                if (!existingBatch.getItemId().equals(reqVO.getItemId())) {
                    throw exception(WM_BATCH_ITEM_MISMATCH);
                }
                // 已有批次不能改变盘号,避免历史库存被误标或不同盘号混合。
                String existingReelNo = StrUtil.isBlank(existingBatch.getReelNo()) ? null : existingBatch.getReelNo();
                if (!ObjUtil.equal(existingReelNo, reelNo)) {
                    throw exception(WM_BATCH_REEL_MISMATCH);
                }
                if (existingReelNo != null && !ObjUtil.equal(existingBatch.getWorkOrderId(), reqVO.getWorkOrderId())) {
                    // 已有追溯批次不能被另一工单复用并覆盖来源。
                    throw exception(WM_BATCH_REEL_MISMATCH);
                }
                // 更新批次属性(仅更新传入的非空值)
                updateBatchProperties(existingBatch, batch);
@@ -372,4 +393,39 @@
        return batchMapper.selectCountByToolId(toolId);
    }
    @Override
    public List<MesWmBatchPurchaseSourceRespVO> getPurchaseSourceList(String code) {
        return batchMapper.selectPurchaseSourceList(code);
    }
    @Override
    public List<MesWmBatchSalesTargetRespVO> getSalesTargetList(String code) {
        return batchMapper.selectSalesTargetList(code);
    }
    @Override
    public List<MesWmBatchProcessTraceRespVO> getProcessTraceList(String code) {
        List<MesWmBatchProcessTraceRespVO> list = batchMapper.selectProcessTraceList(code);
        if (CollUtil.isEmpty(list)) {
            return list;
        }
        // 按工单、工序序号、事件时间排序(sort 可能为空,空值兜底)
        list.sort(Comparator.comparing(MesWmBatchProcessTraceRespVO::getWorkOrderId,
                        Comparator.nullsLast(Comparator.naturalOrder()))
                .thenComparing(MesWmBatchProcessTraceRespVO::getProcessSort,
                        Comparator.nullsLast(Comparator.naturalOrder()))
                .thenComparing(MesWmBatchProcessTraceRespVO::getEventTime,
                        Comparator.nullsLast(Comparator.naturalOrder())));
        return list;
    }
    @Override
    public MesWmBatchDO getBatchBySn(String sn) {
        MesWmSnDO snDO = snMapper.selectOne(MesWmSnDO::getCode, sn);
        if (snDO == null || StrUtil.isBlank(snDO.getBatchCode())) {
            return null;
        }
        return batchMapper.selectByCode(snDO.getBatchCode());
    }
}