This commit is contained in:
2026-08-14 12:50:37 +08:00
parent 91e781b3ff
commit ce6963a25e
46 changed files with 664 additions and 76 deletions
@@ -7,7 +7,100 @@ const GROUPS = [
'manual-state-ocean-trucking',
]
const FIXTURE_UNAVAILABLE = {
inbounds: {
WAIT_PRICING: '自动计费会继续推进,无法稳定保留 WAIT_PRICING',
FEE_CONFIRMING: '当前无可稳定保留的费用确认前公开生成链路',
INBOUNDING: '自动入库在同一调用内继续推进 WAIT_SPLIT,无可暂停 API',
VOIDED: '当前 Controller/Service 没有作废入库单的公开 API',
},
unifiedOrders: {
DELIVERED: '当前后端没有完成派送并写入 DELIVERED 的公开业务 API',
},
}
function rows(value) { return Array.isArray(value) ? value : [] }
function id(value) { return value == null ? '' : String(value) }
export function normalizeStateRequirements(matrix) {
for (const [page, value] of Object.entries(matrix?.pages || {})) {
const supportedStatuses = [...new Set([
...rows(value?.supportedStatuses), ...rows(value?.requiredStatuses),
])]
const unavailable = FIXTURE_UNAVAILABLE[page] || {}
value.supportedStatuses = supportedStatuses
value.requiredStatuses = supportedStatuses.filter((status) => !unavailable[status])
if (Object.keys(unavailable).length > 0) {
value.coverageGaps = Object.fromEntries(Object.entries(unavailable).map(([status, reason]) => [status, {
category: 'fixture-unavailable', reason,
}]))
}
}
return matrix
}
export function missingRequiredStateFixtures(matrix) {
return Object.entries(matrix?.pages || {}).flatMap(([page, value]) => rows(value?.requiredStatuses)
.filter((status) => !value?.fixtures?.[status]?.id)
.map((status) => `${page}:${status}`))
}
function registerFixtureUnavailableGaps(context, matrix) {
for (const [page, value] of Object.entries(matrix?.pages || {})) {
for (const [status, gap] of Object.entries(value?.coverageGaps || {})) {
if (value?.fixtures?.[status]?.id) continue
if (rows(context.coverageGaps).some((item) => item?.category === gap.category
&& String(item?.name || '').includes(status))) continue
context.addCoverageGap?.(MODULE, OPTIONS.scenario, `${page}:${status}`, gap.reason,
gap.category, { marker: context.marker, page, status })
}
}
}
function clearResolvedProvisionalGap(context, status) {
if (!Array.isArray(context.coverageGaps)) return
for (let index = context.coverageGaps.length - 1; index >= 0; index -= 1) {
const gap = context.coverageGaps[index]
if (gap?.module === 'order-inbound-status-fixtures'
&& gap?.scenario === 'manual-order-inbound-status-matrix'
&& gap?.category === 'fixture-unavailable'
&& gap?.name === `统一订单列表保留 ${status}`) context.coverageGaps.splice(index, 1)
}
}
async function attachUnifiedOrderFixture(context, matrix, resourceName, expectedStatus) {
const resource = context.createdResources?.[resourceName]
const inboundId = id(resource?.inboundId)
const tenantId = id(resource?.tenantId)
context.assert(MODULE, `${expectedStatus} 专项资源已生成`, null,
Boolean(inboundId && tenantId),
`resource=${resourceName}, inboundId=${inboundId || 'missing'}, tenantId=${tenantId || 'missing'}`, OPTIONS)
if (!inboundId || !tenantId) return
const inboundResponse = await context.request('GET',
`/api/platform/inbounds/${encodeURIComponent(inboundId)}?tenantId=${encodeURIComponent(tenantId)}`)
const inbound = context.apiSuccess(MODULE, `读取 ${expectedStatus} 专项入库详情`, inboundResponse, '', OPTIONS)
const orderId = id(inbound?.summary?.orderId)
context.assert(MODULE, `${expectedStatus} 入库详情身份与状态正确`, inboundResponse,
id(inbound?.summary?.id) === inboundId && id(inbound?.summary?.tenantId) === tenantId
&& Boolean(orderId) && inbound?.summary?.processStatus === expectedStatus,
`inboundId=${id(inbound?.summary?.id) || 'missing'}, orderId=${orderId || 'missing'}, status=${inbound?.summary?.processStatus || 'missing'}`, OPTIONS)
if (!orderId || inbound?.summary?.processStatus !== expectedStatus) return
const unifiedResponse = await context.request('GET',
`/api/platform/v1/orders/${encodeURIComponent(orderId)}?tenantId=${encodeURIComponent(tenantId)}`)
const unified = context.apiSuccess(MODULE, `读取 ${expectedStatus} 统一订单详情`, unifiedResponse, '', OPTIONS)
const valid = id(unified?.summary?.orderId) === orderId && unified?.summary?.mainStatus === expectedStatus
context.assert(MODULE, `${expectedStatus} 统一订单详情可打开`, unifiedResponse, valid,
`orderId=${id(unified?.summary?.orderId) || 'missing'}, mainStatus=${unified?.summary?.mainStatus || 'missing'}`, OPTIONS)
if (!valid) return
matrix.pages.unifiedOrders.fixtures[expectedStatus] = {
id: orderId, status: expectedStatus, inboundId,
detailPath: `/orders/${orderId}`,
}
clearResolvedProvisionalGap(context, expectedStatus)
}
export async function run(context) {
const matrix = { marker: context.marker, generatedAt: new Date().toISOString(), pages: {} }
@@ -19,10 +112,13 @@ export async function run(context) {
await extension.run(context, matrix)
}
await attachUnifiedOrderFixture(context, matrix, 'phase3ContainerLoading', 'LOADING')
await attachUnifiedOrderFixture(context, matrix, 'phase3Loading', 'LOADED')
normalizeStateRequirements(matrix)
registerFixtureUnavailableGaps(context, matrix)
const pages = Object.entries(matrix.pages)
const missing = pages.flatMap(([page, value]) => rows(value?.requiredStatuses)
.filter((status) => !value?.fixtures?.[status]?.id)
.map((status) => `${page}:${status}`))
const missing = missingRequiredStateFixtures(matrix)
const missingActions = pages.flatMap(([page, value]) => rows(value?.requiredActions)
.filter((action) => !value?.actions?.[action]?.id
|| !value?.actions?.[action]?.documentId || !value?.actions?.[action]?.completedAt)