优化
This commit is contained in:
@@ -11,7 +11,7 @@ const OPTIONAL_MODULES = ['manual-order-splitting-fixture', 'manual-order-splitt
|
||||
'manual-pda-ready-fixture', 'manual-pda-ready-verify',
|
||||
'manual-pda-batch-fixture', 'manual-pda-batch-verify',
|
||||
'manual-loading-complete-fixture', 'manual-loading-complete-verify',
|
||||
'coload-groups', 'dropship-pallet-matrix']
|
||||
'coload-groups', 'dropship-pallet-matrix', 'dropship-browser-fixture']
|
||||
const AVAILABLE_MODULES = new Set([...CONFIGURED_MODULES, ...OPTIONAL_MODULES])
|
||||
const A0_LOCATION_PAGE_SIZE = 200
|
||||
const A0_MAX_LOCATION_MUTATIONS = 8
|
||||
@@ -43,6 +43,7 @@ export function planA0LocationIsolation(locations, requiredSlots = 1,
|
||||
|
||||
const MODULE_DEPENDENCIES = new Map([
|
||||
['dropship-pallet-matrix', ['merchant-qualification-fixture']],
|
||||
['dropship-browser-fixture', ['merchant-qualification-fixture']],
|
||||
['suppliers', ['merchant-qualification-fixture']],
|
||||
['supplemental', ['merchant-qualification-fixture']],
|
||||
['orders', ['merchant-qualification-fixture']],
|
||||
|
||||
@@ -37,6 +37,8 @@ export async function run(context) {
|
||||
|
||||
## 可用上下文
|
||||
|
||||
`dropship-browser-fixture.mjs` 通过总入口 `--modules dropship-browser-fixture` 执行,自动依赖客户资质准备;复用矩阵生产者创建一票四箱两托,完成国内装柜、船节点和按柜生成海外入库计划,明确停在 `READY_FOR_BROWSER_RECEIVING`。只准备新测试数据,不调用海外 PDA 收货或出库、不创建海外操作员;后续由浏览器页面验收。报告仍保存于 `createdResources.dropshipPalletMatrix`,准备通过不代表全流程通过,不自动删除数据。
|
||||
|
||||
`dropship-pallet-matrix.mjs` 验证下述四场景整托手工加入、整托移除、智能推荐、独立订舱与文件放舱、真实柜号关联、预装确认、PDA 整托拣货和五类证据上传;异步装柜完成必须等到任务 `COMPLETED` 并逐票回查 `LOADED`。智能装柜的托盘汇总与装柜详情逐票组成分别核对,不能把共托汇总行的首票编号当作全托归属。随后经正式报关、国内离仓及人工船节点接口推进至 `PICKUP_READY`,再按柜生成逐票海外入库计划,检查来源托盘完整绑定、共享托盘身份一致和同键重放。海外收货使用本轮创建并绑定接柜仓的 PDA 操作员,上传三类照片、签收、逐实物托盘收货、逐票箱数核平和完成入库,同键重放及同托新键扫码均不得重复入账。随后从本轮逐票库存候选创建一件代发专用出库,携带原始箱唛由 PDA 拣货、完成,核对终态、幂等和可用库存扣减;finally 停用本轮操作员。出库重放按业务身份和数据库毫秒时间精度核对。离线合同为 `dropship-pallet-matrix-contract.test.mjs`;脚本覆盖不等于真实 HTTP 已通过,须检查当轮报告和库存审计。
|
||||
|
||||
- `dropship-pallet-matrix` 通过总入口 `--modules dropship-pallet-matrix` 执行,自动依赖客户资质准备。通过正式 HTTP 创建五票订单,覆盖单票多托、单票单托、单票移箱合托、多票共享开放托盘;会创建并保留测试数据,不自动清理。报告 `createdResources.dropshipPalletMatrix` 保存逐票箱唛、托盘及各阶段证据,失败即停止并保留阻断;重跑创建新批次,不借用历史资源。`fullFlowVerified=false`,不能代替海外收货及一件代发专用出库的完整验收。
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// Explicit UI handoff: creates one fresh multi-pallet order and stops before overseas PDA writes.
|
||||
export { prepareBrowserFixture as run } from './dropship-pallet-matrix.mjs'
|
||||
@@ -5,6 +5,16 @@ import { normalizeModuleOrder } from '../admin-test-env-acceptance.mjs'
|
||||
import { sameOutboundTask } from './dropship-pallet-matrix.mjs'
|
||||
import { probePartialPick } from './dropship-outbound-edge-cases.mjs'
|
||||
|
||||
test('browser fixture is explicit and stops before overseas receipt or outbound', () => {
|
||||
assert.deepEqual(normalizeModuleOrder(['dropship-browser-fixture']), ['merchant-qualification-fixture', 'dropship-browser-fixture'])
|
||||
const source = readFileSync(new URL('dropship-pallet-matrix.mjs', import.meta.url), 'utf8')
|
||||
const branch = source.slice(source.indexOf('if (stopBeforeOverseasPda)'), source.indexOf("await verify(await prepare('SINGLE-MULTI'"))
|
||||
assert.match(branch, /prepare\('BROWSER-MULTI', 2\)/)
|
||||
assert.match(branch, /convertOverseas\(\[record\]\)/)
|
||||
assert.match(branch, /READY_FOR_BROWSER_RECEIVING'[\s\S]*return/)
|
||||
assert.doesNotMatch(branch, /receiveOverseas|outboundOverseas|createPicker/)
|
||||
})
|
||||
|
||||
test('partial-pick rejection stays failed; a changed snapshot aborts further picking', async () => {
|
||||
const failures = []
|
||||
const snapshot = { pallets: [{ pickedPackageCount: 0 }] }
|
||||
|
||||
@@ -30,6 +30,14 @@ export function sameOutboundTask(left, right) {
|
||||
// Domestic producer stage: these retained loaded fixtures must subsequently be verified
|
||||
// through overseas receipt and dedicated dropship outbound, not generic dispatch.
|
||||
export async function run(context) {
|
||||
return runWorkflow(context, false)
|
||||
}
|
||||
|
||||
export async function prepareBrowserFixture(context) {
|
||||
return runWorkflow(context, true)
|
||||
}
|
||||
|
||||
async function runWorkflow(context, stopBeforeOverseasPda) {
|
||||
const marker = context.marker
|
||||
const savedOptions = context.options.prepareDropshipManualCount
|
||||
const savedContext = { ...context.context }
|
||||
@@ -472,6 +480,15 @@ export async function run(context) {
|
||||
for (const record of group) record.outbound = { task: completed, selected, detail: outbound, completed: true }
|
||||
}
|
||||
try {
|
||||
if (stopBeforeOverseasPda) {
|
||||
const record = await prepare('BROWSER-MULTI', 2)
|
||||
await verify(record, 2)
|
||||
await allocate([record])
|
||||
await progressShipping([record])
|
||||
await convertOverseas([record])
|
||||
context.createdResources.dropshipPalletMatrix.stage = 'READY_FOR_BROWSER_RECEIVING'
|
||||
return
|
||||
}
|
||||
await verify(await prepare('SINGLE-MULTI', 2), 2)
|
||||
await verify(await prepare('SINGLE-SINGLE', 1), 1)
|
||||
await verify(await prepare('SINGLE-MERGE', 2, { mergeToFirstPallet: true }), 1)
|
||||
|
||||
@@ -7,6 +7,7 @@ const openapi = read('../../firstleg/src/main/resources/openapi/firstleg-v1.yaml
|
||||
const service = read('../../firstleg/src/main/java/com/baiyue/firstleg/service/SmartLoadingService.java')
|
||||
const outbox = read('../../firstleg/src/main/java/com/baiyue/firstleg/service/LoadingCompletedOutboxService.java')
|
||||
const event = read('../../common-event-contract/src/main/java/com/baiyue/common/event/FirstLegLoadingPlanCompletedV2.java')
|
||||
const eventV3 = read('../../common-event-contract/src/main/java/com/baiyue/common/event/FirstLegLoadingPlanCompletedV3.java')
|
||||
const admin = read('../../../apps/admin-web/src/modules/loading-lists/components/LoadingListDetailDrawer.vue')
|
||||
|
||||
test('fixture locks customer and latest internal note sources without cargoRemark leakage', () => {
|
||||
@@ -34,16 +35,18 @@ test('warehouse remark PATCH covers save clear stale version and source preserva
|
||||
assert.match(loading, /preservedRemarkItem\?\.warehouseRemark === warehouseRemark/)
|
||||
})
|
||||
|
||||
test('completed event V2 carries all three remarks with stable event payload', () => {
|
||||
test('completed event V3 retains V2 order remarks with stable event payload', () => {
|
||||
assert.match(outbox, /FirstLegLoadingPlanCompletedV2/)
|
||||
assert.match(outbox, /FirstLegLoadingPlanCompletedV3/)
|
||||
assert.match(eventV3, /List<FirstLegLoadingPlanCompletedV2\.Order> orders/)
|
||||
for (const field of ['customerRemark', 'internalRemark', 'warehouseRemark']) assert.match(event, new RegExp(field))
|
||||
assert.match(outbox, /row\.getCustomerRemark\(\)/)
|
||||
assert.match(outbox, /row\.getInternalRemark\(\)/)
|
||||
assert.match(outbox, /row\.getWarehouseRemark\(\)/)
|
||||
assert.match(outbox, /HANDOVER_VERSION = 2L/)
|
||||
assert.match(outbox, /HANDOVER_VERSION = 3L/)
|
||||
assert.match(outbox, /EventPayloadCanonicalizer\.canonicalize\(payloadNode\)/)
|
||||
assert.match(outbox, /FIRSTLEG_LOADING_COMPLETED:[^\n]*HANDOVER_VERSION/)
|
||||
assert.match(outbox, /EventTypes\.FIRST_LEG_LOADING_PLAN_COMPLETED, 2/)
|
||||
assert.match(outbox, /EventTypes\.FIRST_LEG_LOADING_PLAN_COMPLETED, 3/)
|
||||
})
|
||||
|
||||
test('Admin exposes only warehouse remark editing and keeps completed rows read-only', () => {
|
||||
|
||||
@@ -558,8 +558,8 @@ export async function run(context) {
|
||||
const producer = {
|
||||
marker: context.context?.phase4ProducerMatrixMarker || context.marker,
|
||||
eventType: 'FIRST_LEG_LOADING_PLAN_COMPLETED',
|
||||
eventVersion: 2,
|
||||
eventKey: `FIRSTLEG_LOADING_COMPLETED:${loadingPlanId}:${tenantId}:2`,
|
||||
eventVersion: 3,
|
||||
eventKey: `FIRSTLEG_LOADING_COMPLETED:${loadingPlanId}:${tenantId}:3`,
|
||||
resourceKey: `${context.marker}:${fixture.destinationType || 'UNKNOWN'}:${fixture.containerNo || containerBookingId}`,
|
||||
tenantId,
|
||||
aggregateType: 'LOADING_PLAN',
|
||||
|
||||
@@ -813,7 +813,7 @@ test('finalize publishes a current-marker producer correlation for cross-region
|
||||
assert.match(finalize, /createdResources\.phase3LoadingCompletedProducer = producer/)
|
||||
assert.match(finalize, /marker: context\.context\?\.phase4ProducerMatrixMarker \|\| context\.marker/)
|
||||
assert.match(finalize, /eventType: 'FIRST_LEG_LOADING_PLAN_COMPLETED'/)
|
||||
assert.match(finalize, /eventKey: `FIRSTLEG_LOADING_COMPLETED:\$\{loadingPlanId\}:\$\{tenantId\}:2`/)
|
||||
assert.match(finalize, /eventKey: `FIRSTLEG_LOADING_COMPLETED:\$\{loadingPlanId\}:\$\{tenantId\}:3`/)
|
||||
assert.match(finalize, /sourceStatus: 'LOADED'/)
|
||||
assert.match(finalize, /PRODUCED_IN_COMPLETE_TRANSACTION_PENDING_BRIDGE_CONSUMER_HTTP/)
|
||||
})
|
||||
|
||||
@@ -223,7 +223,6 @@ async function verifyDestinationMergeFeeAndExport(context, details, producer) {
|
||||
function manualPlanBody(order, version, marker) {
|
||||
return {
|
||||
customerId: id(order.customerId), orderId: id(order.id), expectedOrderVersion: Number(version),
|
||||
plannedArrivalDate: new Date(Date.now() + 7 * 86_400_000).toISOString().slice(0, 10),
|
||||
inboundCode: order.inboundCode,
|
||||
palletCount: Math.min(999, Math.max(1, Number(order.palletCount) || 1)),
|
||||
palletType: 'STANDARD', assigned: false, mergeRequired: false, urgent: true,
|
||||
|
||||
@@ -1102,6 +1102,7 @@ $criticalPaths = @(
|
||||
'baiyue-firstleg/gateway-overseas/src/test/java/com/baiyue/gateway/config/OverseasLastlegRouteContractTest.java',
|
||||
'baiyue-firstleg/event-bridge-service/src/main/java/com/baiyue/eventbridge/service/FirstlegEventClient.java',
|
||||
'baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/FirstLegLoadingPlanCompletedV2.java',
|
||||
'baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/FirstLegLoadingPlanCompletedV3.java',
|
||||
'baiyue-firstleg/common-event-contract/src/main/java/com/baiyue/common/event/FirstLegContainerShippingNodeRecordedV1.java',
|
||||
'baiyue-firstleg/firstleg/src/main/java/com/baiyue/firstleg/portschedule/service/CarrierScheduleNodeOutboxService.java',
|
||||
'baiyue-firstleg/lastleg-service/src/main/java/com/baiyue/lastleg/shipping/service/ContainerShippingNodeConsumer.java',
|
||||
|
||||
Reference in New Issue
Block a user