This commit is contained in:
2026-11-04 18:08:19 +08:00
parent 0993dd446e
commit 51291b4c27
16 changed files with 468 additions and 47 deletions
@@ -0,0 +1,70 @@
import { normalizeFixedCustomerId } from './merchant-qualification-fixture.mjs'
export const FIXED_RESOURCE_READONLY_MODULES = Object.freeze([
'customers', 'system', 'master-data', 'notifications', 'pricing', 'phase4-overseas-master-data',
])
const IAM = '/api/platform/v1/iam'
const MASTER = '/api/platform/v1/last-leg/master-data'
const decimalId = value => /^[1-9]\d*$/.test(String(value ?? ''))
const pageShape = value => Array.isArray(value?.records)
&& Number(value.page) === 1 && Number(value.size) === 20
&& ['string', 'number'].includes(typeof value.total) && /^(0|[1-9]\d*)$/.test(String(value.total))
&& Number.isSafeInteger(Number(value.total))
&& Number(value.total) >= value.records.length && value.records.length <= 20
/** 固定资源只检查现有数据;生命周期缺口保留,不能以查询通过代替写入验收。 */
export async function runFixedResourceReadOnly(context, module) {
if (!context.options.fixedCustomerId || !FIXED_RESOURCE_READONLY_MODULES.includes(module))
throw Error('固定资源只读检查必须指定已有客户及受支持模块')
context.addCoverageGap(module, 'fixed-resource-lifecycle', '现有资源只读检查不覆盖创建、修改、发布及停用生命周期',
'复用已有客户、账号、角色和主档;生命周期仍为未验收', 'not-implemented', { blocking: false })
const proof = { mode: 'READ_ONLY', lifecycle: 'NOT_TESTED', checks: [] }
context.createdResources.fixedResourceReadOnly ??= {}
context.createdResources.fixedResourceReadOnly[module] = proof
async function get(label, path, validate) {
const response = await context.request('GET', path)
const value = context.apiSuccess(module, label, response)
const passed = response?.http === 200 && String(response.body?.code) === '200' && validate(value)
context.assert(module, `${label}结构及归属有效`, response, Boolean(passed), '', { deploymentBlocker: true })
proof.checks.push({ path, passed: Boolean(passed),
...(Array.isArray(value) ? { count: value.length }
: Array.isArray(value?.records) ? { count: value.records.length, total: Number(value.total) } : {}) })
if (!passed) throw Error(`${module}现有资源只读核验失败,禁止补建或修改`)
}
const page = (label, path, validate = () => true) => get(label, `${path}?page=1&size=20`,
value => pageShape(value) && value.records.every(validate))
switch (module) {
case 'customers': {
const customerId = normalizeFixedCustomerId(context.options.fixedCustomerId)
await get('读取指定固定客户档案', `${IAM}/tenants/${customerId}`,
value => String(value?.id) === customerId && value.status === 'ACTIVE')
await get('读取指定固定客户尺寸初始化状态', `${IAM}/tenants/${customerId}/dimension-initialization`,
value => value?.status === 'READY')
break
}
case 'system':
await get('读取既有权限目录', `${IAM}/permissions`, value => Array.isArray(value)
&& value.every(row => decimalId(row.id) && typeof row.permissionCode === 'string'))
await get('读取既有角色目录', `${IAM}/roles`, value => Array.isArray(value)
&& value.every(row => decimalId(row.id) && typeof row.roleCode === 'string'))
await page('读取既有平台账号分页', `${IAM}/users`, row => decimalId(row.membershipId) && String(row.tenantId) === '0')
break
case 'master-data':
await page('读取既有公共仓库分页', '/api/platform/v1/warehouse-admin',
row => decimalId(row.id) && String(row.tenantId) === '0')
break
case 'notifications':
await page('读取既有通知模板分页', '/api/platform/v1/notification-templates')
await page('读取既有通知任务分页', '/api/platform/v1/notification-tasks')
break
case 'pricing':
await get('读取既有价格簿目录', '/api/platform/v1/fba-pricing/carrier-rates/price-books', Array.isArray)
break
case 'phase4-overseas-master-data':
await page('读取既有海外报价分页', `${MASTER}/overseas-quotes`)
await page('读取既有汇率分页', `${MASTER}/exchange-rates`)
await page('读取既有海外车辆分页', `${MASTER}/vehicles`)
break
}
}