Files
X-Financial/web/tests/ai-application-precheck-model.test.mjs

153 lines
5.1 KiB
JavaScript
Raw Permalink Normal View History

import assert from 'node:assert/strict'
import test from 'node:test'
import {
buildAiApplicationPrecheck,
buildAiApplicationPrecheckMessage,
buildAiApplicationPrecheckThinkingEvents,
buildAiApplicationSubmitConflictMessage,
isAiApplicationPrecheckBlocking
} from '../src/utils/aiApplicationPrecheckModel.js'
const preview = {
fields: {
applicationType: '差旅费用申请',
time: '2026-02-20 至 2026-02-23',
location: '上海',
reason: '辅助国网仿生产服务器部署',
amount: '2,120元',
days: '4天',
transportMode: '火车'
},
missingFields: []
}
test('application precheck blocks application generation when existing application overlaps', () => {
const precheck = buildAiApplicationPrecheck(preview, {
currentUser: { name: '曹笑竹', departmentName: '技术部' },
claimsPayload: {
items: [
{
claim_no: 'AP-OVERLAP',
document_type: 'expense_application',
expense_type: 'travel_application',
employee_name: '曹笑竹',
status: 'submitted',
risk_flags_json: [
{
source: 'application_detail',
application_detail: {
business_time: '2026-02-21 至 2026-02-22',
reason: '同时间段现场支持',
location: '上海'
}
}
]
}
]
},
budgetSummary: {
total_amount: 10000,
reserved_amount: 8000,
consumed_amount: 500,
available_amount: 1500
}
})
assert.equal(precheck.overlap.status, 'warning')
assert.match(precheck.overlap.summary, /可能重叠/)
assert.equal(precheck.overlap.matches[0].claimNo, 'AP-OVERLAP')
assert.equal(precheck.budget.status, 'warning')
assert.equal(precheck.budget.requiresBudgetReview, true)
assert.match(precheck.budget.summary, /预算管理者审核/)
const message = buildAiApplicationPrecheckMessage(preview, precheck)
assert.match(message, /### 发现同时间段已有申请单/)
assert.match(message, /时间重叠提醒/)
assert.match(message, /AP-OVERLAP/)
assert.match(message, /\| 单据编号 \| 申请时间 \| 状态 \| 事由 \| 操作 \|/)
assert.match(message, /\| AP-OVERLAP \| 2026-02-21 至 2026-02-22 \| 审批中 \| 同时间段现场支持 \| \[查看\]\(#ai-open-application-detail:AP-OVERLAP\) \|/)
assert.match(message, /2026-02-21 至 2026-02-22/)
assert.match(message, /同时间段现场支持/)
assert.match(message, /请先检查本次申请时间是否填写正确/)
assert.doesNotMatch(message, /出差申请表草稿已生成/)
})
test('application submit precheck blocks submit and keeps application detail action link', () => {
const precheck = buildAiApplicationPrecheck(preview, {
currentUser: { name: '曹笑竹', departmentName: '技术部' },
claimsPayload: {
items: [
{
claim_no: 'AP-OVERLAP',
document_type: 'expense_application',
expense_type: 'travel_application',
employee_name: '曹笑竹',
status: 'submitted',
risk_flags_json: [
{
source: 'application_detail',
application_detail: {
business_time: '2026-02-20 至 2026-02-23',
reason: '辅助国网仿生产服务器部署',
location: '上海'
}
}
]
}
]
}
})
assert.equal(isAiApplicationPrecheckBlocking(precheck), true)
const message = buildAiApplicationSubmitConflictMessage(preview, precheck)
assert.match(message, /### 发现相同日期已有申请单/)
assert.match(message, /当前不能继续提交/)
assert.match(message, /请先核对申请时间是否填写正确/)
assert.match(message, /\[查看\]\(#ai-open-application-detail:AP-OVERLAP\)/)
assert.doesNotMatch(message, /生成新的出差申请表/)
})
test('application precheck emits thinking events for overlap, budget, and form generation', () => {
const precheck = buildAiApplicationPrecheck(preview, {
currentUser: { name: '曹笑竹' },
claimsPayload: [],
budgetSummary: {
total_amount: 10000,
reserved_amount: 1000,
consumed_amount: 1000,
available_amount: 8000
}
})
const events = buildAiApplicationPrecheckThinkingEvents(precheck)
assert.equal(events.length, 3)
assert.deepEqual(
events.map((event) => event.eventId),
['application-precheck-overlap', 'application-precheck-budget', 'application-precheck-form']
)
assert.match(events[1].content, /预算/)
})
test('application precheck ignores application candidates without parseable business time', () => {
const precheck = buildAiApplicationPrecheck(preview, {
currentUser: { name: '曹笑竹' },
claimsPayload: {
items: [
{
claim_no: 'AP-NO-TIME',
document_type: 'expense_application',
expense_type: 'travel_application',
employee_name: '曹笑竹',
status: 'submitted'
}
]
},
budgetSummary: {}
})
assert.equal(precheck.overlap.status, 'ok')
assert.deepEqual(precheck.overlap.matches, [])
})