229 lines
6.2 KiB
Markdown
229 lines
6.2 KiB
Markdown
# 二期:报销与退款
|
||
|
||
## 背景
|
||
|
||
家庭账本里有一类收入并不代表真实新增收入,而是对过去支出的抵消,例如:
|
||
|
||
- 公司报销餐费、交通费、差旅费。
|
||
- 商家退款、退货退款、平台补贴返还。
|
||
- AA 或代付后,其他成员转回款项。
|
||
|
||
首版只记录普通收入和支出。二期需要支持“收入关联原支出”,让流水、统计和净支出更接近真实消费。
|
||
|
||
## 目标
|
||
|
||
- 报销和退款在录入时仍作为收入类型保存。
|
||
- 输入金额后,系统可以推荐匹配的历史支出。
|
||
- 用户可以把一笔报销或退款关联到一笔或多笔支出。
|
||
- 流水中能看出某笔收入是报销或退款,以及它关联了哪些支出。
|
||
- 月度统计能区分总支出、报销/退款抵扣、净支出。
|
||
|
||
## 非目标
|
||
|
||
- 不做企业报销流程审批。
|
||
- 不做发票、附件、小票 OCR。
|
||
- 不做复杂应收应付和债务结算。
|
||
- 不自动修改原支出金额。
|
||
- 不要求系统自动判断 100% 正确,必须允许用户手动选择或取消关联。
|
||
|
||
## 概念定义
|
||
|
||
### 普通收入
|
||
|
||
真实增加可支配金额的收入,例如工资、奖金、利息。
|
||
|
||
### 报销
|
||
|
||
对已发生支出的补偿。通常来自公司、组织或共同生活成员。
|
||
|
||
示例:用户先记一笔 `交通 120 元`,之后收到公司报销 `120 元`。
|
||
|
||
### 退款
|
||
|
||
商家、平台或交易对方退回的金额。通常对应购物、服务、押金等历史支出。
|
||
|
||
示例:用户先记一笔 `购物 299 元`,之后退货收到 `299 元`。
|
||
|
||
### 关联支出
|
||
|
||
被报销或退款收入抵消的原始支出记录。
|
||
|
||
## 录入流程
|
||
|
||
### 快速记账入口
|
||
|
||
收入类型下增加收入子类型:
|
||
|
||
- 普通收入
|
||
- 报销
|
||
- 退款
|
||
|
||
用户选择 `报销` 或 `退款` 后:
|
||
|
||
1. 输入收入金额。
|
||
2. 系统根据金额、时间、分类、备注、付款人推荐历史支出。
|
||
3. 用户选择一笔或多笔支出。
|
||
4. 用户确认保存。
|
||
5. 新收入记录保存,并建立与原支出的关联。
|
||
|
||
### 推荐匹配
|
||
|
||
默认推荐范围:
|
||
|
||
- 同一账本内。
|
||
- 未删除支出。
|
||
- 发生时间早于或等于当前报销/退款时间。
|
||
- 最近 180 天内优先。
|
||
- 金额相同或接近优先。
|
||
|
||
推荐排序建议:
|
||
|
||
1. 金额完全相同。
|
||
2. 金额差额较小。
|
||
3. 日期更近。
|
||
4. 分类更相关。
|
||
5. 备注文本有相似词。
|
||
6. 同一付款人。
|
||
|
||
### 手动关联
|
||
|
||
用户必须能:
|
||
|
||
- 搜索历史支出。
|
||
- 改选推荐结果。
|
||
- 选择多笔支出。
|
||
- 不关联任何支出,先保存为未关联报销/退款。
|
||
- 保存后再补充或修改关联。
|
||
|
||
## 金额规则
|
||
|
||
一笔报销或退款可以关联:
|
||
|
||
- 一笔支出。
|
||
- 多笔支出。
|
||
- 一笔支出的一部分金额。
|
||
|
||
关联金额需要单独记录,不能只靠收入金额和支出金额推导。
|
||
|
||
示例:
|
||
|
||
- 支出 `餐饮 100 元`。
|
||
- 报销 `80 元`。
|
||
- 关联金额为 `80 元`,原支出仍显示 `100 元`。
|
||
|
||
多笔关联示例:
|
||
|
||
- 支出 A `交通 60 元`。
|
||
- 支出 B `餐饮 40 元`。
|
||
- 报销 `100 元`。
|
||
- 报销记录同时关联 A 和 B。
|
||
|
||
## 统计规则
|
||
|
||
二期统计至少区分:
|
||
|
||
- 总收入:包含普通收入、报销、退款。
|
||
- 普通收入:只包含真实收入。
|
||
- 总支出:原始支出合计,不被报销/退款改写。
|
||
- 报销/退款抵扣:已关联到支出的报销和退款金额。
|
||
- 净支出:总支出减去报销/退款抵扣。
|
||
|
||
首选展示方式:
|
||
|
||
- 流水仍显示原始收入和支出,保持账目真实发生。
|
||
- 汇总页突出 `净支出`。
|
||
- 报销和退款作为收入展示,但使用不同标签,避免被误认为工资等普通收入。
|
||
|
||
## 流水展示
|
||
|
||
报销/退款收入行应显示:
|
||
|
||
- 金额为正数。
|
||
- 类型标签:报销或退款。
|
||
- 关联状态:已关联、部分关联、未关联。
|
||
- 关联的原支出摘要。
|
||
|
||
原支出行应显示:
|
||
|
||
- 原始支出金额不变。
|
||
- 若已有报销/退款抵扣,显示抵扣金额。
|
||
- 可进入详情查看关联收入。
|
||
|
||
状态建议:
|
||
|
||
- `未关联`:没有任何关联支出。
|
||
- `部分抵扣`:关联金额小于原支出金额。
|
||
- `已抵扣`:关联金额大于或等于原支出金额。
|
||
|
||
## 数据模型建议
|
||
|
||
### entry 扩展
|
||
|
||
在 `entry` 上增加收入子类型字段:
|
||
|
||
- `income_kind`:`regular`、`reimbursement`、`refund`。
|
||
|
||
约束:
|
||
|
||
- `type = income` 时可填写 `income_kind`。
|
||
- `type = expense` 时 `income_kind` 为空。
|
||
- 兼容旧数据时,收入默认视为 `regular`。
|
||
|
||
### entry_link
|
||
|
||
新增关联表:
|
||
|
||
- `id`:客户端生成 UUID。
|
||
- `ledger_id`
|
||
- `source_entry_id`:报销/退款收入。
|
||
- `target_entry_id`:被关联支出。
|
||
- `link_type`:`reimbursement` 或 `refund`。
|
||
- `amount`:本次关联金额,整数分。
|
||
- `created_by`
|
||
- `created_at`
|
||
- `updated_at`
|
||
- `deleted_at`
|
||
- `version`
|
||
|
||
约束:
|
||
|
||
- `source_entry_id` 必须指向收入。
|
||
- `target_entry_id` 必须指向支出。
|
||
- 两条账目必须属于同一账本。
|
||
- 关联金额必须大于 0。
|
||
- 同一收入关联多笔支出的金额合计不应超过收入金额,除非后续明确支持超额报销。
|
||
|
||
## 同步与离线
|
||
|
||
报销/退款关联也必须离线可用:
|
||
|
||
- 新增、修改、删除关联写入本地 IndexedDB。
|
||
- 每次关联变更生成同步操作。
|
||
- 服务端按 `operation_id` 幂等处理。
|
||
- 删除账目时不硬删除关联,使用软删除。
|
||
|
||
冲突策略二期先保持简单:
|
||
|
||
- 同一条关联被多设备修改时,最后写入胜出。
|
||
- 如果原支出或收入已删除,关联保留软删除或标记失效。
|
||
- 汇总统计只计算未删除且有效的关联。
|
||
|
||
## 原型需求
|
||
|
||
需要补充这些原型:
|
||
|
||
- 快速记账收入模式下的 `普通收入 / 报销 / 退款` 切换。
|
||
- 输入金额后的候选支出匹配列表。
|
||
- 手动搜索并选择历史支出。
|
||
- 一笔收入关联多笔支出的选择态。
|
||
- 流水中报销/退款和原支出的关联展示。
|
||
- 账目详情中的关联管理。
|
||
|
||
## 待决策问题
|
||
|
||
- 报销和退款是否共用同一套分类,还是独立于普通收入分类。
|
||
- 未关联的报销/退款是否计入净支出抵扣。
|
||
- 关联金额是否允许超过原支出剩余未抵扣金额。
|
||
- AA 或代付回款是否归入报销,还是后续独立成“代付结算”。
|
||
- 统计页默认展示总支出还是净支出。
|