Merge origin/release/test and preserve storage rent checks with request unlock

This commit is contained in:
2026-10-26 13:51:38 +08:00
52 changed files with 761 additions and 761 deletions
+15 -7
View File
@@ -2,7 +2,7 @@ import test from 'node:test'
import assert from 'node:assert/strict'
import { readFile } from 'node:fs/promises'
import { fulfillment, fulfillmentIdempotencyKey, releaseFulfillmentKey, resetFulfillmentSession, restoreFulfillmentDraft, updateFulfillmentDraft } from '../src/stores/fulfillment.js'
import { fulfillment, fulfillmentIdempotencyKey, resetFulfillmentSession, restoreFulfillmentDraft, updateFulfillmentDraft } from '../src/stores/fulfillment.js'
import {
reviewDispatchLoading, completeDispatchLoading, getDispatchLoading, getDispatchCommand, requireDispatchVersion, completeOutboundTask, getDispatchTask, getOutboundTask,
listDispatchTasks, listOutboundTasks, normalizeDispatchTask, normalizeOutboundTask,
@@ -23,6 +23,15 @@ test('dispatch network failures show recovery guidance and retain diagnostics',
const read = (path) => readFile(new URL(path, import.meta.url), 'utf8')
test('outbound list and detail lead with the outbound number and label the task number separately', async () => {
const page = await read('../src/pages/outbound/outbound.vue')
assert.match(page, /class="business-code">\{\{ task\.outboundNo \|\| '—' \}\}/)
assert.match(page, /class="business-code">\{\{ current\.outboundNo \|\| '—' \}\}/)
assert.match(page, /任务号 \{\{ task\.taskNo \|\| '—' \}\}/)
assert.match(page, /任务号 \{\{ current\.taskNo \|\| '—' \}\}/)
assert.match(page, /@tap="openTask\(task\.taskNo\)"/)
})
test('native dispatch versions preserve explicit zero and reject missing or invalid versions', () => {
assert.equal(requireDispatchVersion(0), 0)
assert.equal(requireDispatchVersion('9007199254740993'), '9007199254740993')
@@ -162,17 +171,16 @@ test('dispatch and outbound adapters retain stable business identifiers and coun
assert.equal(outbound.items[0].positions[0].availablePackages, 3)
})
test('outbound draft restoration retains its retry key and stays scoped to operator and warehouse', () => {
test('outbound draft restoration discards request keys and stays scoped to operator and warehouse', () => {
storageMock(); resetFulfillmentSession(); restoreFulfillmentDraft('operator-a:warehouse-a')
updateFulfillmentDraft('outbound', { currentTaskNo: 'OUT-001' })
const first = fulfillmentIdempotencyKey('outbound', 'pick', { taskNo: 'OUT-001', packages: 3 })
assert.equal(fulfillmentIdempotencyKey('outbound', 'pick', { taskNo: 'OUT-001', packages: 3 }).value, first.value)
assert.notEqual(fulfillmentIdempotencyKey('outbound', 'pick', { taskNo: 'OUT-001', packages: 3 }).value, first.value)
fulfillment.outbound.currentTaskNo = ''; assert.equal(restoreFulfillmentDraft('operator-a:warehouse-a'), true)
assert.equal(fulfillment.outbound.currentTaskNo, 'OUT-001')
releaseFulfillmentKey('outbound', first.signature)
assert.notEqual(fulfillmentIdempotencyKey('outbound', 'pick', { taskNo: 'OUT-001', packages: 3 }).value, first.value)
assert.equal(restoreFulfillmentDraft('operator-b:warehouse-a'), false); assert.equal(fulfillment.outbound.currentTaskNo, '')
assert.throws(() => fulfillmentIdempotencyKey('dispatch', 'pick', {}), /完整原命令/)
assert.equal('pendingKeys' in fulfillment.outbound, false)
})
test('pages retain loading, offline, diagnostics and native loading completion followed by shared loading documents', async () => {
@@ -182,10 +190,10 @@ test('pages retain loading, offline, diagnostics and native loading completion f
assert.doesNotMatch(page, /模拟成功|静默成功|customerId:|warehouseId:|locationId:/)
}
assert.doesNotMatch(dispatch, /departDispatch|canDepart|确认整车发车|等待后台安排派送/); assert.match(dispatch, /DispatchLoadingDocuments/); assert.match(dispatch, /completeDispatchLoading/); assert.match(dispatch, /pickingReconciled === true/)
assert.match(dispatch, /beginDispatchCommand/); assert.match(dispatch, /await getDispatchTask[\s\S]*finishDispatchCommand/)
assert.doesNotMatch(dispatch, /beginDispatchCommand|pendingCommand/); assert.match(dispatch, /submitCommand/)
assert.doesNotMatch(dispatch, /tripDepartureRequest|completeDispatchPicking|fulfillmentIdempotencyKey/)
assert.match(outbound, /resolveOutboundTask[\s\S]*workflow === 'DISPATCH'[\s\S]*pages\/dispatch\/dispatch/)
assert.match(outbound, /outboundPickPayload/); assert.match(outbound, /await getOutboundTask[\s\S]*releaseFulfillmentKey/)
assert.match(outbound, /outboundPickPayload/); assert.match(outbound, /await getOutboundTask/); assert.doesNotMatch(outbound, /releaseFulfillmentKey/)
assert.doesNotMatch(dispatch + outbound, /DeliveryOrder|deliveryStatus|customerVisit|\/deliveries/)
})