85 lines
2.9 KiB
Markdown
85 lines
2.9 KiB
Markdown
# 报销
|
||
|
||
## 产品定义
|
||
|
||
报销是对一笔既有支出的冲减,不属于普通收入。
|
||
|
||
- 报销只能从支出详情发起,不进入快速记账的收入分类。
|
||
- 一笔报销只关联一笔原支出。
|
||
- 一笔支出可以分多次报销,也可以只报销一部分。
|
||
- 累计报销金额不能超过原支出金额。
|
||
- 首版不实现报销单、审批、发票和一笔到账分摊多笔支出。
|
||
|
||
## 录入流程
|
||
|
||
1. 用户进入一笔支出的详情。
|
||
2. 点击“记录报销”。
|
||
3. 输入本次报销金额、到账时间和备注。
|
||
4. 币种、分类和账本自动继承原支出,不能单独修改。
|
||
5. 保存后生成一条独立的报销到账流水。
|
||
|
||
只有原支出的所有者可以记录报销。共享账本成员可以查看报销及净支出,但不能替其他用户操作报销。
|
||
|
||
## 数据模型
|
||
|
||
`entries` 增加自关联字段:
|
||
|
||
```text
|
||
reimbursement_of_entry_id
|
||
```
|
||
|
||
- 普通收入:`type = income`,关联字段为空。
|
||
- 报销到账:`type = income`,关联字段指向原支出。
|
||
- 原支出:`type = expense`。
|
||
|
||
一笔支出的已报销金额等于所有未删除关联流水的金额之和。报销状态由金额计算,不额外存储:
|
||
|
||
- 未报销:已报销金额为零。
|
||
- 部分报销:已报销金额小于原支出。
|
||
- 全额报销:已报销金额等于原支出。
|
||
|
||
存在报销记录时不能删除原支出。原支出仍可修改备注、时间或增加金额,但不能改分类、币种和账本,也不能把金额降到累计报销金额以下。
|
||
|
||
## 流水展示
|
||
|
||
发生报销的原支出保留原始金额,并显示冲减后的净支出:
|
||
|
||
```text
|
||
原金额 ¥3,200(划线)
|
||
净支出 ¥3,000
|
||
```
|
||
|
||
报销到账按实际到账日期显示为独立流水,并标记为“报销”。
|
||
|
||
流水页顶部有报销时使用竖式展示支出:
|
||
|
||
```text
|
||
支出 ¥3,200
|
||
- 200
|
||
─────
|
||
¥3,000
|
||
```
|
||
|
||
没有报销时只显示普通支出金额,不保留竖式空间。
|
||
|
||
## 统计口径
|
||
|
||
- 收入:只统计普通收入,不包含报销到账。
|
||
- 原支出:支出的原始金额。
|
||
- 报销:关联到这些原支出的累计报销金额。
|
||
- 净支出:原支出减去报销。
|
||
- 结余:普通收入减去净支出。
|
||
|
||
报销按原支出的日期、分类和账本冲减。因此即使报销在下个月到账,也会更新原支出所在期间的净支出统计。
|
||
|
||
外币报销首版继承原支出币种。本币净支出按照原支出的本币金额比例冲减,保证全额报销后的本币净支出为零。
|
||
|
||
## 离线与同步
|
||
|
||
报销流水与普通账目使用同一套 IndexedDB 和同步操作:
|
||
|
||
- 离线时可以创建、修改和删除报销到账。
|
||
- 恢复联网后按照操作创建时间同步。
|
||
- 服务端再次验证原支出所有者、币种、分类和累计报销金额。
|
||
- 服务端通过行锁避免多个设备同时报销导致累计金额超限。
|