feat: 重构报销单服务并完善前端提交与审核交互
重构 expense_claims 服务模块结构并优化差旅票据审核逻辑, 增强用户代理服务的票据类型识别,前端报销创建页面拆分为 附件模型和会话模型模块,重构提交编排器和草稿关联确认流 程,更新知识库索引,补充单元测试。
This commit is contained in:
34
web/tests/attachment-association-confirmation.test.mjs
Normal file
34
web/tests/attachment-association-confirmation.test.mjs
Normal file
@@ -0,0 +1,34 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
|
||||
import {
|
||||
ATTACHMENT_ASSOCIATION_CONFIRM_HREF,
|
||||
buildAttachmentAssociationConfirmationMessage
|
||||
} from '../src/views/scripts/travelReimbursementAttachmentModel.js'
|
||||
|
||||
test('attachment association prompt prints recognized receipt details before confirmation link', () => {
|
||||
const message = buildAttachmentAssociationConfirmationMessage({
|
||||
claimNo: 'EXP-202605-001',
|
||||
fileNames: ['train-ticket.pdf'],
|
||||
ocrDocuments: [
|
||||
{
|
||||
filename: 'train-ticket.pdf',
|
||||
document_type: 'train_ticket',
|
||||
scene_label: '差旅票据',
|
||||
summary: '铁路电子客票 武汉-上海 票价 354 元',
|
||||
document_fields: [
|
||||
{ key: 'route', label: '行程', value: '武汉-上海' },
|
||||
{ key: 'amount', label: '票价', value: '354.00' },
|
||||
{ key: 'date', label: '乘车日期', value: '2026-02-20' }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
assert.match(message, /已识别附件信息:/)
|
||||
assert.match(message, /附件类型:差旅票据/)
|
||||
assert.match(message, /行程:武汉-上海/)
|
||||
assert.match(message, /票价:354.00/)
|
||||
assert.match(message, /草稿单号:EXP-202605-001/)
|
||||
assert.match(message, new RegExp(`\\[确认\\]\\(${ATTACHMENT_ASSOCIATION_CONFIRM_HREF}\\)`))
|
||||
})
|
||||
@@ -156,19 +156,19 @@ test('review drawer save action is disabled while receipt recognition is submitt
|
||||
)
|
||||
})
|
||||
|
||||
test('draft creation waits for composer attachments to be persisted before leaving submit state', () => {
|
||||
test('draft creation starts composer attachment persistence after response rendering', () => {
|
||||
assert.match(
|
||||
submitComposerScript,
|
||||
/try \{\s*await syncComposerFilesToDraft\(resolvedDraftClaimId, files\)\s*\} catch \(error\) \{/s
|
||||
/void syncComposerFilesToDraft\(resolvedDraftClaimId, files\)\s*\.then\(\(\) => \{\s*persistSessionState\(\)\s*\}\)\s*\.catch\(\(error\) => \{/s
|
||||
)
|
||||
assert.doesNotMatch(
|
||||
submitComposerScript,
|
||||
/syncComposerFilesToDraft\(resolvedDraftClaimId, files\)\.catch/
|
||||
/await syncComposerFilesToDraft\(resolvedDraftClaimId, files\)/
|
||||
)
|
||||
assert.ok(
|
||||
submitComposerScript.indexOf('await syncComposerFilesToDraft(resolvedDraftClaimId, files)') <
|
||||
submitComposerScript.indexOf('submitting.value = false'),
|
||||
'attachment persistence should finish before submit state is cleared'
|
||||
submitComposerScript.indexOf('replaceMessage(pendingMessage.id, assistantMessage)') <
|
||||
submitComposerScript.indexOf('void syncComposerFilesToDraft(resolvedDraftClaimId, files)'),
|
||||
'assistant response should render before background attachment persistence starts'
|
||||
)
|
||||
assert.match(attachmentsScript, /function normalizeAttachmentMatchName\(value\)/)
|
||||
assert.match(attachmentsScript, /const normalizedMatchBuckets = new Map\(\)/)
|
||||
|
||||
Reference in New Issue
Block a user