import test from 'node:test' import assert from 'node:assert/strict' import { readFile } from 'node:fs/promises' const source = await readFile(new URL('../utils/picking-state.js', import.meta.url), 'utf8') const state = await import(`data:text/javascript;base64,${Buffer.from(source).toString('base64')}`) const items = [{ id: 1 }, { id: 2 }, { id: 3 }] test('inventory resources expose distinct locations and total available cartons', () => { assert.deepEqual(state.summarizeInventoryResources([ { locationCode: 'A0', availablePackageCount: 4 }, { locationCode: 'A0', availablePackageCount: 2 }, { locationCode: 'B-03', availablePackageCount: 1 }, ]), { location: 'A0、B-03', availablePackageCount: 7 }) assert.deepEqual(state.summarizeInventoryResources(null), { location: '', availablePackageCount: null }) }) test('sealed pallet matches its DP code and resolves member cartons as an atomic pallet', () => { const pallet = { id: '1', unitType: 'SEALED_PALLET', indivisible: true, palletNo: 'DP-260909-0143', boxCodes: ['IN#2-1', 'IN#2-2'], qty: 2 } assert.equal(state.classifyScan([pallet], {}, 'IN#2-1').type, 'pallet') assert.equal(state.classifyScan([pallet], {}, pallet.palletNo).type, 'pallet') assert.equal(state.classifyScan([pallet], { 1: state.ITEM_STATUS.PICKED }, pallet.palletNo).type, 'processed') }) test('only the authoritative sealed-pallet unit type selects pallet behavior', () => { assert.equal(state.isSealedPalletItem({ unitType: 'SEALED_PALLET', indivisible: true }), true) assert.equal(state.isSealedPalletItem({ unitType: 'PALLET', indivisible: true }), false) assert.equal(state.isSealedPalletItem({ unitType: 'PACKAGE', indivisible: true }), false) }) test('mixed task keeps package scanning separate from sealed pallet scanning', () => { const mixed = [{ id: '1', unitType: 'SEALED_PALLET', palletNo: 'DP-260909-0001', boxCodes: ['BOX-1'] }, { id: '2', unitType: 'PACKAGE', boxCodes: ['BOX-2'] }] assert.equal(state.classifyScan(mixed, {}, 'BOX-2').item.id, '2') assert.equal(state.classifyScan(mixed, {}, 'DP-260909-0001').item.id, '1') assert.equal(state.classifyScan(mixed, {}, 'BOX-1').type, 'pallet') }) test('createItemStates initializes every item as pending', () => { assert.deepEqual(state.createItemStates(items), { 1: state.ITEM_STATUS.PENDING, 2: state.ITEM_STATUS.PENDING, 3: state.ITEM_STATUS.PENDING, }) }) test('getPickSummary disables submit before any effective pick', () => { const summary = state.getPickSummary(items, { 1: state.ITEM_STATUS.SKIPPED, 2: state.ITEM_STATUS.PENDING, 3: state.ITEM_STATUS.PENDING, }) assert.equal(summary.canSubmit, false) assert.equal(summary.buttonText, '提交拣货完成') assert.equal(summary.progress, 33) }) test('getPickSummary enables early submit after a picked item', () => { const summary = state.getPickSummary(items, { 1: state.ITEM_STATUS.PICKED, 2: state.ITEM_STATUS.PENDING, 3: state.ITEM_STATUS.PENDING, }) assert.equal(summary.canSubmit, true) assert.equal(summary.buttonText, '提交拣货完成') assert.deepEqual( { picked: summary.picked, partial: summary.partial, skipped: summary.skipped, pending: summary.pending }, { picked: 1, partial: 0, skipped: 0, pending: 2 }, ) }) test('getPickSummary enables submit when every item is processed', () => { const summary = state.getPickSummary(items, { 1: state.ITEM_STATUS.SKIPPED, 2: state.ITEM_STATUS.SKIPPED, 3: state.ITEM_STATUS.SKIPPED, }) assert.equal(summary.canSubmit, true) assert.equal(summary.buttonText, '提交拣货完成') assert.equal(summary.progress, 100) }) test('submitStates turns only pending items into skipped', () => { assert.deepEqual(state.submitStates(items, { 1: state.ITEM_STATUS.PICKED, 2: state.ITEM_STATUS.PARTIAL, 3: state.ITEM_STATUS.PENDING, }), { states: { 1: state.ITEM_STATUS.PICKED, 2: state.ITEM_STATUS.PARTIAL, 3: state.ITEM_STATUS.SKIPPED, }, autoSkippedIds: [3], }) }) test('classifyScan distinguishes pending, repeated, and unknown carton codes', () => { const scanItems = [{ id: 1, boxCodes: ['BOX-001'] }, { id: 2, boxCodes: ['BOX-002', 'BOX-003'] }] assert.deepEqual(state.classifyScan(scanItems, { 1: state.ITEM_STATUS.PICKED, 2: state.ITEM_STATUS.PENDING, }, 'BOX-002'), { type: 'pending', item: scanItems[1], }) assert.deepEqual(state.classifyScan(scanItems, { 1: state.ITEM_STATUS.PARTIAL, 2: state.ITEM_STATUS.PENDING, }, 'BOX-001', { 'BOX-001': 1 }), { type: 'processed', item: scanItems[0], status: state.ITEM_STATUS.PARTIAL, }) assert.deepEqual(state.classifyScan(scanItems, {}, 'NO-SUCH-BOX'), { type: 'unknown', item: null, }) }) test('sealed pallet resolves either its DP code or any member carton as one whole-pallet action', () => { const pallet = { id: 9, unitType: 'SEALED_PALLET', palletId: '2098348162978738179', palletNo: 'DP-260911-0047', indivisible: true, boxCodes: ['BOX-001', 'BOX-002'], } assert.deepEqual(state.classifyScan([pallet], {}, 'DP-260911-0047'), { type: 'pallet', item: pallet, }) assert.deepEqual(state.classifyScan([pallet], {}, 'BOX-001'), { type: 'pallet', item: pallet, matchedBy: 'carton', }) assert.deepEqual(state.classifyScan([pallet], { 9: state.ITEM_STATUS.PICKED, }, 'DP-260911-0047', { 'DP-260911-0047': 9 }), { type: 'processed', item: pallet, status: state.ITEM_STATUS.PICKED, }) }) test('a carton duplicated by a stale task payload selects the remaining sealed pallet', () => { const picked = { id: 1, unitType: 'SEALED_PALLET', palletNo: 'DP-260920-0001', boxCodes: ['EXXHWK2809191198#20-01'] } const pending = { id: 2, unitType: 'SEALED_PALLET', palletNo: 'DP-260920-0002', boxCodes: ['EXXHWK2809191198#20-01', 'EXXHWK2809191198#20-19'] } assert.deepEqual(state.classifyScan([picked, pending], { 1: state.ITEM_STATUS.PICKED, 2: state.ITEM_STATUS.PENDING, }, 'EXXHWK2809191198#20-19'), { type: 'pallet', item: pending, matchedBy: 'carton', }) })