fix: 锁定日计划后创建调度领取
This commit is contained in:
@@ -66,4 +66,5 @@ public interface ErrorCodeConstants {
|
|||||||
ErrorCode DAILY_PLAN_CLAIM_INVALID = new ErrorCode(41, "日计划领取标识无效、已结束或已过期");
|
ErrorCode DAILY_PLAN_CLAIM_INVALID = new ErrorCode(41, "日计划领取标识无效、已结束或已过期");
|
||||||
ErrorCode DAILY_PLAN_CLAIM_MISMATCH = new ErrorCode(42, "日计划领取信息与进度确认不一致");
|
ErrorCode DAILY_PLAN_CLAIM_MISMATCH = new ErrorCode(42, "日计划领取信息与进度确认不一致");
|
||||||
ErrorCode DAILY_PLAN_CLAIM_PROGRESS_CONFLICT = new ErrorCode(43, "日计划作业进度已变化,该领取无法确认");
|
ErrorCode DAILY_PLAN_CLAIM_PROGRESS_CONFLICT = new ErrorCode(43, "日计划作业进度已变化,该领取无法确认");
|
||||||
|
ErrorCode DAILY_PLAN_CLAIM_CANDIDATE_CHANGED = new ErrorCode(44, "日计划候选状态已变化,请重新获取");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ public interface DailyPlanMapper extends BaseMapperX<DailyPlanDO> {
|
|||||||
*/
|
*/
|
||||||
DailyPlanDO selectDailyPlanById(@Param("dailyPlanId") Long dailyPlanId);
|
DailyPlanDO selectDailyPlanById(@Param("dailyPlanId") Long dailyPlanId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 锁定并重新校验可调度计划,Claim 必须使用该锁内快照创建。
|
||||||
|
*/
|
||||||
|
DailyPlanDO selectSchedulableForUpdate(@Param("dailyPlanId") Long dailyPlanId,
|
||||||
|
@Param("strategyType") Integer strategyType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 ERP 订单号查询日计划。
|
* 根据 ERP 订单号查询日计划。
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static cn.code.nl.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_CONFLICT;
|
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_CONFLICT;
|
||||||
|
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_CANDIDATE_CHANGED;
|
||||||
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_INVALID;
|
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_INVALID;
|
||||||
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_MISMATCH;
|
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_MISMATCH;
|
||||||
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_PROGRESS_CONFLICT;
|
import static cn.code.nl.module.lms.enums.ErrorCodeConstants.DAILY_PLAN_CLAIM_PROGRESS_CONFLICT;
|
||||||
@@ -84,14 +85,16 @@ public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService {
|
|||||||
}
|
}
|
||||||
if (mode == DailyPlanStrategyModeEnum.SEQUENCE) {
|
if (mode == DailyPlanStrategyModeEnum.SEQUENCE) {
|
||||||
DailyPlanDO selected = candidates.get(0);
|
DailyPlanDO selected = candidates.get(0);
|
||||||
return claimCandidate(selected, remaining(selected, type), mode.getCode(), type, operator);
|
DailyPlanDO locked = lockSchedulablePlan(selected.getDailyPlanId(), type);
|
||||||
|
return claimCandidate(locked, remaining(locked, type), mode.getCode(), type, operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
int selectedIndex = findCursorIndex(candidates, strategy.getCursorDailyPlanId());
|
int selectedIndex = findCursorIndex(candidates, strategy.getCursorDailyPlanId());
|
||||||
DailyPlanDO selected = candidates.get(selectedIndex);
|
DailyPlanDO selected = candidates.get(selectedIndex);
|
||||||
DailyPlanDO next = candidates.get((selectedIndex + 1) % candidates.size());
|
DailyPlanDO next = candidates.get((selectedIndex + 1) % candidates.size());
|
||||||
int quantity = Math.min(selected.getWeight(), remaining(selected, type));
|
DailyPlanDO locked = lockSchedulablePlan(selected.getDailyPlanId(), type);
|
||||||
DailyPlanScheduleCandidate candidate = claimCandidate(selected, quantity, mode.getCode(), type, operator);
|
int quantity = Math.min(locked.getWeight(), remaining(locked, type));
|
||||||
|
DailyPlanScheduleCandidate candidate = claimCandidate(locked, quantity, mode.getCode(), type, operator);
|
||||||
int affected = dailyPlanStrategyMapper.updateCursorWithVersion(strategy.getStrategyId(), next.getDailyPlanId(),
|
int affected = dailyPlanStrategyMapper.updateCursorWithVersion(strategy.getStrategyId(), next.getDailyPlanId(),
|
||||||
strategy.getVersion(), normalizedOperator(operator));
|
strategy.getVersion(), normalizedOperator(operator));
|
||||||
if (affected != 1) {
|
if (affected != 1) {
|
||||||
@@ -101,6 +104,14 @@ public class DailyPlanScheduleServiceImpl implements DailyPlanScheduleService {
|
|||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DailyPlanDO lockSchedulablePlan(Long dailyPlanId, DailyPlanStrategyTypeEnum type) {
|
||||||
|
DailyPlanDO locked = dailyPlanMapper.selectSchedulableForUpdate(dailyPlanId, type.getCode());
|
||||||
|
if (locked == null) {
|
||||||
|
throw exception(DAILY_PLAN_CLAIM_CANDIDATE_CHANGED);
|
||||||
|
}
|
||||||
|
return locked;
|
||||||
|
}
|
||||||
|
|
||||||
private int findCursorIndex(List<DailyPlanDO> candidates, Long cursorDailyPlanId) {
|
private int findCursorIndex(List<DailyPlanDO> candidates, Long cursorDailyPlanId) {
|
||||||
if (cursorDailyPlanId != null) {
|
if (cursorDailyPlanId != null) {
|
||||||
for (int i = 0; i < candidates.size(); i++) {
|
for (int i = 0; i < candidates.size(); i++) {
|
||||||
|
|||||||
@@ -51,6 +51,28 @@
|
|||||||
ORDER BY plan_date DESC, sort_seq ASC, daily_plan_id DESC
|
ORDER BY plan_date DESC, sort_seq ASC, daily_plan_id DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectSchedulableForUpdate"
|
||||||
|
resultType="cn.code.nl.module.lms.dal.dataobject.dailyplan.DailyPlanDO">
|
||||||
|
SELECT <include refid="dailyPlanColumns"/>
|
||||||
|
FROM lms_daily_plan
|
||||||
|
WHERE daily_plan_id = #{dailyPlanId}
|
||||||
|
AND order_status = 1
|
||||||
|
AND deleted = b'0'
|
||||||
|
AND (
|
||||||
|
(#{strategyType} = 1 AND stocking_status = 1 AND stocked_qty < plan_qty + append_qty)
|
||||||
|
OR (#{strategyType} = 2 AND sleeving_status = 1 AND sleeved_qty < plan_qty + append_qty)
|
||||||
|
)
|
||||||
|
AND NOT EXISTS (
|
||||||
|
SELECT 1 FROM lms_daily_plan_claim claim
|
||||||
|
WHERE claim.daily_plan_id = lms_daily_plan.daily_plan_id
|
||||||
|
AND claim.tenant_id = lms_daily_plan.tenant_id
|
||||||
|
AND claim.strategy_type = #{strategyType}
|
||||||
|
AND claim.claim_status = 0 AND claim.active_flag = 1
|
||||||
|
AND claim.expire_time > NOW() AND claim.deleted = b'0'
|
||||||
|
)
|
||||||
|
FOR UPDATE
|
||||||
|
</select>
|
||||||
|
|
||||||
<select id="selectWorkPage"
|
<select id="selectWorkPage"
|
||||||
resultType="cn.code.nl.module.lms.dal.dataobject.dailyplan.DailyPlanDO">
|
resultType="cn.code.nl.module.lms.dal.dataobject.dailyplan.DailyPlanDO">
|
||||||
SELECT <include refid="dailyPlanColumns"/>
|
SELECT <include refid="dailyPlanColumns"/>
|
||||||
|
|||||||
@@ -102,6 +102,9 @@ CREATE TABLE IF NOT EXISTS `lms_daily_plan_operation_log` (
|
|||||||
) COMMENT='LMS日计划操作日志';
|
) COMMENT='LMS日计划操作日志';
|
||||||
|
|
||||||
-- 兼容已执行过旧版脚本的数据库,幂等补充候选组合索引。
|
-- 兼容已执行过旧版脚本的数据库,幂等补充候选组合索引。
|
||||||
|
SET @lms_claim_progress_upgrade = NOT EXISTS(
|
||||||
|
SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE()
|
||||||
|
AND table_name = 'lms_daily_plan_claim' AND column_name = 'progress_qty');
|
||||||
SET @lms_daily_plan_ddl = IF(
|
SET @lms_daily_plan_ddl = IF(
|
||||||
EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
|
EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema = DATABASE()
|
||||||
AND table_name = 'lms_daily_plan' AND index_name = 'idx_stocking_candidate'),
|
AND table_name = 'lms_daily_plan' AND index_name = 'idx_stocking_candidate'),
|
||||||
@@ -118,6 +121,14 @@ SET @lms_daily_plan_ddl = IF(
|
|||||||
PREPARE lms_daily_plan_stmt FROM @lms_daily_plan_ddl;
|
PREPARE lms_daily_plan_stmt FROM @lms_daily_plan_ddl;
|
||||||
EXECUTE lms_daily_plan_stmt;
|
EXECUTE lms_daily_plan_stmt;
|
||||||
DEALLOCATE PREPARE lms_daily_plan_stmt;
|
DEALLOCATE PREPARE lms_daily_plan_stmt;
|
||||||
|
-- 旧版活跃 Claim 没有可靠的领取时进度快照,首次升级时统一释放,避免按默认 0 错误确认。
|
||||||
|
SET @lms_daily_plan_ddl = IF(
|
||||||
|
@lms_claim_progress_upgrade,
|
||||||
|
'UPDATE lms_daily_plan_claim SET claim_status = 2, active_flag = NULL, updater = ''SQL_UPGRADE'' WHERE claim_status = 0 AND active_flag = 1 AND deleted = b''0''',
|
||||||
|
'SELECT 1');
|
||||||
|
PREPARE lms_daily_plan_stmt FROM @lms_daily_plan_ddl;
|
||||||
|
EXECUTE lms_daily_plan_stmt;
|
||||||
|
DEALLOCATE PREPARE lms_daily_plan_stmt;
|
||||||
SET @lms_daily_plan_ddl = IF(
|
SET @lms_daily_plan_ddl = IF(
|
||||||
EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE()
|
EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = DATABASE()
|
||||||
AND table_name = 'lms_daily_plan_claim' AND column_name = 'version'),
|
AND table_name = 'lms_daily_plan_claim' AND column_name = 'version'),
|
||||||
|
|||||||
Reference in New Issue
Block a user