优化
This commit is contained in:
@@ -1,203 +1,117 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import test from 'node:test'
|
||||
import { readInitialization, tableDefinitions, table, seedRows, roleAuthorities } from '../sql-baseline-contract-helpers.mjs'
|
||||
|
||||
const sql = readFileSync(new URL('../../deploy/sql/头程数据库统一增量-MySQL8.sql', import.meta.url), 'utf8')
|
||||
const overseasSql = readFileSync(new URL('../../deploy/sql/海外区域统一增量-MySQL8.sql', import.meta.url), 'utf8')
|
||||
const lastlegBaseline = readFileSync(new URL('../../lastleg-service/src/main/resources/db/lastleg.sql', import.meta.url), 'utf8')
|
||||
const lastlegPermissionSeed = readFileSync(new URL('../../iam/src/main/resources/db/lastleg-permissions.sql', import.meta.url), 'utf8')
|
||||
const phase5DeliveryPermissionSeed = readFileSync(new URL('../../iam/src/main/resources/db/phase5-delivery-permissions.sql', import.meta.url), 'utf8')
|
||||
const overseasWarehousePermissions = readFileSync(new URL('../../../apps/admin-web/src/modules/overseas-warehouse/permissions.ts', import.meta.url), 'utf8')
|
||||
const overseasBusinessPermissions = readFileSync(new URL('../../../apps/admin-web/src/modules/overseas-business/permissions.ts', import.meta.url), 'utf8')
|
||||
const overseasMasterDataPermissions = readFileSync(new URL('../../../apps/admin-web/src/modules/overseas-master-data/permissions.ts', import.meta.url), 'utf8')
|
||||
const iamSeed = readFileSync(new URL('../../iam/src/main/resources/db/phase1-admin-rbac.sql', import.meta.url), 'utf8')
|
||||
const oceanBookingSchema = readFileSync(new URL('../../firstleg/src/main/resources/db/phase3-ocean-booking-schema.sql', import.meta.url), 'utf8')
|
||||
const truckAppointmentSchema = readFileSync(new URL('../../firstleg/src/main/resources/db/phase3-truck-appointment-schema.sql', import.meta.url), 'utf8')
|
||||
const cn = readInitialization()
|
||||
const overseas = readInitialization('OVERSEAS')
|
||||
const domesticSchemas = ['baiyue_auth', 'baiyue_iam', 'baiyue_order', 'baiyue_warehouse',
|
||||
'baiyue_firstleg', 'baiyue_file', 'baiyue_audit', 'baiyue_event_bridge', 'baiyue_finance']
|
||||
const overseasSchemas = ['baiyue_event_bridge_overseas', 'baiyue_lastleg', 'baiyue_lastlag_warehouse']
|
||||
|
||||
test('统一初始化 SQL 只保留平台管理员且不创建固定客户', () => {
|
||||
assert.match(sql, /最小登录基线只保留平台系统管理员/)
|
||||
assert.equal((sql.match(/'platform_admin'/g) || []).length, 1)
|
||||
assert.doesNotMatch(sql, /'merchant_admin'|'IT_TEST'|'IT 测试客户'/)
|
||||
assert.doesNotMatch(iamSeed, /'IT_TEST'|'IT 测试客户'|\(10001,/)
|
||||
const accountSeed = sql.match(/INSERT INTO auth_account \([\s\S]*?deleted = 0;/)?.[0]
|
||||
assert.ok(accountSeed, 'missing auth account seed')
|
||||
assert.doesNotMatch(accountSeed, /ON DUPLICATE KEY UPDATE[\s\S]*?password_hash\s*=/,
|
||||
're-running the unified SQL must not reset an existing account password')
|
||||
})
|
||||
|
||||
test('统一初始化直接提供tenant0商户角色与权限模板', () => {
|
||||
assert.match(sql, /4000100, 0, 'MERCHANT', 'MERCHANT_OWNER'/)
|
||||
assert.match(sql, /5300000, 0, 'MERCHANT', 'MENU',[\s\S]*?'merchant:enterprise'/)
|
||||
assert.match(sql, /5301024, 0, 'MERCHANT', 'BUTTON',[\s\S]*?'merchant:order:quick-create'/)
|
||||
assert.match(sql, /5305000, 0, 'MERCHANT', 'MENU',[\s\S]*?'merchant:finance:statement'/)
|
||||
assert.match(sql, /r\.id=4000100[\s\S]*?客户全局管理员 Finance 模板授权不完整/)
|
||||
})
|
||||
|
||||
test('统一初始化 SQL 提供人工验收所需公共仓储主数据', () => {
|
||||
for (const marker of [
|
||||
"'TP-001'", "'TP-002'", "'A1 普通库位'", "'A0 共享溢出位'",
|
||||
"'CAR-001'", "'CARRIER'", "'SHIPPER'", "'EXP-TEST'", "'IT 测试快递'",
|
||||
]) assert.ok(sql.includes(marker), `missing initialization marker: ${marker}`)
|
||||
assert.match(sql, /'EXP-TEST', 'IT 测试快递'[\s\S]*?'ACTIVE'/)
|
||||
assert.match(sql, /193000000000400003,0,193000000000200003,'RECEIVING','海外收货',1,'16:00:00',[\s\S]*?'洛杉矶仓海外接柜入仓收货能力'/)
|
||||
assert.match(sql, /193000000000400004,0,193000000000200004,'RECEIVING','海外收货',1,'16:00:00',[\s\S]*?'纽约仓海外接柜入仓收货能力'/)
|
||||
assert.match(sql, /固定平台作业仓收货能力写入校验失败/)
|
||||
|
||||
const palletSeed = sql.match(/INSERT INTO wh_pallet \([\s\S]*?deleted = 0;/)?.[0]
|
||||
assert.ok(palletSeed, 'missing pallet initialization seed')
|
||||
assert.doesNotMatch(palletSeed, /\bstatus\b|'AVAILABLE'/)
|
||||
})
|
||||
|
||||
test('国内统一初始化支持真实空库且不越界创建海外业务库', () => {
|
||||
assert.doesNotMatch(sql, /CREATE DATABASE IF NOT EXISTS baiyue_lastleg|USE baiyue_lastleg;/)
|
||||
assert.match(sql, /IF EXISTS \(SELECT 1 FROM information_schema\.tables WHERE table_schema=DATABASE\(\)[\s\S]*?table_name='fl_ocean_booking'\) THEN[\s\S]*?UPDATE fl_container_booking container_booking[\s\S]*?JOIN fl_ocean_booking ocean_booking/)
|
||||
assert.ok(
|
||||
sql.indexOf("table_name='fl_ocean_booking') THEN") < sql.indexOf('CREATE TABLE IF NOT EXISTS fl_ocean_booking ('),
|
||||
'empty-database backfill must be guarded before the ocean-booking baseline is created',
|
||||
)
|
||||
})
|
||||
|
||||
test('国内统一初始化在注释门禁前创建订单申报快照表', () => {
|
||||
for (const table of ['fl_order_declaration_snapshot', 'fl_order_declaration_event']) {
|
||||
const createIndex = sql.indexOf(`CREATE TABLE IF NOT EXISTS ${table} (`)
|
||||
const commentIndex = sql.indexOf(`CALL queue_table_comment('baiyue_firstleg', '${table}'`)
|
||||
assert.ok(createIndex >= 0, `missing domestic baseline table: ${table}`)
|
||||
assert.ok(commentIndex >= 0, `missing domestic table comment gate: ${table}`)
|
||||
assert.ok(createIndex < commentIndex, `${table} must exist before the table-comment gate runs`)
|
||||
test('两个入口分别只操作国内九库与海外三库,包括限定名引用', () => {
|
||||
for (const [sql, allowed, other, count] of [[cn, domesticSchemas, overseasSchemas, 208], [overseas, overseasSchemas, domesticSchemas, 136]]) {
|
||||
assert.deepEqual([...sql.matchAll(/^CREATE DATABASE IF NOT EXISTS (\w+)/gm)].map(m => m[1]), allowed)
|
||||
assert.deepEqual([...new Set([...sql.matchAll(/^USE (\w+);/gm)].map(m => m[1]))], allowed)
|
||||
const body = sql.replace(/^--.*$/gm, '')
|
||||
for (const schema of other) assert.doesNotMatch(body, new RegExp('\\b' + schema + '\\b'))
|
||||
assert.equal(tableDefinitions(sql).size, count)
|
||||
for (const key of tableDefinitions(sql).keys()) assert.ok(allowed.includes(key.split('.')[0]))
|
||||
}
|
||||
})
|
||||
|
||||
test('国内统一增量在 Firstleg 补列前重建已由 Warehouse 段删除的过程', () => {
|
||||
const warehouseDrop = sql.indexOf('DROP PROCEDURE IF EXISTS add_column_if_missing;',
|
||||
sql.indexOf('CALL assert_platform_public_resource_scope();'))
|
||||
const firstlegCall = sql.indexOf("CALL add_column_if_missing('fl_price_book_version', 'voided_by'")
|
||||
const firstlegCreate = sql.lastIndexOf('CREATE PROCEDURE add_column_if_missing(', firstlegCall)
|
||||
const firstlegDrop = sql.indexOf('DROP PROCEDURE IF EXISTS add_column_if_missing;', firstlegCall)
|
||||
|
||||
assert.ok(warehouseDrop >= 0, 'Warehouse migration must clean up its helper procedure')
|
||||
assert.ok(firstlegCreate > warehouseDrop, 'Firstleg must recreate the helper after the Warehouse cleanup')
|
||||
assert.ok(firstlegCreate < firstlegCall, 'Firstleg helper must exist before the price-version ALTER calls')
|
||||
assert.ok(firstlegDrop > firstlegCall, 'Firstleg must clean up the helper after its ALTER calls')
|
||||
test('纯初始化禁止迁移、数据回填、清理、重复建表和提前成功', () => {
|
||||
for (const sql of [cn, overseas]) {
|
||||
const body = sql.replace(/^--.*$/gm, '')
|
||||
assert.doesNotMatch(body, /\bALTER\s+TABLE|\bDROP\s+(?:DATABASE|TABLE)|\bTRUNCATE\b|\bRENAME\s+TABLE/i)
|
||||
assert.doesNotMatch(body, /\bCREATE\s+(?:TEMPORARY\s+TABLE|PROCEDURE)|\bPREPARE\b|\bEXECUTE\b|\bON DUPLICATE KEY UPDATE|\bINSERT IGNORE/i)
|
||||
// Runtime trigger bodies legitimately update the current loading aggregate.
|
||||
assert.doesNotMatch(body.replace(/^CREATE TRIGGER [\s\S]*?\$\$/gm, ''), /^\s*(?:UPDATE|DELETE FROM|REPLACE INTO)\b/gmi)
|
||||
assert.doesNotMatch(body, /CREATE TABLE IF NOT EXISTS/i)
|
||||
assert.equal((body.match(/AS initialization_status/g) ?? []).length, 1)
|
||||
assert.match(body.trim(), /SELECT 'PASS' AS initialization_status, '(CN|OVERSEAS)' AS region, (208|136) AS initialized_tables;$/)
|
||||
}
|
||||
})
|
||||
|
||||
test('海外统一初始化内联空库基线且不依赖模块 SQL', () => {
|
||||
assert.match(overseasSql, /BEGIN INLINE EMPTY-DATABASE BASELINE: LASTLEG/)
|
||||
assert.match(overseasSql, /BEGIN INLINE EMPTY-DATABASE BASELINE: OVERSEAS WAREHOUSE/)
|
||||
assert.match(overseasSql, /CREATE DATABASE IF NOT EXISTS baiyue_lastleg/)
|
||||
assert.match(overseasSql, /CREATE DATABASE IF NOT EXISTS baiyue_lastlag_warehouse/)
|
||||
assert.match(overseasSql, /CREATE TABLE IF NOT EXISTS ll_order \(/)
|
||||
assert.match(overseasSql, /CREATE TABLE IF NOT EXISTS wh_location \(/)
|
||||
assert.ok(
|
||||
overseasSql.indexOf('CREATE TABLE IF NOT EXISTS ll_order (') <
|
||||
overseasSql.indexOf('CREATE TABLE IF NOT EXISTS ll_order_source_pallet ('),
|
||||
'll_order must exist before the source-pallet foreign key is created',
|
||||
)
|
||||
assert.ok(
|
||||
overseasSql.indexOf('CREATE DATABASE IF NOT EXISTS baiyue_lastlag_warehouse') <
|
||||
overseasSql.indexOf('CREATE TABLE IF NOT EXISTS wh_location ('),
|
||||
'the overseas warehouse schema must be selected before its baseline tables are created',
|
||||
)
|
||||
test('平台管理员由外部bcrypt引导,强制首登改密且不创建客户', () => {
|
||||
const accounts = seedRows(cn, 'auth_account')
|
||||
assert.equal(accounts.length, 1)
|
||||
assert.equal(accounts[0].username, 'platform_admin')
|
||||
assert.equal(accounts[0].password_change_required, '1')
|
||||
assert.match(accounts[0].password_hash, /@platform_admin_password_hash/)
|
||||
assert.match(accounts[0].password_hash, /REGEXP/)
|
||||
assert.match(accounts[0].password_hash, /, NULL\)$/)
|
||||
assert.doesNotMatch(cn, /'\$2[aby]\$[0-9]{2}\$[./A-Za-z0-9]{53}'/)
|
||||
assert.deepEqual(seedRows(cn, 'iam_tenant').map(r => r.id), ['0'])
|
||||
assert.deepEqual(seedRows(cn, 'iam_user').map(r => r.auth_user_id), ['1000001'])
|
||||
assert.doesNotMatch(cn, /'merchant_admin'|'IT_TEST'|'EXP-TEST'|'CAR-001'|'TP-001'|'YW-TP-002'/)
|
||||
})
|
||||
|
||||
test('海外空库基线为固定平台管理员提供完整version0授权投影', () => {
|
||||
const authorityBlock = lastlegBaseline.match(
|
||||
/SET @platform_admin_overseas_authorities = JSON_ARRAY\(([\s\S]*?)\n\);/,
|
||||
)?.[1]
|
||||
assert.ok(authorityBlock, 'missing platform_admin overseas authority snapshot')
|
||||
const authorities = [...authorityBlock.matchAll(/'([^']+)'/g)].map((match) => match[1])
|
||||
const deferred = new Set([
|
||||
'platform:overseas-warehouse:carton:list',
|
||||
'platform:overseas-warehouse:carton:create',
|
||||
'platform:overseas-warehouse:carton:edit',
|
||||
'platform:overseas-warehouse:product:list',
|
||||
'platform:overseas-warehouse:product:create',
|
||||
'platform:overseas-warehouse:product:edit',
|
||||
])
|
||||
test('必要系统种子完整保留,但不写入示例资源与业务事实', () => {
|
||||
for (const [name, count] of Object.entries({ iam_role: 8, iam_permission: 346, iam_role_permission: 521,
|
||||
iam_data_scope: 7, wh_warehouse: 318, wh_warehouse_address: 318, wh_service_capability: 4,
|
||||
fl_fee_item: 112, fl_price_channel_catalog: 15, fl_price_origin_alias: 7, fl_price_warehouse_mapping: 4,
|
||||
file_export_task_guard: 1, fin_subject: 1 })) assert.equal(seedRows(cn, name).length, count, name)
|
||||
for (const name of ['wh_pallet', 'wh_location', 'wh_partner', 'wh_partner_type', 'wh_express_company',
|
||||
'ord_order', 'fl_inbound_order', 'fin_fee_source']) assert.equal(seedRows(cn, name).length, 0, name)
|
||||
assert.deepEqual([...new Set([...overseas.matchAll(/^INSERT INTO (\w+)/gm)].map(m => m[1]))], ['ll_security_projection'])
|
||||
assert.ok(seedRows(cn, 'wh_warehouse').every(r => r.tenant_id === '0'))
|
||||
assert.ok(seedRows(cn, 'wh_service_capability').every(r => r.service_type === 'RECEIVING' || r.capability_code === 'RECEIVING' || Object.values(r).includes('RECEIVING')))
|
||||
})
|
||||
|
||||
test('国内IAM权限与角色授权没有丢失或悬挂,客户模板仍完整', () => {
|
||||
const roles = seedRows(cn, 'iam_role'), permissions = seedRows(cn, 'iam_permission')
|
||||
const roleIds = new Set(roles.map(r => r.id)), permissionIds = new Set(permissions.map(r => r.id))
|
||||
assert.equal(new Set(permissions.map(r => r.permission_code)).size, permissions.length)
|
||||
for (const row of seedRows(cn, 'iam_role_permission')) {
|
||||
assert.ok(roleIds.has(row.role_id), 'missing role ' + row.role_id)
|
||||
assert.ok(permissionIds.has(row.permission_id), 'missing permission ' + row.permission_id)
|
||||
}
|
||||
for (const row of permissions) if (row.parent_id && row.parent_id !== '0') assert.ok(permissionIds.has(row.parent_id), 'missing parent ' + row.parent_id)
|
||||
const merchant = roleAuthorities(cn, 'MERCHANT_OWNER')
|
||||
for (const code of ['merchant:enterprise', 'merchant:order:quick-create', 'merchant:finance:statement',
|
||||
'merchant:warehouse:delivery:list', 'merchant:warehouse:delivery:create']) assert.ok(merchant.has(code), code)
|
||||
const admin = roleAuthorities(cn, 'PLATFORM_ADMIN')
|
||||
for (const code of ['platform:order:declaration:edit', 'platform:firstleg:inbound:hold',
|
||||
'platform:overseas-warehouse:last-mile-order:list', 'platform:overseas-business:purchase:list',
|
||||
'platform:overseas-master-data:quote:list', 'platform:finance:fee-source:review']) assert.ok(admin.has(code), code)
|
||||
})
|
||||
|
||||
test('海外固定身份投影完全匹配国内管理员的当前海外权限', () => {
|
||||
const rows = seedRows(overseas, 'll_security_projection')
|
||||
assert.equal(rows.length, 2)
|
||||
const authorization = rows.find(r => r.projection_type === 'AUTHORIZATION' || r.subject_type === 'AUTHORIZATION' || Object.values(r).includes('AUTHORIZATION'))
|
||||
assert.ok(authorization)
|
||||
const authorities = JSON.parse(authorization.authorities_json)
|
||||
const expected = [...roleAuthorities(cn, 'PLATFORM_ADMIN')].filter(code =>
|
||||
/^(platform:finance:|platform:overseas-business:|platform:overseas-master-data:|platform:overseas-warehouse:)/.test(code))
|
||||
assert.equal(authorities.length, 106)
|
||||
assert.ok(overseasSql.includes(`JSON_LENGTH(authorities_json) <> ${authorities.length}`),
|
||||
'fixed-admin SQL assertion must match the complete authority snapshot')
|
||||
assert.equal(new Set(authorities).size, authorities.length, 'baseline authorities must not contain duplicates')
|
||||
assert.equal(authorities.filter((item) => item.startsWith('platform:finance:')).length, 34)
|
||||
assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-business:')).length, 11)
|
||||
assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-master-data:')).length, 15)
|
||||
assert.equal(authorities.filter((item) => item.startsWith('platform:overseas-warehouse:')).length, 46)
|
||||
for (const authority of authorities) {
|
||||
assert.ok(sql.includes(`'${authority}'`), `authority is absent from the domestic IAM baseline: ${authority}`)
|
||||
}
|
||||
for (const source of [overseasWarehousePermissions, overseasBusinessPermissions, overseasMasterDataPermissions]) {
|
||||
const declared = [...source.matchAll(/'((?:platform:overseas-warehouse|platform:overseas-business|platform:overseas-master-data):[^']+)'/g)]
|
||||
.map((match) => match[1]).filter((authority) => !deferred.has(authority))
|
||||
for (const authority of declared) {
|
||||
assert.ok(
|
||||
[lastlegPermissionSeed, phase5DeliveryPermissionSeed].some((seed) => seed.includes(`'${authority}'`)),
|
||||
`Admin permission is absent from the IAM source seed: ${authority}`,
|
||||
)
|
||||
assert.ok(authorities.includes(authority), `Admin permission is absent from the fixed-admin overseas snapshot: ${authority}`)
|
||||
}
|
||||
}
|
||||
for (const authority of deferred) {
|
||||
assert.ok(!lastlegPermissionSeed.includes(`'${authority}'`), `deferred permission entered the IAM source seed: ${authority}`)
|
||||
assert.ok(!authorities.includes(authority), `deferred permission entered the fixed-admin snapshot: ${authority}`)
|
||||
}
|
||||
for (const required of [
|
||||
'platform:overseas-warehouse:last-mile-order:list',
|
||||
'platform:overseas-warehouse:inbound-order:list',
|
||||
'platform:overseas-warehouse:dispatch:list',
|
||||
'platform:overseas-business:purchase:list',
|
||||
'platform:overseas-master-data:quote:list',
|
||||
'platform:finance:fee-source:review',
|
||||
]) assert.ok(authorities.includes(required), `missing fixed-admin overseas authority: ${required}`)
|
||||
|
||||
assert.match(lastlegBaseline, /SET @platform_admin_overseas_roles = JSON_ARRAY\('PLATFORM_ADMIN'\)/)
|
||||
assert.doesNotMatch(lastlegBaseline, /\('AUTHORIZATION','1000001',0,NULL,0,JSON_ARRAY\(\),JSON_ARRAY\(\)/)
|
||||
assert.doesNotMatch(overseasSql, /\('AUTHORIZATION','1000001',0,NULL,0,JSON_ARRAY\(\),JSON_ARRAY\(\)/)
|
||||
|
||||
const inline = overseasSql.match(
|
||||
/-- BEGIN INLINE EMPTY-DATABASE BASELINE: LASTLEG\r?\n([\s\S]*?)\r?\n\r?\n-- END INLINE EMPTY-DATABASE BASELINE: LASTLEG/,
|
||||
)?.[1]
|
||||
assert.ok(inline, 'missing inline Lastleg baseline')
|
||||
assert.equal(inline.replace(/\r\n/g, '\n').trim(), lastlegBaseline.replace(/\r\n/g, '\n').trim())
|
||||
assert.equal(new Set(authorities).size, authorities.length)
|
||||
assert.deepEqual([...authorities].sort(), expected.sort())
|
||||
assert.deepEqual(JSON.parse(authorization.roles_json), ['PLATFORM_ADMIN'])
|
||||
for (const row of rows) assert.ok(Object.values(row).includes('1000001'))
|
||||
})
|
||||
|
||||
test('当前海外基线不从废弃申请回填历史尾程订单', () => {
|
||||
for (const source of [lastlegBaseline, overseasSql]) {
|
||||
assert.doesNotMatch(source, /INSERT IGNORE INTO ll_order\s*\([\s\S]*?SELECT a\.id,a\.discard_no/)
|
||||
}
|
||||
test('跨区域放错位置的最终字段归正确区域且保留财务精度', () => {
|
||||
const fee = table(overseas, 'baiyue_lastleg', 'll_finance_fee_source')
|
||||
for (const name of ['original_currency', 'original_amount', 'exchange_rate', 'exchange_rate_month',
|
||||
'chargeable_quantity', 'quantity_unit', 'unit_price', 'period_start', 'period_end']) assert.match(fee, new RegExp('\\b' + name + '\\b'))
|
||||
assert.match(fee, /original_amount decimal\(20,6\)/i)
|
||||
assert.match(fee, /exchange_rate decimal\(20,6\)/i)
|
||||
const returns = table(overseas, 'baiyue_lastleg', 'll_return_order')
|
||||
assert.match(returns, /lastleg_order_id bigint/i)
|
||||
assert.match(returns, /lastleg_order_no varchar\(32\)/i)
|
||||
assert.match(table(cn, 'baiyue_finance', 'fin_fee_source'), /idx_fin_fee_source_wallet_hold \(wallet_hold_id\)/)
|
||||
})
|
||||
|
||||
test('国内统一初始化补齐入库费用人工调整基线字段', () => {
|
||||
assert.match(sql, /baseline_chargeable_quantity DECIMAL\(18,6\) NOT NULL/)
|
||||
assert.match(sql, /SET baseline_chargeable_quantity = chargeable_quantity[\s\S]*?WHERE baseline_chargeable_quantity IS NULL/)
|
||||
assert.match(sql, /tolerance_percent DECIMAL\(5,2\) NOT NULL DEFAULT 10\.00/)
|
||||
assert.match(sql, /unified_assert_column\('baiyue_firstleg', 'fl_inbound_fee', 'baseline_chargeable_quantity'\)/)
|
||||
assert.match(sql, /unified_assert_column\('baiyue_firstleg', 'fl_inbound_fee', 'tolerance_percent'\)/)
|
||||
})
|
||||
|
||||
test('三期权限迁移删除退役权限并只保留 canonical 权限', () => {
|
||||
for (const source of [sql, oceanBookingSchema]) {
|
||||
assert.match(source, /DELETE FROM iam_permission WHERE id IN \(5102141,5102143,5102144,5102145\)/)
|
||||
assert.match(source, /5102147[\s\S]*?platform:firstleg:ocean-booking:edit/)
|
||||
assert.match(source, /5102148[\s\S]*?platform:firstleg:ocean-booking:delete/)
|
||||
assert.doesNotMatch(source, /platform:firstleg:ocean-booking:(view|cancel|change)/)
|
||||
assert.ok(
|
||||
source.indexOf('DELETE FROM iam_permission WHERE id IN (5102141,5102143,5102144,5102145)') <
|
||||
source.indexOf('(5102147,0,\'PLATFORM\',\'BUTTON\',5102140,\'platform:firstleg:ocean-booking:edit\''),
|
||||
'legacy ocean-booking edit permission must be removed before assigning the code to 5102147',
|
||||
)
|
||||
}
|
||||
|
||||
for (const source of [sql, truckAppointmentSchema]) {
|
||||
assert.match(source, /DELETE FROM iam_permission WHERE id=5102151/)
|
||||
assert.doesNotMatch(source, /platform:firstleg:truck-appointment:view[',]/)
|
||||
}
|
||||
|
||||
assert.match(sql, /status='ACTIVE' AND deleted=0[\s\S]*?id BETWEEN 5102140 AND 5102149/)
|
||||
assert.match(sql, /status='ACTIVE' AND deleted=0[\s\S]*?id BETWEEN 5102150 AND 5102154/)
|
||||
})
|
||||
|
||||
test('海外仓物理托盘初始化与模块基线一致', () => {
|
||||
const baseline = readFileSync(new URL('../../warehouse-overseas-service/src/main/resources/db/warehouse.sql', import.meta.url), 'utf8')
|
||||
const inline = overseasSql.match(/-- BEGIN INLINE EMPTY-DATABASE BASELINE: OVERSEAS WAREHOUSE\r?\n([\s\S]*?)\r?\n\r?\n-- END INLINE EMPTY-DATABASE BASELINE: OVERSEAS WAREHOUSE/)?.[1]
|
||||
assert.ok(inline)
|
||||
assert.equal(inline.slice(inline.indexOf('-- This script is run')).replace(/\r\n/g, '\n').trim(), baseline.replace(/\r\n/g, '\n').trim())
|
||||
test('最终业务触发器与循环外键均存在,不留下发布过程', () => {
|
||||
assert.equal((cn.match(/^CREATE TRIGGER /gm) ?? []).length, 64)
|
||||
assert.doesNotMatch(cn, /CREATE DEFINER=/)
|
||||
for (const name of ['trg_container_booking_before_update', 'trg_loading_pick_task_before_update',
|
||||
'trg_order_fulfillment_split_insert', 'trg_inbound_split_item_before_delete']) assert.match(cn, new RegExp('CREATE TRIGGER ' + name + '\\b'))
|
||||
assert.match(table(cn, 'baiyue_firstleg', 'fl_inbound_measurement_item'), /REFERENCES fl_inbound_split_item/)
|
||||
assert.match(table(cn, 'baiyue_firstleg', 'fl_inbound_split_item'), /REFERENCES fl_inbound_measurement_item/)
|
||||
const disable = cn.indexOf('SET SESSION foreign_key_checks = 0;')
|
||||
const enable = cn.indexOf('SET SESSION foreign_key_checks = 1;')
|
||||
assert.ok(disable >= 0 && enable > disable)
|
||||
assert.ok(!cn.slice(disable, enable).includes('INSERT INTO'))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user