fix(dropship): project sealed carton identities into overseas receiving

This commit is contained in:
2026-09-09 13:20:11 +08:00
parent 90973532f0
commit 748855793d
19 changed files with 558 additions and 33 deletions
@@ -4,11 +4,74 @@ import path from 'node:path'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import { expandOverseasCartonCandidates, run } from './phase4-overseas-pda.mjs'
import { expandOverseasCartonCandidates, resolveCartonFixtures, run } from './phase4-overseas-pda.mjs'
const here = path.dirname(fileURLToPath(import.meta.url))
const source = fs.readFileSync(path.join(here, 'phase4-overseas-pda.mjs'), 'utf8')
test('dropship original counted cartons must resolve exactly before any receiving or inventory checks', async () => {
const inbounds = [{ inboundCode: 'REAL-INBOUND', destinationType: 'OVERSEAS', totalPackages: 2 }]
const producer = { fulfillmentType: 'ONE_CLICK_DROPSHIP', inboundCode: 'REAL-INBOUND', destinationType: 'OVERSEAS',
sealedCartonMarks: ['REAL-INBOUND#2-2', 'REAL-INBOUND#2-1'] }
for (const fault of [null, 'missing-carton', 'wrong-carton', 'wrong-inbound', 'wrong-destination']) {
const calls = []; const checks = []
const context = {
async requestOverseas(method, requestPath, body) {
calls.push({ method, requestPath, body })
const data = { cartonMark: body.cartonMark, inboundCode: 'REAL-INBOUND', destinationType: 'OVERSEAS' }
if (fault === 'wrong-carton') data.cartonMark = 'ANOTHER-CARTON'
if (fault === 'wrong-inbound') data.inboundCode = 'ANOTHER-INBOUND'
if (fault === 'wrong-destination') data.destinationType = 'FBA'
return { http: 200, body: { code: fault === 'missing-carton' ? 'A0404' : '200',
message: 'Carton mark was not found', data }, requestId: 'request', traceId: 'trace' }
},
assert(module, name, response, passed) { checks.push({ name, passed }) },
addStep(module, name, response, passed) { checks.push({ name, passed }) },
addCoverageGap() {},
}
const result = await resolveCartonFixtures(context, 'token', inbounds, ['OLD-CANDIDATE#20-1'], producer)
assert.ok(calls.every(call => call.method === 'POST' && call.requestPath.endsWith('/current/cartons/resolve')))
assert.ok(calls.every(call => producer.sealedCartonMarks.includes(call.body.cartonMark)))
if (fault) {
assert.equal(result, null, fault)
assert.ok(checks.some(check => !check.passed), fault)
assert.ok(!checks.some(check => check.name.includes('排除未实装箱码候选')), fault)
} else {
assert.deepEqual(result.map(item => item.cartonMark), producer.sealedCartonMarks)
assert.equal(calls.length, 2)
assert.ok(checks.every(check => check.passed))
}
}
for (const sealedCartonMarks of [undefined, [], ['REAL-INBOUND#2-1'], ['REAL-INBOUND#2-1', 'REAL-INBOUND#2-1']]) {
const checks = []
const result = await resolveCartonFixtures({ assert(m,n,r,passed) { checks.push(passed) },
async requestOverseas() { assert.fail('incomplete physical fixture must not issue HTTP') } },
'token', inbounds, producer.sealedCartonMarks, { ...producer, sealedCartonMarks })
assert.equal(result, null)
assert.deepEqual(checks, [false])
}
})
test('current loading event binds each pallet carton group to an explicit source detail', () => {
const model = fs.readFileSync(path.join(here, '../../common-event-contract/src/main/java/com/baiyue/common/event/FirstLegLoadingPlanCompletedV2.java'), 'utf8')
const producer = fs.readFileSync(path.join(here, '../../firstleg/src/main/java/com/baiyue/firstleg/service/LoadingCompletedOutboxService.java'), 'utf8')
assert.match(model, /record SkuPackageSnapshot\(String sourceInboundDetailId, String skuCode/)
assert.match(model, /sourceInboundDetailId == null \|\| sourceInboundDetailId\.isBlank\(\)/)
assert.match(producer, /SkuPackageSnapshot\(detail\.detailId\(\)\.toString\(\), detail\.skuCode\(\)/)
assert.match(producer, /SkuPackageSnapshot\(detail\.getSourceInboundDetailId\(\)\.toString\(\), detail\.getSkuCode\(\)/)
const measurement = fs.readFileSync(path.join(here, 'inbound-measurement.mjs'), 'utf8')
const loading = fs.readFileSync(path.join(here, 'phase3-loading.mjs'), 'utf8')
const finalize = fs.readFileSync(path.join(here, 'phase3-loading-finalize.mjs'), 'utf8')
assert.match(measurement, /sealedCartonMarks\.push\(resolved\.boxCode\)/)
assert.match(loading, /phase3Loading\.cartonMarks = marks/)
assert.match(finalize, /sealedCartonMarks: Array\.isArray\(fixture\.sealedCartonMarks\)/)
const entry = fs.readFileSync(path.join(here, '../admin-test-env-acceptance.mjs'), 'utf8')
assert.match(entry, /sealedCartonMarks: Array\.isArray\(fixture\.sealedCartonMarks\)/)
assert.match(entry, /runPhase4ProducerVariant\('OVERSEAS-PRIMARY', 'OVERSEAS', 'ONE_CLICK_DROPSHIP', true\)/)
assert.match(source, /resolveCartonFixtures\(context, token, current\.data\.inbounds, producerCartonMarks, preferredProducer\)/)
assert.ok(source.indexOf('const cartonFixtures = await resolveCartonFixtures') < source.indexOf('const completed = await pda'))
})
test('PDA module is injected, token-scoped, traceable, and contains no direct network or secret source', () => {
assert.match(source, /export async function run\(context\)/)
assert.match(source, /requestOverseas\(/)