优化
This commit is contained in:
@@ -320,6 +320,49 @@ async function convertContainerPlans(context, producer, details) {
|
||||
return plans
|
||||
}
|
||||
|
||||
export async function verifyReceivedOrderHold(context) {
|
||||
const owned = context.createdResources.phase4TailOrderControls
|
||||
if (owned?.marker !== context.marker || !owned.representativeOrderId) throw new Error('缺少本轮暂扣目标订单')
|
||||
const producer = targetProducer(context)
|
||||
const loaded = await detail(context, { id: owned.representativeOrderId, customerId: producer?.tenantId }, '入库后读取本轮暂扣目标')
|
||||
const representative = loaded.data?.order
|
||||
if (!success(loaded.response) || id(representative?.id) !== id(owned.representativeOrderId)
|
||||
|| id(representative?.customerId) !== id(producer?.tenantId)
|
||||
|| representative?.currentStatus !== 'INBOUND_COMPLETED') throw new Error('暂扣正向验收必须使用本轮已完成入库订单')
|
||||
const orderPath = query(`${ORDERS}/${encodeURIComponent(id(representative.id))}/hold`, {
|
||||
customerId: id(representative.customerId),
|
||||
})
|
||||
const holdKey = `${context.marker}-tail-hold`.slice(0, 128)
|
||||
const holdBody = { held: true, chargeable: true, reason: `${context.marker} 暂扣验收`, expectedVersion: Number(representative.version) }
|
||||
const held = await api(context, 'PUT', '暂扣本轮单票尾程订单', orderPath, holdBody, { 'Idempotency-Key': holdKey })
|
||||
context.assert(MODULE, '暂扣只推进单票版本并保留计费原因', held.response,
|
||||
held.data?.held === true && held.data?.chargeable === true
|
||||
&& id(held.data?.orderId) === id(representative.id) && Number(held.data?.version) === Number(representative.version) + 1,
|
||||
trace(held.response), OPTIONS)
|
||||
if (!success(held.response)) return
|
||||
const heldReplay = await api(context, 'PUT', '暂扣命令同键同载荷重放', orderPath, holdBody, { 'Idempotency-Key': holdKey })
|
||||
context.assert(MODULE, '暂扣重放版本零漂移', heldReplay.response,
|
||||
JSON.stringify(heldReplay.data) === JSON.stringify(held.data), trace(heldReplay.response), OPTIONS)
|
||||
const heldConflict = await context.requestOverseas('PUT', orderPath,
|
||||
{ ...holdBody, reason: `${holdBody.reason}-DIFFERENT` }, { 'Idempotency-Key': holdKey }, context.overseasToken)
|
||||
context.addStep(MODULE, '暂扣同键异载荷返回A0409', heldConflict, conflict(heldConflict), trace(heldConflict), OPTIONS)
|
||||
|
||||
const blockedPlanBody = manualPlanBody(representative, held.data.version, context.marker)
|
||||
const blockedPlan = await context.requestOverseas('POST', `${PLANS}/manual`, blockedPlanBody,
|
||||
{ 'Idempotency-Key': `${context.marker}-held-plan`.slice(0, 128) }, context.overseasToken)
|
||||
context.addStep(MODULE, '暂扣尾程订单不能生成人工计划', blockedPlan, conflict(blockedPlan), trace(blockedPlan), OPTIONS)
|
||||
|
||||
const releaseKey = `${context.marker}-tail-release`.slice(0, 128)
|
||||
const releaseBody = { held: false, chargeable: false, reason: `${context.marker} 解除暂扣`, expectedVersion: Number(held.data.version) }
|
||||
const released = await api(context, 'PUT', '解除本轮单票尾程暂扣', orderPath, releaseBody, { 'Idempotency-Key': releaseKey })
|
||||
context.assert(MODULE, '解除暂扣清空计费与原因并推进版本', released.response,
|
||||
released.data?.held === false && released.data?.chargeable === false && released.data?.reason == null
|
||||
&& Number(released.data?.version) === Number(held.data.version) + 1, trace(released.response), OPTIONS)
|
||||
if (!success(released.response)) return
|
||||
|
||||
owned.holdVerifiedAfterReceipt = true
|
||||
}
|
||||
|
||||
export async function run(context) {
|
||||
context.createdResources.phase4TailOrderControls = {
|
||||
marker: context.marker, containerNo: null, orderIds: [], planNos: [], representativeOrderId: null,
|
||||
@@ -355,48 +398,28 @@ export async function run(context) {
|
||||
refreshedDetails.push(refreshed.data.order)
|
||||
}
|
||||
const representative = refreshedDetails[0]
|
||||
const orderPath = query(`${ORDERS}/${encodeURIComponent(id(representative.id))}/hold`, {
|
||||
customerId: id(representative.customerId),
|
||||
})
|
||||
const holdKey = `${context.marker}-tail-hold`.slice(0, 128)
|
||||
const holdBody = { held: true, chargeable: true, reason: `${context.marker} 暂扣验收`, expectedVersion: Number(representative.version) }
|
||||
const held = await api(context, 'PUT', '暂扣本轮单票尾程订单', orderPath, holdBody, { 'Idempotency-Key': holdKey })
|
||||
context.assert(MODULE, '暂扣只推进单票版本并保留计费原因', held.response,
|
||||
held.data?.held === true && held.data?.chargeable === true
|
||||
&& id(held.data?.orderId) === id(representative.id) && Number(held.data?.version) === Number(representative.version) + 1,
|
||||
trace(held.response), OPTIONS)
|
||||
if (!success(held.response)) return
|
||||
const heldReplay = await api(context, 'PUT', '暂扣命令同键同载荷重放', orderPath, holdBody, { 'Idempotency-Key': holdKey })
|
||||
context.assert(MODULE, '暂扣重放版本零漂移', heldReplay.response,
|
||||
JSON.stringify(heldReplay.data) === JSON.stringify(held.data), trace(heldReplay.response), OPTIONS)
|
||||
const heldConflict = await context.requestOverseas('PUT', orderPath,
|
||||
{ ...holdBody, reason: `${holdBody.reason}-DIFFERENT` }, { 'Idempotency-Key': holdKey }, context.overseasToken)
|
||||
context.addStep(MODULE, '暂扣同键异载荷返回A0409', heldConflict, conflict(heldConflict), trace(heldConflict), OPTIONS)
|
||||
|
||||
const blockedPlanBody = manualPlanBody(representative, held.data.version, context.marker)
|
||||
const blockedPlan = await context.requestOverseas('POST', `${PLANS}/manual`, blockedPlanBody,
|
||||
{ 'Idempotency-Key': `${context.marker}-held-plan`.slice(0, 128) }, context.overseasToken)
|
||||
context.addStep(MODULE, '暂扣尾程订单不能生成人工计划', blockedPlan, conflict(blockedPlan), trace(blockedPlan), OPTIONS)
|
||||
|
||||
const releaseKey = `${context.marker}-tail-release`.slice(0, 128)
|
||||
const releaseBody = { held: false, chargeable: false, reason: `${context.marker} 解除暂扣`, expectedVersion: Number(held.data.version) }
|
||||
const released = await api(context, 'PUT', '解除本轮单票尾程暂扣', orderPath, releaseBody, { 'Idempotency-Key': releaseKey })
|
||||
context.assert(MODULE, '解除暂扣清空计费与原因并推进版本', released.response,
|
||||
released.data?.held === false && released.data?.chargeable === false && released.data?.reason == null
|
||||
&& Number(released.data?.version) === Number(held.data.version) + 1, trace(released.response), OPTIONS)
|
||||
if (!success(released.response)) return
|
||||
const rejectedHold = await context.requestOverseas('PUT', query(
|
||||
`${ORDERS}/${encodeURIComponent(id(representative.id))}/hold`, { customerId: id(representative.customerId) }),
|
||||
{ held: true, chargeable: true, reason: `${context.marker} 入库前禁止暂扣`, expectedVersion: Number(representative.version) },
|
||||
{ 'Idempotency-Key': `${context.marker}-pre-receipt-hold` })
|
||||
context.addStep(MODULE, '入库前暂扣必须拒绝', rejectedHold, conflict(rejectedHold), trace(rejectedHold), OPTIONS)
|
||||
const afterHold = await detail(context, representative, '入库前暂扣拒绝后回查订单')
|
||||
const unchanged = success(afterHold.response) && JSON.stringify(afterHold.data?.order) === JSON.stringify(representative)
|
||||
context.assert(MODULE, '拒绝暂扣后订单事实零漂移', afterHold.response, unchanged, trace(afterHold.response), OPTIONS)
|
||||
if (!conflict(rejectedHold) || !unchanged) return
|
||||
// The positive hold/release lifecycle runs only after PDA receiving.
|
||||
|
||||
const nodesPath = query(`${ORDERS}/${encodeURIComponent(id(representative.id))}/manual-nodes`, {
|
||||
customerId: id(representative.customerId),
|
||||
})
|
||||
const nodesKey = `${context.marker}-tail-manual-nodes`.slice(0, 128)
|
||||
const nodesBody = { expectedVersion: Number(released.data.version), nodes: completeManualNodes(context.marker) }
|
||||
const nodesBody = { expectedVersion: Number(representative.version), nodes: completeManualNodes(context.marker) }
|
||||
const nodes = await api(context, 'PUT', '保存尾程八个人工节点快照', nodesPath, nodesBody,
|
||||
{ 'Idempotency-Key': nodesKey })
|
||||
context.assert(MODULE, '人工节点永久切换MANUAL且完整返回八行', nodes.response,
|
||||
nodes.data?.manualOverrideEnabled === true && nodes.data?.nodes?.length === 8
|
||||
&& nodes.data.nodes.every((node) => node?.source === 'MANUAL')
|
||||
&& Number(nodes.data?.version) === Number(released.data.version) + 1,
|
||||
&& Number(nodes.data?.version) === Number(representative.version) + 1,
|
||||
`nodes=${nodes.data?.nodes?.length ?? 'missing'}; ${trace(nodes.response)}`, OPTIONS)
|
||||
if (!success(nodes.response)) return
|
||||
const nodesReplay = await api(context, 'PUT', '人工节点同键同载荷重放', nodesPath, nodesBody,
|
||||
|
||||
Reference in New Issue
Block a user