优化
This commit is contained in:
@@ -25,9 +25,9 @@ const id = value => value == null ? '' : String(value)
|
||||
const success = response => response?.http === 200 && id(response?.body?.code) === '200'
|
||||
const key = () => `fleet-${randomUUID()}`
|
||||
const NATIVE_PROTOCOL = 'NATIVE_DISPATCH_V1'
|
||||
const nativeDeparture = (value, dispatchNo) => value?.action === 'DEPART' && value.dispatchNo === dispatchNo
|
||||
&& value.status === 'ACTIVE' && value.stage === 'DELIVERING' && Number.isFinite(Date.parse(value.result?.departedAt))
|
||||
&& Number.isSafeInteger(Number(value.result.shippedPackages)) && Number(value.result.shippedPackages) > 0
|
||||
const nativeDeparture = (value, dispatchNo) => value?.action === 'LOADING_COMPLETE' && value.dispatchNo === dispatchNo
|
||||
&& value.status === 'ACTIVE' && value.stage === 'DELIVERING' && value.result?.loadingCompletionHash
|
||||
&& Number.isFinite(Date.parse(value.result.loadingCompletedAt)) && value.result.confirmedLoad?.manifestHash
|
||||
const instant = value => typeof value === 'string' && /^\d{4}-\d\d-\d\dT\d\d:\d\d(?::\d\d(?:\.\d+)?)?$/.test(value) ? `${value}Z` : value
|
||||
const sameInstant = (a, b) => Number.isFinite(Date.parse(instant(a))) && Date.parse(instant(a)) === Date.parse(instant(b))
|
||||
const deliveryFacts = rows => JSON.stringify(rows.map(row => [id(row.customerId), row.deliveryNo, row.outboundNo, Number(row.packageCount)]).sort())
|
||||
@@ -342,15 +342,12 @@ export function reviewedFullCheckpoint(report, stage = 'FULL_COVERAGE') {
|
||||
|| resources.fleetFeeCoverageCases.length !== 2 || !proof.originalDispatch?.detail || proof.originalDispatch.detail.dispatchNo !== proof.dispatchNo)
|
||||
throw Error('Only a reviewed read-only FULL_COVERAGE failure can resume; mutated/unknown outcomes require case-specific reconciliation')
|
||||
const persisted = stage === 'FULL_COVERAGE_PERSISTED'
|
||||
if (persisted ? (!full.proof.outboundNo || !full.proof.deliveryNos?.length || !full.proof.confirmationRequest?.idempotencyKey
|
||||
|| !full.proof.confirmationRequest.groups?.length || full.proof.confirmationRequest.recordVersion == null
|
||||
|| !full.proof.requests.some(row => row.method === 'POST' && row.path === `/api/platform/v1/last-leg/dispatches/${full.dispatchNo}/transfer-delivery`
|
||||
&& row.http === 200 && String(row.code) === '200' && row.status === 'RESPONDED'
|
||||
&& JSON.stringify(row.body) === JSON.stringify(full.proof.confirmationRequest)
|
||||
&& row.result?.action === 'ARRANGE_DELIVERY' && row.result.dispatchNo === full.dispatchNo
|
||||
&& row.result.status === 'ACTIVE' && row.result.stage === 'AFTER_LOADING'
|
||||
&& row.result.result?.outbounds?.some(o => o.outboundNo === full.proof.outboundNo)
|
||||
&& JSON.stringify(row.result.result?.deliveries?.map(d => d.deliveryNo).sort()) === JSON.stringify([...full.proof.deliveryNos].sort())))
|
||||
const fullTrip = resources.fleetTrips.find(row => row.dispatchNo === full.dispatchNo)
|
||||
if (persisted ? (!full.proof.outboundNo || !full.proof.deliveryNos?.length || !fullTrip?.loadingCommand?.body?.idempotencyKey
|
||||
|| !fullTrip.loadingCommand.body.measurements?.length || fullTrip.loadingCommand.body.recordVersion == null
|
||||
|| !nativeDeparture(fullTrip.loadingCommand.result, full.dispatchNo)
|
||||
|| !fullTrip.loadingCommand.afterReplay?.main?.documents?.outbounds?.some(o => o.outboundNo === full.proof.outboundNo)
|
||||
|| JSON.stringify(fullTrip.loadingCommand.afterReplay.main.documents.deliveries.map(d => d.deliveryNo).sort()) !== JSON.stringify([...full.proof.deliveryNos].sort()))
|
||||
: (full.proof.requests.some(row => row.method !== 'GET') || full.proof.outboundNo))
|
||||
throw Error('Mutated/unknown outcomes require the exact successful command and persisted document reconciliation')
|
||||
return { resources, marker: proof.marker, persisted }
|
||||
@@ -373,7 +370,7 @@ export async function verifyFleetTerminalState(context) {
|
||||
const detail=await get(`/api/platform/v1/last-leg/dispatches/${encodeURIComponent(proof.dispatchNo)}`)
|
||||
check('原生主单全部正常派送完成且数量守恒',detail.dispatchNo===proof.dispatchNo&&detail.status==='ACTIVE'&&detail.stage==='DELIVERED'
|
||||
&& Number(detail.counts?.packageCount)===Number(detail.counts?.shippedPackageCount)&&Number(detail.counts?.pickedPackageCount)===Number(detail.counts?.shippedPackageCount)
|
||||
&& Number(detail.counts?.shippedPackageCount)===Number(proof.departure.result.shippedPackages))
|
||||
&& Number(detail.counts?.shippedPackageCount)===Number(proof.departureSnapshot.detail.counts.shippedPackageCount))
|
||||
evidence.dispatches.push(detail)
|
||||
const refs=nativeFleetDeliveries(detail)
|
||||
check('签收证明恰好覆盖主单每客户派送一次',JSON.stringify(proof.receipts.map(r=>`${r.customerId}:${r.deliveryNo}`).sort())===JSON.stringify(refs.map(r=>`${r.customerId}:${r.deliveryNo}`).sort()))
|
||||
@@ -408,7 +405,7 @@ export async function verifyDepartedRecovery(context, { costsAlreadyVerified = f
|
||||
}
|
||||
const current = await get(base)
|
||||
check(current.trip?.status === 'IN_TRANSIT' && id(current.trip.recordVersion) === id(expectedTrip.recordVersion)
|
||||
&& sameInstant(current.trip.departedAt, proof.departure.result.departedAt) && id(current.trip.warehouseId) === id(proof.warehouseId)
|
||||
&& sameInstant(current.trip.departedAt, proof.departureSnapshot.detail.dispatchInfo.departedAt) && id(current.trip.warehouseId) === id(proof.warehouseId)
|
||||
&& id(current.trip.vehicleId) === id(expectedTrip.vehicleId) && id(current.trip.driverId) === id(expectedTrip.driverId)
|
||||
&& !current.trip.vehicleRelease && !current.trip.driverRelease, 'trip version, resources or departure changed')
|
||||
const history = await get(`${base}/history?page=1&size=100`)
|
||||
@@ -474,7 +471,7 @@ export async function verifyDepartedRecovery(context, { costsAlreadyVerified = f
|
||||
&& !order.signedAt&&!Number(order.signedPackages||0)&&!order.completedAt&&order.documentSummary?.categories?.every(r=>Number(r.fileCount)===0),'delivery has started, changed or been signed')
|
||||
evidence.deliveries.push(order)
|
||||
}
|
||||
check(evidence.deliveries.reduce((n,row)=>n+Number(row.packageCount),0)===Number(proof.departure.result.shippedPackages),'delivery quantity mismatch')
|
||||
check(evidence.deliveries.reduce((n,row)=>n+Number(row.packageCount),0)===Number(proof.departureSnapshot.detail.counts.shippedPackageCount),'delivery quantity mismatch')
|
||||
if (createdVehicle) {
|
||||
const vehicle = await get(`/api/platform/v1/last-leg/master-data/vehicles/${encodeURIComponent(createdVehicle.snapshot.id)}`)
|
||||
const canonical = value => value && typeof value === 'object' && !Array.isArray(value)
|
||||
@@ -782,33 +779,18 @@ export async function departNativeFleet(context, trip, pickerToken, run) {
|
||||
if (!pickerToken || !run || run.dispatchNo !== trip.dispatchNo || run.tripNo !== trip.tripNo || run.departureRequest)
|
||||
throw Error('Native departure requires owned main and a new original command')
|
||||
const path = `/api/platform/v1/last-leg/dispatches/${encodeURIComponent(trip.dispatchNo)}`
|
||||
const before = await readNativeFleetBundle(context, trip.dispatchNo)
|
||||
const refs = nativeFleetDeliveries(before.detail)
|
||||
const task = await nativeRequest(context, 'GET', `/api/pda/v1/last-leg/dispatches/${encodeURIComponent(trip.dispatchNo)}`, undefined, pickerToken)
|
||||
if (before.detail.status !== 'ACTIVE' || before.detail.stage !== 'AFTER_LOADING' || task.dispatchNo !== trip.dispatchNo || task.status !== 'ACTIVE' || task.stage !== 'AFTER_LOADING'
|
||||
|| id(task.warehouseId) !== id(trip.warehouseId) || id(task.recordVersion) !== id(before.detail.recordVersion) || task.actions?.DEPART?.allowed !== true
|
||||
|| !before.detail.pickingReconciled || !task.pickingReconciled || Number(before.detail.counts?.packageCount) !== Number(task.counts?.packageCount)
|
||||
|| Number(task.counts?.packageCount) !== Number(task.counts?.pickedPackageCount) || Number(task.counts?.shippedPackageCount) !== 0
|
||||
|| before.items.items.some(row => Number(row.pickedPackages) !== Number(row.scheduledPackages))
|
||||
|| before.items.items.reduce((n,row) => n + Number(row.scheduledPackages), 0) !== Number(task.counts?.packageCount)
|
||||
|| refs.reduce((n,d) => n + Number(d.packageCount), 0) !== Number(task.counts.packageCount)) throw Error('Native main is not fully loaded and arranged for both ends')
|
||||
run.departureRequest = { recordVersion: task.recordVersion, idempotencyKey: key(), remark: 'TEST同一原生主单实际发车,不重复扣库存' }
|
||||
await context.checkpoint?.()
|
||||
const departed = await nativeRequest(context, 'POST', `/api/pda/v1/last-leg/dispatches/${encodeURIComponent(trip.dispatchNo)}/depart`, run.departureRequest, pickerToken)
|
||||
if (!nativeDeparture(departed, trip.dispatchNo) || BigInt(dispatchVersion(departed.recordVersion)) <= BigInt(dispatchVersion(task.recordVersion))
|
||||
|| Number(departed.result.shippedPackages) !== Number(task.counts.packageCount)
|
||||
|| !Array.isArray(departed.result.deliveries) || deliveryFacts(departed.result.deliveries) !== deliveryFacts(refs))
|
||||
throw Error('Native departure did not preserve all customer shipment identities and quantities')
|
||||
run.departure = departed
|
||||
const replayed = await nativeRequest(context, 'POST', `${path}/depart`, run.departureRequest)
|
||||
if (!nativeDeparture(replayed, trip.dispatchNo) || replayed.replayed !== true || id(replayed.recordVersion) !== id(departed.recordVersion) || JSON.stringify(replayed.result) !== JSON.stringify(departed.result))
|
||||
throw Error('Native cross-end departure replay changed the original outcome')
|
||||
run.departureReplay = replayed
|
||||
const after = await readNativeFleetBundle(context, trip.dispatchNo)
|
||||
if (after.detail.status !== 'ACTIVE' || after.detail.stage !== 'DELIVERING' || id(after.detail.recordVersion) !== id(departed.recordVersion)
|
||||
|| Number(after.detail.counts.shippedPackageCount) !== Number(task.counts.packageCount) || Number(after.detail.counts.packageCount) !== Number(task.counts.packageCount)
|
||||
|| Number(after.detail.counts.pickedPackageCount) !== Number(after.detail.counts.shippedPackageCount)
|
||||
|| deliveryFacts(nativeFleetDeliveries(after.detail)) !== deliveryFacts(refs)) throw Error('Native departure readback did not conserve physical quantities')
|
||||
const refs = nativeFleetDeliveries(after.detail), original = trip.loadingCommand
|
||||
if (!nativeDeparture(original?.result, trip.dispatchNo) || !original.body?.idempotencyKey
|
||||
|| after.detail.status !== 'ACTIVE' || after.detail.stage !== 'DELIVERING'
|
||||
|| id(after.detail.recordVersion) !== id(original.result.recordVersion)
|
||||
|| Number(after.detail.counts?.shippedPackageCount) !== Number(after.detail.counts?.packageCount)
|
||||
|| refs.reduce((sum, d) => sum + Number(d.packageCount), 0) !== Number(after.detail.counts.packageCount))
|
||||
throw Error('Automatic loading completion must have an original success receipt and complete real delivery documents')
|
||||
const departed = await nativeRequest(context, 'GET', `/api/pda/v1/last-leg/dispatches/${encodeURIComponent(trip.dispatchNo)}/commands/${encodeURIComponent(original.body.idempotencyKey)}`, undefined, pickerToken)
|
||||
if (!nativeDeparture(departed, trip.dispatchNo) || id(departed.recordVersion) !== id(original.result.recordVersion)
|
||||
|| JSON.stringify(departed.result) !== JSON.stringify(original.result.result)) throw Error('Original loading command readback changed its outcome')
|
||||
run.departureRequest = original.body; run.departure = departed; run.departureReplay = original.replay
|
||||
run.departureSnapshot = after; run.dispatchNos = [trip.dispatchNo]
|
||||
run.departureDeliveries = []
|
||||
for (const ref of nativeFleetDeliveries(after.detail)) {
|
||||
|
||||
Reference in New Issue
Block a user