This commit is contained in:
2026-08-15 12:12:34 +08:00
parent 08187363a1
commit 3a9558bd1c
9 changed files with 159 additions and 11 deletions
@@ -25,6 +25,23 @@ function hasTrace(response) {
&& typeof response?.traceId === 'string' && response.traceId.length > 0
}
const BOOKING_TRANSPORT_FIELDS = [
'billOfLadingNo', 'vesselName', 'voyageNo', 'estimatedSailingAt', 'estimatedArrivalAt',
]
function bookingTransportSnapshot(value) {
return Object.fromEntries(BOOKING_TRANSPORT_FIELDS.map((field) => [field, value?.[field] ?? null]))
}
function completeBookingTransport(snapshot) {
return BOOKING_TRANSPORT_FIELDS.every((field) => typeof snapshot?.[field] === 'string'
&& snapshot[field].trim().length > 0)
}
function sameBookingTransport(left, right) {
return BOOKING_TRANSPORT_FIELDS.every((field) => left?.[field] === right?.[field])
}
async function request(context, method, path, body, headers = {}, token = context.token) {
try {
const response = await fetch(`${context.options.gateway}${path}`, {
@@ -131,7 +148,7 @@ async function loadOneFragment(context, state) {
const { tenantId, rootOrderId, sourceOrderId, sourceOrderNo, warehouseId, sourcePackageCount, sequence } = state
const operationBase = `${context.marker}-chain-${sequence}`.slice(0, 100)
const simulationResponse = await request(context, 'POST', CONTAINERS, {
channelCode: state.channelCode, warehouseId, containerType: '40HQ', capacityCbm: 100, maxWeightKg: 100000,
channelCode: state.channelCode, warehouseId, containerType: '40HQ', capacityCbm: 68, maxWeightKg: 28000,
})
const simulation = context.apiSuccess(MODULE, `为 ${sourceOrderNo} 新增内部模拟柜`, simulationResponse, '', OPTIONS)
const containerId = id(simulation?.id)
@@ -221,12 +238,24 @@ async function loadOneFragment(context, state) {
`oceanBookingId=${id(bookingDetail?.oceanBooking?.id) || 'missing'}, containerBookingId=${containerId}, allocations=${bookingDetail?.containerAllocations?.length ?? 'n/a'}`, OPTIONS)
if (!allocationMatches || id(bookingDetail?.oceanBooking?.id) !== oceanBookingId) return null
const createdTransport = bookingTransportSnapshot(bookingCreated?.oceanBooking)
const persistedTransport = bookingTransportSnapshot(bookingDetail?.oceanBooking)
const transportFrozen = completeBookingTransport(createdTransport)
&& completeBookingTransport(persistedTransport)
&& sameBookingTransport(createdTransport, persistedTransport)
context.assert(MODULE, `${sourceOrderNo} 创建响应与详情五项运输字段冻结一致`, bookingDetailResponse,
transportFrozen,
BOOKING_TRANSPORT_FIELDS.map((field) => `${field}=${persistedTransport[field] || 'missing'}`).join(', '), OPTIONS)
if (!transportFrozen) return null
if (bookingDetail.oceanBooking.status === 'CONFIRMED') {
const releaseResponse = await request(context, 'POST', `${bookingPath}/release`, {
expectedVersion: Number(bookingDetail.oceanBooking.version),
billOfLadingNo: `BL-${operationBase}`.slice(0, 128),
vesselName: `SPLIT-VESSEL-${sequence}`.slice(0, 128), voyageNo: `SV-${sequence}`.slice(0, 64),
estimatedSailingAt: '2026-09-16T08:00:00', estimatedArrivalAt: '2026-10-16T08:00:00',
billOfLadingNo: persistedTransport.billOfLadingNo,
vesselName: persistedTransport.vesselName,
voyageNo: persistedTransport.voyageNo,
estimatedSailingAt: persistedTransport.estimatedSailingAt,
estimatedArrivalAt: persistedTransport.estimatedArrivalAt,
reason: context.marker,
}, { 'Idempotency-Key': `${operationBase}-booking-release`.slice(0, 128) })
context.apiSuccess(MODULE, `放舱 ${sourceOrderNo} 的真实订舱并满足 PDA 门禁`, releaseResponse, '', OPTIONS)