import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import test from 'node:test' const migration = readFileSync( new URL('../../db/migrations/141_fulfillment_shadow_model.sql', import.meta.url), 'utf8', ) const auditScript = readFileSync( new URL('../../../scripts/audit-fulfillment-state.ts', import.meta.url), 'utf8', ) const configSyncMigration = readFileSync( new URL('../../db/migrations/144_fulfillment_shadow_configuration_sync.sql', import.meta.url), 'utf8', ) test('正式履约影子模型包含履约、尝试和异常三张表', () => { assert.ok(migration.includes('CREATE TABLE IF NOT EXISTS fulfillments')) assert.ok(migration.includes('CREATE TABLE IF NOT EXISTS fulfillment_attempts')) assert.ok(migration.includes('CREATE TABLE IF NOT EXISTS fulfillment_issues')) assert.ok(migration.includes('uq_fulfillment_attempts_current_unit')) assert.ok(migration.includes('UNIQUE (fulfillment_id, issue_code)')) }) test('影子模型从现有真源回填并持续双写', () => { assert.ok(migration.includes('SELECT sync_fulfillment_shadow(state.order_item_id)')) assert.ok(migration.includes('trg_order_items_fulfillment_shadow')) assert.ok(migration.includes('trg_fulfillment_tasks_shadow')) assert.ok(migration.includes('trg_work_orders_fulfillment_shadow')) assert.ok(migration.includes('assign_fulfillment_event_shadow')) }) test('人工配置和统一渠道规则变化会刷新履约影子', () => { assert.ok(configSyncMigration.includes('trg_manual_fulfillment_config_shadow')) assert.ok(configSyncMigration.includes('trg_internal_sku_channel_shadow')) assert.ok(configSyncMigration.includes('sync_fulfillment_shadow(item.id)')) }) test('人工履约配置不能关联其他来源商品', () => { assert.ok(configSyncMigration.includes('trg_manual_config_product_source')) assert.ok(configSyncMigration.includes("product.canonical_sku LIKE 'man:%'")) assert.ok(configSyncMigration.includes("ERRCODE = '23514'")) assert.ok(configSyncMigration.includes('BEFORE INSERT OR UPDATE ON manual_fulfillment_configs')) assert.ok(configSyncMigration.includes('config.enabled = TRUE')) assert.ok(configSyncMigration.includes("SET status = 'active'")) }) test('明确渠道即视为已路由,不用渠道配置缺失覆盖已选渠道', () => { assert.ok(migration.includes('v_fulfillment_item_state_raw')) assert.ok(migration.includes("WHEN raw.intended_channel IS NOT NULL THEN 'configured'")) assert.ok( migration.includes( "WHEN raw.route_status = 'missing_channel'\n AND raw.intended_channel IS NOT NULL\n THEN ''", ), ) }) test('审计脚本核对影子表、执行尝试、开放异常和事件关联', () => { assert.ok(auditScript.includes('影子履约缺失')) assert.ok(auditScript.includes('影子履约状态差异')) assert.ok(auditScript.includes('影子执行尝试缺失')) assert.ok(auditScript.includes('影子开放异常缺失')) assert.ok(auditScript.includes('履约事件未关联影子记录')) })