This commit is contained in:
2026-10-21 15:10:44 +08:00
parent 40a03978cd
commit 6fe632f28e
34 changed files with 372 additions and 110 deletions
@@ -373,7 +373,8 @@ async function truckFlow(context, customerId) {
after?.destination === `${payload.destination}-EDIT` && Number(after?.version) === Number(before?.version) + 1
&& after?.status === 'PENDING_REVIEW',
`version=${after?.version ?? 'missing'}, destination=${after?.destination || 'missing'}; ${trace(edited.response)}`, OPTIONS)
const stale = await context.request('PATCH', path, { version: Number(before?.version), destination: 'STALE-DO-NOT-APPLY' })
const stale = await context.request('PATCH', path, { ...payload, idempotencyKey: undefined,
version: Number(before?.version), destination: 'STALE-DO-NOT-APPLY' })
expectedConflict(context, '卡车旧 version 编辑返回 A0409', stale, true)
const afterStale = await overseas(context, 'GET', '卡车旧 version 冲突后零漂移回查', path)
const afterStaleSummary = summary(afterStale.data)
@@ -456,38 +457,33 @@ async function looseboardFlow(context, customerId) {
`destination=${afterStaleSummary?.destination || 'missing'}, version=${afterStaleSummary?.version ?? 'missing'}; ${trace(afterStale.response)}`, OPTIONS)
const statusPath = query(`${base}/${encodeURIComponent(orderNo)}/status`, { customerId })
const forwarded = await overseas(context, 'PATCH', '散板状态正向推进到已派车', statusPath,
{ version: Number(afterStaleSummary?.version), status: 'DISPATCHED',
idempotencyKey: `${context.marker}-looseboard-status-dispatched`.slice(0, 255),
remark: `${context.marker}-FORWARD` })
const forwardedSummary = summary(forwarded.data)
context.assert(MODULE, '散板状态正向推进成功', forwarded.response,
forwardedSummary?.status === 'DISPATCHED'
&& Number(forwardedSummary?.version) === Number(afterStaleSummary?.version) + 1,
`status=${forwardedSummary?.status || 'missing'}, version=${forwardedSummary?.version ?? 'missing'}; ${trace(forwarded.response)}`, OPTIONS)
const forwardBody = { version: Number(afterStaleSummary?.version), status: 'DISPATCHED',
idempotencyKey: `${context.marker}-looseboard-status-dispatched`.slice(0, 255),
remark: `${context.marker}-FORWARD` }
const forwardReplay = await overseas(context, 'PATCH', '散板状态同键同载荷精确重放', statusPath,
forwardBody)
context.assert(MODULE, '散板状态重放复用已派车终态且版本不漂移', forwardReplay.response,
summary(forwardReplay.data)?.status === 'DISPATCHED'
&& Number(summary(forwardReplay.data)?.version) === Number(forwardedSummary?.version),
trace(forwardReplay.response), OPTIONS)
const forwardMismatch = await context.request('PATCH', statusPath, { ...forwardBody, remark: 'DIFFERENT-DO-NOT-APPLY' })
expectedConflict(context, '散板状态同键异载荷返回冲突', forwardMismatch)
const reversed = await context.request('PATCH', statusPath, { version: Number(forwardedSummary?.version), status: 'PENDING_ACCEPTANCE',
idempotencyKey: `${context.marker}-looseboard-status-terminal-reverse`.slice(0, 255),
remark: 'REVERSE-DO-NOT-APPLY' })
expectedConflict(context, '散板状态逆向回退返回冲突', reversed)
const history = await overseas(context, 'GET', '散板状态冲突后流水回查', path)
idempotencyKey: `${context.marker}-looseboard-status-dispatched`.slice(0, 255), remark: `${context.marker}-FORWARD` }
// 散板状态由需求池匹配和真实履约驱动,普通状态接口只能取消。
const beforeRejected = JSON.stringify(afterStale.data)
for (const [name, body] of [
['散板禁止绕过需求池直接派车', forwardBody],
['散板被拒命令同键重放仍拒绝', forwardBody],
['散板被拒命令异载荷仍拒绝', { ...forwardBody, remark: 'DIFFERENT-DO-NOT-APPLY' }],
['散板状态逆向回退返回冲突', { ...forwardBody, status: 'PENDING_ACCEPTANCE',
idempotencyKey: `${context.marker}-looseboard-status-terminal-reverse`.slice(0, 255) }],
]) {
const rejected = await context.request('PATCH', statusPath, body)
expectedConflict(context, name, rejected)
}
const history = await overseas(context, 'GET', '散板被拒命令后完整详情与流水回查', path)
const historySummary = summary(history.data)
const histories = Array.isArray(history.data?.histories) ? history.data.histories : []
const operations = new Set(histories.map((item) => item?.operationType))
context.assert(MODULE, '散板流水覆盖创建编辑与正向状态', history.response,
historySummary?.status === 'DISPATCHED' && ['CREATE', 'UPDATE', 'STATUS'].every((type) => operations.has(type))
&& histories.some((item) => String(item?.remark || item?.changeDetail || '').includes(context.marker)),
`status=${historySummary?.status || 'missing'}, historyCount=${histories.length}, operations=${[...operations].join(',') || 'missing'}; ${trace(history.response)}`, OPTIONS)
context.assert(MODULE, '散板非法推进未改变完整详情及流水', history.response,
JSON.stringify(history.data) === beforeRejected && historySummary?.status === 'PENDING_ACCEPTANCE',
trace(history.response), OPTIONS)
const pending = await overseas(context, 'GET', '散板原单进入待匹配需求池',
query(`${BASE}/fleet/capacity-offers/pending-looseboard-demands`, { page: 1, size: 100, keyword: orderNo }))
context.assert(MODULE, '待匹配需求保持本轮原单客户与版本', pending.response,
records(pending.data).some(row => row.orderNo === orderNo && id(row.customerId) === customerId
&& Number(row.version) === Number(historySummary?.version)),
trace(pending.response), OPTIONS)
context.addCoverageGap(MODULE, 'looseboard-pool-fulfillment', '散板需求池接车至签收',
'本模块验证原单进入需求池、禁止手工跳状态及取消;接车、实收、装车、签收需本轮独立车次生产链,未以手工改状态代替。', 'fixture')
Object.assign(registry.looseboard, { version: Number(historySummary?.version), finalStatus: historySummary?.status })
} finally {
await cancelMarkerOrder(context, registry.looseboard, base, ['PENDING_ACCEPTANCE', 'DISPATCHED'], '散板')