This commit is contained in:
2026-08-17 13:24:48 +08:00
parent ac6cf9c904
commit 6739c83467
43 changed files with 1049 additions and 315 deletions
@@ -31,23 +31,25 @@ test('ocean booking fixture blocks creation instead of inventing missing master
assert.match(steps[0][4], /missing=customerId,customerName,channelCode,channelName,warehouseId,warehouseName/)
})
test('shared booking data omits server-owned channelName and includes offline-confirmed transport snapshots', () => {
test('shared booking data omits server-owned names and registers unique real containers', () => {
const draft = oceanBookingDraft({ marker: 'ADMIN-RUN-3' }, '3', {
customerId: '21', customerName: 'IT 测试客户', channelCode: 'SEA-US', channelName: '美西海运',
warehouseId: '41', warehouseName: '深圳仓',
})
for (const key of ['customerId', 'customerName', 'channelCode', 'warehouseId', 'warehouseName']) {
for (const key of ['customerId', 'customerName', 'channelCode', 'warehouseId']) {
assert.ok(draft[key], `${key} is required`)
}
assert.equal(draft.channelName, undefined)
assert.equal(draft.warehouseName, undefined)
assert.equal(draft.shippingCompanyId, null)
assert.equal(draft.shippingCompanyName, null)
assert.equal(draft.bookingAgentId, null)
assert.equal(draft.bookingAgentName, null)
assert.equal(draft.serviceTerm, 'CY-CY')
assert.equal(draft.freightTerm, 'NINGBO')
assert.equal(draft.containerRequirements[0].capacityCbm, 68)
assert.equal(draft.containerRequirements[0].maxWeightKg, 28000)
assert.deepEqual(draft.containers, [{ containerNo: 'TST-3-01', containerType: '40HC',
containerKind: 'FCL', capacityCbm: 76, maxWeightKg: 28000 }])
assert.equal(Object.hasOwn(draft, 'containerRequirements'), false)
assert.equal(draft.billOfLadingNo, 'BL-3')
assert.equal(draft.vesselName, '验收船-3')
assert.equal(draft.voyageNo, 'V-3')
@@ -78,8 +80,22 @@ test('shared booking draft can omit customer identity without inventing placehol
assert.equal(Object.hasOwn(draft, 'customerName'), false)
assert.equal(draft.channelCode, 'SEA-US')
assert.equal(draft.warehouseId, '41')
assert.equal(draft.containerRequirements[0].capacityCbm, 68)
assert.equal(draft.containerRequirements[0].maxWeightKg, 28000)
assert.equal(draft.containers[0].containerType, '40HC')
assert.equal(draft.containers[0].capacityCbm, 76)
assert.equal(draft.containers[0].maxWeightKg, 28000)
})
test('shared booking builder accepts explicit isolated multi-container rows without quantity', () => {
const containers = [
{ containerNo: 'TST-MULTI-01', containerType: '40HC', containerKind: 'FCL', capacityCbm: 76, maxWeightKg: 28000 },
{ containerNo: 'TST-MULTI-02', containerType: '20GP', containerKind: 'FCL', capacityCbm: 33, maxWeightKg: 28000 },
]
const draft = oceanBookingDraft({ marker: 'ADMIN-RUN-MULTI' }, 'multi', {
customerId: '21', customerName: 'IT 测试客户', channelCode: 'SEA-US', channelName: '美西海运',
warehouseId: '41', warehouseName: '深圳仓',
}, { containers })
assert.deepEqual(draft.containers, containers)
assert.equal(draft.containers.some((item) => Object.hasOwn(item, 'quantity')), false)
})
test('platform channel producer queries the selected origin warehouse and publishes current-marker resources', async () => {
@@ -106,18 +122,22 @@ test('platform channel producer queries the selected origin warehouse and publis
test('all direct ocean booking payload builders omit channelName under the frozen DraftData contract', () => {
const regions = [
['manual-state-loading-pda.mjs', 'const draft = {', 'const createResponse'],
['manual-state-ocean-trucking.mjs', 'function oceanPayload', 'async function createOcean'],
['phase3-loading.mjs', 'const bookingDraft = {', 'const bookingCreate'],
['phase3-order-splitting.mjs', 'function bookingPayload', 'async function loadOneFragment'],
['phase3-container-loading.mjs', 'const bookingDraft = {', "context.assert(MODULE, '订舱渠道与仓库快照完整'"],
['manual-state-loading-pda.mjs', 'const draft = {', 'const createResponse', false],
['manual-state-ocean-trucking.mjs', 'function oceanPayload', 'async function createOcean', false],
['phase3-loading.mjs', 'const bookingDraft = {', 'const bookingCreate', false],
['phase3-order-splitting.mjs', 'function bookingPayload', 'async function loadOneFragment', true],
['phase3-container-loading.mjs', 'const bookingDraft = {', "context.assert(MODULE, '订舱渠道与仓库快照完整'", false],
]
for (const [name, start, end] of regions) {
for (const [name, start, end, usesSharedBuilder] of regions) {
const value = readFileSync(new URL(name, import.meta.url), 'utf8')
const region = value.slice(value.indexOf(start), value.indexOf(end))
assert.doesNotMatch(region, /channelName\s*:/, name)
for (const field of ['billOfLadingNo', 'vesselName', 'voyageNo', 'estimatedSailingAt', 'estimatedArrivalAt']) {
assert.match(region, new RegExp(`${field}\\s*:`), `${name} must register ${field}`)
if (usesSharedBuilder) {
assert.match(region, /oceanBookingDraft\(/, `${name} must use the shared formal booking builder`)
} else {
for (const field of ['billOfLadingNo', 'vesselName', 'voyageNo', 'estimatedSailingAt', 'estimatedArrivalAt']) {
assert.match(region, new RegExp(`${field}\\s*:`), `${name} must register ${field}`)
}
}
}
const container = readFileSync(new URL('phase3-container-loading.mjs', import.meta.url), 'utf8')
@@ -140,5 +160,5 @@ test('all independent ocean booking producers use the shared master-data contrac
}
const container = readFileSync(new URL('phase3-container-loading.mjs', import.meta.url), 'utf8')
for (const snippet of ['channelCode', 'publishPlatformLogisticsChannels', 'warehouseId', 'warehouseName',
'capacityCbm: 100', 'maxWeightKg: 100000']) assert.match(container, new RegExp(snippet), snippet)
"containerType: '40HC'", 'capacityCbm: 76', 'maxWeightKg: 28000']) assert.match(container, new RegExp(snippet), snippet)
})