cents/docs/二期-报销与退款.md

229 lines
6.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 二期:报销与退款
## 背景
家庭账本里有一类收入并不代表真实新增收入,而是对过去支出的抵消,例如:
- 公司报销餐费、交通费、差旅费。
- 商家退款、退货退款、平台补贴返还。
- 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 或代付回款是否归入报销,还是后续独立成“代付结算”。
- 统计页默认展示总支出还是净支出。