feat: 数字员工财务报告体系与定时提醒及看板快照调度
- 新增数字员工财务报告生成、邮件投递与渲染调度器 - 引入员工画像扫描调度与定时提醒任务 - 完善财务看板快照、排行口径与部门人员占比计算 - 优化数字员工工作看板仪表盘与技能目录 - 增强前端总览页图表、工作台摘要与顶部导航栏交互 - 新增差旅申请规划推动提醒与报销创建会话状态管理 - 补充财务报告、看板调度、数字员工工作记录测试覆盖
This commit is contained in:
@@ -24,6 +24,13 @@ import {
|
||||
resolveMockApplicationTransportWaitMs,
|
||||
buildSystemApplicationEstimate
|
||||
} from '../src/utils/expenseApplicationEstimate.js'
|
||||
import {
|
||||
TRAVEL_PLANNING_ACTION_GENERATE,
|
||||
TRAVEL_PLANNING_ACTION_SKIP,
|
||||
buildTravelPlanningNudgeMessage,
|
||||
buildTravelPlanningRecommendation,
|
||||
buildTravelPlanningSuggestedActions
|
||||
} from '../src/utils/travelApplicationPlanning.js'
|
||||
import { renderMarkdown } from '../src/utils/markdown.js'
|
||||
import {
|
||||
createMessage as createConversationMessage,
|
||||
@@ -142,6 +149,34 @@ test('application intent uses local preview instead of immediate orchestrator ca
|
||||
assert.match(buildLocalApplicationPreviewMessage(preview), /点击对应行即可直接编辑/)
|
||||
})
|
||||
|
||||
test('travel application submit can continue with conversational planning recommendation', () => {
|
||||
const preview = normalizeApplicationPreview({
|
||||
fields: {
|
||||
applicationType: '差旅费用申请',
|
||||
time: '2026-02-20 至 2026-02-23',
|
||||
location: '上海市',
|
||||
reason: '支撑国网仿生产环境建设',
|
||||
days: '4天',
|
||||
transportMode: '火车'
|
||||
}
|
||||
})
|
||||
const draftPayload = { claim_no: 'AP-202606030001-ABCDE123' }
|
||||
const nudge = buildTravelPlanningNudgeMessage(preview, draftPayload)
|
||||
const actions = buildTravelPlanningSuggestedActions(preview, draftPayload)
|
||||
const recommendation = buildTravelPlanningRecommendation(preview, draftPayload)
|
||||
|
||||
assert.match(nudge, /上海市差旅申请已经提交/)
|
||||
assert.match(nudge, /2026-02-20 至 2026-02-23/)
|
||||
assert.deepEqual(actions.map((item) => item.action_type), [
|
||||
TRAVEL_PLANNING_ACTION_GENERATE,
|
||||
TRAVEL_PLANNING_ACTION_SKIP
|
||||
])
|
||||
assert.match(recommendation, /轻量行程规划/)
|
||||
assert.match(recommendation, /优先看上午到中午抵达 上海市 的火车班次/)
|
||||
assert.match(recommendation, /客户现场周边/)
|
||||
assert.match(recommendation, /AP-202606030001-ABCDE123/)
|
||||
})
|
||||
|
||||
test('application preview renders ordered editable rows and submit text uses edited values', () => {
|
||||
const preview = buildLocalApplicationPreview('申请 2026-05-25 至 2026-05-28 去新疆,伊犁出差,服务美团业务部署,火车,预计费用1800元', {
|
||||
name: '李文静',
|
||||
@@ -767,3 +802,63 @@ test('application preview editor refreshes transport estimate after mode change'
|
||||
assert.ok(persistCount >= 2)
|
||||
assert.equal(toastMessages.at(-1), '已更新出行方式和费用测算。')
|
||||
})
|
||||
|
||||
test('application preview editor recalculates days and subsidy after date range change', async () => {
|
||||
const preview = normalizeApplicationPreview({
|
||||
fields: {
|
||||
applicationType: '\u5dee\u65c5\u8d39\u7528\u7533\u8bf7',
|
||||
time: '2026-05-25',
|
||||
location: '\u4e0a\u6d77',
|
||||
reason: '\u670d\u52a1\u9879\u76ee\u90e8\u7f72',
|
||||
days: '1\u5929',
|
||||
transportMode: '\u706b\u8f66',
|
||||
amount: '',
|
||||
grade: 'P5',
|
||||
applicant: '\u674e\u6587\u9759',
|
||||
department: '\u6280\u672f\u90e8',
|
||||
position: '\u8d22\u52a1\u667a\u80fd\u5316\u4ea7\u54c1\u7ecf\u7406',
|
||||
managerName: '\u5411\u4e07\u7ea2'
|
||||
}
|
||||
})
|
||||
const message = {
|
||||
id: 'application-preview-editor-date-message',
|
||||
applicationPreview: preview,
|
||||
text: ''
|
||||
}
|
||||
const requestedPayloads = []
|
||||
const editor = useApplicationPreviewEditor({
|
||||
persistSessionState: () => {},
|
||||
toast: () => {},
|
||||
currentUser: ref({ grade: 'P5' }),
|
||||
calculateTravelReimbursement: async (payload) => {
|
||||
requestedPayloads.push(payload)
|
||||
return {
|
||||
days: payload.days,
|
||||
location: payload.location,
|
||||
matched_city: payload.location,
|
||||
grade: payload.grade,
|
||||
hotel_rate: 450,
|
||||
hotel_amount: 1800,
|
||||
total_allowance_rate: 100,
|
||||
allowance_amount: 400,
|
||||
total_amount: 2200,
|
||||
rule_name: '\u516c\u53f8\u5dee\u65c5\u8d39\u62a5\u9500\u89c4\u5219',
|
||||
rule_version: 'v1.0.0'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
editor.openApplicationPreviewEditor(message, 'time', message.applicationPreview.fields.time)
|
||||
editor.setApplicationPreviewDateMode('range')
|
||||
editor.applicationPreviewEditor.value.rangeStartDate = '2026-02-20'
|
||||
editor.applicationPreviewEditor.value.rangeEndDate = '2026-02-23'
|
||||
const committed = await editor.commitApplicationPreviewDateEditor(message)
|
||||
|
||||
assert.equal(committed, true)
|
||||
assert.deepEqual(requestedPayloads.at(-1), { days: 4, location: '\u4e0a\u6d77', grade: 'P5' })
|
||||
assert.equal(message.applicationPreview.fields.time, '2026-02-20 \u81f3 2026-02-23')
|
||||
assert.equal(message.applicationPreview.fields.days, '4\u5929')
|
||||
assert.equal(message.applicationPreview.fields.lodgingDailyCap, '450\u5143/\u5929')
|
||||
assert.equal(message.applicationPreview.fields.subsidyDailyCap, '100\u5143/\u5929')
|
||||
assert.match(message.applicationPreview.fields.policyEstimate, /\u8865\u8d34 400\u5143/)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user