feat: 完善审批退回流程与报销申请关联

后端优化报销单访问策略和常量定义,增强退回原因和审批状态
流转,前端完善退回对话框和审批交互组件,新增报销申请关联
模型,优化文档中心行数据和审批收件箱工具函数,增强引导
流程和会话模型,补充单元测试覆盖。
This commit is contained in:
caoxiaozhu
2026-05-27 14:35:17 +08:00
parent 7d32eae74e
commit cbb98f4469
30 changed files with 1794 additions and 250 deletions

View File

@@ -3,12 +3,21 @@ import test from 'node:test'
import { mapExpenseClaimToRequest } from '../src/composables/useRequests.js'
const CREATE_APPLICATION = '\u521b\u5efa\u7533\u8bf7'
const DIRECT_MANAGER_APPROVAL = '\u76f4\u5c5e\u9886\u5bfc\u5ba1\u6279'
const APPROVAL_COMPLETED = '\u5ba1\u6279\u5b8c\u6210'
const RETURNED = '\u9000\u56de'
const WAIT_SUBMIT = '\u5f85\u63d0\u4ea4'
const WAIT_LEADER_LI_APPROVAL = '\u7b49\u5f85 Leader Li \u6279\u590d'
const LEADER_RETURNED_STATUS = '\u9886\u5bfc\u5df2\u9000\u56de\uff0c\u5f85\u91cd\u65b0\u63d0\u4ea4'
test('application claims are mapped as application documents', () => {
const request = mapExpenseClaimToRequest({
id: 'claim-application-1',
claim_no: 'AP-20260525103045-ABCDEFGH',
employee_name: '张三',
department_name: '交付部',
manager_name: 'Leader Li',
expense_type: 'travel_application',
reason: '支撑国网服务器上线部署',
location: '上海',
@@ -32,11 +41,59 @@ test('application claims are mapped as application documents', () => {
assert.equal(request.expenseTableSummary, '预计金额已随申请提交')
assert.deepEqual(
request.progressSteps.map((step) => step.label),
['创建申请', '直属领导审批', '审批完成']
[CREATE_APPLICATION, WAIT_LEADER_LI_APPROVAL, APPROVAL_COMPLETED]
)
assert.equal(request.progressSteps.some((step) => step.label === 'AI预审'), false)
assert.equal(request.progressSteps.some((step) => step.label === '财务审批'), false)
assert.equal(request.progressSteps.find((step) => step.label === '直属领导审批')?.current, true)
assert.equal(request.progressSteps.some((step) => step.label === DIRECT_MANAGER_APPROVAL), false)
assert.equal(request.progressSteps.find((step) => step.label === WAIT_LEADER_LI_APPROVAL)?.rawLabel, DIRECT_MANAGER_APPROVAL)
assert.equal(request.progressSteps.find((step) => step.label === WAIT_LEADER_LI_APPROVAL)?.current, true)
})
test('returned application claims include leader return node and supplement status', () => {
const request = mapExpenseClaimToRequest({
id: 'claim-application-returned',
claim_no: 'APP-20260525-RETURNED',
employee_name: 'Applicant Zhang',
department_name: 'Delivery',
manager_name: 'Leader Li',
expense_type: 'travel_application',
reason: 'Project onsite support',
location: 'Shanghai',
amount: 12000,
invoice_count: 0,
occurred_at: '2026-05-25T00:00:00.000Z',
submitted_at: null,
created_at: '2026-05-25T01:30:00.000Z',
updated_at: '2026-05-25T04:00:00.000Z',
status: 'returned',
approval_stage: WAIT_SUBMIT,
risk_flags_json: [
{
source: 'manual_return',
event_type: 'expense_application_return',
operator: 'Leader Li',
opinion: 'Need clearer budget explanation.',
return_stage_key: 'direct_manager',
next_status: 'returned',
next_approval_stage: WAIT_SUBMIT,
return_count: 2,
created_at: '2026-05-25T04:00:00.000Z'
}
],
items: []
})
assert.deepEqual(
request.progressSteps.map((step) => step.label),
[CREATE_APPLICATION, WAIT_LEADER_LI_APPROVAL, RETURNED, WAIT_SUBMIT]
)
assert.equal(request.progressSteps.find((step) => step.label === RETURNED)?.time, 'Leader Li\u9000\u56de')
assert.match(request.progressSteps.find((step) => step.label === RETURNED)?.detail, /2026-05-25/)
assert.equal(request.progressSteps.find((step) => step.label === WAIT_SUBMIT)?.current, true)
assert.equal(request.secondaryStatusValue, LEADER_RETURNED_STATUS)
assert.equal(request.secondaryStatusTone, 'warning')
assert.equal(request.progressSteps.some((step) => step.label === APPROVAL_COMPLETED), false)
})
test('approved application claims complete after direct manager approval only', () => {