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

142 lines
5.5 KiB
Markdown
Raw 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.
# 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 文件,保留表格格式和高亮样式