Files
admin-web/src/modules/overseas-warehouse/lastMilePresentation.test.ts
T

142 lines
6.6 KiB
TypeScript
Raw Normal View History

2026-08-20 09:10:36 +08:00
import { describe, expect, it } from 'vitest'
2026-09-17 13:36:31 +08:00
import { formatOverseasDateTime, inventoryBusinessTypeLabel, lastMileOrderReference, lastMileStatusLabel, packageDifferenceText, relabelBusinessStatusLabel, toLastMileOrderListItem } from './lastMilePresentation'
2026-08-20 09:10:36 +08:00
describe('last-mile order presentation adapter', () => {
2026-08-28 14:33:57 +08:00
it('formats overseas timestamps with zero-padded seconds', () => {
expect(formatOverseasDateTime('2026-08-27T16:19:46')).toBe('2026-08-27 16:19:46')
expect(formatOverseasDateTime('2026-08-07T06:09:04')).toBe('2026-08-07 06:09:04')
expect(formatOverseasDateTime('2026-08-07')).toMatch(/^2026-08-07 /)
expect(formatOverseasDateTime(new Date(2026, 7, 7, 6, 9, 4))).toBe('2026-08-07 06:09:04')
expect(formatOverseasDateTime('')).toBe('—')
expect(formatOverseasDateTime('not-a-date')).toBe('not-a-date')
})
2026-09-04 17:46:15 +08:00
it.each([
['IN_TRANSIT', '在途入账'],
['STOCK_IN', '入库'],
['STOCK_IN_TRANSIT_RELEASE', '在途库存转入'],
['HOLD', '库存暂扣'],
['RELEASE', '解除暂扣'],
['ALLOCATE', '库存分配'],
['UNALLOCATE', '取消分配'],
['PICK', '拣货'],
['SHIP', '出库'],
['ADJUST', '库存调整'],
['STOCKTAKE_ADJUST', '盘点调整'],
['PALLET_ASSEMBLE', '组托'],
['PALLET_DISASSEMBLE', '拆托'],
['PALLET_SWAP', '换托'],
['PALLET_UNBIND', '解托'],
])('maps inventory business type %s to %s', (code, label) => {
expect(inventoryBusinessTypeLabel(code)).toBe(label)
})
2026-08-20 09:10:36 +08:00
it('maps backend codes, associations and long ids without inventing data', () => {
const row = toLastMileOrderListItem({
2026-08-21 11:20:09 +08:00
id: '190000000000000099', customerId: '190000000000000001', orderNo: 'LL-001', orderType: 'ONE_CLICK_DROPSHIP', currentStatus: 'PENDING_ASSIGNMENT',
2026-08-28 14:33:57 +08:00
abnormal: true, detained: false, packageCount: 12, palletMergeFlag: 'REQUIRED', deliveryOrderNo: 'DEL-READ-ONLY', outboundOrderNo: 'OUT-READ-ONLY',
2026-08-21 11:20:09 +08:00
})
2026-08-20 09:10:36 +08:00
expect(row).toMatchObject({
id: '190000000000000099', customerId: '190000000000000001', orderType: '一件代发', status: '待分配',
2026-08-28 14:33:57 +08:00
warning: '异常', abnormal: '是', held: '否', cartons: 12, consolidated: '待合托', palletMergeFlag: 'REQUIRED', dispatchOrderNo: 'DEL-READ-ONLY', outboundOrderNo: 'OUT-READ-ONLY',
2026-08-20 09:10:36 +08:00
})
expect(row.rejectedAt).toBe('—')
})
2026-08-22 12:24:15 +08:00
it('shows the backend customerName and never guesses the owner from customerId', () => {
expect(toLastMileOrderListItem({
id: '1', customerId: '190000000000000001', customerName: '华远贸易', orderNo: 'LMO-260827-0001',
}).owner).toBe('华远贸易')
expect(toLastMileOrderListItem({
id: '2', customerId: '190000000000000002', customerName: null, orderNo: 'LMO-260827-0002',
}).owner).toBe('—')
})
it('preserves the frozen overseas receiving warehouse id and code as strings', () => {
const row = toLastMileOrderListItem({
id: '190000000000000099', customerId: '190000000000000001', orderNo: 'LMO-260908-0001',
overseasWarehouseId: '190000000000000123', overseasWarehouseCode: 'LAX01', overseasWarehouseName: '洛杉矶接柜仓',
})
expect(row.overseasWarehouseId).toBe('190000000000000123')
expect(row.overseasWarehouseCode).toBe('LAX01')
expect(row.warehouse).toBe('洛杉矶接柜仓')
})
2026-09-01 11:03:45 +08:00
it('preserves the exact server LMO short number without padding, prefixing or deriving it from id', () => {
const serverOrderNo = 'LMO-9A7'
const row = toLastMileOrderListItem({ id: '2092873463568596994', customerId: '100', orderNo: serverOrderNo })
expect(row.orderNo).toBe(serverOrderNo)
expect(lastMileOrderReference(serverOrderNo)).toBe(serverOrderNo)
expect(row.orderNo).not.toContain(row.id)
})
it('preserves real metrics and distinguishes zero from unknown fields and times', () => {
const estimatedArrivalAt = '2026-08-27T12:30:00Z'
const row = toLastMileOrderListItem({
id: '3', customerId: '190000000000000003', orderNo: 'LMO-260827-0003',
palletCount: 3, packageCount: 0, volumeCbm: 12.75, productQuantity: null, volumeWeightKg: 88.6,
estimatedArrivalAt, actualArrivalAt: null, estimatedWarehouseAt: null,
})
expect(row).toMatchObject({
pallets: 3, cartons: 0, volume: 12.75, quantity: '—', volumeWeight: 88.6,
2026-09-15 12:35:46 +08:00
portEta: formatOverseasDateTime(estimatedArrivalAt), portAta: '—',
estimatedWarehouseAt: '', warehouseEta: '—',
})
})
2026-09-17 13:36:31 +08:00
it('maps warehouse transfer receiving quantities and formats differences', () => {
const transfer = toLastMileOrderListItem({
id: '4', customerId: '100', orderNo: 'WT-1', orderType: 'WAREHOUSE_TRANSFER',
packageCount: 10, receivedPackageCount: 12, packageDifference: 2,
})
expect(transfer).toMatchObject({ cartons: 10, cartonDifference: 2 })
expect(packageDifferenceText(2)).toBe('+2')
expect(packageDifferenceText(-2)).toBe('-2')
expect(packageDifferenceText(0)).toBe('0')
expect(packageDifferenceText('—')).toBe('—')
const ordinary = toLastMileOrderListItem({ id: '5', customerId: '100', orderNo: 'LM-1', orderType: 'FIRST_LEG', packageCount: 10 })
expect(ordinary).toMatchObject({ cartons: 10, cartonDifference: '—' })
})
it.each([
['PENDING_REVIEW', '待审核'],
['WAIT_PDA_RECEIVING', '入库测量中'],
['WAIT_CUSTOMER_CONFIRMATION', '待客户确认实测'],
['INBOUND_COMPLETED', '入库完成'],
])('maps warehouse transfer status %s to %s', (status, expected) => {
expect(lastMileStatusLabel(status)).toBe(expected)
})
2026-08-22 12:24:15 +08:00
it.each([
['RELABEL_APPLICATION', '换标下单'],
['WAREHOUSE_TRANSFER', '仓储转运'],
['RETURN_RELABEL', '退货换标'],
['LOCAL_LOOSEBOARD', '本土散板'],
2026-09-15 15:20:28 +08:00
['CARGO_DISCARD', '货物废弃订单'],
2026-08-22 12:24:15 +08:00
])('maps %s to its Chinese display name', (orderType, expected) => {
const row = toLastMileOrderListItem({ id: '1', customerId: '100', orderNo: 'LL-1', orderType })
expect(row.orderType).toBe(expected)
})
2026-08-28 16:30:33 +08:00
2026-08-31 14:42:28 +08:00
it('shows related inbound numbers instead of the shared tail-leg order number', () => {
2026-08-28 16:30:33 +08:00
const row = toLastMileOrderListItem({
id: '11', customerId: '100', orderNo: 'LMO-1', palletMergeFlag: 'MERGED',
2026-08-31 14:42:28 +08:00
palletMergeBatchId: 'PMG-1', palletMergeInboundNos: ['NYEXX2608280001', 'NYEXX2608280002'],
2026-08-28 16:30:33 +08:00
})
2026-08-31 14:42:28 +08:00
expect(row.palletMergeRelation).toBe('NYEXX2608280001、NYEXX2608280002')
2026-08-28 16:30:33 +08:00
})
2026-09-15 15:20:28 +08:00
it.each([
['PENDING_PROCESSING', '待处理'],
['PROCESSING', '处理中'],
2026-09-17 13:36:31 +08:00
['CUSTOMER_CONFIRM_PENDING', '换标完成'],
2026-09-15 15:20:28 +08:00
['READY_FOR_OUTBOUND', '换标完成'],
['COMPLETED', '换标完成'],
])('collapses internal relabel node %s into business status %s', (status, expected) => {
expect(relabelBusinessStatusLabel(status)).toBe(expected)
})
2026-08-20 09:10:36 +08:00
})