feat(consignment): 匹配日志新增寄卖单号列并中文化原因
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import test from 'node:test'
|
||||
|
||||
import ts from 'typescript'
|
||||
|
||||
import {
|
||||
CONSIGNMENT_MATCH_REASON_LABELS,
|
||||
resolveConsignmentMatchReasonLabel,
|
||||
} from '../src/components/admin/consignment-match-log-labels.ts'
|
||||
|
||||
const ENGINE_PATH = fileURLToPath(
|
||||
new URL(
|
||||
'../../backend/src/services/worker-platform/consignment-match-engine-service.ts',
|
||||
import.meta.url,
|
||||
),
|
||||
)
|
||||
const MODAL_PATH = fileURLToPath(
|
||||
new URL('../src/components/admin/ConsignmentMatchLogsModal.tsx', import.meta.url),
|
||||
)
|
||||
|
||||
function collectStringLiterals(expr: ts.Expression, result: Set<string>) {
|
||||
if (ts.isStringLiteralLike(expr)) {
|
||||
result.add(expr.text)
|
||||
return
|
||||
}
|
||||
if (ts.isParenthesizedExpression(expr)) {
|
||||
collectStringLiterals(expr.expression, result)
|
||||
return
|
||||
}
|
||||
if (ts.isConditionalExpression(expr)) {
|
||||
// 只取分支结果,不把条件里的字符串当成原因码。
|
||||
collectStringLiterals(expr.whenTrue, result)
|
||||
collectStringLiterals(expr.whenFalse, result)
|
||||
return
|
||||
}
|
||||
if (
|
||||
ts.isBinaryExpression(expr) &&
|
||||
[
|
||||
ts.SyntaxKind.BarBarToken,
|
||||
ts.SyntaxKind.QuestionQuestionToken,
|
||||
ts.SyntaxKind.PlusToken,
|
||||
].includes(expr.operatorToken.kind)
|
||||
) {
|
||||
collectStringLiterals(expr.left, result)
|
||||
collectStringLiterals(expr.right, result)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/** 匹配日志的 reasonCode 只有两种来源:固定流程原因 + createHttpError 的 errorCode。 */
|
||||
function collectEngineReasonCodes() {
|
||||
const source = readFileSync(ENGINE_PATH, 'utf8')
|
||||
const sourceFile = ts.createSourceFile(ENGINE_PATH, source, ts.ScriptTarget.Latest, true)
|
||||
const result = new Set<string>()
|
||||
|
||||
function visit(node: ts.Node) {
|
||||
if (ts.isCallExpression(node)) {
|
||||
const callee = node.expression.getText(sourceFile).split('.').pop() || ''
|
||||
if (callee === 'recordConsignmentMatchLog') {
|
||||
const objectArg = node.arguments.find((arg): arg is ts.ObjectLiteralExpression =>
|
||||
ts.isObjectLiteralExpression(arg),
|
||||
)
|
||||
for (const property of objectArg?.properties || []) {
|
||||
if (
|
||||
ts.isPropertyAssignment(property) &&
|
||||
property.name.getText(sourceFile) === 'reasonCode'
|
||||
) {
|
||||
collectStringLiterals(property.initializer, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ts.isPropertyAssignment(node) && node.name.getText(sourceFile) === 'errorCode') {
|
||||
collectStringLiterals(node.initializer, result)
|
||||
}
|
||||
ts.forEachChild(node, visit)
|
||||
}
|
||||
|
||||
visit(sourceFile)
|
||||
return result
|
||||
}
|
||||
|
||||
test('寄卖匹配日志:后端写入的每个原因码都必须有中文映射', () => {
|
||||
const reasonCodes = collectEngineReasonCodes()
|
||||
assert.ok(reasonCodes.size > 0, '没有扫描到任何原因码,测试逻辑可能失效')
|
||||
|
||||
const missing = [...reasonCodes].filter((code) => !CONSIGNMENT_MATCH_REASON_LABELS[code]).sort()
|
||||
|
||||
assert.deepEqual(
|
||||
missing,
|
||||
[],
|
||||
`以下原因码缺少中文映射,会在匹配日志里直接显示英文:${missing.join(', ')}`,
|
||||
)
|
||||
})
|
||||
|
||||
test('寄卖匹配日志:原因列优先显示中文,未知码兜底原文', () => {
|
||||
assert.equal(resolveConsignmentMatchReasonLabel('manual_matched', ''), '手动匹配成功')
|
||||
assert.equal(resolveConsignmentMatchReasonLabel('manual_matched', undefined), '手动匹配成功')
|
||||
assert.equal(
|
||||
resolveConsignmentMatchReasonLabel(
|
||||
'consignment_spec_mismatch',
|
||||
'所选库存与订单规格不一致:INV1',
|
||||
),
|
||||
'所选库存与订单规格不一致:INV1',
|
||||
)
|
||||
assert.equal(resolveConsignmentMatchReasonLabel('future_unknown_code', ''), 'future_unknown_code')
|
||||
assert.equal(resolveConsignmentMatchReasonLabel('', ''), '-')
|
||||
})
|
||||
|
||||
test('寄卖匹配日志弹窗:工单右侧新增寄卖单号列', () => {
|
||||
const modalSource = readFileSync(MODAL_PATH, 'utf8')
|
||||
|
||||
assert.ok(modalSource.includes("title: '寄卖单号'"), '必须新增「寄卖单号」列')
|
||||
assert.ok(
|
||||
modalSource.includes("dataIndex: 'consignmentNos'"),
|
||||
'「寄卖单号」列必须读取后端返回的 consignmentNos',
|
||||
)
|
||||
assert.ok(
|
||||
modalSource.indexOf("title: '寄卖单号'") > modalSource.indexOf("title: '工单'"),
|
||||
'「寄卖单号」列必须在「工单」列右侧',
|
||||
)
|
||||
assert.ok(modalSource.includes('resolveConsignmentMatchReasonLabel'), '原因列必须使用中文映射')
|
||||
})
|
||||
Reference in New Issue
Block a user