优化
This commit is contained in:
@@ -1,96 +1,50 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
|
||||
const read = (path) => readFileSync(new URL(path, import.meta.url), 'utf8')
|
||||
const controller = read('../../firstleg/src/main/java/com/baiyue/firstleg/controller/PlatformContainerController.java')
|
||||
const oceanService = read('../../firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/service/OceanBookingService.java')
|
||||
const oceanOpenApi = read('../../firstleg/src/main/resources/openapi/ocean-bookings-v1.yaml')
|
||||
const containerDtos = read('../../firstleg/src/main/java/com/baiyue/firstleg/dto/ContainerDtos.java')
|
||||
const containerService = read('../../firstleg/src/main/java/com/baiyue/firstleg/service/ContainerService.java')
|
||||
const oceanService = read('../../firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/service/OceanBookingService.java')
|
||||
const oceanMapper = read('../../firstleg/src/main/java/com/baiyue/firstleg/oceanbooking/mapper/OceanBookingMapper.java')
|
||||
const firstlegOpenApi = read('../../firstleg/src/main/resources/openapi/firstleg-v1.yaml')
|
||||
const oceanOpenApi = read('../../firstleg/src/main/resources/openapi/ocean-bookings-v1.yaml')
|
||||
const loadingFixture = read('phase3-container-loading.mjs')
|
||||
const fixture = read('phase3-container-loading.mjs')
|
||||
const fullEntry = read('../admin-test-env-acceptance.mjs')
|
||||
const matrix = read('../../../docs/三期/货柜管理全链验收矩阵-2026-08-13.md')
|
||||
|
||||
test('operational ocean booking list excludes unconfirmed data', () => {
|
||||
assert.match(oceanService, /OPERATIONAL_LIST_STATUSES\s*=\s*Set\.of\([\s\S]*CONFIRMED[\s\S]*CHANGE_PENDING[\s\S]*RELEASED[\s\S]*CANCELLED/)
|
||||
assert.match(oceanMapper, /status IN \('CONFIRMED','CHANGE_PENDING','RELEASED','CANCELLED'\)/)
|
||||
assert.match(oceanOpenApi, /enum: \[CONFIRMED, CHANGE_PENDING, RELEASED, CANCELLED\]/)
|
||||
assert.match(oceanOpenApi, /DRAFT is internal to the create transaction and legacy SUBMITTED\/FAILED values are invalid/)
|
||||
assert.doesNotMatch(oceanOpenApi.match(/name: status[^\n]*/)?.[0] || '', /DRAFT|SUBMITTED/)
|
||||
test('booking is an editable DRAFT aggregate and RELEASED is immutable', () => {
|
||||
assert.match(oceanService, /OPERATIONAL_LIST_STATUSES\s*=\s*Set\.of\([\s\S]*DRAFT[\s\S]*RELEASED/)
|
||||
assert.match(oceanOpenApi, /Create an editable DRAFT/)
|
||||
assert.match(oceanOpenApi, /Replace a DRAFT/)
|
||||
assert.match(oceanOpenApi, /Delete a DRAFT; RELEASED is immutable/)
|
||||
assert.doesNotMatch(oceanOpenApi, /CHANGE_PENDING|CANCELLED/)
|
||||
})
|
||||
|
||||
test('simulation creation uses server-owned identity and formal master data', () => {
|
||||
assert.match(controller, /@PostMapping[\s\S]*SimulationCreateRequest request[\s\S]*createSimulation/)
|
||||
assert.match(containerDtos, /SimulationCreateRequest\(@NotBlank[\s\S]*String channelCode[\s\S]*Long warehouseId[\s\S]*String containerType[\s\S]*BigDecimal capacityCbm[\s\S]*BigDecimal maxWeightKg/)
|
||||
assert.match(containerService, /requireDomesticTransitWarehouse\(request\.warehouseId\(\)\)/)
|
||||
assert.match(containerService, /activeVersionId\(\)[\s\S]*priceBooks\.channels\(versionId, warehouse\.id\(\)\)/)
|
||||
assert.match(containerService, /setCabinetNo\("CAB-" \+ value\.getId\(\)\)/)
|
||||
assert.match(firstlegOpenApi, /服务端生成稳定 containerBookingId\/cabinetNo,不要求真实柜号或订舱/)
|
||||
test('booking requirements never carry real container numbers or create allocations', () => {
|
||||
assert.match(oceanOpenApi, /containerRequirements/)
|
||||
assert.match(oceanOpenApi, /ContainerRequirementRequest/)
|
||||
assert.match(oceanOpenApi, /quantity/)
|
||||
assert.match(oceanOpenApi, /no containerNo, container row, or allocation is created/)
|
||||
assert.doesNotMatch(oceanOpenApi.match(/ContainerRequirementRequest:[\s\S]*?ReleaseRequest:/)?.[0] || '', /containerNo/)
|
||||
})
|
||||
|
||||
test('link consumes one active real booking container through the frozen request', () => {
|
||||
assert.match(controller, /@PostMapping\("\/\{id\}\/ocean-booking-link"\)/)
|
||||
assert.match(controller, /@DeleteMapping\("\/\{id\}\/ocean-booking-link"\)/)
|
||||
assert.match(containerDtos, /OceanBookingLinkRequest\(@NotNull @Positive Long realContainerBookingId,[\s\S]*expectedVersion/)
|
||||
assert.match(containerService, /requireFirstLinkMutable\(container\)/)
|
||||
assert.match(containerService, /repository\.findForUpdate\(request\.realContainerBookingId\(\)\)/)
|
||||
assert.match(containerService, /"OCEAN_BOOKING"\.equals\(source\.getSourceType\(\)\)/)
|
||||
assert.match(containerService, /"ACTIVE"\.equals\(source\.getRecordStatus\(\)\)/)
|
||||
assert.match(containerService, /"CONFIRMED"\.equals\(booking\.getStatus\(\)\)[\s\S]*"RELEASED"\.equals\(booking\.getStatus\(\)\)/)
|
||||
assert.match(containerService, /hasPickTask[\s\S]*hasEvidence[\s\S]*hasDocuments/)
|
||||
assert.match(firstlegOpenApi, /realContainerBookingId/)
|
||||
assert.match(firstlegOpenApi, /原真实柜置 MERGED 且不再出现在正常货柜列表/)
|
||||
test('port link mutates the simulation through the frozen four-field request', () => {
|
||||
assert.match(containerDtos, /OceanBookingLinkRequest\(@NotNull @Positive Long oceanBookingId,[\s\S]*Long requirementId,[\s\S]*String containerNo,[\s\S]*Integer expectedVersion/)
|
||||
assert.match(containerService, /request\.oceanBookingId\(\)/)
|
||||
assert.match(containerService, /request\.requirementId\(\)/)
|
||||
assert.match(containerService, /request\.containerNo\(\)/)
|
||||
assert.match(containerService, /["']RELEASED["']\.equals\(booking\.getStatus\(\)\)/)
|
||||
assert.doesNotMatch(fixture, /realContainerBookingId/)
|
||||
assert.match(fixture, /oceanBookingId: bookingId, requirementId: id\(requirement\.id\), containerNo: realContainerNo/)
|
||||
})
|
||||
|
||||
test('real booking merge locks scope and changes all identities atomically', () => {
|
||||
for (const field of ['warehouseId', 'channelCode', 'containerType', 'capacityCbm', 'maxWeightKg']) {
|
||||
assert.match(containerService, new RegExp(`container\\.get${field[0].toUpperCase()}${field.slice(1)}\\(\\)`), field)
|
||||
}
|
||||
assert.match(containerService, /hasMismatchedCustomerItems/)
|
||||
assert.match(containerService, /consumeRealSource\(source\.getId\(\), id/)
|
||||
assert.match(containerService, /mergeRealSource\(id, source\.getId\(\), source\.getContainerNo\(\)/)
|
||||
assert.match(containerService, /reassignAllocation\(source\.getId\(\), id\)/)
|
||||
assert.doesNotMatch(containerService.match(/linkOceanBooking[\s\S]*?return required\(id\);/)?.[0] || '', /container\.setId\(|container\.setCabinetNo\(/)
|
||||
test('HTTP fixture keeps simulation and plan identities and creates allocation at link', () => {
|
||||
assert.match(fixture, /关联前后内部柜次、计划和排货明细身份稳定/)
|
||||
assert.match(fixture, /订舱 allocation 原子创建并指向稳定模拟柜身份/)
|
||||
assert.match(fixture, /已消费订舱需求拒绝再次关联/)
|
||||
assert.match(fixture, /RELEASED 订舱进入正式列表/)
|
||||
})
|
||||
|
||||
test('booking creation atomically registers one real operational container per input row', () => {
|
||||
assert.match(oceanOpenApi, /containers: \{type: array, minItems: 1, maxItems: 20/)
|
||||
assert.match(oceanOpenApi, /required: \[containerNo, containerType, containerKind, capacityCbm, maxWeightKg\]/)
|
||||
assert.match(oceanService, /request\.data\(\)\.containers\(\)\.forEach/)
|
||||
assert.match(oceanService, /同一订舱内集装箱号不能重复/)
|
||||
assert.match(oceanService, /createRealContainers\(value, requirements, request\.data\(\)\.containers\(\)/)
|
||||
assert.match(oceanService, /setSourceType\("OCEAN_BOOKING"\)/)
|
||||
assert.match(oceanService, /setRecordStatus\("ACTIVE"\)/)
|
||||
assert.match(oceanService, /setQuantity\(1\)/)
|
||||
})
|
||||
|
||||
test('HTTP fixture follows simulation arrange link PDA sequence without auto-container fallback', () => {
|
||||
const ordered = [
|
||||
'新增内部模拟柜',
|
||||
'人工分配本轮候选货物',
|
||||
'首次关联真实已确认订舱柜',
|
||||
'查询本轮柜次 PDA 拣货任务',
|
||||
].map((label) => loadingFixture.indexOf(label))
|
||||
assert.ok(ordered.every((value) => value >= 0), `missing sequence label: ${ordered.join(',')}`)
|
||||
assert.ok(ordered.every((value, index) => index === 0 || value > ordered[index - 1]), `invalid sequence: ${ordered.join(',')}`)
|
||||
assert.match(loadingFixture, /ocean-booking-link/)
|
||||
assert.match(loadingFixture, /关联前后内部柜次、计划和排货明细身份稳定/)
|
||||
assert.match(loadingFixture, /已消费 MERGED 真实柜拒绝再次关联/)
|
||||
assert.match(loadingFixture, /已有排货后拒绝解绑或换绑/)
|
||||
assert.match(loadingFixture, /合并后列表仅保留模拟柜原地转成的一条 ACTIVE 操作身份/)
|
||||
assert.match(loadingFixture, /订舱真实柜 allocation 已原子改指稳定模拟柜身份/)
|
||||
assert.doesNotMatch(loadingFixture, /确认订舱并自动生成|确认响应包含自动生成/)
|
||||
})
|
||||
|
||||
test('default full acceptance preserves the linked simulation chain before downstream completion', () => {
|
||||
test('default full acceptance keeps the linked simulation before PDA and finalize', () => {
|
||||
const loading = fullEntry.indexOf("'phase3-container-loading'")
|
||||
const pda = fullEntry.indexOf("'phase3-pda-convergence'")
|
||||
const finalize = fullEntry.indexOf("'phase3-loading-finalize'")
|
||||
const outbound = fullEntry.indexOf("'phase3-outbound-dispatch'")
|
||||
assert.ok(loading >= 0 && pda > loading && finalize > pda && outbound > finalize)
|
||||
assert.match(matrix, /内部模拟柜关联真实订舱增量/)
|
||||
assert.doesNotMatch(matrix, /CONFIRMED` 自动建柜[\s\S]*既有冻结/)
|
||||
assert.ok(loading >= 0 && pda > loading && finalize > pda)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user