import assert from 'node:assert/strict' import test from 'node:test' import { createFirstLegPartySnapshot } from '../data/firstLegParties.ts' import { canClientCancelFirstLegOrder, canClientEditFirstLegOrder, createEmptyCargoItem, FIRST_LEG_PROGRESS_STAGES, getFirstLegProgressIndex, getFirstLegStatusLabel, getFirstLegPickingStatusLabel, getFirstLegStatusTone, 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: '家居用品', unitsPerPackage: 100, pieces: 100, grossWeightKg: 1200, volumeCbm: 3.5, shipmentId: 'FBA-001', referenceId: 'REF-001' }], } } test('keeps picking states distinct from order completion and hides unknown internal codes', () => { assert.equal(getFirstLegPickingStatusLabel('PENDING'), '待拣货') assert.equal(getFirstLegPickingStatusLabel('IN_PROGRESS'), '拣货中') assert.equal(getFirstLegPickingStatusLabel('COMPLETED'), '拣货完成') assert.equal(getFirstLegPickingStatusLabel('NEW_INTERNAL_STATE'), '未知状态') assert.equal(getFirstLegPickingStatusLabel(null), '待更新') assert.equal(getFirstLegPickingStatusLabel(''), '待更新') }) test('uses the confirmed status and transport labels', () => { assert.equal(getFirstLegStatusLabel('CANCELLED'), '已取消') assert.equal(getFirstLegStatusLabel('NOT_A_STATUS'), '未知状态') assert.equal(getFirstLegStatusTone('CANCELLED'), 'info') assert.equal(getFirstLegProgressIndex('CANCELLED'), -1) assert.equal(canClientEditFirstLegOrder('CANCELLED'), false) assert.equal(canClientCancelFirstLegOrder('CANCELLED'), false) assert.equal(getFirstLegStatusLabel('WAIT_MEASURE'), '待测量数据') assert.equal(getFirstLegStatusLabel('WAIT_PALLETIZE'), '待组托') assert.equal(getFirstLegStatusLabel('WAIT_SPLIT'), '待分柜') assert.equal(getFirstLegStatusLabel('LOADING'), '装柜中') assert.equal(getFirstLegStatusLabel('LOADED'), '装柜完成') assert.equal(getFirstLegStatusLabel('DELIVERED'), '派送完成') assert.equal(getFirstLegTransportModeLabel('FCL'), '海运整箱 FCL') assert.deepEqual(FIRST_LEG_PROGRESS_STAGES.map((item) => item.code), [ 'PENDING_REVIEW', 'WAIT_MEASURE', 'WAIT_PALLETIZE', 'WAIT_SPLIT', 'LOADING', 'LOADED', 'DELIVERED', 'COMPLETED', ]) assert.equal(getFirstLegProgressIndex('WAIT_PALLETIZE'), 2) }) 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_PALLETIZE'), 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 const errors = validateFirstLegOrderDraft(invalid) assert.ok(errors.includes('请选择平台收货仓')) assert.ok(errors.includes('第 1 条货物毛重必须大于 0')) }) test('rejects a total quantity that does not equal units per package multiplied by package count', () => { const draft = validDraft() draft.items[0].unitsPerPackage = 24 draft.items[0].packageCount = 5 draft.items[0].pieces = 119 assert.ok(validateFirstLegOrderDraft(draft).includes('第 1 条货物总数量应等于每箱数量 × 箱数(120)')) draft.items[0].pieces = 120 assert.ok(!validateFirstLegOrderDraft(draft).some((message) => message.includes('总数量应等于'))) }) 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 warehouse and cargo-level shipment, reference and SKU while keeping UPC optional', () => { const draft = validDraft() draft.referenceNo = '' draft.amazonWarehouseCode = '' draft.shipmentId = '' draft.items[0].sku = '' draft.items[0].upc = '' draft.items[0].shipmentId = '' draft.items[0].referenceId = '' const errors = validateFirstLegOrderDraft(draft) assert.ok(errors.includes('FBA 订单请填写 Amazon 仓库编码')) assert.ok(errors.includes('第 1 条货物缺少客户 SKU')) assert.ok(!errors.includes('第 1 条货物缺少 UPC')) assert.ok(errors.includes('第 1 条货物缺少货件编号')) assert.ok(errors.includes('第 1 条货物缺少跟踪编号')) }) 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('requires customs inspection when any cargo is a wooden product', () => { const draft = validDraft() draft.items[0].woodenProduct = true draft.items.push({ ...draft.items[0], id: 'cargo-2' }) draft.customsInspection = null assert.ok(validateFirstLegOrderDraft(draft).includes('第 1、2 条货物为木制品,“是否商检”必须选择“是”')) draft.customsInspection = false assert.ok(validateFirstLegOrderDraft(draft).includes('第 1、2 条货物为木制品,“是否商检”必须选择“是”')) draft.customsInspection = true assert.ok(!validateFirstLegOrderDraft(draft).some((message) => message.includes('为木制品'))) }) 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, }) }) test('counts one physical carton series for SKU lines in the same mixed-carton group', () => { const first = { ...validDraft().items[0], packingGroupNo: 'A', packageCount: 10, pieces: 20, unitsPerPackage: 2 } const second = { ...first, id: 'cargo-2', sku: 'SKU-002', pieces: 30, unitsPerPackage: 3 } assert.deepEqual(summarizeFirstLegCargo([first, second]), { pieces: 50, packageCount: 10, grossWeightKg: first.grossWeightKg, volumeCbm: first.volumeCbm, }) const draft = { ...validDraft(), fulfillmentType: 'ONE_CLICK_DROPSHIP', items: [first, second] } assert.ok(!validateFirstLegOrderDraft(draft).some((message) => message.includes('同箱 SKU'))) second.packageCount = 9 assert.ok(validateFirstLegOrderDraft(draft).includes('同箱 SKU 的箱数、包装类型、箱规、重量和体积必须一致')) }) test('distinguishes first-leg draft, review, active handling and completion', () => { assert.equal(getFirstLegStatusTone('DRAFT'), 'info') assert.equal(getFirstLegStatusTone('PENDING_REVIEW'), 'warning') for (const status of ['WAIT_MEASURE', 'WAIT_PALLETIZE', 'WAIT_SPLIT', 'LOADING']) { assert.equal(getFirstLegStatusTone(status), 'primary') } assert.equal(getFirstLegStatusTone('LOADED'), 'success') assert.equal(getFirstLegStatusTone('DELIVERED'), 'success') assert.equal(getFirstLegStatusTone('COMPLETED'), 'success') assert.equal(getFirstLegStatusLabel('SUBMITTED'), '\u5f85\u5ba1\u6838') assert.equal(getFirstLegStatusLabel('COMPLETED'), '已完成') assert.equal(getFirstLegStatusLabel('UNRECOGNIZED'), '未知状态') assert.equal(getFirstLegStatusTone('UNRECOGNIZED'), 'info') })