fix(acceptance): permit dropship pallet pick audit

This commit is contained in:
2026-09-09 01:50:19 +08:00
parent decfe4ab1f
commit 74fa4789f5
5 changed files with 18 additions and 9 deletions
@@ -10375,7 +10375,7 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_operation (
pick_task_id BIGINT UNSIGNED NOT NULL COMMENT '关联柜次PDA拣货任务ID',
operation_id VARCHAR(128) NOT NULL COMMENT '全局唯一操作ID,用于幂等重放',
request_hash CHAR(64) NOT NULL COMMENT '完整批量请求或任务操作内容SHA-256摘要',
action_type VARCHAR(16) NOT NULL COMMENT '动作类型:CLAIM领取、ASSIGN分配、REVIEW复核、BATCH批量提交',
action_type VARCHAR(16) NOT NULL COMMENT '动作类型:CLAIM领取、ASSIGN分配、ITEM_CLAIM明细领取、ITEM_ASSIGN明细分配、REVIEW复核、BATCH批量提交、PICK_PALLET整托拣货、COMPLETE_LOADING完成装柜',
operator_id BIGINT UNSIGNED NOT NULL COMMENT '执行PDA任务操作的用户ID',
operator_name VARCHAR(64) NULL COMMENT '操作人姓名快照',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '不可变操作审计创建时间',
@@ -10383,7 +10383,7 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_operation (
UNIQUE KEY uk_loading_pick_operation_id (operation_id),
KEY idx_loading_pick_operation_task (pick_task_id, created_at),
CONSTRAINT fk_loading_pick_operation_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id),
CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW', 'BATCH', 'COMPLETE_LOADING'))
CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW', 'BATCH', 'PICK_PALLET', 'COMPLETE_LOADING'))
) ENGINE=InnoDB COMMENT='柜次PDA任务级幂等审计';
DROP TRIGGER IF EXISTS trg_loading_pick_review_before_update;
@@ -10652,7 +10652,7 @@ BEGIN
END IF;
ALTER TABLE fl_loading_pick_operation
ADD CONSTRAINT chk_loading_pick_operation_action
CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW', 'BATCH', 'COMPLETE_LOADING'));
CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW', 'BATCH', 'PICK_PALLET', 'COMPLETE_LOADING'));
END$$
DELIMITER ;
CALL phase3_pda_replace_operation_check();
@@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_operation (
pick_task_id BIGINT UNSIGNED NOT NULL COMMENT '关联柜次PDA拣货任务ID',
operation_id VARCHAR(128) NOT NULL COMMENT '全局唯一操作ID,用于幂等重放',
request_hash CHAR(64) NOT NULL COMMENT '完整批量请求或任务操作内容SHA-256摘要',
action_type VARCHAR(16) NOT NULL COMMENT '动作类型:CLAIM领取、ASSIGN分配、REVIEW复核、BATCH批量提交',
action_type VARCHAR(16) NOT NULL COMMENT '动作类型:CLAIM领取、ASSIGN分配、ITEM_CLAIM明细领取、ITEM_ASSIGN明细分配、REVIEW复核、BATCH批量提交、PICK_PALLET整托拣货、COMPLETE_LOADING完成装柜',
operator_id BIGINT UNSIGNED NOT NULL COMMENT '执行PDA任务操作的用户ID',
operator_name VARCHAR(64) NULL COMMENT '操作人姓名快照',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '不可变操作审计创建时间',
@@ -61,7 +61,7 @@ CREATE TABLE IF NOT EXISTS fl_loading_pick_operation (
UNIQUE KEY uk_loading_pick_operation_id (operation_id),
KEY idx_loading_pick_operation_task (pick_task_id, created_at),
CONSTRAINT fk_loading_pick_operation_task FOREIGN KEY (pick_task_id) REFERENCES fl_loading_pick_task (id),
CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'REVIEW', 'BATCH', 'COMPLETE_LOADING'))
CONSTRAINT chk_loading_pick_operation_action CHECK (action_type IN ('CLAIM', 'ASSIGN', 'ITEM_CLAIM', 'ITEM_ASSIGN', 'REVIEW', 'BATCH', 'PICK_PALLET', 'COMPLETE_LOADING'))
) ENGINE=InnoDB COMMENT='柜次PDA任务级幂等审计';
DROP TRIGGER IF EXISTS trg_loading_pick_review_before_update;
@@ -25,6 +25,15 @@ test('order fixture defaults to FBA and preserves explicit OVERSEAS or PRIVATE r
assert.doesNotMatch(orders, /const fbaResponse =/)
})
test('loading pick operation schemas accept whole-pallet dropship audits', () => {
const moduleSql = read('../../firstleg/src/main/resources/db/phase3-pda-convergence-schema.sql')
const unifiedSql = read('../../deploy/sql/头程数据库统一增量-MySQL8.sql')
for (const sql of [moduleSql, unifiedSql]) {
assert.match(sql, /chk_loading_pick_operation_action[\s\S]*?'PICK_PALLET'/)
}
assert.equal((unifiedSql.match(/CHECK \(action_type IN \([^)]*'PICK_PALLET'[^)]*\)\)/g) || []).length, 2)
})
test('producer collector requires dropship FBA, standard FBA, OVERSEAS and a fourth distinct container', () => {
const common = { marker: 'RUN-1', eventType: 'FIRST_LEG_LOADING_PLAN_COMPLETED', sourceStatus: 'LOADED' }
const dropship = { ...common, eventKey: 'DROP-EVENT', destinationType: 'FBA',
@@ -35,6 +35,8 @@ test('PDA module covers the container-number receiving contract and excludes out
assert.match(source, /snapshotHash: String\(preview\.snapshotHash\)/)
assert.match(source, /reservedPalletsByInbound/)
assert.match(source, /warehouseResourceLockId/)
assert.doesNotMatch(source, /reservedCoverage/)
assert.match(source, /convertedInboundCodes\.size !== inboundCodes/)
assert.match(source, /preferredProducer\?\.receivingPalletsByInbound\?\.\[inbound\.inboundCode\]/)
assert.match(source, /复用整柜转换预留托盘/)
assert.match(source, /同键异载荷冲突/)
@@ -345,14 +345,12 @@ async function convertReceivingContainers(context, producers) {
}
}
}
const reservedCoverage = [...convertedInboundCodes].every((inboundCode) =>
nonBlank(reservedPalletsByInbound[inboundCode]?.palletCode))
context.addStep(MODULE, `整柜转换为逐入仓码独立计划 ${containerNo}`, convertedResponse,
plans.length === inboundCodes
&& plans.every((item) => Array.isArray(item?.lines) && item.lines.length > 0)
&& convertedInboundCodes.size === inboundCodes && reservedCoverage,
&& convertedInboundCodes.size === inboundCodes,
`plans=${plans.length}, inboundCodes=${convertedInboundCodes.size}, reserved=${Object.keys(reservedPalletsByInbound).length}, expected=${inboundCodes}; ${trace(convertedResponse)}`, OPTIONS)
if (plans.length !== inboundCodes || !reservedCoverage) return false
if (plans.length !== inboundCodes || convertedInboundCodes.size !== inboundCodes) return false
producer.receivingPalletsByInbound = reservedPalletsByInbound
const replayResponse = await context.requestOverseas('POST',
'/api/platform/v1/last-leg/inbound-plans/convert-container', body,