diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java index cf2ddc97..5b1a6c1f 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/ErrorCodeConstants.java @@ -68,4 +68,14 @@ public interface ErrorCodeConstants { ErrorCode DAILY_PLAN_CLAIM_PROGRESS_CONFLICT = new ErrorCode(43, "日计划作业进度已变化,该领取无法确认"); ErrorCode DAILY_PLAN_CLAIM_CANDIDATE_CHANGED = new ErrorCode(44, "日计划候选状态已变化,请重新获取"); ErrorCode DAILY_PLAN_ERP_TOKEN_NOT_CONFIGURED = new ErrorCode(45, "ERP日计划接口令牌未配置"); + + // ========== 管芯实例与PDA绑定 ========== + ErrorCode CORE_TUBE_BIND_POINT_NOT_EXISTS = new ErrorCode(46, "托盘未位于备货区域点位"); + ErrorCode CORE_TUBE_BIND_POINT_NOT_ALLOWED = new ErrorCode(47, "托盘当前点位不允许绑定管芯"); + ErrorCode CORE_TUBE_BIND_SLOT_OCCUPIED = new ErrorCode(48, "托盘格位{}已绑定管芯"); + ErrorCode CORE_TUBE_BIND_SLOT_DUPLICATED = new ErrorCode(49, "绑定请求中的托盘格位{}重复"); + ErrorCode CORE_TUBE_BIND_REQUEST_CONFLICT = new ErrorCode(50, "绑定请求号已用于其他托盘"); + ErrorCode CORE_TUBE_MATERIAL_NOT_EXISTS = new ErrorCode(51, "管芯物料不存在"); + ErrorCode CORE_TUBE_CODE_GENERATE_FAILED = new ErrorCode(52, "管芯编号生成失败"); + ErrorCode CORE_TUBE_BIND_FAILED = new ErrorCode(53, "管芯绑定失败,请刷新托盘后重试"); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java new file mode 100644 index 00000000..78fdb339 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/CoreTubePdaController.java @@ -0,0 +1,56 @@ +package cn.code.nl.module.lms.controller.pda.coretube; + +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindReqVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubePalletRespVO; +import cn.code.nl.module.lms.service.coretube.CoreTubeBindingService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.code.nl.framework.common.pojo.CommonResult.success; + +/** + * PDA 管芯托盘绑定接口。 + */ +@Tag(name = "PDA - 管芯托盘绑定") +@RestController +@RequestMapping("/api/pda/coreTube") +@Validated +public class CoreTubePdaController { + + @Resource + private CoreTubeBindingService coreTubeBindingService; + + /** 查询管芯托盘和5×5格位。 */ + @GetMapping("/pallet") + @Operation(summary = "查询管芯托盘和5×5格位") + @Parameter(name = "vehicleCode", description = "管芯托盘号", required = true) + @PreAuthorize("@ss.hasPermission('lms:core-tube:bind')") + public CommonResult getPallet( + @RequestParam("vehicleCode") @NotBlank String vehicleCode) { + return success(coreTubeBindingService.getPallet(vehicleCode)); + } + + /** 批量绑定管芯到托盘格位。 */ + @PostMapping("/bind") + @Operation(summary = "批量绑定管芯到托盘格位") + @PreAuthorize("@ss.hasPermission('lms:core-tube:bind')") + public CommonResult> bind(@Valid @RequestBody CoreTubeBindReqVO reqVO) { + return success(coreTubeBindingService.bind(reqVO)); + } +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindItemReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindItemReqVO.java new file mode 100644 index 00000000..1e47bfce --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindItemReqVO.java @@ -0,0 +1,35 @@ +package cn.code.nl.module.lms.controller.pda.coretube.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * PDA 管芯格位绑定请求。 + */ +@Schema(description = "PDA - 管芯格位绑定 Request VO") +@Data +public class CoreTubeBindItemReqVO { + + @Schema(description = "行号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "行号不能为空") + @Min(value = 1, message = "行号必须在1到5之间") + @Max(value = 5, message = "行号必须在1到5之间") + private Integer rowNum; + + @Schema(description = "列号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "列号不能为空") + @Min(value = 1, message = "列号必须在1到5之间") + @Max(value = 5, message = "列号必须在1到5之间") + private Integer colNum; + + @Schema(description = "管芯重量(kg)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "管芯重量不能为空") + @DecimalMin(value = "0.001", message = "管芯重量必须大于0") + private BigDecimal coreWeight; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindReqVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindReqVO.java new file mode 100644 index 00000000..f32d0ec9 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindReqVO.java @@ -0,0 +1,41 @@ +package cn.code.nl.module.lms.controller.pda.coretube.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +/** + * PDA 批量绑定管芯请求。 + */ +@Schema(description = "PDA - 批量绑定管芯 Request VO") +@Data +public class CoreTubeBindReqVO { + + @Schema(description = "客户端请求号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "客户端请求号不能为空") + @Size(max = 64, message = "客户端请求号不能超过64个字符") + private String requestNo; + + @Schema(description = "管芯托盘号", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "管芯托盘号不能为空") + @Size(max = 32, message = "管芯托盘号不能超过32个字符") + private String vehicleCode; + + @Schema(description = "管芯物料ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "管芯物料ID不能为空") + @Positive(message = "管芯物料ID必须为正数") + private Long materialId; + + @Schema(description = "待绑定格位", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "待绑定格位不能为空") + @Size(max = 25, message = "一次最多绑定25根管芯") + @Valid + private List items; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindRespVO.java new file mode 100644 index 00000000..d33a4078 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeBindRespVO.java @@ -0,0 +1,25 @@ +package cn.code.nl.module.lms.controller.pda.coretube.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * PDA 管芯绑定结果。 + */ +@Schema(description = "PDA - 管芯绑定 Response VO") +@Data +public class CoreTubeBindRespVO { + + @Schema(description = "管芯实例ID") + private Long coreTubeId; + @Schema(description = "虚拟管芯编号") + private String coreTubeCode; + @Schema(description = "行号") + private Integer rowNum; + @Schema(description = "列号") + private Integer colNum; + @Schema(description = "管芯重量(kg)") + private BigDecimal coreWeight; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubePalletRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubePalletRespVO.java new file mode 100644 index 00000000..34fe798e --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubePalletRespVO.java @@ -0,0 +1,27 @@ +package cn.code.nl.module.lms.controller.pda.coretube.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * PDA 管芯托盘详情。 + */ +@Schema(description = "PDA - 管芯托盘详情 Response VO") +@Data +public class CoreTubePalletRespVO { + + @Schema(description = "管芯托盘号") + private String vehicleCode; + @Schema(description = "所在点位ID") + private Long pointId; + @Schema(description = "所在点位编码") + private String pointCode; + @Schema(description = "所在点位名称") + private String pointName; + @Schema(description = "点位类型") + private String pointType; + @Schema(description = "5×5格位中已有的管芯") + private List slots; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeSlotRespVO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeSlotRespVO.java new file mode 100644 index 00000000..e8f29922 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/controller/pda/coretube/vo/CoreTubeSlotRespVO.java @@ -0,0 +1,31 @@ +package cn.code.nl.module.lms.controller.pda.coretube.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * PDA 管芯托盘格位。 + */ +@Schema(description = "PDA - 管芯托盘格位 Response VO") +@Data +public class CoreTubeSlotRespVO { + + @Schema(description = "行号") + private Integer rowNum; + @Schema(description = "列号") + private Integer colNum; + @Schema(description = "管芯实例ID") + private Long coreTubeId; + @Schema(description = "虚拟管芯编号") + private String coreTubeCode; + @Schema(description = "物料编码") + private String materialCode; + @Schema(description = "物料名称") + private String materialName; + @Schema(description = "物料规格") + private String materialSpec; + @Schema(description = "管芯重量(kg)") + private BigDecimal coreWeight; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/coretube/CoreTubeDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/coretube/CoreTubeDO.java new file mode 100644 index 00000000..847bf663 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/coretube/CoreTubeDO.java @@ -0,0 +1,67 @@ +package cn.code.nl.module.lms.dal.dataobject.coretube; + +import cn.code.nl.framework.tenant.core.db.TenantBaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 管芯实例数据对象。 + */ +@TableName("lms_core_tube") +@Data +public class CoreTubeDO extends TenantBaseDO { + + /** 管芯实例ID。 */ + @TableId + private Long coreTubeId; + /** 虚拟管芯编号。 */ + private String coreTubeCode; + /** PDA绑定请求号。 */ + private String bindRequestNo; + /** 物料ID。 */ + private Long materialId; + /** 物料编码。 */ + private String materialCode; + /** 物料名称。 */ + private String materialName; + /** 物料规格。 */ + private String materialSpec; + /** 管芯重量。 */ + private BigDecimal coreWeight; + /** 重量单位。 */ + private String weightUnit; + /** 生命周期阶段。 */ + private Integer stage; + /** 占用状态。 */ + private Integer status; + /** 当前托盘号。 */ + private String vehicleCode; + /** 托盘行号。 */ + private Integer rowNum; + /** 托盘列号。 */ + private Integer colNum; + /** 有效托盘格位唯一标记。 */ + private Integer activeSlot; + /** 当前位置类型。 */ + private Integer currentLocationType; + /** 当前位置记录ID。 */ + private Long currentLocationId; + /** 当前位置编码。 */ + private String currentLocationCode; + /** 来源日计划ID。 */ + private Long sourceDailyPlanId; + /** 当前预占日计划ID。 */ + private Long reservedDailyPlanId; + /** 当前调度领取标识。 */ + private String reservedClaimToken; + /** 当前现场任务ID。 */ + private Long reservedTaskId; + /** 预占过期时间。 */ + private LocalDateTime reserveExpireTime; + /** 乐观锁版本。 */ + private Integer version; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/stockingivt/PaperVehicleDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/stockingivt/PaperVehicleDO.java index 52be0233..ff978803 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/stockingivt/PaperVehicleDO.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/stockingivt/PaperVehicleDO.java @@ -16,6 +16,10 @@ public class PaperVehicleDO { /** 库存记录标识。 */ @TableId private String ivtId; + /** 管芯实例ID。 */ + private Long coreTubeId; + /** 虚拟管芯编号。 */ + private String coreTubeCode; /** 托盘号。 */ private String vehicleCode; /** 行号。 */ @@ -26,6 +30,10 @@ public class PaperVehicleDO { private String materialCode; /** 物料名称。 */ private String materialName; + /** 物料规格。 */ + private String materialSpec; + /** 管芯重量。 */ + private BigDecimal coreWeight; /** 数量。 */ private BigDecimal qty; } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java new file mode 100644 index 00000000..0a1bcacd --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/coretube/CoreTubeMapper.java @@ -0,0 +1,24 @@ +package cn.code.nl.module.lms.dal.mysql.coretube; + +import cn.code.nl.framework.mybatis.core.mapper.BaseMapperX; +import cn.code.nl.module.lms.dal.dataobject.coretube.CoreTubeDO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 管芯实例 Mapper。 + */ +@Mapper +public interface CoreTubeMapper extends BaseMapperX { + + /** 根据绑定请求号查询管芯。 */ + List selectByBindRequestNo(@Param("bindRequestNo") String bindRequestNo); + + /** 根据托盘号查询管芯。 */ + List selectByVehicleCode(@Param("vehicleCode") String vehicleCode); + + /** 插入管芯实例。 */ + int insertCoreTube(@Param("tube") CoreTubeDO tube); +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java index 3a3793f8..aa204788 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/mysql/stockingivt/StockingIvtMapper.java @@ -37,6 +37,16 @@ public interface StockingIvtMapper extends BaseMapperX { */ StockingIvtDO selectStockingIvtById(@Param("ivtId") Long ivtId); + /** + * 根据托盘号查询所在点位。 + */ + StockingIvtDO selectByVehicleCode(@Param("vehicleCode") String vehicleCode); + + /** + * 锁定托盘所在点位。 + */ + StockingIvtDO selectByVehicleCodeForUpdate(@Param("vehicleCode") String vehicleCode); + /** * 更新备货区域点位的可编辑字段。 */ @@ -46,4 +56,26 @@ public interface StockingIvtMapper extends BaseMapperX { * 根据托盘号查询纸管库存。 */ List selectPaperVehicleList(@Param("vehicleCode") String vehicleCode); + + /** + * 锁定指定托盘格位。 + */ + PaperVehicleDO selectPaperVehicleSlotForUpdate(@Param("vehicleCode") String vehicleCode, + @Param("rowNum") Integer rowNum, + @Param("colNum") Integer colNum); + + /** + * 将已有托盘格位绑定到管芯。 + */ + int updatePaperVehicleCoreTube(@Param("ivtId") String ivtId, + @Param("coreTubeId") Long coreTubeId, + @Param("coreTubeCode") String coreTubeCode, + @Param("materialCode") String materialCode, + @Param("materialName") String materialName, + @Param("updater") String updater); + + /** + * 新增管芯托盘格位。 + */ + int insertPaperVehicleCoreTube(@Param("tube") cn.code.nl.module.lms.dal.dataobject.coretube.CoreTubeDO tube); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java new file mode 100644 index 00000000..441b3d23 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeLocationTypeEnum.java @@ -0,0 +1,22 @@ +package cn.code.nl.module.lms.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 管芯当前位置类型。 + */ +@Getter +@AllArgsConstructor +public enum CoreTubeLocationTypeEnum { + + STOCKING_BINDING(1), + STOCKING_CACHE(2), + STOCKING_DOCK(3), + CORE_WAREHOUSE(4), + EQUIPMENT(5), + IN_TRANSIT(6), + SLEEVING_CACHE(7); + + private final Integer code; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeStageEnum.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeStageEnum.java new file mode 100644 index 00000000..9290ce91 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeStageEnum.java @@ -0,0 +1,23 @@ +package cn.code.nl.module.lms.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 管芯生命周期阶段。 + */ +@Getter +@AllArgsConstructor +public enum CoreTubeStageEnum { + + STOCKING_AREA(1), + STOCKING_PICKING(2), + CORE_WAREHOUSE(3), + CORE_OUTBOUND(4), + SLEEVING(5), + SLEEVING_CACHE(6), + CONSUMED(7), + ABNORMAL(8); + + private final Integer code; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeStatusEnum.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeStatusEnum.java new file mode 100644 index 00000000..8cfd4526 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeStatusEnum.java @@ -0,0 +1,21 @@ +package cn.code.nl.module.lms.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 管芯占用状态。 + */ +@Getter +@AllArgsConstructor +public enum CoreTubeStatusEnum { + + AVAILABLE(1), + RESERVED(2), + PROCESSING(3), + USED(4), + FROZEN(5), + ABNORMAL(6); + + private final Integer code; +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java new file mode 100644 index 00000000..7dcdede6 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingService.java @@ -0,0 +1,20 @@ +package cn.code.nl.module.lms.service.coretube; + +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindReqVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubePalletRespVO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * 管芯托盘绑定服务。 + */ +public interface CoreTubeBindingService { + + /** 查询管芯托盘详情。 */ + CoreTubePalletRespVO getPallet(String vehicleCode); + + /** 批量绑定管芯到托盘格位。 */ + List bind(@Valid CoreTubeBindReqVO reqVO); +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java new file mode 100644 index 00000000..64c620ad --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeBindingServiceImpl.java @@ -0,0 +1,223 @@ +package cn.code.nl.module.lms.service.coretube; + +import cn.code.nl.framework.common.exception.ServiceException; +import cn.code.nl.framework.common.pojo.CommonResult; +import cn.code.nl.module.base.api.codegen.CodeGenApi; +import cn.code.nl.module.base.api.codegen.dto.CodeGenerateReqDTO; +import cn.code.nl.module.base.api.materialbase.MaterialBaseApi; +import cn.code.nl.module.base.api.materialbase.dto.MaterialBaseRespDTO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindItemReqVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindReqVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeBindRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubePalletRespVO; +import cn.code.nl.module.lms.controller.pda.coretube.vo.CoreTubeSlotRespVO; +import cn.code.nl.module.lms.dal.dataobject.coretube.CoreTubeDO; +import cn.code.nl.module.lms.dal.dataobject.stockingivt.PaperVehicleDO; +import cn.code.nl.module.lms.dal.dataobject.stockingivt.StockingIvtDO; +import cn.code.nl.module.lms.dal.mysql.coretube.CoreTubeMapper; +import cn.code.nl.module.lms.dal.mysql.stockingivt.StockingIvtMapper; +import cn.code.nl.module.lms.enums.CoreTubeLocationTypeEnum; +import cn.code.nl.module.lms.enums.CoreTubeStageEnum; +import cn.code.nl.module.lms.enums.CoreTubeStatusEnum; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import jakarta.annotation.Resource; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.code.nl.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_FAILED; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_POINT_NOT_ALLOWED; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_POINT_NOT_EXISTS; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_REQUEST_CONFLICT; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_SLOT_DUPLICATED; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_BIND_SLOT_OCCUPIED; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_CODE_GENERATE_FAILED; +import static cn.code.nl.module.lms.enums.ErrorCodeConstants.CORE_TUBE_MATERIAL_NOT_EXISTS; + +/** + * 管芯托盘绑定服务实现。 + */ +@Service +@Validated +public class CoreTubeBindingServiceImpl implements CoreTubeBindingService { + + private static final String CORE_TUBE_CODE_RULE = "CORE_TUBE_CODE"; + private static final String BINDING_POINT_TYPE = "1"; + private static final String ENABLED = "0"; + private static final String WEIGHT_UNIT = "kg"; + + @Resource + private CoreTubeMapper coreTubeMapper; + @Resource + private StockingIvtMapper stockingIvtMapper; + @Resource + private MaterialBaseApi materialBaseApi; + @Resource + private CodeGenApi codeGenApi; + + /** 查询管芯托盘详情。 */ + @Override + public CoreTubePalletRespVO getPallet(String vehicleCode) { + StockingIvtDO point = stockingIvtMapper.selectByVehicleCode(vehicleCode); + if (point == null) { + throw exception(CORE_TUBE_BIND_POINT_NOT_EXISTS); + } + CoreTubePalletRespVO response = new CoreTubePalletRespVO(); + response.setVehicleCode(vehicleCode); + response.setPointId(point.getIvtId()); + response.setPointCode(point.getPointCode()); + response.setPointName(point.getPointName()); + response.setPointType(point.getPointType()); + List inventory = stockingIvtMapper.selectPaperVehicleList(vehicleCode); + List slots = new ArrayList<>(inventory.size()); + for (PaperVehicleDO item : inventory) { + CoreTubeSlotRespVO slot = new CoreTubeSlotRespVO(); + slot.setRowNum(item.getRowNum()); + slot.setColNum(item.getColNum()); + slot.setCoreTubeId(item.getCoreTubeId()); + slot.setCoreTubeCode(item.getCoreTubeCode()); + slot.setMaterialCode(item.getMaterialCode()); + slot.setMaterialName(item.getMaterialName()); + slot.setMaterialSpec(item.getMaterialSpec()); + slot.setCoreWeight(item.getCoreWeight()); + slots.add(slot); + } + response.setSlots(slots); + return response; + } + + /** 批量绑定管芯到托盘格位。 */ + @Override + @Transactional(rollbackFor = Exception.class) + public List bind(CoreTubeBindReqVO reqVO) { + List existing = coreTubeMapper.selectByBindRequestNo(reqVO.getRequestNo()); + if (!CollectionUtils.isEmpty(existing)) { + if (!reqVO.getVehicleCode().equals(existing.get(0).getVehicleCode())) { + throw exception(CORE_TUBE_BIND_REQUEST_CONFLICT); + } + return convertBindResult(existing); + } + StockingIvtDO point = stockingIvtMapper.selectByVehicleCodeForUpdate(reqVO.getVehicleCode()); + if (point == null) { + throw exception(CORE_TUBE_BIND_POINT_NOT_EXISTS); + } + if (!BINDING_POINT_TYPE.equals(point.getPointType()) || !ENABLED.equals(point.getIsUsed())) { + throw exception(CORE_TUBE_BIND_POINT_NOT_ALLOWED); + } + MaterialBaseRespDTO material = getMaterial(reqVO.getMaterialId()); + Set positions = new HashSet<>(); + for (CoreTubeBindItemReqVO item : reqVO.getItems()) { + String position = item.getRowNum() + ":" + item.getColNum(); + if (!positions.add(position)) { + throw exception(CORE_TUBE_BIND_SLOT_DUPLICATED, position); + } + } + String operator = String.valueOf(getLoginUserId()); + List created = new ArrayList<>(reqVO.getItems().size()); + try { + for (CoreTubeBindItemReqVO item : reqVO.getItems()) { + created.add(bindOne(reqVO, item, point, material, operator)); + } + } catch (DuplicateKeyException ex) { + throw exception(CORE_TUBE_BIND_FAILED); + } + return convertBindResult(created); + } + + /** 绑定单根管芯。 */ + private CoreTubeDO bindOne(CoreTubeBindReqVO reqVO, CoreTubeBindItemReqVO item, StockingIvtDO point, + MaterialBaseRespDTO material, String operator) { + PaperVehicleDO slot = stockingIvtMapper.selectPaperVehicleSlotForUpdate( + reqVO.getVehicleCode(), item.getRowNum(), item.getColNum()); + if (slot != null && slot.getCoreTubeId() != null) { + throw exception(CORE_TUBE_BIND_SLOT_OCCUPIED, item.getRowNum() + ":" + item.getColNum()); + } + CoreTubeDO tube = new CoreTubeDO(); + tube.setCoreTubeId(IdWorker.getId()); + tube.setCoreTubeCode(generateCoreTubeCode()); + tube.setBindRequestNo(reqVO.getRequestNo()); + tube.setMaterialId(material.getMaterialId()); + tube.setMaterialCode(material.getMaterialCode()); + tube.setMaterialName(material.getMaterialName()); + tube.setMaterialSpec(material.getMaterialSpec()); + tube.setCoreWeight(item.getCoreWeight()); + tube.setWeightUnit(WEIGHT_UNIT); + tube.setStage(CoreTubeStageEnum.STOCKING_AREA.getCode()); + tube.setStatus(CoreTubeStatusEnum.AVAILABLE.getCode()); + tube.setVehicleCode(reqVO.getVehicleCode()); + tube.setRowNum(item.getRowNum()); + tube.setColNum(item.getColNum()); + tube.setCurrentLocationType(CoreTubeLocationTypeEnum.STOCKING_BINDING.getCode()); + tube.setCurrentLocationId(point.getIvtId()); + tube.setCurrentLocationCode(point.getPointCode()); + tube.setCreator(operator); + tube.setUpdater(operator); + if (coreTubeMapper.insertCoreTube(tube) != 1) { + throw exception(CORE_TUBE_BIND_FAILED); + } + int affected = slot == null + ? stockingIvtMapper.insertPaperVehicleCoreTube(tube) + : stockingIvtMapper.updatePaperVehicleCoreTube(slot.getIvtId(), tube.getCoreTubeId(), + tube.getCoreTubeCode(), tube.getMaterialCode(), tube.getMaterialName(), operator); + if (affected != 1) { + throw exception(CORE_TUBE_BIND_FAILED); + } + return tube; + } + + /** 查询并校验物料。 */ + private MaterialBaseRespDTO getMaterial(Long materialId) { + CommonResult result = materialBaseApi.getMaterialBase(materialId); + if (result == null) { + throw exception(CORE_TUBE_MATERIAL_NOT_EXISTS); + } + if (!result.isSuccess()) { + throw new ServiceException(result.getCode(), result.getMsg()); + } + if (result.getData() == null) { + throw exception(CORE_TUBE_MATERIAL_NOT_EXISTS); + } + return result.getData(); + } + + /** 生成虚拟管芯编号。 */ + private String generateCoreTubeCode() { + CodeGenerateReqDTO request = new CodeGenerateReqDTO(); + request.setRuleCode(CORE_TUBE_CODE_RULE); + CommonResult result = codeGenApi.generate(request); + if (result == null) { + throw exception(CORE_TUBE_CODE_GENERATE_FAILED); + } + if (!result.isSuccess()) { + throw new ServiceException(result.getCode(), result.getMsg()); + } + if (result.getData() == null || result.getData().isBlank()) { + throw exception(CORE_TUBE_CODE_GENERATE_FAILED); + } + return result.getData(); + } + + /** 转换绑定结果。 */ + private List convertBindResult(List tubes) { + List result = new ArrayList<>(tubes.size()); + for (CoreTubeDO tube : tubes) { + CoreTubeBindRespVO item = new CoreTubeBindRespVO(); + item.setCoreTubeId(tube.getCoreTubeId()); + item.setCoreTubeCode(tube.getCoreTubeCode()); + item.setRowNum(tube.getRowNum()); + item.setColNum(tube.getColNum()); + item.setCoreWeight(tube.getCoreWeight()); + result.add(item); + } + return result; + } +} diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml new file mode 100644 index 00000000..6fb46fb0 --- /dev/null +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/coretube/CoreTubeMapper.xml @@ -0,0 +1,51 @@ + + + + + + core_tube_id, core_tube_code, bind_request_no, + material_id, material_code, material_name, material_spec, + core_weight, weight_unit, stage, status, + vehicle_code, row_num, col_num, active_slot, + current_location_type, current_location_id, current_location_code, + source_daily_plan_id, reserved_daily_plan_id, reserved_claim_token, + reserved_task_id, reserve_expire_time, version, + creator, create_time, updater, update_time, deleted, tenant_id + + + + + + + + INSERT INTO lms_core_tube + (core_tube_id, core_tube_code, bind_request_no, + material_id, material_code, material_name, material_spec, + core_weight, weight_unit, stage, status, + vehicle_code, row_num, col_num, active_slot, + current_location_type, current_location_id, current_location_code, + version, creator, updater) + VALUES + (#{tube.coreTubeId}, #{tube.coreTubeCode}, #{tube.bindRequestNo}, + #{tube.materialId}, #{tube.materialCode}, #{tube.materialName}, #{tube.materialSpec}, + #{tube.coreWeight}, #{tube.weightUnit}, #{tube.stage}, #{tube.status}, + #{tube.vehicleCode}, #{tube.rowNum}, #{tube.colNum}, 1, + #{tube.currentLocationType}, #{tube.currentLocationId}, #{tube.currentLocationCode}, + 0, #{tube.creator}, #{tube.updater}) + + diff --git a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml index eca695eb..43fe0648 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml +++ b/nl-module-lms/nl-module-lms-server/src/main/resources/mapper/stockingivt/StockingIvtMapper.xml @@ -42,6 +42,21 @@ WHERE ivt_id = #{ivtId} + + + + UPDATE lms_ivt_stockingivt SET vehicle_code = #{vehicleCode}, @@ -57,13 +72,52 @@ + + + + UPDATE lms_base_papervehicle + SET core_tube_id = #{coreTubeId}, + core_tube_code = #{coreTubeCode}, + material_code = #{materialCode}, + material_name = #{materialName}, + qty = 1, + updater = #{updater} + WHERE ivt_id = #{ivtId} + AND core_tube_id IS NULL + + + + INSERT INTO lms_base_papervehicle + (ivt_id, core_tube_id, core_tube_code, vehicle_code, row_num, col_num, + material_code, material_name, qty, creator, updater) + VALUES + (CAST(#{tube.coreTubeId} AS CHAR), #{tube.coreTubeId}, #{tube.coreTubeCode}, + #{tube.vehicleCode}, CAST(#{tube.rowNum} AS CHAR), CAST(#{tube.colNum} AS CHAR), + #{tube.materialCode}, #{tube.materialName}, 1, #{tube.creator}, #{tube.updater}) + + diff --git a/sql/mysql/lms_core_tube.sql b/sql/mysql/lms_core_tube.sql new file mode 100644 index 00000000..c9f0732d --- /dev/null +++ b/sql/mysql/lms_core_tube.sql @@ -0,0 +1,143 @@ +-- LMS 管芯实例、托盘绑定、字典及编码规则初始化。 +CREATE TABLE IF NOT EXISTS `lms_core_tube` ( + `core_tube_id` bigint NOT NULL COMMENT '管芯实例ID', + `core_tube_code` varchar(64) NOT NULL COMMENT '虚拟管芯编号', + `bind_request_no` varchar(64) NOT NULL COMMENT 'PDA绑定请求号', + `material_id` bigint NOT NULL COMMENT '管芯物料ID', + `material_code` varchar(64) NOT NULL COMMENT '管芯物料编码', + `material_name` varchar(128) NOT NULL COMMENT '管芯物料名称', + `material_spec` varchar(128) DEFAULT NULL COMMENT '管芯规格', + `core_weight` decimal(12,3) NOT NULL COMMENT '管芯重量', + `weight_unit` varchar(16) NOT NULL DEFAULT 'kg' COMMENT '重量单位', + `stage` tinyint NOT NULL COMMENT '生命周期阶段', + `status` tinyint NOT NULL COMMENT '占用状态', + `vehicle_code` varchar(32) DEFAULT NULL COMMENT '当前管芯托盘号', + `row_num` tinyint DEFAULT NULL COMMENT '托盘行号', + `col_num` tinyint DEFAULT NULL COMMENT '托盘列号', + `active_slot` tinyint DEFAULT 1 COMMENT '有效托盘格位唯一标记,解绑后置空', + `current_location_type` tinyint NOT NULL COMMENT '当前位置类型', + `current_location_id` bigint DEFAULT NULL COMMENT '当前位置记录ID', + `current_location_code` varchar(64) DEFAULT NULL COMMENT '当前位置编码', + `source_daily_plan_id` bigint DEFAULT NULL COMMENT '来源日计划ID', + `reserved_daily_plan_id` bigint DEFAULT NULL COMMENT '当前预占日计划ID', + `reserved_claim_token` varchar(64) DEFAULT NULL COMMENT '当前调度领取标识', + `reserved_task_id` bigint DEFAULT NULL COMMENT '当前现场任务ID', + `reserve_expire_time` datetime(6) DEFAULT NULL COMMENT '预占过期时间', + `version` int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', + `creator` varchar(64) DEFAULT '' COMMENT '创建者', + `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updater` varchar(64) DEFAULT '' COMMENT '更新者', + `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', + `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', + PRIMARY KEY (`core_tube_id`), + UNIQUE KEY `uk_core_tube_code_tenant` (`core_tube_code`, `tenant_id`), + UNIQUE KEY `uk_core_tube_bind_request_slot` (`tenant_id`, `bind_request_no`, `row_num`, `col_num`), + UNIQUE KEY `uk_core_tube_active_slot` (`tenant_id`, `vehicle_code`, `row_num`, `col_num`, `active_slot`), + KEY `idx_core_tube_schedule` (`tenant_id`, `material_id`, `stage`, `status`, `deleted`), + KEY `idx_core_tube_reserved_task` (`tenant_id`, `reserved_task_id`, `deleted`) +) COMMENT='LMS管芯实例主表'; + +-- 兼容已有托盘明细表,幂等补充管芯关联字段和索引。 +SET @lms_core_tube_ddl = IF( + EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() + AND table_name = 'lms_base_papervehicle' AND column_name = 'core_tube_id'), + 'SELECT 1', + 'ALTER TABLE lms_base_papervehicle ADD COLUMN core_tube_id BIGINT DEFAULT NULL COMMENT ''管芯实例ID'' AFTER ivt_id'); +PREPARE lms_core_tube_stmt FROM @lms_core_tube_ddl; +EXECUTE lms_core_tube_stmt; +DEALLOCATE PREPARE lms_core_tube_stmt; + +SET @lms_core_tube_ddl = IF( + EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() + AND table_name = 'lms_base_papervehicle' AND column_name = 'core_tube_code'), + 'SELECT 1', + 'ALTER TABLE lms_base_papervehicle ADD COLUMN core_tube_code VARCHAR(64) DEFAULT NULL COMMENT ''虚拟管芯编号'' AFTER core_tube_id'); +PREPARE lms_core_tube_stmt FROM @lms_core_tube_ddl; +EXECUTE lms_core_tube_stmt; +DEALLOCATE PREPARE lms_core_tube_stmt; + +SET @lms_core_tube_ddl = IF( + EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE() + AND table_name = 'lms_base_papervehicle' AND index_name = 'idx_papervehicle_vehicle_slot'), + 'SELECT 1', + 'ALTER TABLE lms_base_papervehicle ADD INDEX idx_papervehicle_vehicle_slot (vehicle_code, row_num, col_num)'); +PREPARE lms_core_tube_stmt FROM @lms_core_tube_ddl; +EXECUTE lms_core_tube_stmt; +DEALLOCATE PREPARE lms_core_tube_stmt; + +SET @lms_core_tube_ddl = IF( + EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() + AND table_name = 'lms_daily_plan_strategy' AND column_name = 'cursor_executed_qty'), + 'SELECT 1', + 'ALTER TABLE lms_daily_plan_strategy ADD COLUMN cursor_executed_qty INT NOT NULL DEFAULT 0 COMMENT ''当前权重轮转已执行数量'' AFTER cursor_daily_plan_id'); +PREPARE lms_core_tube_stmt FROM @lms_core_tube_ddl; +EXECUTE lms_core_tube_stmt; +DEALLOCATE PREPARE lms_core_tube_stmt; + +-- 管芯编码规则:GX + yyyyMMdd + 6位日流水。 +INSERT INTO base_code_rule + (id, rule_name, rule_code, segment_config, code_separator, letter_case, total_length, + seq_strategy, status, remark, creator, create_time, updater, update_time, deleted) +SELECT 2094000000000000001, 'LMS管芯编码', 'CORE_TUBE_CODE', + JSON_ARRAY( + JSON_OBJECT('type', 'PREFIX', 'value', 'GX', 'format', NULL, 'resetBy', NULL, 'startAt', NULL, 'maxValue', NULL, 'paddingLen', NULL, 'paddingChar', NULL), + JSON_OBJECT('type', 'DATE', 'value', NULL, 'format', 'yyyyMMdd', 'resetBy', NULL, 'startAt', NULL, 'maxValue', NULL, 'paddingLen', NULL, 'paddingChar', NULL), + JSON_OBJECT('type', 'SEQUENCE', 'value', NULL, 'format', NULL, 'resetBy', 'DAY', 'startAt', 1, 'maxValue', 999999, 'paddingLen', 6, 'paddingChar', '0') + ), '', 0, 16, 'segment', 0, 'LMS管芯编码,格式GXyyyyMMdd000001', '1', NOW(), '1', NOW(), 0 +WHERE NOT EXISTS (SELECT 1 FROM base_code_rule WHERE rule_code = 'CORE_TUBE_CODE'); + +-- 管芯生命周期和占用状态字典。 +INSERT INTO system_dict_type + (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) +SELECT 2094000000000000010, 'LMS管芯生命周期阶段', 'lms_core_tube_stage', 0, + 'LMS管芯生命周期阶段', '1', NOW(), '1', NOW(), b'0', '1970-01-01 00:00:00' +WHERE NOT EXISTS (SELECT 1 FROM system_dict_type WHERE type = 'lms_core_tube_stage' AND deleted = b'0'); + +INSERT INTO system_dict_type + (id, name, type, status, remark, creator, create_time, updater, update_time, deleted, deleted_time) +SELECT 2094000000000000020, 'LMS管芯占用状态', 'lms_core_tube_status', 0, + 'LMS管芯占用状态', '1', NOW(), '1', NOW(), b'0', '1970-01-01 00:00:00' +WHERE NOT EXISTS (SELECT 1 FROM system_dict_type WHERE type = 'lms_core_tube_status' AND deleted = b'0'); + +INSERT INTO system_dict_data + (id, sort, label, value, dict_type, status, color_type, css_class, remark, + creator, create_time, updater, update_time, deleted) +SELECT 2094000000000000010 + stage.code, stage.code, stage.label, CAST(stage.code AS CHAR), + 'lms_core_tube_stage', 0, stage.color_type, '', CONCAT('管芯', stage.label), + '1', NOW(), '1', NOW(), b'0' +FROM ( + SELECT 1 code, '备货区' label, 'info' color_type UNION ALL + SELECT 2, '备货抓取中', 'warning' UNION ALL + SELECT 3, '管芯库', 'success' UNION ALL + SELECT 4, '管芯出库中', 'warning' UNION ALL + SELECT 5, '套管中', 'primary' UNION ALL + SELECT 6, '套管缓存位', 'success' UNION ALL + SELECT 7, '已消耗', 'info' UNION ALL + SELECT 8, '异常', 'danger' +) stage +WHERE NOT EXISTS ( + SELECT 1 FROM system_dict_data existing + WHERE existing.dict_type = 'lms_core_tube_stage' + AND existing.value = CONVERT(stage.code, CHAR) COLLATE utf8mb4_unicode_ci + AND existing.deleted = b'0'); + +INSERT INTO system_dict_data + (id, sort, label, value, dict_type, status, color_type, css_class, remark, + creator, create_time, updater, update_time, deleted) +SELECT 2094000000000000020 + state.code, state.code, state.label, CAST(state.code AS CHAR), + 'lms_core_tube_status', 0, state.color_type, '', CONCAT('管芯', state.label), + '1', NOW(), '1', NOW(), b'0' +FROM ( + SELECT 1 code, '可用' label, 'success' color_type UNION ALL + SELECT 2, '已预占', 'warning' UNION ALL + SELECT 3, '作业中', 'primary' UNION ALL + SELECT 4, '已使用', 'info' UNION ALL + SELECT 5, '冻结', 'warning' UNION ALL + SELECT 6, '异常', 'danger' +) state +WHERE NOT EXISTS ( + SELECT 1 FROM system_dict_data existing + WHERE existing.dict_type = 'lms_core_tube_status' + AND existing.value = CONVERT(state.code, CHAR) COLLATE utf8mb4_unicode_ci + AND existing.deleted = b'0'); diff --git a/sql/mysql/lms_daily_plan.sql b/sql/mysql/lms_daily_plan.sql index 22004f4c..ff71a9f2 100644 --- a/sql/mysql/lms_daily_plan.sql +++ b/sql/mysql/lms_daily_plan.sql @@ -48,6 +48,7 @@ CREATE TABLE IF NOT EXISTS `lms_daily_plan_strategy` ( `strategy_type` tinyint NOT NULL COMMENT '策略类型:1备货,2套管', `strategy_mode` tinyint NOT NULL DEFAULT 1 COMMENT '策略模式:1顺序,2权重', `cursor_daily_plan_id` bigint DEFAULT NULL COMMENT '当前游标日计划ID', + `cursor_executed_qty` int NOT NULL DEFAULT 0 COMMENT '当前权重轮转已执行数量', `version` int NOT NULL DEFAULT 0 COMMENT '乐观锁版本号', `creator` varchar(64) DEFAULT '' COMMENT '创建者', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', @@ -59,6 +60,16 @@ CREATE TABLE IF NOT EXISTS `lms_daily_plan_strategy` ( UNIQUE KEY `uk_strategy_type_tenant` (`strategy_type`, `tenant_id`) ) COMMENT='LMS日计划调度策略'; +-- 兼容已执行过旧版脚本的数据库,幂等补充逐根权重轮转计数。 +SET @lms_daily_plan_ddl = IF( + EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE() + AND table_name = 'lms_daily_plan_strategy' AND column_name = 'cursor_executed_qty'), + 'SELECT 1', + 'ALTER TABLE lms_daily_plan_strategy ADD COLUMN cursor_executed_qty INT NOT NULL DEFAULT 0 COMMENT ''当前权重轮转已执行数量'' AFTER cursor_daily_plan_id'); +PREPARE lms_daily_plan_stmt FROM @lms_daily_plan_ddl; +EXECUTE lms_daily_plan_stmt; +DEALLOCATE PREPARE lms_daily_plan_stmt; + CREATE TABLE IF NOT EXISTS `lms_daily_plan_claim` ( `claim_id` bigint NOT NULL COMMENT '领取ID', `claim_token` varchar(64) NOT NULL COMMENT '对外领取标识', diff --git a/sql/mysql/lms_stocking_ivt_menu.sql b/sql/mysql/lms_stocking_ivt_menu.sql index e3afdec7..4b40b8bf 100644 --- a/sql/mysql/lms_stocking_ivt_menu.sql +++ b/sql/mysql/lms_stocking_ivt_menu.sql @@ -64,6 +64,21 @@ WHERE menu.component = 'lms/stockingivt/index' WHERE permission = 'lms:stocking-ivt:update' AND deleted = b'0' ); +INSERT INTO system_menu + (id, name, permission, type, sort, parent_id, path, icon, component, component_name, + status, visible, keep_alive, always_show, creator, create_time, updater, update_time, deleted) +SELECT 2092000000000000104, '管芯托盘绑定', 'lms:core-tube:bind', 3, 3, menu.id, '', '', + '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0' +FROM system_menu menu +WHERE menu.component = 'lms/stockingivt/index' + AND menu.deleted = b'0' + AND NOT EXISTS ( + SELECT 1 FROM system_menu existing + WHERE existing.parent_id = menu.id + AND existing.permission = 'lms:core-tube:bind' + AND existing.deleted = b'0' + ); + -- 已授权备货区域的角色同步获得父目录权限。 INSERT INTO system_role_menu (role_id, menu_id, creator, create_time, updater, update_time, deleted, tenant_id)