Files
EmailBill/openspec/changes/saving-detail-calculation/specs/saving-detail-display/spec.md
SunCheng 4cc205fc25 feat(budget): 实现存款明细计算核心逻辑
- 添加 BudgetItemCalculator 辅助类,实现明细项计算规则
  - 收入:实际>0取实际,否则取预算
  - 支出:取MAX(预算, 实际)
  - 硬性支出未发生:按天数折算
  - 归档数据:直接使用实际值

- 实现月度和年度存款核心公式
  - 月度:收入预算 + 本月年度收入 - 支出预算 - 本月年度支出
  - 年度:归档已实收 + 未来收入预算 - 归档已实支 - 未来支出预算

- 定义存款明细数据结构
  - SavingsDetail: 包含收入/支出明细列表和汇总
  - BudgetDetailItem: 预算明细项(含计算用金额、计算说明等)
  - SavingsCalculationSummary: 计算汇总信息

- 新增单元测试
  - BudgetItemCalculatorTest: 11个测试覆盖所有计算规则
  - BudgetSavingsCalculationTest: 6个测试验证核心公式

测试结果:所有测试通过 (366 passed, 0 failed)
2026-02-20 16:26:04 +08:00

5.5 KiB
Raw Blame History

Spec: 存款明细前端展示组件

ADDED Requirements

Requirement: 明细数据结构返回

系统 SHALL 返回结构化的明细数据,包含以下信息:

  • 收入明细列表(IncomeItems
  • 支出明细列表(ExpenseItems
  • 计算汇总(Summary

每个明细项包含:

  • Id: 预算ID
  • Name: 预算名称
  • Type: 预算类型(月度/年度)
  • BudgetLimit: 预算金额
  • ActualAmount: 实际金额
  • EffectiveAmount: 计算用金额
  • CalculationNote: 计算说明("使用预算"/"使用实际"/"按天折算"/"使用实际(超支)"
  • IsOverBudget: 是否超支/未达标

Scenario: 月度明细数据结构

  • WHEN 用户查询2月月度存款明细
  • THEN 系统返回 JSON 结构包含 IncomeItems(工资、奖金等)、ExpenseItems(房租、餐饮等)和 Summary(收入合计、支出合计、计划存款)

Scenario: 年度明细数据结构

  • WHEN 用户查询2026年度存款明细
  • THEN 系统返回包含归档月份明细和未来月份明细的完整数据结构

Requirement: 明细表格展示列

明细表格 SHALL 包含以下列:

  • 名称Name
  • 类型(月度/年度)
  • 预算金额BudgetLimit
  • 实际金额ActualAmount
  • 计算用金额EffectiveAmount
  • 计算说明CalculationNote

Scenario: 明细表格基本展示

  • WHEN 用户打开存款明细页面
  • THEN 表格显示所有收入和支出项的上述6列信息

Scenario: 不限额预算显示

  • WHEN 预算项为不记额NoLimit = true
  • THEN 预算金额列显示"不限额"

Requirement: 超支/未达标高亮显示

系统 SHALL 对超支或未达标的预算项进行高亮显示:

  • 支出超预算:实际 > 预算,高亮显示为红色/警告色
  • 收入未达标:实际 > 0 且 实际 < 预算,高亮显示为橙色/提示色

Scenario: 支出超预算高亮

  • WHEN 餐饮预算2000实际2500超支
  • THEN 该行背景色为浅红色,计算说明显示"使用实际(超支)"

Scenario: 收入未达标高亮

  • WHEN 工资预算10000实际9500未达标
  • THEN 该行背景色为浅橙色,计算说明显示"使用实际"

Scenario: 正常范围不高亮

  • WHEN 房租预算3000实际3000正常
  • THEN 该行无特殊背景色

Requirement: 计算过程说明展示

系统 SHALL 在明细下方展示计算过程的文字说明,包括:

  • 收入合计的计算公式工资10000 + 奖金5000 = 15000
  • 支出合计的计算公式房租3000 + 餐饮2000 = 5000
  • 计划存款的计算公式15000 - 5000 = 10000

Scenario: 月度计算过程说明

  • WHEN 用户查看2月月度存款明细
  • THEN 页面底部显示:
    收入合计 = 工资10000 + 奖金5000 = 15000
    支出合计 = 房租3000 + 餐饮2000 = 5000
    本月发生的年度支出 = 旅游3000
    月度计划存款 = 15000 - 5000 - 3000 = 7000
    

Scenario: 年度计算过程说明

  • WHEN 用户查看2026年度存款明细
  • THEN 页面底部显示:
    归档月已实收 = 1月15000 + 2月14000 = 29000
    未来月收入预算 = (工资10000 + 奖金5000) × 10月 = 150000
    归档月已实支 = 1月4800 + 2月5200 = 10000
    未来月支出预算 = (房租3000 + 餐饮2000) × 10月 = 50000
    年度计划存款 = 29000 + 150000 - 10000 - 50000 = 119000
    

Requirement: 归档月份和未来月份分组展示

在年度明细中,系统 SHALL 将数据分为两组展示:

  • 已归档月份明细:显示各归档月的实际收支
  • 未来月份预算明细:显示当前及未来月份的预算和预测

Scenario: 年度明细分组

  • WHEN 用户在3月查询年度存款明细
  • THEN 页面分为两个表格:
    • 表格1已归档明细1月、2月
    • 表格2未来月份预算3~12月

Scenario: 归档月份合并显示

  • WHEN 同一预算项在多个归档月出现如工资1月10000、2月10000
  • THEN 可选择合并显示为"工资1~2月预算10000/月实际合计20000"

Requirement: 响应式布局支持

明细表格 SHALL 支持移动端响应式布局:

  • 桌面端:完整表格展示
  • 移动端:卡片式折叠展示,点击展开详情

Scenario: 移动端卡片展示

  • WHEN 用户在手机上打开存款明细页面
  • THEN 每个预算项以卡片形式展示,显示名称、计算用金额和计算说明,点击展开显示完整信息

Scenario: 桌面端表格展示

  • WHEN 用户在桌面浏览器打开存款明细页面
  • THEN 以完整表格形式展示所有列

Requirement: 排序和筛选功能

系统 SHALL 支持明细列表的排序和筛选:

  • 按预算金额排序(降序/升序)
  • 按实际金额排序
  • 筛选显示:全部/仅超支/仅未达标

Scenario: 按预算金额降序排序

  • WHEN 用户点击"预算金额"列标题
  • THEN 列表按预算金额从高到低排序

Scenario: 仅显示超支项目

  • WHEN 用户选择"仅超支"筛选
  • THEN 列表仅显示 IsOverBudget = true 且为支出类的项目

Requirement: 导出功能

系统 SHALL 支持将明细数据导出为 CSV 或 Excel 格式。

Scenario: 导出为 CSV

  • WHEN 用户点击"导出 CSV"按钮
  • THEN 浏览器下载包含所有明细数据的 CSV 文件,文件名为"存款明细_YYYYMM.csv"

Scenario: 导出为 Excel

  • WHEN 用户点击"导出 Excel"按钮
  • THEN 浏览器下载包含所有明细数据的 Excel 文件,保留表格格式和高亮样式