10 小时以前 16b8e4293a4eba8449018c2b833bab0524846e88
feat(mes): 新增包装袋型管理和托盘自动生成功能

- 在 DictTypeConstants 中添加包装袋型字典常量
- 在 ErrorCodeConstants 中添加袋型相关错误码定义
- 修改 MesProBagCodeController 的 generateBagCodes 接口返回托盘标签数据
- 在 MesProBagCodeMapper 中添加查询未绑定有效袋码的方法
- 更新 MesProBagCodeService 接口返回托盘生成结果
- 在 MesProBatchDO 中添加 bagType 字段存储包装袋型
- 在 MesProBatchRespVO 和 SaveReqVO 中添加包装袋型字段
- 实现批次袋型校验和修改限制逻辑
- 在 MesProPalletDO 中添加 autoGenerated 自动生成标识字段
- 在 MesProPalletRespVO 中添加自动生成标识字段
- 实现 MesProPalletService 的 autoCreatePallets 自动托盘生成功能
- 添加 MesProBagCodeGenerateRespVO 和 MesProPalletAutoPrintRespVO 数据传输对象
- 定义 MesProBagTypeEnum 枚举包含小袋大袋类型和阈值
- 提供前端联调文档和数据库迁移脚本
已修改5个文件
95 ■■■■■ 文件已修改
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/batch/MesProBatchDO.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/bagcode/MesProBagCodeDO.java
@@ -10,16 +10,6 @@
import java.time.LocalDateTime;
import cn.iocoder.yudao.module.mes.enums.DictTypeConstants;
/**
 * MES 袋码赋码(一袋一码)DO
 * <p>
 * 根据批次信息自动生成唯一二维码数据包:码值 = 批次号 + - + 袋序号,全局唯一,满足唯一性、可识别性、可追溯性要求。
 * 支持批量导出交付印刷,并与托盘码关联。
 *
 * @author 超级管理员
 */
@TableName("mes_pro_bag_code")
@KeySequence("mes_pro_bag_code_seq")
@Data
@@ -29,66 +19,22 @@
@NoArgsConstructor
@AllArgsConstructor
public class MesProBagCodeDO extends BaseDO {
    /**
     * 编号
     */
    @TableId
    private Long id;
    /**
     * 生成组 UUID(标记同一次生成的数据包)
     */
    private String uuid;
    /**
     * 袋码(二维码内容:批次号-袋序号,全局唯一)
     */
    private String code;
    /**
     * 批次内袋序号
     */
    private Integer bagNo;
    /**
     * 生产批次编号
     * <p>
     * 关联 {@link MesProBatchDO#getId()}
     */
    private Long batchId;
    /**
     * 批次号(冗余,便于展示)
     */
    private String batchCode;
    /**
     * 绑定托盘编号
     * <p>
     * 关联 {@link MesProPalletDO#getId()}
     */
    private Long palletId;
    /**
     * 托盘码(冗余,便于展示)
     */
    private String palletCode;
    /**
     * 状态
     * <p>
     * 字典 {@link DictTypeConstants#MES_PRO_BAG_CODE_STATUS}
     * 枚举 {@link cn.iocoder.yudao.module.mes.enums.pro.MesProBagCodeStatusEnum}
     */
    private Integer status;
    /**
     * 导出(交付印刷)时间
     */
    private LocalDateTime printTime;
    /**
     * 作废时间
     */
    private LocalDateTime cancelTime;
    /**
     * 作废原因
     */
    private String cancelReason;
    /**
     * 备注
     */
    private LocalDateTime inboundTime;
    private Long inboundEventId;
    private String inboundDeviceCode;
    private String inboundLineCode;
    private String remark;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/pro/batch/MesProBatchDO.java
@@ -84,6 +84,16 @@
     * 已生成托盘码数量
     */
    private Integer palletQuantity;
    /** 入库时间 */
    private LocalDateTime inboundTime;
    /** 累计入库袋数 */
    private Integer inboundBagQuantity;
    /** 最近入库事件编号 */
    private Long inboundEventId;
    /** 入库设备编码 */
    private String inboundDeviceCode;
    /** 入库产线编码 */
    private String inboundLineCode;
    /**
     * 批次状态
     * <p>
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/bagcode/MesProBagCodeMapper.java
@@ -28,6 +28,15 @@
        return selectOne(MesProBagCodeDO::getCode, code);
    }
    default MesProBagCodeDO selectByCodeForUpdate(String code) {
        return selectOne(new LambdaQueryWrapperX<MesProBagCodeDO>()
                .eq(MesProBagCodeDO::getCode, code).last("FOR UPDATE"));
    }
    @org.apache.ibatis.annotations.Update("UPDATE mes_pro_bag_code SET inbound_time = NOW(), inbound_event_id = #{eventId}, inbound_device_code = #{deviceCode}, inbound_line_code = #{lineCode}, update_time = NOW() WHERE id = #{id} AND deleted = 0 AND inbound_event_id IS NULL")
    int markInbound(@org.apache.ibatis.annotations.Param("id") Long id, @org.apache.ibatis.annotations.Param("eventId") Long eventId,
                    @org.apache.ibatis.annotations.Param("deviceCode") String deviceCode, @org.apache.ibatis.annotations.Param("lineCode") String lineCode);
    default List<MesProBagCodeDO> selectListByUuid(String uuid) {
        return selectList(MesProBagCodeDO::getUuid, uuid);
    }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pro/batch/MesProBatchMapper.java
@@ -27,6 +27,10 @@
    @Select("SELECT * FROM mes_pro_batch WHERE id = #{id} AND deleted = 0 FOR UPDATE")
    MesProBatchDO selectByIdForUpdate(@org.apache.ibatis.annotations.Param("id") Long id);
    @org.apache.ibatis.annotations.Update("UPDATE mes_pro_batch SET inbound_time = NOW(), inbound_event_id = #{eventId}, inbound_device_code = #{deviceCode}, inbound_line_code = #{lineCode}, inbound_bag_quantity = COALESCE(inbound_bag_quantity, 0) + 1, update_time = NOW() WHERE id = #{id} AND deleted = 0")
    int markInbound(@org.apache.ibatis.annotations.Param("id") Long id, @org.apache.ibatis.annotations.Param("eventId") Long eventId,
                    @org.apache.ibatis.annotations.Param("deviceCode") String deviceCode, @org.apache.ibatis.annotations.Param("lineCode") String lineCode);
    default PageResult<MesProBatchDO> selectPage(MesProBatchPageReqVO reqVO) {
        return selectPage(reqVO, new LambdaQueryWrapperX<MesProBatchDO>()
                .likeIfPresent(MesProBatchDO::getCode, reqVO.getCode())
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -9,6 +9,16 @@
 */
public interface ErrorCodeConstants {
    // ========== MES 生产管理-扫码入库(1-040-755-000) ==========
    ErrorCode PRO_SCAN_EVENT_BAG_NOT_EXISTS = new ErrorCode(1_040_755_000, "袋码不存在");
    ErrorCode PRO_SCAN_EVENT_ALREADY_INBOUND = new ErrorCode(1_040_755_001, "袋码已入库");
    ErrorCode PRO_SCAN_EVENT_BATCH_NOT_EXISTS = new ErrorCode(1_040_755_002, "生产批次不存在");
    ErrorCode PRO_SCAN_EVENT_WIP_WAREHOUSE_NOT_EXISTS = new ErrorCode(1_040_755_003, "WIP虚拟仓不存在");
    ErrorCode PRO_SCAN_EVENT_LOCATION_INVALID = new ErrorCode(1_040_755_004, "扫码入库库位无效");
    ErrorCode PRO_SCAN_EVENT_TRANSACTION_FAILED = new ErrorCode(1_040_755_005, "库存事务处理失败");
    ErrorCode PRO_SCAN_EVENT_ID_CONFLICT = new ErrorCode(1_040_755_006, "事件号已存在但内容不一致");
    ErrorCode PRO_SCAN_EVENT_FAILED = new ErrorCode(1_040_755_007, "扫码入库失败");
    // ========== MES 基础数据-物料分类(1-040-100-000) ==========
    ErrorCode MD_ITEM_TYPE_NOT_EXISTS = new ErrorCode(1_040_100_000, "物料分类不存在");
    ErrorCode MD_ITEM_TYPE_EXITS_CHILDREN = new ErrorCode(1_040_100_001, "存在子分类,无法删除");