This commit is contained in:
2026-08-17 16:07:20 +08:00
parent 68d9216cb8
commit 75580c3585
9 changed files with 249 additions and 78 deletions
@@ -13,6 +13,9 @@ const loading = read('./phase3-loading.mjs')
const convergence = read('./phase3-pda-convergence.mjs')
const customs = read('./phase3-customs.mjs')
const finalize = read('./phase3-loading-finalize.mjs')
const loadingPickService = read('../../firstleg/src/main/java/com/baiyue/firstleg/service/LoadingPickService.java')
const loadingDeliveryService = read('../../firstleg/src/main/java/com/baiyue/firstleg/loading/service/LoadingDeliveryService.java')
const loadingDeliveryServiceTest = read('../../firstleg/src/test/java/com/baiyue/firstleg/loading/service/LoadingDeliveryServiceTest.java')
function ordered(source, fragments) {
let cursor = -1
@@ -73,7 +76,7 @@ test('HTTP chain refreshes after stale inventory and keeps one stable PDA identi
assert.doesNotMatch(loading, /\/loading\/complete\?tenantId=/)
})
test('downstream modules stop before HTTP until the new truck-coupled complete contract freezes', () => {
test('downstream finalizer uses the frozen truck-coupled complete contract', () => {
assert.match(convergence, /summary\?\.status === 'LOADING'/)
assert.match(convergence, /!operations\.some\(\(item\) => item\.actionType === 'COMPLETE_LOADING'\)/)
assert.match(customs, /\['AWAITING_REVIEW', 'LOADED'\]/)
@@ -81,17 +84,58 @@ test('downstream modules stop before HTTP until the new truck-coupled complete c
assert.doesNotMatch(customs, /truck\?\.finalStatus !== 'COMPLETED'/)
ordered(finalize, [
'最终装柜前保持 LOADING 且版本有效',
'PDA complete 联动拖车并原子推进 LOADED',
'return',
'const taskPath =',
'结算递增 inboundVersion 后 final complete 必须使用最新版本',
'入库单终态 LOADED、版本递增且审计历史存在',
])
assert.match(finalize, /BLOCKED_CONTRACT:用户已确认拖车缺失或未完成不再阻断/)
assert.doesNotMatch(finalize, /BLOCKED_CONTRACT/)
assert.doesNotMatch(finalize, /truck\?\.finalStatus === 'COMPLETED'/)
assert.doesNotMatch(finalize, /\/loading\/complete\?tenantId=/)
})
test('current PDA complete OpenAPI remains a blocker because it still requires pre-completed truck', () => {
test('PDA complete OpenAPI freezes optional truck coupling and atomic rollback', () => {
assert.match(pdaOpenApi, /\/api\/platform\/v1\/first-leg\/pda-loading\/tasks\/\{taskId\}\/complete:/)
assert.match(pdaOpenApi, /先无写入校验全部关联入库单的RELEASED订舱、COMPLETED拖车和五类ACTIVE证据/)
assert.match(finalize, /BLOCKED_CONTRACT/)
assert.match(pdaOpenApi, /拖车状态不是前置门禁/)
assert.match(pdaOpenApi, /没有有效拖车则直接继续/)
assert.match(pdaOpenApi, /恰有一条有效拖车时由服务端加锁推进为COMPLETED并写历史/)
assert.match(pdaOpenApi, /多条有效拖车或并发修改返回A0409且全部Firstleg本地状态回滚/)
assert.match(pdaOpenApi, /同operationId重放返回冻结结果,不重复推进拖车或写历史/)
})
test('PDA final completion refreshes post-settlement versions for full and partial split', () => {
ordered(loadingPickService, [
'settlementService.settle(taskId, operatorId, operatorName)',
'loadingDeliveryService.completeAfterPdaSettlement',
])
assert.doesNotMatch(loadingPickService,
/new LoadingRequests\.CompleteLoadingRequest\(entry\.getValue\(\)\.version\(\), remark\)/)
ordered(loadingDeliveryService, [
'CompletionTarget target = repository.completionTarget(tenantId, inboundId)',
'Snapshot current = repository.findInboundForUpdate(tenantId, completionInboundId)',
'new CompleteLoadingRequest(current.version(), remark)',
])
for (const regression of [
'pdaFinalizeUsesSourceVersionIncrementedByFullSettlement',
'pdaFinalizeLocksAndUsesLoadedSliceVersionAfterPartialSettlement',
'pdaFinalizeKeepsOptimisticConflictForRealConcurrentChange',
]) assert.match(loadingDeliveryServiceTest, new RegExp(regression))
assert.match(loadingDeliveryServiceTest, /verify\(repository, never\(\)\)\.completeLoadedChild\(10, 20, 7, 6\)/)
assert.match(loadingDeliveryServiceTest, /verify\(histories, never\(\)\)\.insert/)
})
test('HTTP finalizer preserves failure evidence and verifies the settled slice', () => {
ordered(finalize, [
'读取结算前计划即时版本',
'读取结算前 PDA 操作历史基线',
'结算递增 inboundVersion 后 final complete 必须使用最新版本',
'final complete 失败后回查 PDA 任务',
'final complete 失败后回查计划',
'final complete 失败后回查入库单',
'结算或版本冲突失败后 task/plan/inbound/operation 全部零写入',
'结算后回查柜次实际履约分片',
'结算递增版本后实际完成分片唯一且柜次身份稳定',
])
assert.match(finalize, /requestId=\$\{completeResponse\.requestId \|\| 'missing'\}/)
assert.match(finalize, /traceId=\$\{completeResponse\.traceId \|\| 'missing'\}/)
assert.match(finalize, /settlementMode = remainderSlice \? 'PARTIAL' : 'FULL'/)
})