优化
This commit is contained in:
@@ -8,6 +8,11 @@ const ROOT = '/api/platform/v1/last-leg'
|
||||
const MERCHANT = '/api/merchant/v1/last-leg/warehouse-transfers'
|
||||
const OPTIONS = { scenario: MODULE, deploymentBlocker: true }
|
||||
const id = value => value == null ? '' : String(value)
|
||||
export function safeFixtureCount(value) {
|
||||
if (!['number', 'string'].includes(typeof value) || !/^(0|[1-9]\d*)$/.test(String(value))
|
||||
|| !Number.isSafeInteger(Number(value))) throw new Error('原生夹具数量须为非负安全整数')
|
||||
return Number(value)
|
||||
}
|
||||
const encode = encodeURIComponent
|
||||
const ok = response => response?.http === 200 && id(response.body?.code) === '200'
|
||||
const buckets = ['availablePackages', 'holdPackages', 'allocatedPackages', 'pickedPackages', 'receivingPackages']
|
||||
@@ -22,7 +27,7 @@ const localTime = delay => {
|
||||
export const preparationContract = Object.freeze({
|
||||
stage: fixtureContract.stage,
|
||||
inputs: 'execute:true, current-run context, warehouseId (public active OVERSEAS with RECEIVING), destinationWarehouseId (public active FBA), pdaToken bound to warehouseId, readInventory(scope) returning all raw balances/positions/ledger with CUSTOMER_WAREHOUSE_COMPLETE scope',
|
||||
writes: 'Two fresh qualified customers; one ordinary WarehouseTransfer and one PDA-measured pallet/box per customer; two dispatches, one shared trip with a test vehicle/qualified driver, two outbounds and deliveries. No picking.',
|
||||
writes: 'Two fresh qualified customers; one ordinary WarehouseTransfer and one PDA-measured pallet/box per customer; one native cross-customer dispatch with one automatic Fleet resource record and a TEST vehicle/qualified driver; both reviews approved. No picking or delivery arrangement yet.',
|
||||
lifecycle: 'Caller creates/disables PDA identity and supplies raw readFleetInventory for verification. This helper logs out its own merchant sessions, retains all business fixtures, and refuses automatic retry. No SQL, environment files or external bookings.',
|
||||
})
|
||||
|
||||
@@ -59,8 +64,8 @@ export async function createFleetCrossCustomerFixture(context, { execute = false
|
||||
inboundCode: member.incomingNo, page: '1', size: '200' })
|
||||
const grouped = await request('GET', `${ROOT}/inventory/balances?${query}`, undefined, 'Read exact fresh receipt balance page')
|
||||
const ledger = await request('GET', `${ROOT}/inventory/ledger?${query}&businessOrderNo=${encode(member.incomingNo)}`, undefined, 'Read exact receipt movement page')
|
||||
check('Fresh one-box receipt has one complete balance and movement page', grouped?.records?.length === 1 && Number(grouped.total) === 1
|
||||
&& ledger?.records?.length === 1 && Number(ledger.total) === 1 && id(grouped.records[0].id))
|
||||
check('Fresh one-box receipt has one complete balance and movement page', grouped?.records?.length === 1 && safeFixtureCount(grouped.total) === 1
|
||||
&& ledger?.records?.length === 1 && safeFixtureCount(ledger.total) === 1 && id(grouped.records[0].id))
|
||||
const path = `${ROOT}/inventory/balances/${encode(grouped.records[0].id)}`
|
||||
const balance = await request('GET', `${path}?${own(member)}`, undefined, 'Read original raw balance identity')
|
||||
const positions = await request('GET', `${path}/positions?${own(member)}`, undefined, 'Read original raw physical position')
|
||||
@@ -146,7 +151,7 @@ export async function createFleetCrossCustomerFixture(context, { execute = false
|
||||
destinationWarehouseCode: destination.warehouse.warehouseCode, destinationWarehouseName: destination.warehouse.warehouseName,
|
||||
deliveryAddress, packageCount: 1, volumeCbm: 1, deliveryMethod: 'CUSTOMER_DELIVERY', estimatedArrivalAt: localTime(1800000),
|
||||
needRelabel: false, remark: member.customerMarker, idempotencyKey: key(`CREATE-${suffix}`),
|
||||
items: [{ skuCode: `CROSS-${key(suffix).slice(0, 16)}`, productNameZh: '受控测试一箱货物', packageCount: 1 }] }
|
||||
items: [{ skuCode: `CROSS-${key(suffix).slice(0, 16)}`, productNameZh: '受控测试一箱货物', packageCount: 1, quantity: 1 }] }
|
||||
let incoming = await request('POST', MERCHANT, createBody, `Create new incoming ${suffix}`, auth.accessToken)
|
||||
member.incomingNo = incoming?.transferNo
|
||||
check('Ordinary transfer creates fresh incoming without borrowed source inventory', member.incomingNo && incoming.inboundCode === member.incomingNo
|
||||
@@ -162,8 +167,14 @@ export async function createFleetCrossCustomerFixture(context, { execute = false
|
||||
check('PDA task is untouched and belongs to the requested receiving warehouse', task?.transferNo === member.incomingNo
|
||||
&& task.inboundCode === member.incomingNo && id(task.operatingWarehouseId) === id(warehouseId)
|
||||
&& task.status === 'WAIT_PDA_RECEIVING' && task.pallets?.length === 0)
|
||||
const measured = await request('POST', `${pdaPath}/pallets/drafts`, { idempotencyKey: key(`MEASURE-${suffix}`),
|
||||
cartonCount: 1, lengthCm: 100, widthCm: 100, heightCm: 100, volumeCbm: 1, grossWeightKg: 100 }, 'Measure one real test pallet', pdaToken)
|
||||
const forecastItem = task.items?.[0], forecastCarton = task.cartons?.[0]
|
||||
check('One original forecast carton and declared SKU belong to this fresh one-box incoming', safeFixtureCount(task.packageCount) === 1
|
||||
&& task.items?.length === 1 && forecastItem?.id && forecastItem.skuCode === createBody.items[0].skuCode
|
||||
&& safeFixtureCount(forecastItem.packageCount) === 1 && safeFixtureCount(forecastItem.quantity) === 1
|
||||
&& task.cartons?.length === 1 && forecastCarton?.cartonMark
|
||||
&& (forecastCarton.transferItemId == null || id(forecastCarton.transferItemId) === id(forecastItem.id)))
|
||||
// PalletDraft creates only an empty identity; measurements belong to the real carton-count command below.
|
||||
const measured = await request('POST', `${pdaPath}/pallets/drafts`, { idempotencyKey: key(`MEASURE-${suffix}`) }, 'Create empty TEST pallet draft', pdaToken)
|
||||
check('Measurement created one pallet draft', measured?.pallets?.length === 1 && measured.pallets[0].id && measured.pallets[0].status === 'DRAFT')
|
||||
const palletPath = `${pdaPath}/pallets/${encode(measured.pallets[0].id)}`
|
||||
const generated = await request('POST', `${palletPath}/generate`, { idempotencyKey: key(`GENERATE-${suffix}`) }, 'Generate authoritative warehouse pallet', pdaToken)
|
||||
@@ -171,12 +182,32 @@ export async function createFleetCrossCustomerFixture(context, { execute = false
|
||||
check('Generated physical pallet has real references', generated?.pallets?.length === 1 && pallet.status === 'GENERATED' && pallet.warehousePalletId && pallet.palletNo)
|
||||
member.palletId = id(pallet.warehousePalletId); member.palletNo = pallet.palletNo
|
||||
const bound = await request('POST', `${palletPath}/bind`, { palletCode: member.palletNo, idempotencyKey: key(`BIND-${suffix}`) }, 'Bind scanned physical pallet', pdaToken)
|
||||
check('Bound pallet is exactly the measured one-box pallet', bound?.pallets?.length === 1 && bound.pallets[0].status === 'BOUND'
|
||||
&& id(bound.pallets[0].warehousePalletId) === member.palletId && Number(bound.pallets[0].cartonCount) === 1)
|
||||
check('Bound pallet is exactly the generated empty physical pallet before carton counting', bound?.pallets?.length === 1 && bound.pallets[0].status === 'BOUND'
|
||||
&& id(bound.pallets[0].id) === id(measured.pallets[0].id)
|
||||
&& id(bound.pallets[0].warehousePalletId) === member.palletId && safeFixtureCount(bound.pallets[0].cartonCount) === 0)
|
||||
const counted = await request('POST', `${pdaPath}/cartons/count`, { idempotencyKey: key(`COUNT-${suffix}`),
|
||||
forecastPackageCount: safeFixtureCount(task.packageCount), boxes: [{ cartonMark: forecastCarton.cartonMark,
|
||||
transferItemId: id(forecastItem.id), transferPalletId: id(measured.pallets[0].id),
|
||||
length: 100, width: 100, height: 100, weight: 100,
|
||||
items: [{ skuCode: forecastItem.skuCode, quantity: safeFixtureCount(forecastItem.quantity) }] }] },
|
||||
'Count original TEST carton, record dimensions/SKU and allocate it to the bound pallet', pdaToken)
|
||||
const countedCarton = counted?.cartons?.[0], countedPallet = counted?.pallets?.[0]
|
||||
check('Actual carton count proves one declared box/SKU on the original bound pallet', counted?.transferNo === member.incomingNo
|
||||
&& counted.cartons?.length === 1 && countedCarton.cartonMark === forecastCarton.cartonMark
|
||||
&& countedCarton.status === 'COUNTED' && countedCarton.countedAt
|
||||
&& id(countedCarton.transferPalletId) === id(measured.pallets[0].id)
|
||||
&& id(countedCarton.transferItemId) === id(forecastItem.id)
|
||||
&& ['length', 'width', 'height', 'weight'].every(field => Number(countedCarton[field]) === 100)
|
||||
&& safeFixtureCount(countedCarton.quantity) === 1 && countedCarton.items?.length === 1
|
||||
&& countedCarton.items[0].skuCode === forecastItem.skuCode
|
||||
&& id(countedCarton.items[0].transferItemId) === id(forecastItem.id) && safeFixtureCount(countedCarton.items[0].quantity) === 1
|
||||
&& counted.pallets?.length === 1 && countedPallet.status === 'BOUND' && id(countedPallet.id) === id(measured.pallets[0].id)
|
||||
&& id(countedPallet.warehousePalletId) === member.palletId && safeFixtureCount(countedPallet.cartonCount) === 1
|
||||
&& Number(countedPallet.grossWeightKg) === 100 && Number(countedPallet.volumeCbm) === 1)
|
||||
const photoPath = `${pdaPath}/measurement-photos/files`
|
||||
const photo = record('POST', photoPath, undefined, await context.requestMultipart('POST', photoPath,
|
||||
{ name: `${member.customerMarker}-TEST-MEASUREMENT.png`, type: 'image/png', content: testImage }, pdaToken), 'Upload TEST measurement evidence')
|
||||
check('Measurement evidence is a stored file', photo?.fileId && Number(photo.sizeBytes) > 0)
|
||||
check('Measurement evidence is a stored file', photo?.fileId && safeFixtureCount(photo.sizeBytes) > 0)
|
||||
incoming = await request('POST', `${pdaPath}/palletize`, { idempotencyKey: key(`PALLETIZE-${suffix}`), photoFileIds: [id(photo.fileId)] }, 'Complete real PDA receipt', pdaToken)
|
||||
check('Real PDA receipt completed with original physical pallet', incoming?.status === 'WAIT_CUSTOMER_CONFIRMATION'
|
||||
&& incoming.pallets?.length === 1 && incoming.pallets[0].status === 'COMPLETED' && id(incoming.pallets[0].warehousePalletId) === member.palletId)
|
||||
@@ -184,73 +215,51 @@ export async function createFleetCrossCustomerFixture(context, { execute = false
|
||||
check('Customer confirmation makes ordinary incoming dispatchable', incoming?.transferNo === member.incomingNo && incoming.status === 'READY_FOR_DISPATCH')
|
||||
member.receipt = await stock(member)
|
||||
member.balanceId = id(member.receipt.balance.id); member.positionId = id(member.receipt.positions[0].id); member.receiptVerified = true
|
||||
const dispatchBase = `${ROOT}/dispatches`
|
||||
const candidates = await request('GET', `${dispatchBase}/candidates?${new URLSearchParams({ sourceStage: 'RECEIVED', orderNo: member.incomingNo })}`, undefined, 'Read own real received dispatch candidate')
|
||||
check('Candidate has exact customer, incoming, warehouse and physical pallet ownership', candidates?.length === 1
|
||||
&& id(candidates[0].customerId) === member.customerId && id(candidates[0].overseasWarehouseId) === id(warehouseId)
|
||||
&& candidates[0].inboundCode === member.incomingNo && id(candidates[0].warehousePalletId) === member.palletId
|
||||
&& candidates[0].palletNo === member.palletNo && candidates[0].sourceStage === 'RECEIVED' && Number(candidates[0].packageCount) === 1 && candidates[0].planPalletId)
|
||||
member.draftToken = key(`DRAFT-${suffix}`)
|
||||
const container = await request('POST', `${dispatchBase}/drafts/containers`, { draftToken: member.draftToken, capacity: 30 }, 'Create isolated dispatch draft')
|
||||
check('Dispatch draft has explicit container identity', container?.id)
|
||||
member.draftContainerId = id(container.id)
|
||||
await request('POST', `${dispatchBase}/draft-locks/lock`, { planPalletId: id(candidates[0].planPalletId), draftToken: member.draftToken,
|
||||
draftContainerId: member.draftContainerId }, 'Lock this customer received pallet')
|
||||
const dispatch = await request('POST', `${dispatchBase}/pre-arrange`, { planPalletIds: [id(candidates[0].planPalletId)], draftToken: member.draftToken }, 'Prearrange one independent customer dispatch')
|
||||
check('Dispatch contains exactly this unpicked pallet', dispatch?.dispatchNo && dispatch.status === 'PENDING_DEPARTURE'
|
||||
&& dispatch.items?.length === 1 && id(dispatch.items[0].warehousePalletId) === member.palletId
|
||||
&& Number(dispatch.packageCount) === 1 && Number(dispatch.pickedPackageCount) === 0 && Number(dispatch.shippedPackageCount) === 0)
|
||||
member.dispatchNo = dispatch.dispatchNo
|
||||
member.measurementReceipt = { sourceBusinessNo: member.incomingNo, syntheticTestMaterials: true, countedCarton,
|
||||
sourceType: 'WAREHOUSE_TRANSFER_PDA', finalizedPallet: incoming.pallets?.find(row => id(row.warehousePalletId) === member.palletId) }
|
||||
const candidates = await request('GET', `${ROOT}/dispatches/candidates?${new URLSearchParams({ warehouseId: id(warehouseId), orderNo: member.incomingNo })}`,
|
||||
undefined, 'Read own native received source selection')
|
||||
check('Candidate list is complete and has exact customer, incoming, warehouse and physical pallet ownership', candidates?.complete === true
|
||||
&& candidates.candidates?.length === 1 && id(candidates.candidates[0].customerId) === member.customerId
|
||||
&& id(candidates.candidates[0].warehouseId) === id(warehouseId) && candidates.candidates[0].inboundCode === member.incomingNo
|
||||
&& candidates.candidates[0].palletNo === member.palletNo && safeFixtureCount(candidates.candidates[0].availablePackages) === 1
|
||||
&& candidates.candidates[0].selection?.sourceType === 'INBOUND_PLAN' && candidates.candidates[0].selection.planPalletId
|
||||
&& candidates.candidates[0].sourceVersion && candidates.candidates[0].selection.sourceVersion === candidates.candidates[0].sourceVersion
|
||||
&& candidates.candidates[0].blockReasons?.length === 0)
|
||||
member.selection = candidates.candidates[0].selection
|
||||
member.destination = candidates.candidates[0].destination
|
||||
}
|
||||
for (const field of ['customerId', 'incomingNo', 'palletId', 'positionId', 'balanceId', 'dispatchNo'])
|
||||
for (const field of ['customerId', 'incomingNo', 'palletId', 'positionId', 'balanceId'])
|
||||
check(`Both customers have independent ${field}`, new Set(proof.members.map(row => row[field])).size === 2)
|
||||
const tripProof = await prepareFleetTrip(context, MODULE, proof.members[0].dispatchNo, id(warehouseId))
|
||||
proof.createDispatchRequest = { idempotencyKey: key('CREATE_ONE_NATIVE_DISPATCH'), warehouseId: id(warehouseId),
|
||||
vehicle: null, driver: null, plannedDepartureAt: null, estimatedArrivalAt: null,
|
||||
remark: `${context.marker} TEST跨客户同仓一张排车一趟车`, cargo: proof.members.map(member => member.selection), batchAllocations: [] }
|
||||
const created = await request('POST', `${ROOT}/dispatches`, proof.createDispatchRequest, 'Create one native dispatch from both real customers')
|
||||
check('One native Create returns both unpicked pallets without client-supplied customer identity', created?.dispatchNo && created.status === 'ACTIVE'
|
||||
&& created.stage === 'BEFORE_LOADING' && safeFixtureCount(created.counts?.packageCount) === 2 && safeFixtureCount(created.counts?.pickedPackageCount) === 0 && safeFixtureCount(created.counts?.shippedPackageCount) === 0)
|
||||
proof.dispatchNo = created.dispatchNo
|
||||
for (const member of proof.members) member.dispatchNo = proof.dispatchNo
|
||||
const tripProof = await prepareFleetTrip(context, MODULE, proof.dispatchNo, id(warehouseId))
|
||||
proof.tripNo = tripProof.tripNo
|
||||
const tripPath = `${ROOT}/fleet/trips/${encode(proof.tripNo)}`
|
||||
let detail = await request('GET', tripPath, undefined, 'Read first member trip version')
|
||||
detail = await request('POST', `${tripPath}/dispatches/bind`, { recordVersion: detail.trip.recordVersion,
|
||||
dispatchNo: proof.members[1].dispatchNo, reason: context.marker }, 'Bind second independent customer dispatch')
|
||||
const loading = await request('GET', `${tripPath}/loading`, undefined, 'Read complete two-customer cargo destinations')
|
||||
check('Shared trip cargo consists of exactly both owned physical pallets', loading?.cargo?.length === 2 && proof.members.every(member =>
|
||||
loading.cargo.some(row => row.dispatchNo === member.dispatchNo && id(row.customerId) === member.customerId
|
||||
&& id(row.warehousePalletId) === member.palletId && row.palletNo === member.palletNo && row.destinationKey && Number(row.packages) === 1)))
|
||||
const destinations = new Map(loading.cargo.map(row => [row.destinationKey, { name: row.destinationLabel, destinationKey: row.destinationKey }]))
|
||||
detail = await request('PUT', `${tripPath}/plan`, { recordVersion: detail.trip.recordVersion,
|
||||
plannedDepartureAt: detail.trip.plannedDepartureAt, expectedDriverEndAt: detail.trip.expectedDriverEndAt,
|
||||
stops: [{ name: origin.warehouse.warehouseName }, ...destinations.values()], reason: context.marker }, 'Replace route with complete actual destinations')
|
||||
tripProof.stops = detail.trip.stops
|
||||
check('Route includes every actual destination', [...destinations.keys()].every(destinationKey => detail.trip.stops?.slice(1).some(row => row.destinationKey === destinationKey)))
|
||||
for (const [index, member] of proof.members.entries()) {
|
||||
const path = `${ROOT}/dispatches/${encode(member.dispatchNo)}`
|
||||
const freight = await request('GET', `${path}/external-freight`, undefined, 'Verify ordinary incoming has no external quote')
|
||||
check('Ordinary incoming requires its own explicit delivery fee', freight?.requiresDeliveryFee === true && freight.quotes?.length === 0)
|
||||
const transferred = await request('POST', `${path}/transfer-delivery`, { idempotencyKey: key(`DELIVERY-${index}`), plannedDeliveryAt: localTime(21600000),
|
||||
deliveryMethod: 'TRUCK_PALLET', pickupMethod: 'WAREHOUSE_PICKUP', loadingType: 'PALLET', vehicleType: 'TRUCK',
|
||||
vehicleSize: Number(detail.trip.maxPalletSpaces) <= 15 ? '15托' : '30托', vehiclePlate: detail.trip.vehiclePlate,
|
||||
driverName: detail.trip.driverName, driverPhone: detail.trip.driverPhone, appointmentAccount: 'SELF', remark: member.customerMarker,
|
||||
fees: [{ feeType: 'DELIVERY_FEE', feeName: '受控测试派送费', direction: 'RECEIVABLE', currency: 'CNY', amount: 30 }] }, 'Create this customer outbound and delivery')
|
||||
check('One customer dispatch produces one outbound and one delivery', transferred?.dispatchNo === member.dispatchNo && transferred.outboundNo
|
||||
&& transferred.deliveries?.length === 1 && transferred.deliveries[0].deliveryNo && Number(transferred.packageCount) === 1)
|
||||
member.outboundNo = transferred.outboundNo; member.deliveryNo = transferred.deliveries[0].deliveryNo
|
||||
const delivery = await request('GET', `${ROOT}/delivery-orders/${encode(member.deliveryNo)}?${own(member)}`, undefined, 'Verify independently owned delivery')
|
||||
const outbound = await request('GET', `${ROOT}/outbound-orders/${encode(member.outboundNo)}?${own(member)}`, undefined, 'Verify independently owned outbound')
|
||||
const dispatch = await request('GET', path, undefined, 'Verify customer dispatch remains unpicked')
|
||||
check('Customer execution records are distinct and untouched', id(delivery?.order?.customerId) === member.customerId
|
||||
&& delivery.order.deliveryNo === member.deliveryNo && delivery.order.dispatchNo === member.dispatchNo && delivery.order.outboundNo === member.outboundNo
|
||||
&& delivery.order.status === 'WAIT_DELIVERY' && outbound?.outbound?.outboundNo === member.outboundNo && outbound.outbound.dispatchNo === member.dispatchNo
|
||||
&& id(outbound.outbound.overseasWarehouseId) === id(warehouseId) && outbound.outbound.status === 'WAIT_OUTBOUND'
|
||||
&& outbound.deliveries?.length === 1 && id(outbound.deliveries[0].customerId) === member.customerId && outbound.deliveries[0].deliveryNo === member.deliveryNo
|
||||
&& dispatch?.status === 'PENDING_DEPARTURE' && Number(dispatch.pickedPackageCount) === 0 && Number(dispatch.shippedPackageCount) === 0)
|
||||
const finalStock = await stock(member)
|
||||
check('Trip preparation preserves original available receipt records', JSON.stringify(finalStock) === JSON.stringify(member.receipt))
|
||||
const dispatchPath = `${ROOT}/dispatches/${encode(proof.dispatchNo)}`
|
||||
const detail = await request('GET', dispatchPath, undefined, 'Read one reviewed native cross-customer dispatch')
|
||||
const items = await request('GET', `${dispatchPath}/items`, undefined, 'Read native per-customer cargo identities')
|
||||
check('Both actual customer pallets share one reviewed native dispatch before any picking', detail.dispatchNo === proof.dispatchNo
|
||||
&& detail.status === 'ACTIVE' && detail.stage === 'LOADING' && detail.reviewState === 'APPROVED'
|
||||
&& safeFixtureCount(detail.counts?.packageCount) === 2 && safeFixtureCount(detail.counts?.pickedPackageCount) === 0 && safeFixtureCount(detail.counts?.shippedPackageCount) === 0
|
||||
&& detail.documents?.outbounds?.length === 0 && detail.documents?.deliveries?.length === 0
|
||||
&& items.dispatchNo === proof.dispatchNo && id(items.recordVersion) === id(detail.recordVersion) && items.items?.length === 2
|
||||
&& proof.members.every(member => items.items.some(row => id(row.customerId) === member.customerId
|
||||
&& id(row.warehousePalletId) === member.palletId && row.palletNo === member.palletNo && row.destination?.key === member.destination?.key
|
||||
&& safeFixtureCount(row.scheduledPackages) === 1 && safeFixtureCount(row.pickedPackages) === 0 && row.dispatchItemId)))
|
||||
for (const member of proof.members) {
|
||||
member.dispatchItemId = id(items.items.find(row => id(row.customerId) === member.customerId).dispatchItemId)
|
||||
check('Trip preparation preserves original available receipt records', JSON.stringify(await stock(member)) === JSON.stringify(member.receipt))
|
||||
}
|
||||
detail = await request('GET', tripPath, undefined, 'Verify final two-customer shared trip membership')
|
||||
check('Final trip has only the two fresh customers and remains planned', detail?.trip?.status === 'PLANNED' && detail.dispatches?.length === 2
|
||||
&& proof.members.every(member => detail.dispatches.some(row => row.dispatchNo === member.dispatchNo && id(row.customerId) === member.customerId)))
|
||||
for (const field of ['outboundNo', 'deliveryNo']) check(`Independent ${field}`, new Set(proof.members.map(row => row[field])).size === 2)
|
||||
fixture = { marker: context.marker, stage: fixtureContract.stage, tripNo: proof.tripNo, warehouseId: id(warehouseId), pdaToken,
|
||||
members: proof.members.map(({ marker, customerId, incomingNo, dispatchNo, outboundNo, deliveryNo, balanceId, positionId, palletId, palletNo, receiptVerified }) =>
|
||||
({ marker, customerId, incomingNo, dispatchNo, outboundNo, deliveryNo, balanceId, positionId, palletId, palletNo, receiptVerified })) }
|
||||
fixture = { marker: context.marker, stage: fixtureContract.stage, dispatchNo: proof.dispatchNo, tripNo: proof.tripNo,
|
||||
warehouseId: id(warehouseId), pdaToken, tripProof,
|
||||
members: proof.members.map(({ marker, customerId, incomingNo, dispatchNo, dispatchItemId, balanceId, positionId, palletId, palletNo, receiptVerified, measurementReceipt, destination }) =>
|
||||
({ marker, customerId, incomingNo, dispatchNo, dispatchItemId, balanceId, positionId, palletId, palletNo, receiptVerified, measurementReceipt, destination })) }
|
||||
} catch (error) { failure = error }
|
||||
// Always attempt every successfully opened session, including partial fixture failures. PDA lifecycle belongs to caller.
|
||||
const cleanupErrors = []
|
||||
|
||||
Reference in New Issue
Block a user