Merge remote-tracking branch 'origin/test' into dev

# Conflicts:
#	scripts/acceptance-finance-full-contract.test.mjs
#	scripts/admin-test-env-acceptance.mjs
This commit is contained in:
2026-09-04 16:43:43 +08:00
11 changed files with 76 additions and 12 deletions
+23 -7
View File
@@ -5,7 +5,7 @@ import { dirname, resolve } from 'node:path'
import { pathToFileURL } from 'node:url'
import process from 'node:process'
const CONFIGURED_MODULES = ['merchant-qualification-fixture', 'customers', 'overseas-storage-fees', 'system', 'notifications', 'master-data', 'suppliers', 'domestic-container', 'orders', 'fee-items', 'pricing', 'downloads', 'inbound-weight-ocr', 'inbound-measurement', 'inbound-fees', 'phase3-container-loading', 'phase3-container-overview', 'phase3-loading', 'phase3-loading-model-bridge', 'phase3-pda-convergence', 'phase3-evidence-gate', 'supplemental', 'supplemental-boundaries', 'ocean-bookings', 'truck-appointments', 'service-center-flow', 'phase3-loading-finalize', 'phase3-container-documents', 'phase3-customs', 'phase3-container-customs', 'phase3-port-schedules', 'phase3-carrier-schedule-queries', 'phase3-outbound-dispatch', 'phase3-outbound-aggregate', 'phase3-dispatch-gate', 'phase3-waiting-for-loading', 'phase3-warehouse-rbac', 'phase3-order-splitting', 'manual-state-matrix', 'phase4-overseas-warehouse', 'phase4-carrier-pickup-ready', 'phase4-overseas-pda', 'phase4-overseas-pda-operations', 'phase4-overseas-inbound-operations', 'phase4-overseas-client-services', 'phase4-overseas-dispatch', 'phase5-overseas-fulfillment', 'phase4-cross-region-events', 'phase4-overseas-business', 'phase4-overseas-master-data', 'phase4-carrier-nodes', 'finance-full-fixtures', 'finance-reconciliation-full', 'finance-settlement-full', 'finance-downloads', 'firstleg-container-fee-allocation', 'finance-direct-paid-isolation', 'phase4-overseas-finance-cross-region', 'customer-operating-statistics']
const CONFIGURED_MODULES = ['merchant-qualification-fixture', 'customers', 'overseas-storage-fees', 'system', 'notifications', 'master-data', 'suppliers', 'domestic-container', 'orders', 'fee-items', 'pricing', 'downloads', 'inbound-weight-ocr', 'inbound-measurement', 'inbound-fees', 'phase3-container-loading', 'phase3-container-overview', 'phase3-loading', 'phase3-loading-model-bridge', 'phase3-pda-convergence', 'phase3-evidence-gate', 'supplemental', 'supplemental-boundaries', 'ocean-bookings', 'truck-appointments', 'service-center-flow', 'phase3-loading-finalize', 'phase3-container-documents', 'phase3-customs', 'phase3-container-customs', 'phase3-port-schedules', 'phase3-carrier-schedule-queries', 'phase3-outbound-dispatch', 'phase3-outbound-aggregate', 'phase3-dispatch-gate', 'phase3-waiting-for-loading', 'phase3-warehouse-rbac', 'phase3-order-splitting', 'manual-state-matrix', 'phase4-overseas-warehouse', 'phase4-carrier-pickup-ready', 'phase4-overseas-pda', 'phase4-overseas-pda-operations', 'phase4-overseas-inbound-operations', 'phase4-overseas-client-services', 'phase4-overseas-dispatch', 'phase5-overseas-fulfillment', 'phase4-cross-region-events', 'phase4-overseas-business', 'phase4-overseas-master-data', 'phase4-carrier-nodes', 'finance-full-fixtures', 'finance-reconciliation-full', 'finance-direct-paid-isolation', 'finance-settlement-full', 'finance-downloads', 'firstleg-container-fee-allocation', 'phase4-overseas-finance-cross-region', 'customer-operating-statistics']
const OPTIONAL_MODULES = ['manual-order-splitting-fixture', 'manual-order-splitting-verify',
'manual-preload-push-fixture', 'manual-preload-push-verify',
'manual-pda-ready-fixture', 'manual-pda-ready-verify',
@@ -188,7 +188,8 @@ export function normalizeModuleOrder(modules) {
const missing = prerequisites.filter((name) => !normalized.includes(name))
if (missing.length > 0) normalized.splice(targetIndex, 0, ...missing)
}
const financeChain = ['finance-full-fixtures', 'finance-reconciliation-full', 'finance-settlement-full']
const financeChain = ['finance-full-fixtures', 'finance-reconciliation-full',
'finance-direct-paid-isolation', 'finance-settlement-full']
const firstFinanceIndex = normalized.findIndex((name) => financeChain.includes(name))
if (firstFinanceIndex >= 0) {
const prerequisites = ['merchant-qualification-fixture', 'orders', 'inbound-measurement', 'phase3-container-loading']
@@ -912,11 +913,26 @@ export class AcceptanceRun {
async findAvailablePhone(module = 'customers') {
this.phoneSequence = Number(this.phoneSequence || 0) + 1
const markerDigits = this.marker.replace(/\D/g, '').slice(-7).padStart(7, '0')
const phone = `18${markerDigits}${String(this.phoneSequence % 100).padStart(2, '0')}`
this.addStep(module, '生成本轮隔离测试联系电话', null, /^1\d{10}$/.test(phone),
`sequence=${this.phoneSequence}`)
return phone
for (let attempt = 0; attempt < 100; attempt += 1) {
const seed = `${this.marker}:${this.phoneSequence}:${attempt}`
let hash = 2166136261
for (const character of seed) {
hash ^= character.charCodeAt(0)
hash = Math.imul(hash, 16777619) >>> 0
}
const phone = `18${String(hash).padStart(9, '0').slice(-9)}`
const response = await this.request('GET',
`/api/platform/v1/iam/tenants/administrator-phone-availability?phone=${encodeURIComponent(phone)}`)
const available = response?.http === 200 && String(response?.body?.code) === '200'
&& response?.body?.data === true
if (!available) continue
this.addStep(module, '生成本轮隔离测试联系电话', response, true,
`sequence=${this.phoneSequence}, attempts=${attempt + 1}`)
return phone
}
this.addStep(module, '生成本轮隔离测试联系电话', null, false,
`sequence=${this.phoneSequence}, attempts=100;未找到可用手机号`, { deploymentBlocker: true })
throw new Error('未找到可用的隔离测试手机号')
}
async runCustomerDimensionRules(tenantId) {