import assert from 'node:assert/strict' import { readFileSync } from 'node:fs' import { fileURLToPath } from 'node:url' import test from 'node:test' import { computeConsignmentMatchScore, describeConsignmentMatch, resolveMatchCoverage, } from '../src/utils/consignment-match-coverage.ts' test('匹配打分:与仓库列表同口径(精确 100 / 高配 85 / 未知 50 / 冲突 0)', () => { assert.equal(computeConsignmentMatchScore({ matchType: 'exact', matchDetails: [] }), 100) assert.equal(computeConsignmentMatchScore({ matchType: 'partial', matchDetails: [] }), 85) assert.equal(computeConsignmentMatchScore({ matchType: 'unknown', matchDetails: [] }), 50) assert.equal(computeConsignmentMatchScore({ matchType: 'conflict', matchDetails: [] }), 0) assert.equal( computeConsignmentMatchScore({ matchType: 'partial', matchDetails: [ { key: 'grade', label: '等级', orderValue: 'A', inventoryValue: 'S', status: 'match', }, { key: 'series', label: '系列', orderValue: 'A', inventoryValue: 'S', status: 'partial', }, ], }), 93, ) }) test('匹配说明:精确/非精确/冲突都必须有可读文案', () => { assert.equal(describeConsignmentMatch({ matchType: 'exact' }), '规格完全一致') assert.equal( describeConsignmentMatch({ matchType: 'partial', matchReasons: [] }), '规格高于要求(非精确)', ) assert.equal( describeConsignmentMatch({ matchType: 'conflict', matchReasons: ['系统不一致', '区服不一致'], }), '不匹配:系统不一致;区服不一致', ) }) test('拼单覆盖:1+1 不够 3 份,2+1 才允许提交', () => { const short = resolveMatchCoverage({ sharingEnabled: true, totalQuantity: 3, activeQuantity: 0, selected: [ { inventoryId: 1, remainingQuantity: 1 }, { inventoryId: 2, remainingQuantity: 1 }, ], }) assert.equal(short.requiredQuantity, 3) assert.equal(short.selectedQuantity, 2) assert.equal(short.sufficient, false) assert.equal(short.gap, 1) const enough = resolveMatchCoverage({ sharingEnabled: true, totalQuantity: 3, activeQuantity: 0, selected: [ { inventoryId: 1, remainingQuantity: 2 }, { inventoryId: 2, remainingQuantity: 1 }, ], }) assert.equal(enough.selectedQuantity, 3) assert.equal(enough.sufficient, true) assert.equal(enough.gap, 0) }) test('拼单覆盖:已匹配 1 份时只需再选 2 份', () => { const result = resolveMatchCoverage({ sharingEnabled: true, totalQuantity: 3, activeQuantity: 1, selected: [{ inventoryId: 1, remainingQuantity: 2 }], }) assert.equal(result.requiredQuantity, 2) assert.equal(result.sufficient, true) }) test('整单覆盖:必须一条库存满足全部数量', () => { const short = resolveMatchCoverage({ sharingEnabled: false, totalQuantity: 3, activeQuantity: 0, selected: [{ inventoryId: 1, remainingQuantity: 2 }], }) assert.equal(short.requiredQuantity, 3) assert.equal(short.selectedQuantity, 2) assert.equal(short.sufficient, false) assert.equal(short.gap, 1) const enough = resolveMatchCoverage({ sharingEnabled: false, totalQuantity: 3, activeQuantity: 0, selected: [{ inventoryId: 1, remainingQuantity: 3 }], }) assert.equal(enough.sufficient, true) }) test('工单页:internal_matching 显示「手动匹配寄卖」入口', () => { const source = readFileSync( fileURLToPath(new URL('../src/pages/admin/panels/WorkOrdersPanel.tsx', import.meta.url)), 'utf8', ) assert.ok(source.includes('手动匹配寄卖'), '内部匹配中的按钮文案必须是手动匹配寄卖') assert.ok( source.includes("String(row.status || '') === 'internal_matching'"), '按钮文案必须只在 internal_matching 下切换', ) }) test('工单页:手动匹配寄卖成功后必须按真实查询键刷新列表与库存', () => { const source = readFileSync( fileURLToPath(new URL('../src/pages/admin/panels/WorkOrdersPanel.tsx', import.meta.url)), 'utf8', ) const modalIndex = source.indexOf(' 0, '工单页必须挂载手动匹配寄卖弹窗') const matchedIndex = source.indexOf('onMatched={() => {', modalIndex) const matchedBlock = source.slice(matchedIndex, source.indexOf('}}', matchedIndex) + 2) assert.ok(matchedBlock.includes('refreshAll()'), '匹配成功必须调用 refreshAll() 重取列表') assert.ok( !matchedBlock.includes("'admin-work-orders'") && !matchedBlock.includes("'admin-work-orders-stats'"), '不得 invalidate 不存在的 admin-work-orders / admin-work-orders-stats 查询键', ) const refreshIndex = source.indexOf('async function refreshAll()') const refreshBlock = source.slice( refreshIndex, source.indexOf('async function runAction', refreshIndex), ) for (const key of [ 'admin-worker-platform-orders', 'admin-worker-platform-summary', 'admin-consignment-inventories', 'admin-consignment-stats', ]) { assert.ok(refreshBlock.includes(key), `refreshAll() 必须刷新 ${key}`) } })