This commit is contained in:
2026-08-17 18:32:38 +08:00
parent 5c22018edd
commit 5199146e97
13 changed files with 194 additions and 17 deletions
+1 -1
View File
@@ -104,7 +104,7 @@ Dry-run 只检查根 `pom.xml` 和关键回归测试文件并打印 Maven 命令
### 本地 MySQL 全量验收
正式入口是 `local-db-full-acceptance.ps1`,只允许连接本机 `127.0.0.1` 或 `localhost`,默认端口 `3306`;测试库 `8.163.30.128` 会立即以退出码 2 拒绝。脚本固定校验统一 SQL SHA-256 `1DBA47099AE501B21C4BEC22A50D065571BA46264C15C6C543CBE6F1CC597463` 和 15215 行,并静态确认中文注释升级采用校验入队、每表一次 ALTER、结构签名复核、九库覆盖断言及唯一最终 `PASS`。
正式入口是 `local-db-full-acceptance.ps1`,只允许连接本机 `127.0.0.1` 或 `localhost`,默认端口 `3306`;测试库 `8.163.30.128` 会立即以退出码 2 拒绝。脚本固定校验统一 SQL SHA-256 `00E8F9C24CE16FE6B4D2B6AF60460AE1AF1D264DFE110D4BDCE611F09EB69EAA` 和 15403 行,并静态确认中文注释升级采用校验入队、每表一次 ALTER、结构签名复核、九库覆盖断言及唯一最终 `PASS`。
```powershell
.\scripts\local-db-full-acceptance.ps1 -DryRun
@@ -3,13 +3,18 @@ import assert from 'node:assert/strict'
import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { EXPORT_SPECS, run } from './finance-downloads.mjs'
import { EXPORT_SPECS, REQUIRED_PERMISSIONS, run } from './finance-downloads.mjs'
import { normalizeModuleOrder } from '../admin-test-env-acceptance.mjs'
const here = path.dirname(fileURLToPath(import.meta.url))
const source = fs.readFileSync(path.join(here, 'finance-downloads.mjs'), 'utf8')
test('八类 Finance XLSX 契约均有正式表头并在完整链末尾执行', () => {
assert.deepEqual(REQUIRED_PERMISSIONS, [
'platform:download:list', 'platform:finance:customer-account:export',
'platform:finance:customer-arap:export', 'platform:finance:customer-statement:export',
'platform:finance:settlement-ar:export', 'platform:finance:settlement-ap:export',
])
assert.deepEqual(Object.keys(EXPORT_SPECS), [
'FINANCE_CUSTOMER_ACCOUNT_LIST', 'FINANCE_CUSTOMER_ACCOUNT_LEDGER', 'FINANCE_FEE_SOURCE_LIST',
'FINANCE_RECONCILIATION_STATEMENT_LIST', 'FINANCE_RECEIVABLE_SETTLEMENT_LIST',
@@ -39,11 +44,17 @@ test('未部署时能力探测后记录部署前置,不借历史业务数据',
const steps = []; const gaps = []
const context = {
marker: 'ADMIN-API-PROBE', createdResources: {},
apiSuccess(module, name) { steps.push({ module, name, passed: false }); return null },
apiSuccess(module, name, response) {
const passed = response.http === 200 && String(response.body?.code) === '200'
steps.push({ module, name, passed }); return passed ? response.body.data : null
},
assert(module, name) { steps.push({ module, name, passed: false }) },
addStep(module, name, response, passed, evidence, options) { steps.push({ module, name, passed, evidence, options }) },
addCoverageGap(...args) { gaps.push(args) },
async request() { return { http: 200, body: { code: 'A0403', message: 'not deployed' } } },
async request(method, path) {
if (path.endsWith('/authorization/permissions')) return { http: 200, body: { code: '200', data: REQUIRED_PERMISSIONS } }
return { http: 200, body: { code: 'A0403', message: 'not deployed' } }
},
}
await run(context)
assert.equal(context.createdResources.financeExportTasks.marker, context.marker)
@@ -3,6 +3,14 @@ import { inflateRawSync } from 'node:zlib'
const MODULE = 'finance-downloads'
const TERMINAL = new Set(['SUCCEEDED', 'FAILED', 'EXPIRED'])
const OPTIONS = { scenario: 'finance-download-center', deploymentBlocker: true }
export const REQUIRED_PERMISSIONS = Object.freeze([
'platform:download:list',
'platform:finance:customer-account:export',
'platform:finance:customer-arap:export',
'platform:finance:customer-statement:export',
'platform:finance:settlement-ar:export',
'platform:finance:settlement-ap:export',
])
export const EXPORT_SPECS = Object.freeze({
FINANCE_CUSTOMER_ACCOUNT_LIST: ['客户编码', '客户', '联系人', '联系电话', '待收(CNY)', '待开账(CNY)', '本期已收(CNY)', '待付(CNY)', '客户状态', '最近变动'],
@@ -180,15 +188,26 @@ async function noPermission(context) {
export async function run(context) {
context.createdResources.financeExportTasks = { marker: context.marker, tasks: {} }
const permissionsResponse = await context.request('GET', '/api/platform/v1/iam/authorization/permissions')
const permissionData = context.apiSuccess(MODULE, 'fresh login 权限快照', permissionsResponse, '', OPTIONS)
const permissions = new Set(Array.isArray(permissionData) ? permissionData : [])
const missingPermissions = REQUIRED_PERMISSIONS.filter((permission) => !permissions.has(permission))
context.assert(MODULE, '下载中心与五项 Finance export 权限齐全', permissionsResponse,
missingPermissions.length === 0, `missing=${missingPermissions.join(',') || 'none'}`, OPTIONS)
if (missingPermissions.length > 0) {
context.addCoverageGap(MODULE, 'finance-download-center', '八类 Finance 下载中心真实链',
`fresh login 权限快照缺失:${missingPermissions.join(',')}`, 'deployment-prerequisite')
return
}
const longMissingCustomerId = '9223372036854775806'
const probe = await createTask(context, 'FINANCE_CUSTOMER_ACCOUNT_LIST',
{ customerId: longMissingCustomerId }, 'CAPABILITY-PROBE', EXPORT_SPECS.FINANCE_CUSTOMER_ACCOUNT_LIST)
context.createdResources.financeExportTasks.probe = probe
if (!probe || probe.status !== 'SUCCEEDED') {
context.addCoverageGap(MODULE, 'finance-download-center', '八类 Finance 下载中心真实链',
'Finance/File/权限/配置尚未完整部署,能力探测未成功;部署后重跑完整链', 'deployment-prerequisite')
return
}
context.createdResources.financeExportTasks.probe = probe
context.assert(MODULE, '长 ID 字符串与空结果', null,
probe.processedRows === 0, `customerIdType=string, customerId=${longMissingCustomerId}, rows=${probe.processedRows}`, OPTIONS)
await noPermission(context)
+2 -2
View File
@@ -11,8 +11,8 @@ $ErrorActionPreference = 'Stop'
$Repo = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path
$Workspace = (Resolve-Path (Join-Path $Repo '..')).Path
$Acceptance = Join-Path $Workspace '.codex-tmp\p23-04-acceptance'
$ExpectedSha256 = '1DBA47099AE501B21C4BEC22A50D065571BA46264C15C6C543CBE6F1CC597463'
$ExpectedLines = 15215
$ExpectedSha256 = '00E8F9C24CE16FE6B4D2B6AF60460AE1AF1D264DFE110D4BDCE611F09EB69EAA'
$ExpectedLines = 15403
if ($TargetHost -notin @('127.0.0.1', 'localhost')) {
[Console]::Error.WriteLine('Refusing non-local database; only 127.0.0.1 or localhost is allowed.')