This commit is contained in:
2026-08-06 20:14:54 +08:00
parent 20f8a436e0
commit ac762ed302
6 changed files with 136 additions and 23 deletions
@@ -118,7 +118,7 @@ test('does not expose the contradictory backend rejected state in the client mod
})
test('maps the final backend timeline and keeps missing custom nodes empty', () => {
assert.match(storeSource, /detail\.timeline\.flatMap/)
assert.match(storeSource, /\(detail\.timeline \?\? \[\]\)\.flatMap/)
assert.match(storeSource, /item\.mainStatus/)
assert.match(storeSource, /\(detail\.customNodes \?\? \[\]\)/)
assert.match(storeSource, /\.filter\(\(item\) => item\.customerVisible\)/)
@@ -127,6 +127,21 @@ test('maps the final backend timeline and keeps missing custom nodes empty', ()
assert.match(storeSource, /\.sort\(\(left, right\)/)
})
test('keeps unified detail mapping recoverable for historical partial responses', () => {
assert.match(storeSource, /\(detail\.parties \?\? \[\]\)\.find/)
assert.match(storeSource, /\(detail\.statusHistory \?\? \[\]\)\.map/)
assert.match(storeSource, /item\.attachmentIds\?\.length \?\? 0/)
assert.match(storeSource, /if \(!detail\?\.summary \|\| !detail\.order\?\.order\) throw new Error\('订单详情数据不完整,请刷新列表后重试'\)/)
})
test('maps customer-visible carrier and order lifecycle snapshots into detail', () => {
assert.match(apiSource, /export interface MerchantFirstLegOrder[\s\S]*carrierId\?: number \| string \| null/)
assert.match(storeSource, /carrierName: order\.carrierName \?\? ''/)
assert.match(storeSource, /receivingTime: order\.receivingTime \?\? ''/)
assert.match(storeSource, /submittedAt: order\.submittedAt \?\? ''/)
assert.match(storeSource, /completedAt: order\.completedAt \?\? ''/)
})
test('maps backend warehouse snapshots and fulfillment courier fields', () => {
assert.match(storeSource, /order\.receivingWarehouseAddress/)
assert.match(storeSource, /order\.expressCompany \?\? ''/)
+10 -6
View File
@@ -153,7 +153,7 @@ function orderWarehouseSnapshot(order: MerchantFirstLegOrder, warehouse?: Platfo
}
function partySnapshot(detail: MerchantFirstLegOrderDetail, type: 'SENDER' | 'RECEIVER'): FirstLegPartySnapshot | null {
const party = detail.parties.find((item) => item.partyType === type)
const party = (detail.parties ?? []).find((item) => item.partyType === type)
if (!party) return null
return {
id: String(party.id), code: type, name: party.companyName, role: type === 'SENDER' ? 'SHIPPER' : 'CONSIGNEE',
@@ -163,7 +163,7 @@ function partySnapshot(detail: MerchantFirstLegOrderDetail, type: 'SENDER' | 'RE
}
function timeline(detail: MerchantFirstLegOrderDetail): FirstLegOrderTimelineItem[] {
return detail.statusHistory.map((item) => {
return (detail.statusHistory ?? []).map((item) => {
const status = clientStatus(item.toStatus)
return {
id: String(item.id),
@@ -222,7 +222,7 @@ const unifiedActionLabels: Readonly<Record<string, string>> = {
}
function unifiedTimeline(detail: MerchantUnifiedOrderDetail): FirstLegOrderTimelineItem[] {
const statusItems: FirstLegOrderTimelineItem[] = detail.timeline.flatMap((item, index) => item.mainStatus ? [{
const statusItems: FirstLegOrderTimelineItem[] = (detail.timeline ?? []).flatMap((item, index) => item.mainStatus ? [{
id: `status-${item.source}-${item.eventType}-${index}`,
kind: 'MAIN_STATUS' as const,
status: item.mainStatus,
@@ -248,7 +248,7 @@ function unifiedTimeline(detail: MerchantUnifiedOrderDetail): FirstLegOrderTimel
occurredAt: item.completedAt ?? item.plannedAt ?? '',
plannedAt: item.plannedAt ?? '',
completed: Boolean(item.completedAt),
attachmentCount: item.attachmentIds.length,
attachmentCount: item.attachmentIds?.length ?? 0,
}))
return [...statusItems, ...customItems].sort((left, right) => {
const timeDifference = Date.parse(left.occurredAt) - Date.parse(right.occurredAt)
@@ -280,8 +280,10 @@ function mapOrder(order: MerchantFirstLegOrder, warehouses: PlatformReceivingWar
tradeTerm: order.tradeTerm ?? '', destinationCountryCode: order.destinationCountryCode,
destinationWarehouseId: order.destinationWarehouseId ? String(order.destinationWarehouseId) : '',
destinationWarehouseName: order.destinationWarehouseName, pickupMethod: order.pickupMethod, channelCode: order.channelCode,
channelName: order.channelName, taxMode: order.taxMode, customsInspection: order.customsInspection,
channelName: order.channelName, carrierId: order.carrierId == null ? '' : String(order.carrierId), carrierName: order.carrierName ?? '',
taxMode: order.taxMode, customsInspection: order.customsInspection,
destinationType: order.destinationType, amazonWarehouseCode: order.amazonWarehouseCode ?? '', shipmentId: order.shipmentId ?? '',
receivingTime: order.receivingTime ?? '', submittedAt: order.submittedAt ?? '', completedAt: order.completedAt ?? '',
}
}
@@ -299,12 +301,14 @@ function mapUnifiedOrderRow(summary: MerchantUnifiedOrderRow, warehouses: Platfo
createdAt: summary.createdAt, updatedAt: summary.updatedAt, tradeTerm: '', destinationCountryCode: '',
destinationWarehouseId: summary.destinationWarehouseId == null ? '' : String(summary.destinationWarehouseId),
destinationWarehouseName: summary.destinationWarehouseName ?? '', pickupMethod: 'SELF_EXPRESS', channelCode: '',
channelName: summary.channelName ?? '', taxMode: 'BUY_DECLARATION', customsInspection: false,
channelName: summary.channelName ?? '', carrierId: '', carrierName: '', taxMode: 'BUY_DECLARATION', customsInspection: false,
destinationType: 'PRIVATE', amazonWarehouseCode: '', shipmentId: '',
receivingTime: '', submittedAt: '', completedAt: '',
}
}
function mapUnifiedOrderDetail(detail: MerchantUnifiedOrderDetail, warehouses: PlatformReceivingWarehouse[]): FirstLegOrder {
if (!detail?.summary || !detail.order?.order) throw new Error('订单详情数据不完整,请刷新列表后重试')
const mapped = mapOrder(detail.order.order, warehouses, detail.order)
mapped.id = String(detail.summary.orderId)
mapped.status = detail.summary.mainStatus