4.9 KiB
4.9 KiB
小团队报销填报与校验完善:技术设计
1. Design boundary
本任务在现有报销详情和预检链路内增量实现,不新增数据库表,不建设通用规则引擎,不改变审批、付款和资产状态机。
核心数据流:
明细/发票/附件数据库事实
-> reimbursement precheck 聚合
-> GET detail / POST precheck API
-> PC 与手机详情呈现
-> submit 事务重新汇总
-> 现有审批规则、预算与工作流
服务端负责金额、日期和证据状态的权威判断;前端只负责输入约束、可理解呈现和刷新。
2. Contracts
2.1 Runtime configuration
- 在
server/src/config.js增加reimbursementMaxAgeDays。 - 环境变量:
REIMBURSEMENT_MAX_AGE_DAYS。 - 默认:
365;允许:180 | 365;非法值在启动时失败,不静默回退。 - 配置只影响警告阈值,不改变数据、审批或付款状态。
2.2 Reimbursement precheck extension
在现有预检响应中追加向后兼容字段:
type ReimbursementEvidenceSummary = {
invoiceCount: number;
attachmentCount: number;
items: Array<{
itemId: string;
linkedInvoiceCount: number;
invoiceState: "linked" | "unlinked";
}>;
};
type ReimbursementTimelinessCheck = {
itemId: string;
expenseDate: string;
ageDays: number;
maxAgeDays: 180 | 365;
overdue: boolean;
crossCalendarYear: boolean;
};
type ReimbursementAssetHint = {
required: boolean;
itemCount: number;
};
- 新字段缺失时旧客户端继续使用既有预检字段。
- 超期、跨年度、明细未关联发票和资产候选通过现有
warnings/nextActions合并,并保留结构化摘要供 UI 定位。 - 明细未关联发票是警告而非新阻断,因为当前存在整单发票、OCR 未完成和合法无票差旅补助等兼容场景。
2.3 Amount validation
- 手工 item POST/PATCH 将
amount=0视为无效。 - 模板/差旅创建仍可内部写入零金额草稿,不经过手工 item POST 门禁。
- submit 在同一事务和行锁内读取所有明细:无明细或任一金额
<= 0时返回定位明确的校验错误。 - 校验通过后调用现有重算逻辑,将返回值写回本次提交上下文;后续预算和审批规则只使用该值。
- 不依赖前端合计,不接受客户端提交整单总额。
2.4 Header editing
- 扩展前端 API 为通用
updateReimbursement,旅行摘要函数可继续包装或迁移到该函数,避免重复 HTTP 合同。 - PC 与手机复用小型编辑块:报销日期、报销事由、保存、取消。
- 保存成功后刷新 detail、list 和 precheck 查询;使用现有未保存编辑保护模式,避免刷新丢失。
2.5 Totals and evidence UI
- PC 表格 footer 显示条数与
detail.totalAmount;手机列表尾显示相同事实。 - 概况标签统一为“报销总额”。打印页保留现有合计行。
- 证据提示在明细与材料区使用同一预检摘要,不在前端重新推导业务规则。
- 当 OCR off 或发票金额为空时,不显示误导性的“发票金额差额”;本任务只展示数量和关联状态。
2.6 Asset reminder
- 服务端基于明细费用类型
category=assets生成结构化提示。 - UI 只显示候选数量、人工核对说明和授权后的资产模块入口。
- 不调用资产创建 API,不保存报销侧资产状态。
3. Compatibility and migration
- 无 Prisma schema 或数据库迁移。
- API 仅新增可选响应字段并收紧非法普通报销提交,现有合法报销兼容。
- 历史草稿中的零金额明细可以继续查看和修改,但必须修正后才能提交。
- 已提交、已通过和已付款记录保持只读,不回填时效或资产状态。
- 现有附件仍为整单材料,现有发票绑定、OCR、查重和连续预览不变。
4. Risks and mitigations
- 日期偏移:使用既有 date-only 工具和
APP_TIMEZONE,测试阈值当天、闰年和跨年边界。 - 预检字段重复计算:在服务端一次加载报销证据上下文,避免 PC/手机各自实现规则。
- 模板回归:只在手工明细接口和提交阶段收紧正金额,保留模板草稿零金额。
- 既有未绑定发票:只警告不阻断,保持现有整单至少一张发票门禁。
- 资产权限泄露:资产入口按现有权限决定,预检不返回资产卡或敏感字段。
- 提交总额竞争:继续使用报销行锁,并在同一事务内重算后再做预算和审批规则选择。
5. Rollout and rollback
- 部署前明确
REIMBURSEMENT_MAX_AGE_DAYS;缺省为 365。 - 先部署服务端兼容字段和校验,再部署前端展示;旧前端可继续工作。
- 回滚前端不会破坏服务端数据;回滚服务端仅移除新提示和正金额收紧,无迁移回滚。
- 公网验收覆盖普通办公用品、宽带/技术服务、IT 硬件三类合成记录,不使用真实票据内容。