fix(pda): stage sealed pallet scans for atomic batch picking

This commit is contained in:
2026-09-09 12:29:46 +08:00
parent 0745e9600c
commit b19cecb54f
10 changed files with 136 additions and 11 deletions
+32
View File
@@ -6,6 +6,38 @@ const source = await readFile(new URL('../api/pda-loading.js', import.meta.url),
const http = await readFile(new URL('../api/http.js', import.meta.url), 'utf8')
const page = await readFile(new URL('../pages/picking/picking.vue', import.meta.url), 'utf8')
test('sealed pallets use atomic batch actions and cannot use manual package actions', () => {
assert.doesNotMatch(source, /\/pallets\/pick/)
assert.match(source, /palletNo: action\.type === 'PICK_PALLET' \? action\.palletNo : null/)
assert.match(page, /type: 'PICK_PALLET', itemId: item\.taskItemId \?\? item\.id, palletNo: item\.palletNo/)
assert.match(page, /if \(isPalletItem\(result\.item\)\) return this\.pickScannedPallet\(result\.item\)/)
assert.match(page, /itemState\(item\) === ITEM_STATUS\.PENDING && !isPalletItem\(item\)/)
assert.match(page, /if \(isPalletItem\(item\)\) \{ this\.showToast\('请扫描托盘码整体拣出'/)
assert.match(page, /if \(isPalletItem\(item\)\) return/)
assert.match(page, /item\.palletNo \|\| '托盘码待同步'/)
})
test('a DP scan changes all same-pallet rows locally without any remote command', async () => {
const method = page.match(/pickScannedPallet\(item\) \{[\s\S]*?\n\t\t\t\},/)?.[0]
assert.ok(method)
const stateSource = await readFile(new URL('../utils/picking-state.js', import.meta.url), 'utf8')
const { isPalletItem, ITEM_STATUS } = await import(`data:text/javascript;base64,${Buffer.from(stateSource).toString('base64')}`)
const undo = page.match(/undoPallet\(item\) \{[\s\S]*?\n\t\t\t\},/)?.[0]
const behavior = new Function('isPalletItem', 'ITEM_STATUS', `return ({${method}${undo}})`)(isPalletItem, ITEM_STATUS)
let saved = 0
const rows = [{ id: '1', unitType: 'PALLET', palletNo: 'DP-260909-0143', qty: 2, itemStatus: 'PENDING' }, { id: '2', unitType: 'PALLET', palletNo: 'DP-260909-0143', qty: 3, itemStatus: 'PENDING' }, { id: '3', unitType: 'PACKAGE', qty: 1, itemStatus: 'PENDING' }]
const context = { submitting: false, requirePickingOperation: () => true, currentBox: { items: rows }, itemStates: {}, partialQuantities: {}, scannedBoxCodes: {}, recordScanResult() {}, showToast() {}, persistSession() { saved++ } }
behavior.pickScannedPallet.call(context, rows[0])
assert.deepEqual(context.itemStates, { 1: 'picked', 2: 'picked' })
assert.deepEqual(context.partialQuantities, { 1: 2, 2: 3 })
assert.equal(saved, 1)
behavior.undoPallet.call(context, rows[0])
assert.deepEqual(context.itemStates, { 1: 'pending', 2: 'pending' })
assert.deepEqual(context.scannedBoxCodes, {})
assert.equal(saved, 2)
assert.doesNotMatch(method, /await|pickContainer|syncRemote|request\(/)
})
test('PDA loading adapter uses only task-scoped cabinet evidence paths', () => {
for (const path of [
'/first-leg/pda-loading/tasks/pending'