import assert from 'node:assert/strict' import test from 'node:test' import { createFirstLegPartySnapshot } from '../data/firstLegParties.ts' import { canClientCancelFirstLegOrder, canClientEditFirstLegOrder, createEmptyCargoItem, getFirstLegStatusLabel, getFirstLegTransportModeLabel, summarizeFirstLegCargo, validateFirstLegOrderDraft, } from './firstLegOrder.ts' const shipperParty = { id: 'CP001', code: 'SHIPPER-001', name: '测试发货企业', roles: ['SHIPPER'], contactName: '测试联系人', phone: '13800000000', email: 'shipper@example.test', countryRegion: '中国', province: '浙江省', city: '宁波市', postalCode: '315000', address: '测试发货地址', status: 'ACTIVE', } const consigneeParty = { id: 'CP002', code: 'CONSIGNEE-001', name: 'TEST CONSIGNEE LLC', roles: ['CONSIGNEE'], contactName: 'Test Receiver', phone: '+1 555 0100', email: 'receiver@example.test', countryRegion: '美国', province: 'California', city: 'Los Angeles', postalCode: '90001', address: '100 Test Logistics Ave', status: 'ACTIVE', } function validDraft() { return { referenceNo: 'REF-001', transportMode: 'FCL', businessType: 'EXPORT', origin: '宁波', destination: '洛杉矶', receivingWarehouseId: 'WH005', expectedDepartureDate: '2026-08-08', shipperPartyId: 'CP001', shipperPartySnapshot: createFirstLegPartySnapshot(shipperParty, 'SHIPPER'), shipper: shipperParty.name, consigneePartyId: 'CP003', consigneePartySnapshot: createFirstLegPartySnapshot(consigneeParty, 'CONSIGNEE'), consignee: consigneeParty.name, priority: 'NORMAL', customerRemark: '', tradeTerm: 'FOB', destinationCountryCode: 'US', destinationWarehouseId: 'WH-FBA-ONT8', destinationWarehouseName: 'ONT8', pickupMethod: 'SELF_EXPRESS', channelCode: 'SEA-US-FBA', channelName: '美国海运渠道', pricingTaxMode: 'TAX_INCLUDED', taxMode: 'BUY_DECLARATION', customsInspection: false, destinationType: 'FBA', amazonWarehouseCode: 'ONT8', shipmentId: 'FBA-001', items: [{ ...createEmptyCargoItem('cargo-1'), sku: 'SKU-001', upc: '012345678905', cargoNameCn: '家居用品', pieces: 100, grossWeightKg: 1200, volumeCbm: 3.5, containerType: '40HQ', containerCount: 1 }], } } test('uses the confirmed status and transport labels', () => { assert.equal(getFirstLegStatusLabel('WAIT_MEASURE'), '待测量数据') assert.equal(getFirstLegStatusLabel('INBOUNDED'), '已入库') assert.equal(getFirstLegStatusLabel('WAIT_SPLIT'), '待分柜') assert.equal(getFirstLegStatusLabel('LOADING'), '装柜中') assert.equal(getFirstLegStatusLabel('LOADED'), '装柜完成') assert.equal(getFirstLegStatusLabel('DELIVERED'), '派送完成') assert.equal(getFirstLegTransportModeLabel('FCL'), '海运整箱 FCL') }) test('only allows draft orders to be edited in the confirmed phase-one flow', () => { assert.equal(canClientEditFirstLegOrder('DRAFT'), true) assert.equal(canClientEditFirstLegOrder('PENDING_REVIEW'), false) assert.equal(canClientCancelFirstLegOrder('DRAFT'), true) assert.equal(canClientCancelFirstLegOrder('PENDING_REVIEW'), true) assert.equal(canClientCancelFirstLegOrder('WAIT_MEASURE'), false) assert.equal(canClientCancelFirstLegOrder('WAIT_SPLIT'), false) }) test('validates the confirmed minimum submission fields', () => { assert.deepEqual(validateFirstLegOrderDraft(validDraft()), []) const invalid = validDraft() invalid.receivingWarehouseId = '' invalid.items[0].grossWeightKg = 0 invalid.items[0].containerType = '' invalid.items[0].containerCount = 0 const errors = validateFirstLegOrderDraft(invalid) assert.ok(errors.includes('请选择平台收货仓')) assert.ok(errors.includes('第 1 条货物毛重必须大于 0')) assert.ok(errors.includes('第 1 条货物需要填写箱型和柜量')) }) test('only requires sender for pickup and receiver for a private destination', () => { const publicDraft = validDraft() publicDraft.shipperPartySnapshot = null publicDraft.consigneePartySnapshot = null assert.deepEqual(validateFirstLegOrderDraft(publicDraft), []) const pickupDraft = validDraft() pickupDraft.pickupMethod = 'PICKUP' pickupDraft.shipperPartySnapshot = null assert.ok(validateFirstLegOrderDraft(pickupDraft).includes('请填写提货联系人')) const privateDraft = validDraft() privateDraft.destinationType = 'PRIVATE' privateDraft.destinationWarehouseId = '' privateDraft.amazonWarehouseCode = '' privateDraft.shipmentId = '' privateDraft.referenceNo = '' privateDraft.consigneePartySnapshot = null assert.ok(validateFirstLegOrderDraft(privateDraft).includes('请填写收件人姓名')) }) test('requires FBA reference, warehouse, shipment, SKU and UPC fields', () => { const draft = validDraft() draft.referenceNo = '' draft.amazonWarehouseCode = '' draft.shipmentId = '' draft.items[0].sku = '' draft.items[0].upc = '' const errors = validateFirstLegOrderDraft(draft) assert.ok(errors.includes('FBA 订单请填写客户参考号')) assert.ok(errors.includes('FBA 订单请填写 Amazon 仓库编码')) assert.ok(errors.includes('FBA 订单请填写 Shipment ID')) assert.ok(errors.includes('第 1 条货物缺少客户 SKU')) assert.ok(errors.includes('第 1 条货物缺少 UPC')) }) test('requires public destination ids while keeping private addresses detached from public warehouses', () => { const publicDraft = validDraft() publicDraft.destinationWarehouseId = '' assert.ok(validateFirstLegOrderDraft(publicDraft).includes('请选择平台维护的目的仓')) const privateDraft = validDraft() privateDraft.destinationType = 'PRIVATE' privateDraft.destinationWarehouseId = 'WH-FBA-ONT8' privateDraft.amazonWarehouseCode = '' privateDraft.shipmentId = '' privateDraft.referenceNo = '' assert.ok(validateFirstLegOrderDraft(privateDraft).includes('私人地址不能引用平台公共仓库')) }) test('does not require container details for non-FCL cargo', () => { const draft = validDraft() draft.transportMode = 'AIR' draft.items[0].containerType = '' draft.items[0].containerCount = 0 assert.deepEqual(validateFirstLegOrderDraft(draft), []) }) test('summarizes cargo values from line items', () => { const first = validDraft().items[0] const second = { ...first, id: 'cargo-2', pieces: 40, packageCount: 4, grossWeightKg: 300, volumeCbm: 1.25 } assert.deepEqual(summarizeFirstLegCargo([first, second]), { pieces: 140, packageCount: 5, grossWeightKg: 1500, volumeCbm: 4.75, }) })