Files
EmailBill/openspec/specs/budget-stats/spec.md
SunCheng c49f66757e
Some checks failed
Docker Build & Deploy / Build Docker Image (push) Waiting to run
Docker Build & Deploy / Deploy to Production (push) Has been cancelled
Docker Build & Deploy / Cleanup Dangling Images (push) Has been cancelled
Docker Build & Deploy / WeChat Notification (push) Has been cancelled
1
2026-02-18 21:16:45 +08:00

3.0 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Budget statistics API response includes complete data

预算统计 API (GET /api/budget/stats/{category}) SHALL 返回完整的统计数据,包括用于前端图表渲染的 Trend 数组和用于明细弹窗的 Description HTML 内容。

响应结构中的 MonthYear 对象 MUST 包含以下字段:

  • Limit: 预算限额
  • Current: 当前实际金额
  • Remaining: 剩余金额
  • UsagePercentage: 使用百分比
  • Trend: 每日/每月累计金额数组 (List<decimal?>)
  • Description: HTML 格式的详细说明,包含计算公式和数据表格 (string)

Scenario: Monthly stats with trend data

  • WHEN 客户端请求月度预算统计 GET /api/budget/stats/food?date=2026-02
  • THEN 响应的 month 对象包含 trend 数组长度等于该月天数如28/29/30/31
  • AND trend 数组每个元素表示截至该天的累计金额(支出类为递减,收入类为递增)
  • AND trend 数组中未到达的日期对应的元素为 null

Scenario: Monthly stats with description

  • WHEN 客户端请求月度预算统计 GET /api/budget/stats/food?date=2026-02
  • THEN 响应的 month 对象包含 description 字段
  • AND description 是 HTML 格式字符串,包含 <table> 标签展示明细数据
  • AND description 包含计算公式说明(如"剩余 = 限额 - 已用"

Scenario: Yearly stats with trend data

  • WHEN 客户端请求年度预算统计 GET /api/budget/stats/salary?date=2026
  • THEN 响应的 year 对象包含 trend 数组长度为12代表12个月
  • AND trend 数组每个元素表示截至该月的累计金额
  • AND trend 数组中未到达的月份对应的元素为 null

Scenario: Yearly stats with description

  • WHEN 客户端请求年度预算统计 GET /api/budget/stats/salary?date=2026
  • THEN 响应的 year 对象包含 description 字段
  • AND description 是 HTML 格式字符串,包含年度统计明细

Requirement: DTO mapping preserves all Service layer data

Application 层的 BudgetApplication.GetCategoryStatsAsync 方法在将 Service 层的 BudgetStatsDto 映射到 API 响应 DTO 时MUST 保留所有数据字段,不得丢失 TrendDescription

Scenario: Mapping from Service DTO to API DTO

  • WHEN BudgetApplication.GetCategoryStatsAsync 接收到 Service 层返回的 BudgetStatsDto
  • THEN 映射后的 BudgetStatsDetail 对象包含 Trend 字段,其值等于 BudgetStatsDto.Month.TrendBudgetStatsDto.Year.Trend
  • AND 映射后的 BudgetStatsDetail 对象包含 Description 字段,其值等于 BudgetStatsDto.Month.DescriptionBudgetStatsDto.Year.Description

Scenario: API response schema validation

  • WHEN 前端调用 /api/budget/stats/{category} 并解析 JSON 响应
  • THEN TypeScript 类型检查不报错,响应对象符合 BudgetStatsResponse 接口定义
  • AND month.trendmonth.description 字段存在且非 undefined