feat(dispatch): unify whole vehicle scheduling, source ownership and staged execution

This commit is contained in:
2026-10-19 23:40:42 +08:00
parent e0677e7ae7
commit 9dd34791f7
346 changed files with 29245 additions and 12602 deletions
@@ -12,6 +12,8 @@ const cents = value => {
if (!match) throw new Error('成本金额不是非负两位小数')
return BigInt(match[1]) * 100n + BigInt((match[2] || '').padEnd(2, '0'))
}
const departureMillis = value => typeof value === 'string' && value
? Date.parse(/(?:Z|[+-]\d\d:\d\d)$/i.test(value) ? value : `${value}Z`) : NaN
export const TRIP_COST_EXPECTATIONS = Object.freeze({ initialCny: '100.01', finalCny: '100.03', usd: '13.07', rows: 2,
history: { CNY: ['CREATE', 'UPDATE'], USD: ['CREATE'] }, allocationMethod: 'SAME_ROUTE_PALLET_SPACES' })
@@ -38,11 +40,13 @@ export function expectedAllocations(amount, shares) {
export async function verifyFleetTripCosts(context, module, tripProof, inputs = {}) {
const run = context.createdResources?.fleetAcceptance, shares = inputs.shares
if (!context.marker || !context.createdResources?.fleetTrips?.includes(tripProof) || !tripProof?.tripNo || !tripProof.marker
|| run?.marker !== context.marker || run.tripNo !== tripProof.tripNo || run.departure?.tripNo !== tripProof.tripNo
|| run.departure.status !== 'IN_TRANSIT' || !run.departure.departedAt || tripProof.costAcceptance
|| run?.marker !== context.marker || run.tripNo !== tripProof.tripNo || !tripProof.dispatchNo
|| run.departure?.dispatchNo !== tripProof.dispatchNo || run.departure.action !== 'DEPART'
|| run.departure.status !== 'ACTIVE' || run.departure.stage !== 'DELIVERING'
|| !Number.isFinite(departureMillis(run.departure.result?.departedAt)) || tripProof.costAcceptance
|| !inputs.listOnlyToken || !inputs.deniedToken || inputs.listOnlyToken === inputs.deniedToken
|| !Array.isArray(shares) || !shares.length || new Set(shares.map(row => row.businessNo)).size !== shares.length
|| shares.some(row => !row.businessNo || !row.dispatchNo || !['OWN', 'EXTERNAL'].includes(row.sourceType)
|| shares.some(row => !row.businessNo || row.dispatchNo !== tripProof.dispatchNo || !['OWN', 'EXTERNAL'].includes(row.sourceType)
|| !Number.isSafeInteger(row.palletSpaces) || row.palletSpaces < 1 || !Array.isArray(row.warehousePalletIds)
|| !row.warehousePalletIds.length || row.warehousePalletIds.some(id => !id)))
throw new Error('车次成本验收须提供本轮唯一真实DEPART车次、独立托位预期及两类权限会话;禁止借旧样本或重复开始')
@@ -113,7 +117,8 @@ export async function verifyFleetTripCosts(context, module, tripProof, inputs =
&& history.records.filter(row => row.action === 'DEPART').length === 1)
departure = history.records.find(row => row.action === 'DEPART'); proof.departure = clone(departure)
const snapshot = departure.snapshot, load = snapshot?.confirmedLoad
check('发车实物与本轮车次绑定', snapshot?.trip?.tripNo === tripProof.tripNo && snapshot.trip.departedAt === run.departure.departedAt
check('发车实物与本轮车次绑定', snapshot?.trip?.tripNo === tripProof.tripNo
&& departureMillis(snapshot.trip.departedAt) === departureMillis(run.departure.result.departedAt)
&& load?.manifestHash && load.pallets?.length > 0 && load.cargo?.length > 0)
const ids = shares.flatMap(row => row.warehousePalletIds).map(String)
check('独立预期覆盖全部实物且没有重叠托盘', new Set(ids).size === ids.length