fix(order): preserve submitted review status

This commit is contained in:
2026-09-02 12:19:46 +08:00
parent 9e70f4339a
commit a4d8fa9f8b
6 changed files with 204 additions and 24 deletions
+61 -3
View File
@@ -25,6 +25,23 @@ function rotate(values, offset) {
return [...values.slice(shift), ...values.slice(0, shift)]
}
function key(context, operation) { return `${context.marker}-${operation}`.slice(0, 128) }
function declarationCargo(source, index) {
const number = (value) => Number.isFinite(Number(value)) ? Number(value) : 0
const optionalNumber = (value) => value === null || value === undefined || value === '' ? null : number(value)
return {
itemNo: number(source?.itemNo) || index + 1,
cargoName: String(source?.cargoName || ''), cargoNameEn: source?.cargoNameEn || null,
skuNo: source?.skuNo || null, model: source?.model || null,
packageCount: number(source?.packageCount), totalQuantity: number(source?.totalQuantity),
lengthCm: number(source?.lengthCm), widthCm: number(source?.widthCm), heightCm: number(source?.heightCm),
grossWeightKg: number(source?.grossWeightKg), volumeCbm: number(source?.volumeCbm),
netWeightKg: optionalNumber(source?.netWeightKg), hsCode: source?.hsCode || null,
customsHsCode: source?.customsHsCode || null, unitsPerPackage: optionalNumber(source?.unitsPerPackage),
unitDeclaredValue: optionalNumber(source?.unitDeclaredValue), declaredValue: optionalNumber(source?.declaredValue),
currency: source?.currency || null, material: source?.material || null, usage: source?.usage || null,
brand: source?.brand || null, cargoRemark: source?.cargoRemark || source?.remark || null,
}
}
export function orderPersistenceFacts(detail) {
return JSON.stringify({
order: detail?.order ?? null,
@@ -353,7 +370,7 @@ function buildPayload(context, profile, master, productImageFileId) {
const selectedBoxes = BOXES.slice(0, skuCount)
const orderProfile = context.context?.orderProfile || {}
const isPrivate = master.destinationType === 'PRIVATE'
const pickupMethod = orderProfile.pickupMethod || 'PICKUP'
const pickupMethod = orderProfile.pickupMethod || 'SELF_EXPRESS'
const receiver = isPrivate ? {
companyName: `${companyName} 私人收件人`, contactName: `收件人-${context.marker}`.slice(0, 64),
phone: '12025550188', email: 'private-receiver@example.com', countryCode: 'US',
@@ -405,7 +422,7 @@ function buildPayload(context, profile, master, productImageFileId) {
shipmentId: master.destinationType === 'FBA' ? shipmentId : null,
referenceId: master.destinationType === 'FBA' ? referenceId : null,
upcNo: `${Date.now()}${index}`.slice(-12),
productImageFileId, dangerousGoods: false,
productImageFileId, dangerousGoods: false, woodenProduct: false,
cargoRemark: `${context.marker} boxType=${box.boxType}`,
}
}),
@@ -665,9 +682,50 @@ export async function run(context) {
pageOk(inboundPage) && records(inboundPage).some((row) => id(row.id) === inboundId),
`inboundId=${inboundId}, total=${inboundPage?.total ?? 'n/a'}`)
const editableDetailResponse = await context.request('GET', firstLegDetailPath)
const editableDetail = context.apiSuccess(MODULE, 'Admin 读取审核后客户申报资料', editableDetailResponse)
const declarationVersion = Number(editableDetail?.order?.version)
const declarationRemark = `${context.marker} Admin 修改客户申报资料`
const declarationPayload = {
expectedVersion: declarationVersion,
customerRemark: declarationRemark,
expectedArrivalAt: editableDetail?.order?.expectedArrivalAt || editableDetail?.summary?.expectedArrivalAt || null,
channelCode: editableDetail?.order?.channelCode || editableDetail?.summary?.channelCode,
channelName: editableDetail?.order?.channelName || editableDetail?.summary?.channelName,
cargoes: (editableDetail?.cargoes || []).map(declarationCargo),
}
const declarationUpdateResponse = await context.request('PUT',
`/api/platform/v1/orders/${encodeURIComponent(orderId)}/declaration?tenantId=${encodeURIComponent(tenantId)}`,
declarationPayload)
const declarationUpdate = context.apiSuccess(MODULE, 'Admin 修改审核后客户申报资料', declarationUpdateResponse)
context.assert(MODULE, '申报修改保持订单号入仓码和渠道且版本递增', declarationUpdateResponse,
Number.isFinite(declarationVersion) && Number(declarationUpdate?.version) === declarationVersion + 1
&& id(declarationUpdate?.inboundCode) === id(inbound.summary.inboundCode)
&& declarationUpdate?.channelChanged === false,
`version=${declarationVersion}->${declarationUpdate?.version ?? 'missing'}, inboundCode=${declarationUpdate?.inboundCode ?? 'missing'}`,
CONTRACT_OPTIONS)
const staleDeclarationResponse = await context.request('PUT',
`/api/platform/v1/orders/${encodeURIComponent(orderId)}/declaration?tenantId=${encodeURIComponent(tenantId)}`,
{ ...declarationPayload, customerRemark: `${declarationRemark} stale` })
context.assert(MODULE, '申报资料旧版本并发修改返回A0409', staleDeclarationResponse,
staleDeclarationResponse.http === 200 && String(staleDeclarationResponse.body?.code) === 'A0409',
`code=${staleDeclarationResponse.body?.code ?? 'missing'}`, CONTRACT_OPTIONS)
let declarationConverged = false
let convergedInboundResponse = inboundResponse
for (let attempt = 0; attempt < 30; attempt += 1) {
convergedInboundResponse = await context.request('GET', inboundPath)
const currentInbound = success(convergedInboundResponse) ? convergedInboundResponse.body?.data : null
if (currentInbound?.publicRemark === declarationRemark) { declarationConverged = true; break }
if (attempt < 29) await sleep(1_000)
}
context.assert(MODULE, '申报修改异步同步到Firstleg入库事实', convergedInboundResponse,
declarationConverged, `expectedRemark=${declarationRemark}`, CONTRACT_OPTIONS)
context.createdResources.orders.inboundId = inboundId
context.createdResources.orders.inboundCode = inbound.summary.inboundCode
context.createdResources.orders.customerRemark = payload.customerRemark
context.createdResources.orders.customerRemark = declarationRemark
context.createdResources.orders.internalRemark = `${context.marker} Admin 订单链路验收`
context.createdResources.orders.cargoRemark = payload.cargoes?.[0]?.cargoRemark || null
context.createdResources.orders.processStatus = inbound.summary.processStatus