From 704265308b1227dbada5a36b2027b588c062ded2 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 12 十月 2026 09:14:37 +0800
Subject: [PATCH] feat(mes): 新增业务码支持并优化追溯查询功能

---
 yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java |  102 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
index c0ae4ce..6830e19 100644
--- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
+++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
@@ -5,6 +5,7 @@
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.mes.controller.admin.pro.bagcode.vo.MesProBagCodePageReqVO;
 import cn.iocoder.yudao.module.mes.dal.dataobject.pro.bagcode.MesProBagCodeDO;
+import cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
@@ -27,6 +28,18 @@
         return selectOne(MesProBagCodeDO::getCode, code);
     }
 
+    /** 鍐呴儴鎵爜鍏煎涓氬姟鐮佷笌鍘嗗彶杩芥函鐮侊紱鍏紬杩芥函缁х画鍙寜 code 鏌ヨ銆� */
+    default MesProBagCodeDO selectByScanCode(String code) {
+        return selectOne(new LambdaQueryWrapperX<MesProBagCodeDO>()
+                .and(q -> q.eq(MesProBagCodeDO::getBusinessCode, code).or().eq(MesProBagCodeDO::getCode, code)));
+    }
+
+    default MesProBagCodeDO selectByScanCodeForUpdate(String code) {
+        return selectOne(new LambdaQueryWrapperX<MesProBagCodeDO>()
+                .and(q -> q.eq(MesProBagCodeDO::getBusinessCode, code).or().eq(MesProBagCodeDO::getCode, code))
+                .last("FOR UPDATE"));
+    }
+
     default MesProBagCodeDO selectByCodeForUpdate(String code) {
         return selectOne(new LambdaQueryWrapperX<MesProBagCodeDO>()
                 .eq(MesProBagCodeDO::getCode, code).last("FOR UPDATE"));
@@ -38,13 +51,13 @@
 
     /** 鎵规鏁存壒鍏ュ簱鏃舵壒閲忔爣璁板叾涓嬫湭鍏ュ簱琚嬬爜锛堝箓绛夛級锛屼繚鎸佽鐮佷笌搴撳瓨鐘舵�佷竴鑷� */
     @Update("UPDATE mes_pro_bag_code SET inbound_time = NOW(), inbound_event_id = #{eventId}, inbound_line_code = #{lineCode}, update_time = NOW() "
-            + "WHERE deleted = 0 AND inbound_event_id IS NULL AND batch_id = #{batchId}")
+            + "WHERE deleted = 0 AND status <> 30 AND inbound_event_id IS NULL AND batch_id = #{batchId}")
     int markInboundByBatchId(@Param("batchId") Long batchId, @Param("eventId") Long eventId,
                              @Param("lineCode") String lineCode);
 
     /** 鏁存墭鍏ュ簱鏃舵壒閲忔爣璁版墭鐩樹笅鏈叆搴撹鐮侊紙骞傜瓑锛� */
     @Update("UPDATE mes_pro_bag_code SET inbound_time = NOW(), inbound_event_id = #{eventId}, inbound_line_code = #{lineCode}, update_time = NOW() "
-            + "WHERE deleted = 0 AND inbound_event_id IS NULL AND pallet_id = #{palletId}")
+            + "WHERE deleted = 0 AND status <> 30 AND inbound_event_id IS NULL AND pallet_id = #{palletId}")
     int markInboundByPalletId(@Param("palletId") Long palletId, @Param("eventId") Long eventId,
                               @Param("lineCode") String lineCode);
 
@@ -72,6 +85,29 @@
         return selectList(MesProBagCodeDO::getBatchId, batchId);
     }
 
+    /**
+     * 鏌ヨ鐢熸垚缁勪笅鍙嵃鍒风殑琚嬬爜锛堟帓闄ゅ凡浣滃簾锛夛紝鐢ㄤ簬浜岀淮鐮佹爣绛惧鍑�
+     * <p>
+     * 宸蹭綔搴熻鐮佺殑鏍囩涓嶅緱鍐嶅嵃鍒凤細鍏舵爣绛捐嫢璐村埌浜у搧涓婏紝娑堣垂鑰呮壂鐮佷細琚彁绀恒�岃杩芥函鐮佸凡浣滃簾銆嶏紝
+     * 瀵艰嚧鐪熷搧琚鍒や负鍋囪揣銆�
+     */
+    default List<MesProBagCodeDO> selectPrintableListByUuid(String uuid) {
+        return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>()
+                .eq(MesProBagCodeDO::getUuid, uuid)
+                .ne(MesProBagCodeDO::getStatus, MesProBagCodeStatusEnum.CANCELED.getStatus())
+                .orderByAsc(MesProBagCodeDO::getBagNo));
+    }
+
+    /**
+     * 鏌ヨ鎵规涓嬪彲鍗板埛鐨勮鐮侊紙鎺掗櫎宸蹭綔搴燂級锛岀敤浜庝簩缁寸爜鏍囩瀵煎嚭
+     */
+    default List<MesProBagCodeDO> selectPrintableListByBatchId(Long batchId) {
+        return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>()
+                .eq(MesProBagCodeDO::getBatchId, batchId)
+                .ne(MesProBagCodeDO::getStatus, MesProBagCodeStatusEnum.CANCELED.getStatus())
+                .orderByAsc(MesProBagCodeDO::getBagNo));
+    }
+
     default Long selectCountByBatchId(Long batchId) {
         return selectCount(MesProBagCodeDO::getBatchId, batchId);
     }
@@ -83,17 +119,28 @@
     default List<MesProBagCodeDO> selectListByPalletId(Long palletId) {
         return selectList(MesProBagCodeDO::getPalletId, palletId);
     }
+    default List<MesProBagCodeDO> selectListByPalletIdForUpdate(Long palletId) {
+        return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>().eq(MesProBagCodeDO::getPalletId, palletId).orderByAsc(MesProBagCodeDO::getId).last("FOR UPDATE"));
+    }
+    default List<MesProBagCodeDO> selectListByBatchIdForUpdate(Long batchId) {
+        return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>().eq(MesProBagCodeDO::getBatchId, batchId).orderByAsc(MesProBagCodeDO::getId).last("FOR UPDATE"));
+    }
 
     default PageResult<MesProBagCodeDO> selectPage(MesProBagCodePageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<MesProBagCodeDO>()
-                .likeIfPresent(MesProBagCodeDO::getCode, reqVO.getCode())
+                .likeIfPresent(MesProBagCodeDO::getBusinessCode, reqVO.getBusinessCode())
                 .eqIfPresent(MesProBagCodeDO::getBatchId, reqVO.getBatchId())
                 .likeIfPresent(MesProBagCodeDO::getBatchCode, reqVO.getBatchCode())
                 .eqIfPresent(MesProBagCodeDO::getUuid, reqVO.getUuid())
                 .eqIfPresent(MesProBagCodeDO::getPalletId, reqVO.getPalletId())
+                .eqIfPresent(MesProBagCodeDO::getItemId, reqVO.getItemId())
                 .eqIfPresent(MesProBagCodeDO::getStatus, reqVO.getStatus())
                 .betweenIfPresent(MesProBagCodeDO::getCreateTime, reqVO.getCreateTime())
-                .orderByAsc(MesProBagCodeDO::getBagNo));
+                .orderByDesc(MesProBagCodeDO::getCreateTime)
+                .orderByDesc(MesProBagCodeDO::getId)
+                .and(cn.hutool.core.util.StrUtil.isNotBlank(reqVO.getCode()), q ->
+                        q.like(MesProBagCodeDO::getCode, reqVO.getCode()).or()
+                                .like(MesProBagCodeDO::getBusinessCode, reqVO.getCode())));
     }
 
     /**
@@ -111,6 +158,18 @@
     }
 
     /**
+     * 鎵樼洏姝e紡鐮佺敓鎴愬悗锛屽洖鍐欏叾涓嬫墍鏈夎鐮佺殑鍐椾綑鎵樼洏鐮�
+     *
+     * @param palletId   鎵樼洏缂栧彿
+     * @param palletCode 姝e紡鎵樼洏鐮�
+     */
+    default void updatePalletCodeByPalletId(Long palletId, String palletCode) {
+        update(null, new LambdaUpdateWrapper<MesProBagCodeDO>()
+                .set(MesProBagCodeDO::getPalletCode, palletCode)
+                .eq(MesProBagCodeDO::getPalletId, palletId));
+    }
+
+    /**
      * 鎵归噺瑙g粦鎵樼洏锛堢疆绌烘墭鐩樼紪鍙蜂笌鎵樼洏鐮侊級
      *
      * @param ids 琚嬬爜缂栧彿鍒楄〃
@@ -123,19 +182,36 @@
     }
 
     /**
-     * 鏌ヨ鎵规鍐呰鐮佹渶澶у簭鍙凤紙鍖呭惈宸查�昏緫鍒犻櫎璁板綍锛屼繚璇佸簭鍙蜂笉鍥為��銆佺爜鍊煎敮涓�锛�
+     * 鏌ヨ鍏ㄥ眬鏈�澶ц搴忓彿锛堣搴忓彿涓哄叏灞�搴忓彿锛屼笉鍖哄垎鎵规锛涘寘鍚凡閫昏緫鍒犻櫎璁板綍锛屼繚璇佸簭鍙蜂笉鍥為��锛�
+     * <p>
+     * 浠呯敤浜庝负 Redis 搴忓彿鍒嗛厤鎻愪緵鍩哄噯鍊硷紝涓嶈鍦ㄤ笟鍔′腑鐩存帴鐢ㄣ�岃繑鍥炲�� + 1銆嶄綔涓鸿捣濮嬪簭鍙封�斺��
+     * 閭f槸鍏堣鍚庡啓锛屽苟鍙戠敓鎴愪細浜х敓閲嶅搴忓彿銆傝浣跨敤
+     * {@code MesCodeRedisDAO#allocateBagNoStart(int, Integer)} 鍘熷瓙鍒嗛厤銆�
      *
-     * @param batchId 鎵规缂栧彿
-     * @return 鏈�澶ц搴忓彿锛屾棤璁板綍杩斿洖 0
+     * @return 鍏ㄥ眬鏈�澶ц搴忓彿锛屾棤璁板綍杩斿洖 0
      */
     @Select("SELECT IFNULL(MAX(bag_no), 0) FROM mes_pro_bag_code")
     Integer selectMaxBagNo();
 
     @Update("<script>UPDATE mes_pro_bag_code SET batch_id = #{batchId}, batch_code = #{batchCode}, update_time = NOW() " +
-            "WHERE deleted = 0 AND batch_id IS NULL AND status = #{status} AND id IN " +
+            "WHERE deleted = 0 AND batch_id IS NULL AND status IN " +
+            "<foreach collection='statuses' item='st' open='(' separator=',' close=')'>#{st}</foreach> AND id IN " +
             "<foreach collection='ids' item='id' open='(' separator=',' close=')'>#{id}</foreach></script>")
     int bindBatchByIds(@Param("ids") Collection<Long> ids, @Param("batchId") Long batchId,
-                       @Param("batchCode") String batchCode, @Param("status") Integer status);
+                       @Param("batchCode") String batchCode, @Param("statuses") Collection<Integer> statuses);
+
+    /** 鏌ヨ鎵樼洏涓嬪皻鏈粦瀹氭壒娆$殑琚嬬爜锛堟墭鐩樼粦瀹氭壒娆℃椂绾ц仈褰曞叆鐢級 */
+    default List<MesProBagCodeDO> selectUnboundListByPalletIds(Collection<Long> palletIds) {
+        return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>()
+                .in(MesProBagCodeDO::getPalletId, palletIds)
+                .isNull(MesProBagCodeDO::getBatchId)
+                .orderByAsc(MesProBagCodeDO::getId));
+    }
+
+    /** 鎵规鍐呮湁鏁堣鐮佺殑鍝佺缂栧彿闆嗗悎锛堝拷鐣ュ巻鍙茬┖鍝佺琚嬬爜锛夛紝鐢ㄤ簬褰曞叆鎵规鏃剁殑鍝佺涓�鑷存�ф牎楠� */
+    @Select("SELECT DISTINCT item_id FROM mes_pro_bag_code " +
+            "WHERE deleted = 0 AND status <> 30 AND batch_id = #{batchId} AND item_id IS NOT NULL")
+    List<Long> selectDistinctItemIdsByBatchId(@Param("batchId") Long batchId);
 
     default List<MesProBagCodeDO> selectListByIdsForUpdate(Collection<Long> ids) {
         return selectList(new LambdaQueryWrapperX<MesProBagCodeDO>()
@@ -164,6 +240,14 @@
             "AND deleted = 0 AND status <> 30")
     int selectEffectiveCountByBatchId(@Param("batchId") Long batchId);
 
+    @Select("SELECT COUNT(*) FROM mes_pro_bag_code WHERE deleted = 0 AND status <> 30 "
+            + "AND inbound_event_id IS NULL AND batch_id = #{batchId}")
+    int selectPendingInboundCountByBatchId(@Param("batchId") Long batchId);
+
+    @Select("SELECT COUNT(*) FROM mes_pro_bag_code WHERE deleted = 0 AND status <> 30 "
+            + "AND inbound_event_id IS NULL AND pallet_id = #{palletId}")
+    int selectPendingInboundCountByPalletId(@Param("palletId") Long palletId);
+
     /**
      * 鎵归噺鏍囪涓哄凡瀵煎嚭鍗板埛锛堜粎鏇存柊澶勪簬鐩爣鍘熺姸鎬佺殑璁板綍锛�
      *

--
Gitblit v1.9.3