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