fix(claim): align risk advice with expense rows

This commit is contained in:
caoxiaozhu
2026-06-15 20:53:48 +08:00
parent 5747e85acf
commit 792741709a
7 changed files with 596 additions and 178 deletions

View File

@@ -393,6 +393,55 @@ test('attachment risk cards do not duplicate claim fallback flags for the same i
assert.equal(riskCards[0].risk, '住宿标准:当前酒店识别金额约 880.00 元/晚。')
})
test('AI advice hides generic auto review summaries when a specific hotel over-standard risk exists', () => {
const riskCards = buildAttachmentRiskCards({
expenseItems: [
{
id: 'hotel-over-standard-item',
name: '住宿票',
itemType: 'hotel_ticket',
invoiceId: 'hotel-over-standard.png'
}
],
attachmentMetaByItemId: {
'hotel-over-standard-item': {
analysis: {
severity: 'high',
label: '高风险',
headline: 'AI提示住宿金额超出报销标准',
summary: '当前住宿票据金额超过规则中心差旅住宿标准。',
points: ['住宿标准P5在上海的住宿标准为 250.00 元/晚,当前酒店识别金额约 362.00 元/晚。'],
suggestion: '请补充超标说明。'
}
}
},
claimRiskFlags: [
{
source: 'submission_review',
severity: 'high',
label: '自动检测重点复核',
message: '自动检测发现 1 条高风险附件,已随单流转给审批人重点复核。'
},
{
source: 'submission_review',
severity: 'high',
label: '住宿超标待说明',
message: 'P5 职级在上海的住宿标准为 250.00 元/晚,当前酒店识别金额约 362.00 元/晚。 当前未识别到超标说明,请先补充原因。'
},
{
source: 'submission_review',
severity: 'medium',
label: '自动检测重点复核',
message: '自动检测发现需审批重点关注事项:存在高风险票据,需审批人重点复核;住宿金额超出当前职级差标,且未补充超标说明。'
}
]
})
assert.equal(riskCards.length, 1)
assert.equal(riskCards[0].title, '第 1 条AI提示住宿金额超出报销标准')
assert.equal(riskCards[0].tone, 'high')
})
test('AI advice view model exposes grouped completion and risk sections', () => {
const advice = buildAiAdviceViewModel({
completionItems: ['补充业务地点', '补充报销金额'],
@@ -567,6 +616,71 @@ test('expense risk indicator can focus and flash related risk card', () => {
assert.match(detailViewStyle, /@keyframes risk-card-flash/)
})
test('route-level risk cards keep related item ids for every affected expense row', () => {
const riskCards = buildAttachmentRiskCards({
expenseItems: [
{ id: 'travel-item-1', name: '火车票', category: '火车票' },
{ id: 'travel-item-2', name: '火车票', category: '火车票' },
{ id: 'travel-item-3', name: '火车票', category: '火车票' }
],
claimRiskFlags: [
{
source: 'submission_review',
severity: 'high',
label: '多城市行程待说明',
message: '检测到本次差旅涉及 深圳 多个目的地,但当前报销事由未说明中转、多地拜访或改签原因。',
item_ids: ['travel-item-2', 'travel-item-3']
}
]
})
assert.equal(riskCards.length, 1)
assert.deepEqual(riskCards[0].itemIds, ['travel-item-2', 'travel-item-3'])
assert.equal(riskCards[0].title, '第 2、3 条:多城市行程待说明')
assert.match(detailViewScript, /cardItemIds\.includes\(itemId\)/)
})
test('legacy route-level risk cards infer affected travel rows when backend has no item ids', () => {
const riskCards = buildAttachmentRiskCards({
expenseItems: [
{
id: 'train-outbound',
name: '火车票',
category: '火车票',
desc: '武汉-上海',
detail: '起始地-目的地',
invoiceId: 'outbound.png'
},
{
id: 'train-transfer',
name: '火车票',
category: '火车票',
desc: '上海-深圳',
detail: '起始地-目的地',
invoiceId: 'transfer.png'
},
{
id: 'allowance-row',
name: '出差补贴',
category: '出差补贴',
desc: '系统自动计算',
detail: '直辖市/特区'
}
],
claimRiskFlags: [
{
source: 'submission_review',
severity: 'high',
label: '多城市行程待说明',
message: '检测到本次差旅涉及 深圳 多个目的地,但当前报销事由未说明中转、多地拜访或改签原因。'
}
]
})
assert.equal(riskCards.length, 1)
assert.deepEqual(riskCards[0].itemIds, ['train-outbound', 'train-transfer'])
})
test('AI advice shows only the latest manual return while preserving return count context', () => {
const riskCards = buildAttachmentRiskCards({
claimRiskFlags: [