This commit is contained in:
2026-08-26 15:24:48 +08:00
parent 3f9ee28d22
commit 4ae236fe11
18 changed files with 198 additions and 92 deletions
@@ -23,29 +23,27 @@ export async function run(context) {
'本轮未取得 phase3-outbound-dispatch 的 marker 隔离聚合,未使用历史资源', 'fixture')
return
}
const selector = `inboundId=${encodeURIComponent(fixture.inboundId)}&containerBookingId=${encodeURIComponent(fixture.containerBookingId)}`
const response = await context.request('GET', `${BASE}/detail?${selector}`)
const detail = context.apiSuccess(MODULE, '复核出仓主聚合与统一时间线', response, selector, OPTIONS)
const response = await context.request('GET', `${BASE}/${encodeURIComponent(fixture.containerBookingId)}`)
const detail = context.apiSuccess(MODULE, '复核柜级出仓主聚合与统一时间线', response,
`containerBookingId=${fixture.containerBookingId}`, OPTIONS)
const aggregate = detail?.aggregate
const inbound = aggregate?.inbounds?.find?.((item) => id(item?.inboundId) === id(fixture.inboundId))
const timeline = Array.isArray(detail?.timeline) ? detail.timeline : []
const expectedModules = ['INBOUND', 'LOADING_PLAN', 'PDA_PICK', 'LOADING_EVIDENCE',
'OCEAN_BOOKING', 'TRUCK_APPOINTMENT', 'CUSTOMS', 'SAILING_SCHEDULE', 'OUTBOUND_DISPATCH']
'OCEAN_BOOKING', 'CUSTOMS', 'OUTBOUND_DISPATCH']
context.assert(MODULE, '聚合唯一关联本轮订单、入库单、柜次和客户', response,
id(aggregate?.orderId) === id(fixture.orderId) && id(aggregate?.tenantId) === id(fixture.tenantId)
&& id(aggregate?.inboundId) === id(fixture.inboundId)
id(inbound?.orderId) === id(fixture.orderId) && id(inbound?.tenantId) === id(fixture.tenantId)
&& id(inbound?.inboundId) === id(fixture.inboundId)
&& id(aggregate?.containerBookingId) === id(fixture.containerBookingId),
`orderId=${id(aggregate?.orderId) || 'missing'}, inboundId=${id(aggregate?.inboundId) || 'missing'}, containerBookingId=${id(aggregate?.containerBookingId) || 'missing'}`, OPTIONS)
`orderId=${id(inbound?.orderId) || 'missing'}, inboundId=${id(inbound?.inboundId) || 'missing'}, containerBookingId=${id(aggregate?.containerBookingId) || 'missing'}`, OPTIONS)
context.assert(MODULE, '统一时间线有序且各子流程包含审计字段', response,
timeline.length > 0 && ordered(timeline)
&& expectedModules.every((module) => timeline.some((item) => item.module === module))
&& timeline.every((item) => Boolean(item.action) && Boolean(item.occurredAt)),
`timeline=${timeline.length}, modules=${[...new Set(timeline.map((item) => item.module))].join(',')}`, OPTIONS)
const other = context.createdResources?.phase3ContainerLoading
if (other?.inboundId && other?.containerBookingId
&& (id(other.inboundId) !== id(fixture.inboundId) || id(other.containerBookingId) !== id(fixture.containerBookingId))) {
const forged = await context.request('GET', `${BASE}/detail?inboundId=${encodeURIComponent(fixture.inboundId)}&containerBookingId=${encodeURIComponent(other.containerBookingId)}`)
context.addStep(MODULE, '伪造跨资源入库单与柜次组合不可匹配', forged, rejected(forged),
`HTTP=${forged.http}, code=${codeOf(forged)}`, OPTIONS)
}
context.assert(MODULE, '拖车和独立船期时间线只作参考', response,
['TRUCK_APPOINTMENT', 'SAILING_SCHEDULE'].every((module) => timeline
.filter((item) => item.module === module).every((item) => Boolean(item.action) && Boolean(item.occurredAt))),
`referenceModules=${timeline.filter((item) => ['TRUCK_APPOINTMENT', 'SAILING_SCHEDULE'].includes(item.module)).length}`, OPTIONS)
}