diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanOrderStatusEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanOrderStatusEnum.java index 260bde11..3089056d 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanOrderStatusEnum.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanOrderStatusEnum.java @@ -10,9 +10,13 @@ import lombok.Getter; @AllArgsConstructor public enum DailyPlanOrderStatusEnum { + /** 尚未开始,可编辑、开始或取消。 */ NOT_STARTED(0), + /** 订单执行中,允许备货和套管作业参与调度。 */ IN_PROGRESS(1), + /** 订单已结束,不再产生新的现场任务。 */ FINISHED(2), + /** 订单已取消,不再产生新任务,但取消前已下发任务允许回写结果。 */ CANCELED(3); /** diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanSourceTypeEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanSourceTypeEnum.java index f23a5fb8..7896d492 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanSourceTypeEnum.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanSourceTypeEnum.java @@ -10,7 +10,9 @@ import lombok.Getter; @AllArgsConstructor public enum DailyPlanSourceTypeEnum { + /** ERP 接口推送的日计划。 */ ERP(1), + /** LMS 页面人工创建的日计划。 */ MANUAL(2); /** diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyModeEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyModeEnum.java index 597c8e8c..80b7b8a0 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyModeEnum.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyModeEnum.java @@ -10,7 +10,9 @@ import lombok.Getter; @AllArgsConstructor public enum DailyPlanStrategyModeEnum { + /** 严格按顺序号选择最靠前的可执行日计划。 */ SEQUENCE(1), + /** 仍按顺序轮转,并按每张日计划的权重连续执行指定根数。 */ WEIGHT_ROUND_ROBIN(2); /** diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyTypeEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyTypeEnum.java index 13530910..2ad6d02a 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyTypeEnum.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanStrategyTypeEnum.java @@ -10,7 +10,9 @@ import lombok.Getter; @AllArgsConstructor public enum DailyPlanStrategyTypeEnum { + /** 管芯从备货区进入管芯库的作业策略。 */ STOCKING(1), + /** 管芯从管芯库送往套管机构的作业策略。 */ SLEEVING(2); /** diff --git a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanWorkStatusEnum.java b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanWorkStatusEnum.java index 8b0363a3..aea73713 100644 --- a/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanWorkStatusEnum.java +++ b/nl-module-lms/nl-module-lms-api/src/main/java/cn/code/nl/module/lms/enums/DailyPlanWorkStatusEnum.java @@ -10,9 +10,13 @@ import lombok.Getter; @AllArgsConstructor public enum DailyPlanWorkStatusEnum { + /** 作业尚未开始,不参与定时调度。 */ NOT_STARTED(0), + /** 作业进行中,且完成量不足时参与定时调度。 */ IN_PROGRESS(1), + /** 作业数量已达到订单总量;追加数量后会重新进入进行中。 */ COMPLETED(2), + /** 作业人工取消,不产生新的任务。 */ CANCELED(3); /** diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanClaimDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanClaimDO.java index 54ec9b1f..d3774280 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanClaimDO.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanClaimDO.java @@ -12,19 +12,33 @@ import java.time.LocalDateTime; @Data public class DailyPlanClaimDO extends TenantBaseDO { + /** 领取记录ID。 */ @TableId private Long claimId; + /** 对外使用的领取令牌,现场任务回调必须原样携带。 */ private String claimToken; + /** 被领取的日计划ID。 */ private Long dailyPlanId; + /** 作业类型:备货或套管。 */ private Integer strategyType; + /** 本次预占数量;当前现场任务固定为一根。 */ private Integer claimedQty; + /** 领取时日计划通用版本,仅用于追踪领取快照。 */ private Integer planVersion; + /** 领取时对应作业的完成数量,用于防止重复或乱序累计。 */ private Integer progressQty; + /** Claim 自身乐观锁版本。 */ private Integer version; + /** 领取状态:0活动、1已确认、2已释放、3已过期。 */ private Integer claimStatus; + /** 活动唯一标记;结束后置空以释放唯一索引。 */ private Integer activeFlag; + /** 是否已经成功创建现场任务;已创建任务不按普通租约自动回收。 */ private Boolean taskCreated; + /** 未创建任务时的领取租约过期时间。 */ private LocalDateTime expireTime; + /** 任务完成并确认进度的时间。 */ private LocalDateTime confirmedTime; + /** 领取、确认或释放该记录的执行者。 */ private String operator; } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanStrategyDO.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanStrategyDO.java index 666ddff2..5d0b9c98 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanStrategyDO.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/dal/dataobject/dailyplan/DailyPlanStrategyDO.java @@ -15,14 +15,14 @@ public class DailyPlanStrategyDO extends TenantBaseDO { /** 策略 ID */ @TableId private Long strategyId; - /** 策略类型 */ + /** 策略类型;备货和套管各维护一套独立策略。 */ private Integer strategyType; - /** 策略模式 */ + /** 策略模式:顺序或权重轮转。 */ private Integer strategyMode; - /** 当前游标日计划 ID */ + /** 权重模式下当前应执行的日计划ID。 */ private Long cursorDailyPlanId; - /** 当前权重轮转已执行数量 */ + /** 当前游标计划已成功创建的单根任务数量。 */ private Integer cursorExecutedQty; - /** 乐观锁版本号 */ + /** 乐观锁版本号,防止策略切换与定时调度互相覆盖。 */ private Integer version; } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeHandleCodeConstants.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeHandleCodeConstants.java index 6a040b19..c2af29ac 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeHandleCodeConstants.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeHandleCodeConstants.java @@ -2,6 +2,8 @@ package cn.code.nl.module.lms.enums; /** 管芯任务回调处理器编码。 */ public interface CoreTubeHandleCodeConstants { + /** 备货区托盘搬运及单根抓取任务回调处理器。 */ String CORE_TUBE_STOCKING_TASK = "CORE_TUBE_STOCKING_TASK"; + /** 管芯库单根出库任务回调处理器。 */ String CORE_TUBE_SLEEVING_TASK = "CORE_TUBE_SLEEVING_TASK"; } 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 index 441b3d23..a0fc950f 100644 --- 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 @@ -10,13 +10,21 @@ import lombok.Getter; @AllArgsConstructor public enum CoreTubeLocationTypeEnum { + /** PDA 绑定管芯时托盘所在的绑定位。 */ STOCKING_BINDING(1), + /** 备货区缓存位。 */ STOCKING_CACHE(2), + /** 备货区与桁架交接的对接位。 */ STOCKING_DOCK(3), + /** 管芯已经完成备货并进入管芯库。 */ CORE_WAREHOUSE(4), + /** 管芯位于套管等生产设备。 */ EQUIPMENT(5), + /** 管芯或托盘正在搬运途中。 */ IN_TRANSIT(6), + /** 套管完成后的管芯缓存位。 */ SLEEVING_CACHE(7); + /** 位置类型编码,与 lms_core_tube.current_location_type 对应。 */ 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 index 9290ce91..095fbd73 100644 --- 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 @@ -10,14 +10,23 @@ import lombok.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); + /** 生命周期阶段编码,与 lms_core_tube.stage 对应。 */ 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 index 8cfd4526..30759618 100644 --- 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 @@ -10,12 +10,19 @@ import lombok.Getter; @AllArgsConstructor public enum CoreTubeStatusEnum { + /** 可被新的日计划任务选择。 */ AVAILABLE(1), + /** 已取得日计划 Claim,尚未成功绑定现场任务。 */ RESERVED(2), + /** 已绑定现场任务,禁止其他任务重复选择。 */ PROCESSING(3), + /** 已使用,不再参与库存分配。 */ USED(4), + /** 人工冻结,暂不参与调度。 */ FROZEN(5), + /** 状态异常,等待恢复处理。 */ ABNORMAL(6); + /** 占用状态编码,与 lms_core_tube.status 对应。 */ private final Integer code; } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeTaskBizTypeEnum.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeTaskBizTypeEnum.java index c76845c4..16dc26a8 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeTaskBizTypeEnum.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/enums/CoreTubeTaskBizTypeEnum.java @@ -2,8 +2,12 @@ package cn.code.nl.module.lms.enums; /** 管芯现场任务业务类型。 */ public enum CoreTubeTaskBizTypeEnum { + /** 将目标规格托盘从缓存位搬入对接位。 */ CORE_TUBE_PALLET_IN, + /** 将对接位上非当前需要的托盘移回缓存位。 */ CORE_TUBE_PALLET_OUT, + /** 从对接位托盘抓取一根管芯并送入管芯库。 */ CORE_TUBE_STOCKING_PICK, + /** 从管芯库取出一根管芯并送往套管机构。 */ CORE_TUBE_SLEEVING_OUT } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/DailyPlanCoreTubeJob.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/DailyPlanCoreTubeJob.java index 0cd7dfac..0fa62dea 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/DailyPlanCoreTubeJob.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/job/DailyPlanCoreTubeJob.java @@ -13,10 +13,15 @@ import org.springframework.stereotype.Component; @Component public class DailyPlanCoreTubeJob { + /** 管芯现场任务调度服务。 */ @Resource private CoreTubeTaskDispatchService dispatchService; - /** 每次每租户最多创建一条备货现场任务。 */ + /** + * 执行备货调度。 + * + *

{@link TenantJob} 会按租户分别执行;每个租户每次最多创建一条管芯抓取或托盘搬运任务。

+ */ @XxlJob("dailyPlanStockingJob") @TenantJob public void dailyPlanStockingJob() { @@ -26,7 +31,11 @@ public class DailyPlanCoreTubeJob { XxlJobHelper.handleSuccess(result); } - /** 每次每租户最多创建一条单根管芯出库任务。 */ + /** + * 执行套管调度。 + * + *

{@link TenantJob} 会按租户分别执行;每个租户每次最多创建一条单根管芯出库任务。

+ */ @XxlJob("dailyPlanSleevingJob") @TenantJob public void dailyPlanSleevingJob() { diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskContext.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskContext.java index 0faf976f..66416de7 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskContext.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskContext.java @@ -5,14 +5,24 @@ import lombok.Data; /** 管芯现场任务回调上下文。 */ @Data public class CoreTubeTaskContext { + /** 现场任务业务类型,用于在统一回调中区分处理分支。 */ private String bizType; + /** 任务服务的日计划。托盘移出任务可为空。 */ private Long dailyPlanId; + /** 单根任务对应的排他领取令牌。托盘任务为空。 */ private String claimToken; + /** 单根管芯实例ID。托盘任务为空。 */ private Long coreTubeId; + /** 虚拟管芯编号。 */ private String coreTubeCode; + /** 托盘号;单根任务中用于追踪管芯原托盘。 */ private String vehicleCode; + /** 起始点位记录ID。 */ private Long sourcePointId; + /** 起始点位编码。 */ private String sourcePointCode; + /** 目标点位记录ID;设备逻辑点位可能为空。 */ private Long targetPointId; + /** 目标点位编码。 */ private String targetPointCode; } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchService.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchService.java index 9fda9a9d..ae3893ce 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchService.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchService.java @@ -3,15 +3,19 @@ package cn.code.nl.module.lms.service.coretube; /** 管芯日计划现场任务调度服务。 */ public interface CoreTubeTaskDispatchService { - /** 执行一轮备货调度。 */ + /** + * 执行一轮备货调度。 + * + *

优先从对接位抓取一根目标管芯;全部候选都不能直接抓取时,本轮最多创建一条托盘任务。

+ */ String dispatchStockingOnce(); - /** 执行一轮套管调度。 */ + /** 从管芯库选择一根目标管芯并创建出库任务;本轮最多创建一条。 */ String dispatchSleevingOnce(); - /** 处理任务完成。 */ + /** 幂等处理现场任务完成,仅单根任务完成时累计对应日计划进度。 */ void handleFinished(Long taskId, boolean sleeving); - /** 处理任务取消。 */ + /** 幂等处理现场任务取消,释放管芯占用及未确认的日计划 Claim。 */ void handleCancelled(Long taskId, boolean sleeving); } diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java index bc96b59e..e64095da 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/coretube/CoreTubeTaskDispatchServiceImpl.java @@ -32,34 +32,52 @@ import java.util.Set; @Service public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchService { + /** 定时调度写入数据库的操作人标识。 */ private static final String OPERATOR = "SCHEDULER"; + /** Task 模块业务防重使用的归属服务。 */ private static final String OWNER_SERVICE = "LMS"; + /** 日计划候选、排他领取及进度确认服务。 */ @Resource private DailyPlanScheduleService dailyPlanScheduleService; + /** 管芯实例数据库访问对象。 */ @Resource private CoreTubeMapper coreTubeMapper; + /** 备货区点位及托盘格位数据库访问对象。 */ @Resource private StockingIvtMapper stockingIvtMapper; + /** 现场运输任务远程服务。 */ @Resource private TransportTaskApi transportTaskApi; + /** AGV 系统类型,由现场 Task/ACS 配置约定。 */ @Value("${lms.core-tube.agv-system-type:AGV}") private String agvSystemType; + /** 缓存位到对接位的托盘移入 ACS 任务类型。 */ @Value("${lms.core-tube.pallet-in-acs-type:CORE_PALLET_IN}") private String palletInAcsType; + /** 对接位到缓存位的托盘移出 ACS 任务类型。 */ @Value("${lms.core-tube.pallet-out-acs-type:CORE_PALLET_OUT}") private String palletOutAcsType; + /** 对接位单根管芯抓取 ACS 任务类型。 */ @Value("${lms.core-tube.stocking-pick-acs-type:CORE_STOCKING_PICK}") private String stockingPickAcsType; + /** 管芯库单根出库 ACS 任务类型。 */ @Value("${lms.core-tube.sleeving-out-acs-type:CORE_SLEEVING_OUT}") private String sleevingOutAcsType; + /** 备货抓取任务的管芯库入口逻辑点位。 */ @Value("${lms.core-tube.stocking-target-point:CORE_WAREHOUSE_IN}") private String stockingTargetPoint; + /** 管芯出库任务的套管机构入口逻辑点位。 */ @Value("${lms.core-tube.sleeving-target-point:SLEEVING_IN}") private String sleevingTargetPoint; - /** 执行一轮备货调度。 */ + /** + * 执行一轮备货调度。 + * + *

按当前顺序/权重策略扫描不同规格,任一对接位存在目标管芯时立即创建一条单根抓取任务。 + * 全部规格都不能直接抓取时,才允许创建一条托盘移出或移入任务,避免一轮产生多条托盘任务。

+ */ @Override @Transactional(rollbackFor = Exception.class) public String dispatchStockingOnce() { @@ -81,7 +99,12 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ return createPalletTask(candidates, checkedMaterials); } - /** 执行一轮套管调度。 */ + /** + * 执行一轮套管调度。 + * + *

按策略扫描不同规格,从管芯库选择一根可用管芯创建出库任务。缺货时只记录 + * “正在备货”或“备货区库存不足”,继续尝试下一规格。

+ */ @Override @Transactional(rollbackFor = Exception.class) public String dispatchSleevingOnce() { @@ -108,7 +131,12 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ return "全部待套管规格当前均无可出库管芯"; } - /** 创建单根抓取或出库任务。 */ + /** + * 创建单根抓取或出库任务。 + * + *

先领取日计划的一根额度,再原子预占管芯并创建 Task。只有 Task 创建及本地绑定都成功, + * 才标记 Claim 已创建任务并推进权重游标;任一步失败由外层事务回滚本地占用。

+ */ protected Long createSingleTubeTask(DailyPlanScheduleCandidate preview, CoreTubeDO tube, boolean sleeving) { DailyPlanScheduleCandidate claim = sleeving ? dailyPlanScheduleService.claimSleevingCandidate(preview.getDailyPlanId(), OPERATOR) @@ -141,7 +169,12 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ return taskId; } - /** 所有规格不能直接抓取时创建一条托盘任务。 */ + /** + * 所有规格都不能直接抓取时创建一条托盘任务。 + * + *

对接位有托盘时优先移出;对接位为空时,按“可一次满足剩余量的最小托盘, + * 否则库存最多托盘”选择缓存位托盘。业务键保证同规格未完成移入任务唯一。

+ */ private String createPalletTask(List candidates, Set checkedMaterials) { StockingIvtDO occupiedDock = stockingIvtMapper.selectOccupiedDockPoint(); if (occupiedDock != null) { @@ -229,7 +262,12 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ return request; } - /** 创建任务并处理响应不确定场景。 */ + /** + * 创建任务并处理远程响应不确定场景。 + * + *

Task 模块按 ownerService、bizType、bizId 防重。远程响应丢失时回查未完成任务, + * 避免调用方重试再创建一条相同现场任务。

+ */ private Long createTask(TransportTaskCreateReqDTO request, String bizType, String bizId) { request.setBizType(bizType); request.setBizId(bizId); @@ -262,7 +300,12 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ || CoreTubeTaskBizTypeEnum.CORE_TUBE_STOCKING_PICK.name().equals(task.getBizType())); } - /** 处理任务完成。 */ + /** + * 幂等处理任务完成。 + * + *

托盘任务只迁移点位和整托盘管芯位置,不累计日计划数量;单根抓取/出库任务 + * 完成后才清理管芯占用、确认 Claim,并分别累计已备货或已套管数量。

+ */ @Override @Transactional(rollbackFor = Exception.class) public void handleFinished(Long taskId, boolean sleeving) { @@ -302,7 +345,11 @@ public class CoreTubeTaskDispatchServiceImpl implements CoreTubeTaskDispatchServ } } - /** 处理任务取消。 */ + /** + * 幂等处理任务取消。 + * + *

只有仍绑定当前 taskId 的管芯会恢复为可用,同时释放对应 Claim;重复取消不会重复释放。

+ */ @Override @Transactional(rollbackFor = Exception.class) public void handleCancelled(Long taskId, boolean sleeving) { diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanScheduleServiceImpl.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanScheduleServiceImpl.java index 96ce945d..d5992b56 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanScheduleServiceImpl.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanScheduleServiceImpl.java @@ -41,25 +41,37 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_VERSION_ @Service public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService { + /** 备货进度日志对象编码。 */ private static final String TARGET_STOCKING = "STOCKING"; + /** 套管进度日志对象编码。 */ private static final String TARGET_SLEEVING = "SLEEVING"; + /** 进度变更日志操作类型。 */ private static final String TYPE_PROGRESS = "PROGRESS"; + /** Claim 活动状态。 */ private static final int CLAIM_ACTIVE = 0; + /** Claim 已确认状态。 */ private static final int CLAIM_CONFIRMED = 1; + /** 日计划及进度数据库访问对象。 */ @Resource private DailyPlanMapper dailyPlanMapper; + /** 日计划排他领取数据库访问对象。 */ @Resource private DailyPlanClaimMapper dailyPlanClaimMapper; + /** 顺序/权重调度策略数据库访问对象。 */ @Resource private DailyPlanStrategyMapper dailyPlanStrategyMapper; + /** 日计划操作日志数据库访问对象。 */ @Resource private DailyPlanOperationLogMapper dailyPlanOperationLogMapper; + /** 当前租户默认策略初始化器。 */ @Resource private DailyPlanStrategyInitializer strategyInitializer; + /** 未创建现场任务的 Claim 默认租期,单位秒。 */ @Value("${lms.daily-plan.claim-timeout-seconds:300}") private long claimTimeoutSeconds; + /** 兼容通用调度调用:领取当前策略下第一张备货候选计划。 */ @Override @Transactional(rollbackFor = Exception.class) public DailyPlanScheduleCandidate getNextStockingCandidate(String operator) { @@ -68,6 +80,7 @@ public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService { return candidates.isEmpty() ? null : claimStockingCandidate(candidates.get(0).getDailyPlanId(), operator); } + /** 兼容通用调度调用:领取当前策略下第一张套管候选计划。 */ @Override @Transactional(rollbackFor = Exception.class) public DailyPlanScheduleCandidate getNextSleevingCandidate(String operator) { @@ -88,7 +101,12 @@ public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService { return previewCandidates(DailyPlanStrategyTypeEnum.SLEEVING, dailyPlanMapper.selectSleevingCandidates()); } - /** 按当前策略排列候选,但不产生领取。 */ + /** + * 按当前策略排列候选,但不产生领取。 + * + *

顺序模式从排序最小的计划开始;权重模式从策略游标开始轮转。预览阶段只决定尝试顺序, + * 不提前分配库存,也不会消耗权重。

+ */ private List previewCandidates(DailyPlanStrategyTypeEnum type, List candidates) { DailyPlanStrategyDO strategy = strategyInitializer.getOrCreate(type); @@ -155,7 +173,12 @@ public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService { return 0; } - /** 创建单根排他领取。 */ + /** + * 创建单根排他领取。 + * + *

同一日计划的备货与套管使用不同 strategyType,可并行各自领取;同一种作业通过 + * 活动唯一键保证同一时刻最多一个 Claim。

+ */ private DailyPlanScheduleCandidate claimCandidate(DailyPlanDO plan, int quantity, Integer strategyMode, DailyPlanStrategyTypeEnum type, String operator) { LocalDateTime expireTime = nextClaimExpireTime(); @@ -202,7 +225,11 @@ public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService { return candidate; } - /** 现场单根任务创建成功后推进权重轮转。 */ + /** + * 现场单根任务创建成功后推进权重轮转。 + * + *

AGV 托盘任务和候选跳过都不会调用本方法,因此不会提前消耗某张计划的权重。

+ */ @Override @Transactional(rollbackFor = Exception.class) public void confirmTaskCreated(String claimToken, String operator) { diff --git a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanStrategyInitializer.java b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanStrategyInitializer.java index 2e167c0c..dd77932b 100644 --- a/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanStrategyInitializer.java +++ b/nl-module-lms/nl-module-lms-server/src/main/java/cn/code/nl/module/lms/service/dailyplan/DailyPlanStrategyInitializer.java @@ -19,13 +19,22 @@ import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_STRATEGY @Component public class DailyPlanStrategyInitializer { + /** 系统调度操作人标识。 */ private static final String SYSTEM_OPERATOR = "SCHEDULER"; + /** 日计划策略数据库访问对象。 */ @Resource private DailyPlanStrategyMapper strategyMapper; + /** 用于建立独立事务,隔离并发初始化产生的唯一键冲突。 */ @Resource private PlatformTransactionManager transactionManager; + /** + * 获取当前租户、指定作业类型的策略;不存在时初始化为顺序模式。 + * + *

初始化始终使用独立事务。并发插入冲突后,必须等冲突事务回滚,再使用全新的事务读取 + * 另一线程已经提交的策略,避免 MySQL 可重复读快照导致误判策略仍不存在。

+ */ public DailyPlanStrategyDO getOrCreate(DailyPlanStrategyTypeEnum type) { TransactionTemplate transaction = new TransactionTemplate(transactionManager); transaction.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); @@ -42,6 +51,7 @@ public class DailyPlanStrategyInitializer { } } + /** 在独立事务内查询或创建默认策略。 */ private DailyPlanStrategyDO loadOrInsert(DailyPlanStrategyTypeEnum type) { DailyPlanStrategyDO current = strategyMapper.selectByStrategyType(type.getCode()); if (current != null) {