优化
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# Warehouse 服务局部脚本
|
||||
|
||||
本目录只放 Warehouse 服务自身的离线分析或数据合同,不放仓库级 HTTP 验收、部署脚本或共享工具。
|
||||
|
||||
| 脚本 | 用途 | 副作用 | 运行方式 |
|
||||
|---|---|---|---|
|
||||
| `warehouse-public-master-data-contract.test.mjs` | 校验公共 FBA 仓 CSV、四个固定平台仓和 `warehouse-public-master-data.sql` 的数量、唯一性、字段完整性及 SQL 安全边界 | 只读 Warehouse 源码中的 CSV/SQL;不连接数据库、不执行 SQL、不写文件 | 从后端根执行 `node --test warehouse/scripts/warehouse-public-master-data-contract.test.mjs` |
|
||||
|
||||
新增 Warehouse 局部 Node 脚本时应放在本目录,并同步本表。跨服务或仓库级脚本仍放根 `scripts/`,Java/JUnit 测试仍放 `src/test/java/`。
|
||||
@@ -0,0 +1,122 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
|
||||
const currentDir = dirname(fileURLToPath(import.meta.url))
|
||||
const warehouseRoot = resolve(currentDir, '..')
|
||||
const sqlPath = resolve(warehouseRoot, 'src/main/resources/db/warehouse-public-master-data.sql')
|
||||
const acceptedPath = resolve(warehouseRoot, 'src/main/resources/db/master-data/fba-public-addresses.accepted.csv')
|
||||
const rejectedPath = resolve(warehouseRoot, 'src/main/resources/db/master-data/fba-public-addresses.rejected.csv')
|
||||
const fixedWarehousePath = resolve(warehouseRoot, 'src/main/resources/db/master-data/platform-fixed-warehouses.csv')
|
||||
|
||||
function parseCsv(text) {
|
||||
const rows = []
|
||||
let field = ''
|
||||
let row = []
|
||||
let quoted = false
|
||||
for (let index = 0; index < text.length; index += 1) {
|
||||
const char = text[index]
|
||||
if (quoted) {
|
||||
if (char === '"' && text[index + 1] === '"') {
|
||||
field += '"'
|
||||
index += 1
|
||||
} else if (char === '"') {
|
||||
quoted = false
|
||||
} else {
|
||||
field += char
|
||||
}
|
||||
} else if (char === '"') {
|
||||
quoted = true
|
||||
} else if (char === ',') {
|
||||
row.push(field)
|
||||
field = ''
|
||||
} else if (char === '\n') {
|
||||
row.push(field.replace(/\r$/, ''))
|
||||
rows.push(row)
|
||||
row = []
|
||||
field = ''
|
||||
} else {
|
||||
field += char
|
||||
}
|
||||
}
|
||||
if (field.length > 0 || row.length > 0) {
|
||||
row.push(field)
|
||||
rows.push(row)
|
||||
}
|
||||
const [headers, ...data] = rows.filter((item) => item.some((value) => value !== ''))
|
||||
return data.map((values) => Object.fromEntries(headers.map((header, index) => [header, values[index] ?? ''])))
|
||||
}
|
||||
|
||||
const sql = readFileSync(sqlPath, 'utf8')
|
||||
const accepted = parseCsv(readFileSync(acceptedPath, 'utf8'))
|
||||
const rejected = parseCsv(readFileSync(rejectedPath, 'utf8'))
|
||||
const fixedWarehouses = parseCsv(readFileSync(fixedWarehousePath, 'utf8'))
|
||||
|
||||
assert.equal(accepted.length, 252)
|
||||
assert.equal(rejected.length, 54)
|
||||
assert.equal(fixedWarehouses.length, 4)
|
||||
|
||||
const codes = new Set()
|
||||
const warehouseIds = new Set()
|
||||
const addressIds = new Set()
|
||||
for (const row of accepted) {
|
||||
assert.match(row.warehouse_code, /^[A-Z0-9]{3,5}$/)
|
||||
assert.equal(row.warehouse_code, row.warehouse_code.trim().toUpperCase())
|
||||
assert.ok(row.city.trim())
|
||||
assert.ok(row.state_province.trim())
|
||||
assert.ok(row.address_line1.trim())
|
||||
assert.ok(row.postal_code.trim())
|
||||
assert.ok(row.timezone.trim())
|
||||
assert.equal(row.country_code, 'US')
|
||||
assert.ok(!codes.has(row.warehouse_code), `duplicate code ${row.warehouse_code}`)
|
||||
assert.ok(!warehouseIds.has(row.warehouse_id_seed), `duplicate warehouse id ${row.warehouse_id_seed}`)
|
||||
assert.ok(!addressIds.has(row.address_id_seed), `duplicate address id ${row.address_id_seed}`)
|
||||
codes.add(row.warehouse_code)
|
||||
warehouseIds.add(row.warehouse_id_seed)
|
||||
addressIds.add(row.address_id_seed)
|
||||
}
|
||||
|
||||
assert.ok(rejected.some((row) => row.reject_reason.includes('non_fba_business_node')))
|
||||
assert.equal(rejected.filter((row) => row.reject_reason.includes('timezone_pending_confirmation')).length, 1)
|
||||
|
||||
assert.deepEqual(fixedWarehouses.map((row) => row.warehouse_code), [
|
||||
'CN-YIWU-01',
|
||||
'CN-DONGGUAN-01',
|
||||
'US-LAX-01',
|
||||
'US-NYC-01',
|
||||
])
|
||||
assert.deepEqual(fixedWarehouses.map((row) => row.timezone), [
|
||||
'UTC+8',
|
||||
'UTC+8',
|
||||
'UTC-8',
|
||||
'UTC-5',
|
||||
])
|
||||
assert.ok(fixedWarehouses.every((row) => row.address_line1.includes('待维护') || row.address_line1.includes('pending maintenance')))
|
||||
|
||||
assert.match(sql, /CREATE TEMPORARY TABLE tmp_wh_fixed_platform_warehouse/)
|
||||
assert.match(sql, /'CN-YIWU-01','义乌仓','DOMESTIC','CN','UTC\+8'/)
|
||||
assert.match(sql, /'CN-DONGGUAN-01','东莞仓','DOMESTIC','CN','UTC\+8'/)
|
||||
assert.match(sql, /'US-LAX-01','洛杉矶仓','OVERSEAS','US','UTC-8'/)
|
||||
assert.match(sql, /'US-NYC-01','纽约仓','OVERSEAS','US','UTC-5'/)
|
||||
assert.match(sql, /固定平台仓地址种子ID与既有数据冲突/)
|
||||
assert.match(sql, /固定平台仓地址父子解析失败/)
|
||||
assert.match(sql, /FROM tmp_wh_fixed_platform_warehouse source[\s\S]+ON DUPLICATE KEY UPDATE\s+tenant_id = VALUES\(tenant_id\);/)
|
||||
|
||||
assert.match(sql, /CREATE TEMPORARY TABLE tmp_wh_fba_public_master_data/)
|
||||
assert.match(sql, /JOIN wh_warehouse warehouse\s+ON warehouse\.tenant_id = 0\s+AND warehouse\.warehouse_code = source\.warehouse_code/s)
|
||||
assert.match(sql, /ON DUPLICATE KEY UPDATE\s+warehouse_type = VALUES\(warehouse_type\),\s+country_code = VALUES\(country_code\),\s+timezone = VALUES\(timezone\),\s+updated_at = CURRENT_TIMESTAMP\(3\);/s)
|
||||
assert.doesNotMatch(sql, /status\s*=\s*VALUES\(status\)/)
|
||||
assert.doesNotMatch(sql, /contact_name\s*=\s*VALUES\(contact_name\)/)
|
||||
assert.doesNotMatch(sql, /contact_phone\s*=\s*VALUES\(contact_phone\)/)
|
||||
assert.doesNotMatch(sql, /contact_email\s*=\s*VALUES\(contact_email\)/)
|
||||
assert.doesNotMatch(sql, /remark\s*=\s*VALUES\(remark\)/)
|
||||
assert.match(sql, /四个固定平台作业仓必须启用收货能力/)
|
||||
assert.match(sql, /INSERT INTO wh_service_capability[\s\S]+?'RECEIVING'/i)
|
||||
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, /warehouse_id IN \(193000000000200001,193000000000200002,193000000000200003,193000000000200004\)[\s\S]*?<> 4 THEN[\s\S]*?固定平台作业仓收货能力写入校验失败/)
|
||||
const fbaBlock = sql.slice(sql.indexOf('CREATE TEMPORARY TABLE tmp_wh_fba_public_master_data'))
|
||||
assert.doesNotMatch(fbaBlock, /INSERT INTO wh_service_capability/i)
|
||||
assert.match(sql, /FBA公共主数据地址种子ID与既有数据冲突/)
|
||||
assert.match(sql, /FBA公共地址不得创建平台作业能力/)
|
||||
Reference in New Issue
Block a user