diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index 4dec21448..b94d687e1 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -1494,7 +1494,7 @@ VALUES '/downloads', 40, 'ACTIVE', 1, 0) ON DUPLICATE KEY UPDATE permission_name = VALUES(permission_name), route_path = VALUES(route_path), sort_no = VALUES(sort_no), - status = 'ACTIVE', built_in = 1, deleted = 0; + status = VALUES(status), built_in = 1, deleted = VALUES(deleted); INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, @@ -8857,10 +8857,10 @@ BEGIN END IF; IF (SELECT COUNT(*) FROM baiyue_iam.iam_permission WHERE tenant_id=0 AND app_code='PLATFORM' AND id BETWEEN 5102140 AND 5102149 - AND permission_code LIKE 'platform:firstleg:ocean-booking:%') <> 10 + AND permission_code LIKE 'platform:firstleg:ocean-booking:%') <> 9 OR (SELECT COUNT(*) FROM baiyue_iam.iam_permission WHERE tenant_id=0 AND app_code='PLATFORM' AND id BETWEEN 5102150 AND 5102154 - AND permission_code LIKE 'platform:firstleg:truck-appointment:%') <> 5 THEN + AND permission_code LIKE 'platform:firstleg:truck-appointment:%') <> 4 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:订舱或拖车预约权限未完整写入'; END IF; IF (SELECT COUNT(DISTINCT CONCAT(r.role_code, '|', p.permission_code)) @@ -8868,13 +8868,13 @@ BEGIN JOIN baiyue_iam.iam_role r ON r.id=rp.role_id AND r.tenant_id=rp.tenant_id JOIN baiyue_iam.iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id WHERE r.tenant_id=0 AND r.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR') - AND p.permission_code LIKE 'platform:firstleg:ocean-booking:%') <> 20 + AND p.permission_code LIKE 'platform:firstleg:ocean-booking:%') <> 18 OR (SELECT COUNT(DISTINCT CONCAT(r.role_code, '|', p.permission_code)) FROM baiyue_iam.iam_role_permission rp JOIN baiyue_iam.iam_role r ON r.id=rp.role_id AND r.tenant_id=rp.tenant_id JOIN baiyue_iam.iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id WHERE r.tenant_id=0 AND r.role_code IN ('PLATFORM_ADMIN','ORDER_OPERATOR') - AND p.permission_code LIKE 'platform:firstleg:truck-appointment:%') <> 10 THEN + AND p.permission_code LIKE 'platform:firstleg:truck-appointment:%') <> 8 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='统一迁移失败:订舱或拖车预约角色授权未完整写入'; END IF; END$$ @@ -13913,7 +13913,7 @@ BEGIN IF EXISTS ( SELECT 1 FROM baiyue_iam.iam_permission - OR (id = 5105024 AND permission_code <> 'platform:finance:fee-source:review') + WHERE (id = 5105024 AND permission_code <> 'platform:finance:fee-source:review') OR (id = 5105025 AND permission_code <> 'platform:finance:fee-source:settlement') OR (id = 5105026 AND permission_code <> 'platform:finance:reconciliation:create') OR (id = 5105027 AND permission_code <> 'platform:finance:reconciliation:review') @@ -13967,7 +13967,7 @@ BEGIN permission_type = VALUES(permission_type), parent_id = VALUES(parent_id), permission_name = VALUES(permission_name), route_path = VALUES(route_path), http_method = VALUES(http_method), sort_no = VALUES(sort_no), - status = 'ACTIVE', built_in = 1, deleted = 0; + status = VALUES(status), built_in = 1, deleted = VALUES(deleted); IF (SELECT COUNT(*) FROM baiyue_iam.iam_permission @@ -13989,7 +13989,7 @@ BEGIN 'platform:finance:settlement-ar:create', 'platform:finance:settlement-ap:create', 'platform:finance:payment:create', - 'platform:finance:settlement:void')) <> 13 THEN + 'platform:finance:settlement:void')) <> 11 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'finance G1-G4 permission catalog is incomplete'; END IF; @@ -13998,6 +13998,14 @@ DELIMITER ; CALL migrate_finance_g1_g4_permissions(); DROP PROCEDURE IF EXISTS migrate_finance_g1_g4_permissions; +DELETE rp FROM baiyue_iam.iam_role_permission rp +JOIN baiyue_iam.iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id +WHERE p.tenant_id=0 AND p.app_code='PLATFORM' + AND p.permission_code IN ('platform:finance:bill:view','platform:finance:account:view','platform:finance:fee-source:view','platform:finance:settlement-ar:view','platform:finance:settlement-ap:view'); +UPDATE baiyue_iam.iam_permission SET status='INACTIVE',deleted=1 +WHERE tenant_id=0 AND app_code='PLATFORM' + AND permission_code IN ('platform:finance:bill:view','platform:finance:account:view','platform:finance:fee-source:view','platform:finance:settlement-ar:view','platform:finance:settlement-ap:view'); + INSERT INTO baiyue_iam.iam_role_permission (role_id, permission_id, tenant_id) SELECT 4000001, id, 0 FROM baiyue_iam.iam_permission WHERE tenant_id=0 AND app_code='PLATFORM' AND permission_code IN ( @@ -14012,7 +14020,6 @@ ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id); INSERT INTO baiyue_iam.iam_role_permission (role_id, permission_id, tenant_id) SELECT 4000001, id, 0 FROM baiyue_iam.iam_permission WHERE tenant_id=0 AND app_code='PLATFORM' AND permission_code IN ( - 'platform:finance:account:view', 'platform:finance:fee-source:view', 'platform:finance:fee-source:review', 'platform:finance:fee-source:settlement', 'platform:finance:reconciliation:create', 'platform:finance:reconciliation:review', 'platform:finance:reconciliation:issue', 'platform:finance:reconciliation:adjust', @@ -14025,7 +14032,21 @@ SELECT 4000101, id, 10001 FROM baiyue_iam.iam_permission WHERE tenant_id=10001 AND app_code='MERCHANT' AND (permission_code='merchant:finance:statement' OR permission_code LIKE 'merchant:finance:%') ON DUPLICATE KEY UPDATE tenant_id=VALUES(tenant_id); +-- 开发期 list-only 收口:先移除角色关联并停用旧只读资源,再执行最终 Finance 断言。 +DELETE rp FROM baiyue_iam.iam_role_permission rp +JOIN baiyue_iam.iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id +WHERE p.tenant_id=0 AND p.app_code='PLATFORM' + AND p.permission_code IN ('platform:finance:bill:view','platform:finance:account:view', + 'platform:finance:fee-source:view','platform:finance:settlement-ar:view', + 'platform:finance:settlement-ap:view'); +UPDATE baiyue_iam.iam_permission SET status='INACTIVE', deleted=1 +WHERE tenant_id=0 AND app_code='PLATFORM' + AND permission_code IN ('platform:finance:bill:view','platform:finance:account:view', + 'platform:finance:fee-source:view','platform:finance:settlement-ar:view', + 'platform:finance:settlement-ap:view'); + -- Finance 权限和角色授权断言。 +DROP PROCEDURE IF EXISTS assert_finance_permissions; DELIMITER $$ CREATE PROCEDURE assert_finance_permissions() BEGIN @@ -14472,17 +14493,12 @@ VALUES (5105044,0,'PLATFORM','MENU',5105000,'platform:finance:settlement-ap:list','结算单应付','/finance/settlement-payables','GET',50,'ACTIVE',1,0) ON DUPLICATE KEY UPDATE permission_type=VALUES(permission_type), parent_id=VALUES(parent_id), permission_name=VALUES(permission_name), route_path=VALUES(route_path), http_method=VALUES(http_method), sort_no=VALUES(sort_no), status='ACTIVE', built_in=1, deleted=0; UPDATE iam_permission SET status='INACTIVE', deleted=1 WHERE tenant_id=0 AND app_code='PLATFORM' AND permission_code IN ('platform:overseas-storage-fee:create','platform:overseas-storage-fee:delete'); +DELETE rp FROM iam_role_permission rp JOIN iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id WHERE p.tenant_id=0 AND p.app_code='PLATFORM' AND p.permission_code IN ('platform:finance:bill:view','platform:finance:account:view','platform:finance:fee-source:view','platform:finance:settlement-ar:view','platform:finance:settlement-ap:view'); +UPDATE iam_permission SET status='INACTIVE', deleted=1 WHERE tenant_id=0 AND app_code='PLATFORM' AND permission_code IN ('platform:finance:bill:view','platform:finance:account:view','platform:finance:fee-source:view','platform:finance:settlement-ar:view','platform:finance:settlement-ap:view'); INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at) SELECT 0, r.id, p.id, CURRENT_TIMESTAMP(3) FROM iam_role r JOIN iam_permission p ON p.tenant_id=0 AND p.app_code='PLATFORM' WHERE r.tenant_id=0 AND r.app_code='PLATFORM' AND r.role_code='PLATFORM_ADMIN' AND p.permission_code IN ('platform:finance:customer-account:list','platform:finance:customer-arap:list','platform:finance:customer-statement:list','platform:finance:settlement-ar:list','platform:finance:settlement-ap:list'); -UPDATE iam_permission p JOIN (SELECT 'platform:finance:account:view' code,5105040 parent_id UNION ALL SELECT 'platform:finance:fee-source:view',5105041 UNION ALL SELECT 'platform:finance:fee-source:review',5105041 UNION ALL SELECT 'platform:finance:fee-source:settlement',5105041 UNION ALL SELECT 'platform:finance:reconciliation:create',5105042 UNION ALL SELECT 'platform:finance:reconciliation:review',5105042 UNION ALL SELECT 'platform:finance:reconciliation:issue',5105042 UNION ALL SELECT 'platform:finance:reconciliation:adjust',5105042 UNION ALL SELECT 'platform:finance:reconciliation:void',5105042 UNION ALL SELECT 'platform:finance:settlement-ar:create',5105043 UNION ALL SELECT 'platform:finance:settlement-ap:create',5105044 UNION ALL SELECT 'platform:finance:payment:create',5105044) mapping ON mapping.code=p.permission_code SET p.parent_id=mapping.parent_id WHERE p.tenant_id=0 AND p.app_code='PLATFORM' AND p.permission_type='BUTTON'; - -DELETE rp FROM iam_role_permission rp JOIN iam_permission p ON p.id=rp.permission_id AND p.tenant_id=rp.tenant_id -WHERE p.tenant_id=0 AND p.app_code='PLATFORM' - AND p.permission_code IN('platform:finance:bill:view','platform:finance:settlement-ar:view','platform:finance:settlement-ap:view'); -UPDATE iam_permission SET status='INACTIVE',deleted=1 -WHERE tenant_id=0 AND app_code='PLATFORM' - AND permission_code IN('platform:finance:bill:view','platform:finance:settlement-ar:view','platform:finance:settlement-ap:view'); +UPDATE iam_permission p JOIN (SELECT 'platform:finance:fee-source:review' code,5105041 parent_id UNION ALL SELECT 'platform:finance:fee-source:settlement',5105041 UNION ALL SELECT 'platform:finance:reconciliation:create',5105042 UNION ALL SELECT 'platform:finance:reconciliation:review',5105042 UNION ALL SELECT 'platform:finance:reconciliation:issue',5105042 UNION ALL SELECT 'platform:finance:reconciliation:adjust',5105042 UNION ALL SELECT 'platform:finance:reconciliation:void',5105042 UNION ALL SELECT 'platform:finance:settlement-ar:create',5105043 UNION ALL SELECT 'platform:finance:settlement-ap:create',5105044 UNION ALL SELECT 'platform:finance:payment:create',5105044) mapping ON mapping.code=p.permission_code SET p.parent_id=mapping.parent_id WHERE p.tenant_id=0 AND p.app_code='PLATFORM' AND p.permission_type='BUTTON'; INSERT INTO baiyue_iam.iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, deleted) diff --git a/iam/src/test/java/com/baiyue/iam/repository/AdminPrototypeMenuPermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/AdminPrototypeMenuPermissionSqlContractTest.java index fab5961a5..fe3314af1 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/AdminPrototypeMenuPermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/AdminPrototypeMenuPermissionSqlContractTest.java @@ -25,13 +25,13 @@ class AdminPrototypeMenuPermissionSqlContractTest { assertThat(sql).contains("(" + (5105040 + index) + ",0,'PLATFORM','MENU',5105000,'" + FINANCE_MENUS[index] + "'"); } assertThat(sql) - .contains("'platform:finance:account:view' code, 5105040 parent_id") - .contains("'platform:finance:fee-source:view', 5105041") + .contains("'platform:finance:fee-source:review' code, 5105041 parent_id") .contains("'platform:finance:reconciliation:create', 5105042") .contains("'platform:finance:settlement-ar:create', 5105043") .contains("'platform:finance:settlement-ap:create', 5105044") .contains("'platform:finance:payment:create', 5105044)") - .contains("'platform:finance:bill:view','platform:finance:settlement-ar:view'") + .contains("'platform:finance:bill:view','platform:finance:account:view'") + .contains("'platform:finance:fee-source:view','platform:finance:settlement-ar:view'") .contains("'platform:finance:settlement-ap:view'") .doesNotContain("SELECT 'platform:finance:settlement-ar:view', 5105043") .doesNotContain("SELECT 'platform:finance:settlement-ap:view', 5105044") diff --git a/iam/src/test/java/com/baiyue/iam/repository/FinanceG1G2PermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/FinanceG1G2PermissionSqlContractTest.java index 7a1d6c5a9..d8a050ce3 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/FinanceG1G2PermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/FinanceG1G2PermissionSqlContractTest.java @@ -11,22 +11,21 @@ import static org.assertj.core.api.Assertions.assertThat; class FinanceG1G2PermissionSqlContractTest { @Test - void declaresTheFourControllerPermissionsUnderFinance() throws Exception { + void declaresActionPermissionsAndRetiresSupersededReadPermissions() throws Exception { String sql = new ClassPathResource("db/finance-g1-g2-permissions.sql") .getContentAsString(StandardCharsets.UTF_8); assertThat(sql) - .contains("(5105022, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:account:view'") - .contains("(5105023, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:view'") .contains("(5105024, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:review'") .contains("(5105025, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:settlement'") - .contains("NULL, 'GET', 130, 'ACTIVE', 1, 0") - .contains("NULL, 'GET', 140, 'ACTIVE', 1, 0") .contains("NULL, 'POST', 150, 'ACTIVE', 1, 0") .contains("NULL, 'PUT', 160, 'ACTIVE', 1, 0") .contains("ON DUPLICATE KEY UPDATE") .contains("CALL migrate_finance_g1_g2_permissions()") - .contains("DROP PROCEDURE IF EXISTS migrate_finance_g1_g2_permissions"); + .contains("DROP PROCEDURE IF EXISTS migrate_finance_g1_g2_permissions") + .contains("status='INACTIVE', deleted=1") + .doesNotContain("'platform:finance:account:view',\n '查看客户财务账户及流水'") + .doesNotContain("'platform:finance:fee-source:view',\n '查看财务费用来源'"); } @Test @@ -36,7 +35,6 @@ class FinanceG1G2PermissionSqlContractTest { assertThat(sql) .contains("SIGNAL SQLSTATE '45000'") - .contains("id = 5105022 AND permission_code <> 'platform:finance:account:view'") .contains("permission_code = 'platform:finance:fee-source:settlement' AND id <> 5105025") .contains("tenant_id <> 0 OR app_code <> 'PLATFORM'") .contains("parent_id = 5105000") @@ -53,21 +51,17 @@ class FinanceG1G2PermissionSqlContractTest { sql.indexOf("CALL assert_unified_final_schema()")); assertThat(financeSection) - .contains("(5105022, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:account:view'") - .contains("(5105023, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:view'") .contains("(5105024, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:review'") .contains("(5105025, 0, 'PLATFORM', 'BUTTON', 5105000, 'platform:finance:fee-source:settlement'") - .contains("NULL, 'GET', 130, 'ACTIVE', 1, 0") - .contains("NULL, 'GET', 140, 'ACTIVE', 1, 0") .contains("NULL, 'POST', 150, 'ACTIVE', 1, 0") .contains("NULL, 'PUT', 160, 'ACTIVE', 1, 0") .contains("permission_code IN (\n 'platform:finance',") - .contains("permission_code LIKE 'platform:finance:%' AND status='ACTIVE' AND deleted=0) <> 24") + .contains("permission_code LIKE 'platform:finance:%' AND status='ACTIVE' AND deleted=0) <> 22") .contains("平台管理员 Finance 授权不完整") .contains("Finance G1-G4"); assertThat(financeSection) .contains("SELECT 4000001, id, 0 FROM baiyue_iam.iam_permission") - .contains("platform:finance:account:view"); + .contains("status='INACTIVE',deleted=1"); assertThat(sql) .contains("platform:finance:settlement-ar:list") .contains("platform:finance:settlement-ap:list"); diff --git a/iam/src/test/java/com/baiyue/iam/repository/FinanceG3G4PermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/FinanceG3G4PermissionSqlContractTest.java index d13c2b7a9..3b1375b7a 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/FinanceG3G4PermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/FinanceG3G4PermissionSqlContractTest.java @@ -45,7 +45,7 @@ class FinanceG3G4PermissionSqlContractTest { assertThat(financeSection) .contains("migrate_finance_g1_g4_permissions") .contains("finance G1-G4 permission id/code conflict") - .contains("permission_code LIKE 'platform:finance:%' AND status='ACTIVE' AND deleted=0) <> 24"); + .contains("permission_code LIKE 'platform:finance:%' AND status='ACTIVE' AND deleted=0) <> 22"); assertThat(financeSection) .contains("SELECT 4000001, id, 0 FROM baiyue_iam.iam_permission") .contains("platform:finance:reconciliation:create"); diff --git a/scripts/README.md b/scripts/README.md index dc7710420..057252ab1 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -87,7 +87,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 `BE7C5C98712D5202F5D187EA9A37C64EAB9F6AA9AE772C89A51F186507B1AE53` 和 14706 行,并静态确认中文注释升级采用校验入队、每表一次 ALTER、结构签名复核、九库覆盖断言及唯一最终 `PASS`。 +正式入口是 `local-db-full-acceptance.ps1`,只允许连接本机 `127.0.0.1` 或 `localhost`,默认端口 `3306`;测试库 `8.163.30.128` 会立即以退出码 2 拒绝。脚本固定校验统一 SQL SHA-256 `3E0A02C2E3B971AB7D8AB9C9D8AEE1D933F950DBCE82BD9B6AD431A4DD179F8A` 和 14713 行,并静态确认中文注释升级采用校验入队、每表一次 ALTER、结构签名复核、九库覆盖断言及唯一最终 `PASS`。 ```powershell .\scripts\local-db-full-acceptance.ps1 -DryRun diff --git a/scripts/admin-test-env-modules/manual-state-loading-pda-contract.test.mjs b/scripts/admin-test-env-modules/manual-state-loading-pda-contract.test.mjs index 88ce55674..130f30ba6 100644 --- a/scripts/admin-test-env-modules/manual-state-loading-pda-contract.test.mjs +++ b/scripts/admin-test-env-modules/manual-state-loading-pda-contract.test.mjs @@ -17,7 +17,7 @@ test('retains all clickable container, loading-list and PDA workflow states thro assert.match(source, /\.\/orders\.mjs/) assert.match(source, /\.\/inbound-measurement\.mjs/) assert.doesNotMatch(source, /context\.request\('POST', CONTAINERS/) - assert.match(source, /\['WAIT_SPLIT', 'INBOUNDED'\]\.includes/) + assert.match(source, /summary\?\.processStatus === 'WAIT_SPLIT'/) const batch = source.slice(source.indexOf('async function pickAll'), source.indexOf('async function complete')) assert.doesNotMatch(batch, /containerNo:/) }) diff --git a/scripts/admin-test-env-modules/manual-state-loading-pda.mjs b/scripts/admin-test-env-modules/manual-state-loading-pda.mjs index ff0bf4568..d9f3ec0ba 100644 --- a/scripts/admin-test-env-modules/manual-state-loading-pda.mjs +++ b/scripts/admin-test-env-modules/manual-state-loading-pda.mjs @@ -88,7 +88,7 @@ async function readInbound(context, fixture) { const value = context.apiSuccess(MODULE, '读取人工装柜独立入库单', response, '', OPTIONS) const warehouseId = id(value?.summary?.warehouseId) context.assert(MODULE, '人工装柜来源入库单可独立排柜', response, - ['WAIT_SPLIT', 'INBOUNDED'].includes(value?.summary?.processStatus) + value?.summary?.processStatus === 'WAIT_SPLIT' && value?.summary?.measureReviewStatus === 'APPROVED' && Boolean(warehouseId), `inboundId=${fixture.inboundId}, status=${value?.summary?.processStatus || 'missing'}`, OPTIONS) diff --git a/scripts/admin-test-env-modules/order-inbound-status-fixtures-contract.test.mjs b/scripts/admin-test-env-modules/order-inbound-status-fixtures-contract.test.mjs index 9934d418b..1fea56218 100644 --- a/scripts/admin-test-env-modules/order-inbound-status-fixtures-contract.test.mjs +++ b/scripts/admin-test-env-modules/order-inbound-status-fixtures-contract.test.mjs @@ -39,8 +39,8 @@ test('入库不可独立保留状态显式阻断', () => { assert.match(source, new RegExp(`${status}:`)) } assert.match(source, /AutomaticInboundCompletionService 在同一调用内立即从 INBOUNDING 推进 WAIT_SPLIT/) - assert.match(source, /processStatus=INBOUNDED/) - assert.match(source, /查询存量 INBOUNDED 兼容样本/) + assert.match(source, /processStatus=WAIT_SPLIT/) + assert.match(source, /查询存量 WAIT_SPLIT 样本/) assert.match(source, /没有作废入库单 API/) assert.match(source, /context\.assert\(MODULE, `入库列表保留 \$\{status\}`/) }) @@ -48,7 +48,7 @@ test('入库不可独立保留状态显式阻断', () => { test('统一订单声明合法可达状态并显式阻断废弃或无 API 状态', () => { assert.match(source, /result\.unifiedOrders\.PENDING_REVIEW/) assert.match(source, /result\.unifiedOrders\.WAIT_MEASURE/) - for (const status of ['INBOUNDED', 'WAIT_SPLIT', 'LOADING', 'LOADED', 'DELIVERED']) { + for (const status of ['WAIT_SPLIT', 'LOADING', 'LOADED', 'DELIVERED']) { assert.match(source, new RegExp(`'${status}'`)) } assert.doesNotMatch(source, /WAIT_SPLIT 标记为历史废弃状态/) diff --git a/scripts/admin-test-env-modules/order-inbound-status-fixtures.mjs b/scripts/admin-test-env-modules/order-inbound-status-fixtures.mjs index 96d04d5e0..37b291e3c 100644 --- a/scripts/admin-test-env-modules/order-inbound-status-fixtures.mjs +++ b/scripts/admin-test-env-modules/order-inbound-status-fixtures.mjs @@ -15,10 +15,10 @@ const ORDER_TARGETS = [ ] const INBOUND_FILTER_STATUSES = [ 'WAIT_MEASURE', 'MEASURING', 'MEASURE_PENDING', 'MEASURE_REJECTED', 'WAIT_PRICING', - 'FEE_CONFIRMING', 'INBOUNDING', 'INBOUNDED', 'VOIDED', + 'FEE_CONFIRMING', 'INBOUNDING', 'WAIT_SPLIT', 'VOIDED', ] const UNIFIED_FILTER_STATUSES = [ - 'PENDING_REVIEW', 'WAIT_MEASURE', 'INBOUNDED', 'WAIT_SPLIT', 'LOADING', 'LOADED', 'DELIVERED', + 'PENDING_REVIEW', 'WAIT_MEASURE', 'WAIT_SPLIT', 'LOADING', 'LOADED', 'DELIVERED', ] function id(value) { return value == null ? '' : String(value) } @@ -277,19 +277,19 @@ export async function run(context, matrix = context.createdResources.manualState } const legacyResponse = await context.request('GET', - `/api/platform/v1/inbounds?tenantId=${query(fixture.tenantId)}&processStatus=INBOUNDED&page=1&size=20`) - const legacyPage = context.apiSuccess(MODULE, '查询存量 INBOUNDED 兼容样本', legacyResponse, '', OPTIONS) + `/api/platform/v1/inbounds?tenantId=${query(fixture.tenantId)}&processStatus=WAIT_SPLIT&page=1&size=20`) + const legacyPage = context.apiSuccess(MODULE, '查询存量 WAIT_SPLIT 样本', legacyResponse, '', OPTIONS) const legacyInbound = rows(legacyPage)[0] if (legacyInbound?.id && legacyInbound?.orderId) { const sample = { inboundId: id(legacyInbound.id), orderId: id(legacyInbound.orderId), tenantId: fixture.tenantId, - status: 'INBOUNDED', inboundCode: legacyInbound.inboundCode || null } - result.inbounds.INBOUNDED = sample - result.unifiedOrders.INBOUNDED = sample - matrix.pages.inbounds.fixtures.INBOUNDED = { - id: sample.inboundId, status: 'INBOUNDED', detailPath: `/orders/${sample.orderId}`, + status: 'WAIT_SPLIT', inboundCode: legacyInbound.inboundCode || null } + result.inbounds.WAIT_SPLIT = sample + result.unifiedOrders.WAIT_SPLIT = sample + matrix.pages.inbounds.fixtures.WAIT_SPLIT = { + id: sample.inboundId, status: 'WAIT_SPLIT', detailPath: `/orders/${sample.orderId}`, } - matrix.pages.unifiedOrders.fixtures.INBOUNDED = { - id: sample.orderId, status: 'INBOUNDED', detailPath: `/orders/${sample.orderId}`, + matrix.pages.unifiedOrders.fixtures.WAIT_SPLIT = { + id: sample.orderId, status: 'WAIT_SPLIT', detailPath: `/orders/${sample.orderId}`, } } diff --git a/scripts/admin-test-env-modules/phase3-container-loading.mjs b/scripts/admin-test-env-modules/phase3-container-loading.mjs index 01c6cb2e0..a3466b2f6 100644 --- a/scripts/admin-test-env-modules/phase3-container-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-container-loading.mjs @@ -62,7 +62,7 @@ export async function run(context) { `tenantId=${tenantId}, inboundId=${inboundId}`, OPTIONS) const warehouseId = id(inbound?.summary?.warehouseId) context.assert(MODULE, '柜次候选入库单状态、测量和仓库门禁有效', inboundResponse, - ['WAIT_SPLIT', 'INBOUNDED'].includes(inbound?.summary?.processStatus) + inbound?.summary?.processStatus === 'WAIT_SPLIT' && inbound?.summary?.measureReviewStatus === 'APPROVED' && Boolean(warehouseId), `status=${inbound?.summary?.processStatus || 'missing'}, review=${inbound?.summary?.measureReviewStatus || 'missing'}, warehouseId=${warehouseId || 'missing'}`, OPTIONS) diff --git a/scripts/admin-test-env-modules/phase3-loading.mjs b/scripts/admin-test-env-modules/phase3-loading.mjs index 587a65dc0..adece17fd 100644 --- a/scripts/admin-test-env-modules/phase3-loading.mjs +++ b/scripts/admin-test-env-modules/phase3-loading.mjs @@ -108,9 +108,9 @@ export async function run(context) { const initialStatus = initial?.summary?.processStatus const initialVersion = Number(initial?.summary?.version) context.assert(MODULE, '隔离入库单处于智能分柜门禁状态', initialResponse, - ['INBOUNDED', 'WAIT_SPLIT'].includes(initialStatus) && Number.isInteger(initialVersion), + initialStatus === 'WAIT_SPLIT' && Number.isInteger(initialVersion), `status=${initialStatus || 'missing'}, version=${initial?.summary?.version ?? 'missing'}`, OPTIONS) - if (!['INBOUNDED', 'WAIT_SPLIT'].includes(initialStatus) || !Number.isInteger(initialVersion)) return + if (initialStatus !== 'WAIT_SPLIT' || !Number.isInteger(initialVersion)) return const base = `/api/platform/v1/inbounds/${inboundId}` const suffix = context.marker.replace(/\D/g, '').slice(-10) @@ -168,7 +168,7 @@ export async function run(context) { const smartData = context.apiSuccess(MODULE, '智能分柜并生成预装清单', smart, `inboundId=${inboundId}`, OPTIONS) const planId = id(smartData?.preloadPlan?.id) context.assert(MODULE, '智能分柜预装计划 PENDING、版本和明细正确', smart, - smartData?.mainStatus === 'INBOUNDED' && Boolean(planId) && smartData?.preloadPlan?.status === 'PENDING' + smartData?.mainStatus === 'WAIT_SPLIT' && Boolean(planId) && smartData?.preloadPlan?.status === 'PENDING' && Number(smartData?.preloadPlan?.version) === 0 && smartData?.preloadPlan?.items?.length === 1, `mainStatus=${smartData?.mainStatus || 'missing'}, planId=${planId || 'missing'}, status=${smartData?.preloadPlan?.status || 'missing'}`, OPTIONS) if (!planId) return diff --git a/scripts/client-phase2-test-env-acceptance.mjs b/scripts/client-phase2-test-env-acceptance.mjs index aceb35cc4..ef969e6cf 100644 --- a/scripts/client-phase2-test-env-acceptance.mjs +++ b/scripts/client-phase2-test-env-acceptance.mjs @@ -628,7 +628,7 @@ async function unifiedOrderModule() { const row = pageRecords(json.data) .find((item) => String(item.orderId) === report.resources.terminalOrderId) assertPresent(row, 'unified terminal order row') - assertEqual(row.mainStatus, 'INBOUNDED', 'unified main status') + assertEqual(row.mainStatus, 'WAIT_SPLIT', 'unified main status') assertEqual(String(row.inboundId), report.resources.terminalInboundId, 'unified inbound id') assertEqual(row.measurement?.reviewStatus, 'APPROVED', 'unified measurement review status') assertTrue(Number(row.actualGrossWeightKg) > 0, 'unified actual gross weight must be positive') @@ -646,7 +646,7 @@ async function unifiedOrderModule() { }, ({ json }) => { requireSuccess(json) assertEqual(String(json.data?.summary?.orderId), report.resources.terminalOrderId, 'unified order id') - assertEqual(json.data?.summary?.mainStatus, 'INBOUNDED', 'unified main status') + assertEqual(json.data?.summary?.mainStatus, 'WAIT_SPLIT', 'unified main status') assertEqual(String(json.data?.summary?.inboundId), report.resources.terminalInboundId, 'unified inbound id') assertEqual(json.data?.summary?.measurement?.reviewStatus, 'APPROVED', diff --git a/scripts/local-db-full-acceptance.ps1 b/scripts/local-db-full-acceptance.ps1 index 8bee9dc85..479bea2eb 100644 --- a/scripts/local-db-full-acceptance.ps1 +++ b/scripts/local-db-full-acceptance.ps1 @@ -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 = 'BE7C5C98712D5202F5D187EA9A37C64EAB9F6AA9AE772C89A51F186507B1AE53' -$ExpectedLines = 14706 +$ExpectedSha256 = '3E0A02C2E3B971AB7D8AB9C9D8AEE1D933F950DBCE82BD9B6AD431A4DD179F8A' +$ExpectedLines = 14713 if ($TargetHost -notin @('127.0.0.1', 'localhost')) { [Console]::Error.WriteLine('Refusing non-local database; only 127.0.0.1 or localhost is allowed.') diff --git a/scripts/phase2-test-env-acceptance.ps1 b/scripts/phase2-test-env-acceptance.ps1 index 9bf019567..d6e30f771 100644 --- a/scripts/phase2-test-env-acceptance.ps1 +++ b/scripts/phase2-test-env-acceptance.ps1 @@ -405,16 +405,16 @@ try { $approvedInboundResponse = Invoke-Api GET "/api/platform/inbounds/$($ids.inboundId)?tenantId=$TenantId" $platformToken $approvedInbound = Require-Success '审核后回查入库单' $approvedInboundResponse $versions.inbound = [int]$approvedInbound.summary.version - Require-Condition '二期边界停在 INBOUNDED' $approvedInboundResponse ($approvedInbound.summary.processStatus -eq 'INBOUNDED' -and $approvedInbound.summary.measureReviewStatus -eq 'APPROVED') "processStatus=$($approvedInbound.summary.processStatus), reviewStatus=$($approvedInbound.summary.measureReviewStatus)" + Require-Condition '二期边界停在 WAIT_SPLIT' $approvedInboundResponse ($approvedInbound.summary.processStatus -eq 'WAIT_SPLIT' -and $approvedInbound.summary.measureReviewStatus -eq 'APPROVED') "processStatus=$($approvedInbound.summary.processStatus), reviewStatus=$($approvedInbound.summary.measureReviewStatus)" $feeResponse = Invoke-Api POST "/api/platform/v1/inbounds/$($ids.inboundId)/fees/calculate?tenantId=$TenantId" $platformToken @{} @{ 'Idempotency-Key' = (New-Key 'fee-calculate') } $calculatedFee = Require-Success '二期计费接口试算' $feeResponse $ids.feeId = [string]$calculatedFee.feeId - Require-Condition '计费试算保持 INBOUNDED 主流程边界' $feeResponse ($calculatedFee.nextProcessStatus -eq 'INBOUNDED') "nextProcessStatus=$($calculatedFee.nextProcessStatus)" + Require-Condition '计费试算保持 WAIT_SPLIT 主流程边界' $feeResponse ($calculatedFee.nextProcessStatus -eq 'WAIT_SPLIT') "nextProcessStatus=$($calculatedFee.nextProcessStatus)" $feeConfirmResponse = Invoke-Api POST "/api/platform/v1/inbounds/$($ids.inboundId)/fees/confirm?tenantId=$TenantId" $platformToken $null @{ 'Idempotency-Key' = (New-Key 'fee-confirm') } $confirmedFee = Require-Success '确认二期费用快照' $feeConfirmResponse - Require-Condition '费用确认后仍保持 INBOUNDED 主流程边界' $feeConfirmResponse ($confirmedFee.feeStatus -eq 'CONFIRMED' -and $confirmedFee.nextProcessStatus -eq 'INBOUNDED') "feeStatus=$($confirmedFee.feeStatus), nextProcessStatus=$($confirmedFee.nextProcessStatus)" + Require-Condition '费用确认后仍保持 WAIT_SPLIT 主流程边界' $feeConfirmResponse ($confirmedFee.feeStatus -eq 'CONFIRMED' -and $confirmedFee.nextProcessStatus -eq 'WAIT_SPLIT') "feeStatus=$($confirmedFee.feeStatus), nextProcessStatus=$($confirmedFee.nextProcessStatus)" } catch { $fatal = $_.Exception.Message