test(fba): preserve verified fleet and fulfillment acceptance workflows

This commit is contained in:
2026-10-03 06:26:33 +08:00
parent c55bd7f4b6
commit d858357c5d
52 changed files with 4217 additions and 103 deletions
@@ -1,4 +1,5 @@
import { readFile, writeFile } from 'node:fs/promises'
import { controlledPalletMeasurements } from './admin-test-env-modules/fleet-trip-fulfillment.mjs'
const domestic = process.env.ADMIN_TEST_GATEWAY || 'http://127.0.0.1:9000'
const overseas = process.env.ADMIN_OVERSEAS_GATEWAY || 'http://127.0.0.1:9300'
@@ -50,14 +51,7 @@ const pdaToken = directPdaToken || pdaLogin.overseasAccessToken
let task = await api(overseas, pdaToken, 'GET', `/api/pda/v1/last-leg/dispatches/${dispatchNo}`)
let alreadyDeparted = task.status === 'DEPARTED'
|| (task.status === 'COMPLETED' && String(task.departBlockReason || '').includes('已发车'))
if (!alreadyDeparted && task.status === 'PENDING') {
await api(overseas, platformToken, 'PUT', `/api/platform/v1/last-leg/dispatches/${dispatchNo}`, {
vehiclePlate: `UAT-${marker.slice(-8)}`, driverName: '尾程验收司机', driverPhone: '19900000000',
carrierName: '尾程验收车队', route: `${marker}-ROUTE`,
estimatedArrivalAt: new Date(Date.now() + 86400000).toISOString(),
})
}
assert(alreadyDeparted || task.tripNo, 'Prepare and bind a qualified fleet trip before running retained dispatch fulfillment')
const existingPage = await api(overseas, platformToken, 'GET',
`/api/platform/v1/last-leg/delivery-orders?customerId=${customerId}&page=1&size=20&dispatchNo=${encodeURIComponent(dispatchNo)}`)
const existingDeliveries = (existingPage.records || []).filter((value) => value.dispatchNo === dispatchNo)
@@ -78,7 +72,6 @@ const transfer = existingDeliveries.length > 0 ? {
idempotencyKey: key('TRANSFER'), plannedDeliveryAt: new Date(Date.now() + 172800000).toISOString(),
deliveryMethod: 'TRUCK_PALLET', waybillNo: `${marker}-WAYBILL`, carrierName: '尾程验收车队',
pickupMethod: 'WAREHOUSE_PICKUP', loadingType: 'PALLET', vehicleType: 'TRUCK', vehicleSize: '15托',
driverName: '尾程验收司机', driverPhone: '19900000000', vehiclePlate: `UAT-${marker.slice(-8)}`,
appointmentAccount: 'SELF', remark: marker, fees: [{ feeType: 'DELIVERY_FEE', feeName: '派送费',
direction: 'RECEIVABLE', currency: 'CNY', amount: 10, remark: marker }],
})
@@ -93,14 +86,6 @@ const expectedPdaItems = scenario.partialRelabel ? 1 : 2
assert(Array.isArray(task.items) && task.items.length === expectedPdaItems,
`Expected ${expectedPdaItems} PDA pallet items`)
if (!alreadyDeparted) {
if (task.items.every(item => Number(item.pickedPackages) === 0)) {
await api(overseas, platformToken, 'PUT', `/api/platform/v1/last-leg/dispatches/${dispatchNo}`, {
vehiclePlate: `UAT-${marker.slice(-8)}`, driverName: '尾程验收司机', driverPhone: '19900000000',
carrierName: '尾程验收车队', fbaAppointmentNo: `UAT-${marker.slice(-8)}`,
fbaAppointmentStatus: 'CONFIRMED', vehicleAppointmentStatus: 'CONFIRMED',
estimatedArrivalAt: new Date(Date.now() + 172800000).toISOString().slice(0, 19),
})
}
for (const [itemIndex, item] of task.items.entries()) {
let remaining = Number(item.scheduledPackages) - Number(item.pickedPackages)
for (const [positionIndex, position] of item.positions.entries()) {
@@ -118,7 +103,6 @@ if (!alreadyDeparted) {
}
task = await api(overseas, pdaToken, 'GET', `/api/pda/v1/last-leg/dispatches/${dispatchNo}`)
alreadyDeparted = task.status === 'DEPARTED'
|| (task.status === 'COMPLETED' && String(task.departBlockReason || '').includes('已发车'))
}
if (!alreadyDeparted && task.status !== 'COMPLETED') {
const pickingCompleted = await api(overseas, pdaToken, 'POST',
@@ -127,12 +111,21 @@ if (!alreadyDeparted && task.status !== 'COMPLETED') {
task = await api(overseas, pdaToken, 'GET', `/api/pda/v1/last-leg/dispatches/${dispatchNo}`)
}
assert(alreadyDeparted || task.status === 'COMPLETED', 'Dispatch did not finish picking')
const departed = alreadyDeparted ? {
status: 'DEPARTED',
shippedPackages: task.items.reduce((total, item) => total + Number(item.pickedPackages), 0),
} : await api(overseas, pdaToken, 'POST',
`/api/pda/v1/last-leg/dispatches/${dispatchNo}/depart`, { idempotencyKey: key('DEPART'), remark: marker })
assert(departed.status === 'DEPARTED', 'Dispatch did not reach DEPARTED')
if (!alreadyDeparted) {
const tripPath = `/api/platform/v1/last-leg/fleet/trips/${encodeURIComponent(task.tripNo)}`
const trip = await api(overseas, platformToken, 'GET', tripPath)
const loading = await api(overseas, platformToken, 'GET', `${tripPath}/loading`)
assert(!loading.blockReason, `Trip not ready: ${loading.blockReason}`)
const confirmed = await api(overseas, platformToken, 'POST', `${tripPath}/loading`, {
recordVersion: loading.recordVersion, manifestHash: loading.manifestHash,
pallets: controlledPalletMeasurements(loading.cargo, trip.trip.stops), reason: '受控测试测量,每实托100kg/1m³/1托位',
})
const departed = await api(overseas, pdaToken, 'POST', `/api/pda/v1/last-leg/dispatches/${dispatchNo}/depart`,
{ recordVersion: confirmed.recordVersion, idempotencyKey: key('DEPART').slice(0,128), remark: marker })
assert(departed.status === 'IN_TRANSIT' && departed.dispatches?.some(item => item.dispatchNo === dispatchNo), 'Whole-trip departure missing dispatch')
}
const departedDispatch = await api(overseas, platformToken, 'GET', `/api/platform/v1/last-leg/dispatches/${dispatchNo}`)
assert(departedDispatch.status === 'DEPARTED', 'Dispatch did not reach DEPARTED')
const outbound = await api(overseas, platformToken, 'GET',
`/api/platform/v1/last-leg/outbound-orders/${transfer.outboundNo}?page=1&size=20`)
@@ -176,9 +169,9 @@ const visit = (visits.records || []).find((value) => value.deliveryNo === delive
assert(visit?.status === 'PENDING', 'Delivery completion did not create a pending customer visit')
const report = { marker, scope: 'OVERSEAS_LASTLEG_ONLY', sourceReport, relabelNo: scenario.relabelNo,
dispatchNo, dispatchStatus: departed.status, outboundNo: transfer.outboundNo,
dispatchNo, dispatchStatus: departedDispatch.status, outboundNo: transfer.outboundNo,
outboundStatus: outbound.outbound.status, deliveryNo,
deliveryStatus: delivery.order.status, visitId: id(visit.id), shippedPackages: departed.shippedPackages,
deliveryStatus: delivery.order.status, visitId: id(visit.id), shippedPackages: departedDispatch.shippedPackageCount,
passed: true, finishedAt: new Date().toISOString() }
await writeFile(output, JSON.stringify(report, null, 2), 'utf8')
console.log(JSON.stringify(report, null, 2))