Files
SunCheng 9dce12c61b
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 18s
Docker Build & Deploy / Deploy to Production (push) Successful in 6s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 1s
Docker Build & Deploy / WeChat Notification (push) Successful in 1s
归档
2026-02-21 21:58:55 +08:00

6.8 KiB
Raw Blame History

Spec: 存款明细计算核心算法

ADDED Requirements

Requirement: 月度计划存款计算公式

系统 SHALL 使用以下公式计算月度计划存款:

月度计划存款 = 收入预算 + 发生在本月的年度收入 - 支出预算 - 发生在本月的年度支出

其中:

  • 收入预算:所有月度收入预算项的预算金额之和
  • 发生在本月的年度收入年度收入预算项在本月实际发生的金额actual > 0
  • 支出预算:所有月度支出预算项的预算金额之和
  • 发生在本月的年度支出年度支出预算项在本月实际发生的金额actual > 0

Scenario: 纯月度预算计算

  • WHEN 用户查询 2026年2月的月度存款且只有月度预算工资10000、奖金5000、房租3000、餐饮2000
  • THEN 系统返回计划存款 = 10000 + 5000 - 3000 - 2000 = 10000

Scenario: 月度预算 + 本月发生的年度预算

  • WHEN 用户查询 2026年2月的月度存款月度预算工资10000、房租3000且年度旅游支出在本月实际发生3000元
  • THEN 系统返回计划存款 = 10000 - 3000 - 3000 = 4000

Scenario: 年度预算未在本月发生

  • WHEN 用户查询 2026年2月的月度存款月度预算工资10000、房租3000年度年终奖预算50000但本月实际为0
  • THEN 系统返回计划存款 = 10000 - 3000 = 7000年终奖不计入

Requirement: 年度计划存款计算公式

系统 SHALL 使用以下公式计算年度计划存款:

年度计划存款 = 归档月已实收 + 未来月(包含本月)收入预算 - 归档月已实支 - 未来月(包含本月)支出预算

其中:

  • 归档月已实收已归档月份1月~当前月-1的实际收入金额之和BudgetArchive 读取
  • 未来月收入预算:当前月及未来月份的月度收入预算 × 剩余月数
  • 归档月已实支:已归档月份的实际支出金额之和,从 BudgetArchive 读取
  • 未来月支出预算:当前月及未来月份的月度支出预算 × 剩余月数

Scenario: 年初无归档数据

  • WHEN 用户在 2026年1月查询年度存款月度预算工资10000/月、房租3000/月),无归档数据
  • THEN 系统返回计划存款 = (10000 - 3000) × 12 = 84000

Scenario: 年中有归档数据

  • WHEN 用户在 2026年3月查询年度存款1月归档已实收15000、已实支48002月归档已实收14000、已实支52003~12月月度预算工资10000、房租3000
  • THEN 系统返回计划存款 = (15000 + 14000) + (10000 × 10) - (4800 + 5200) - (3000 × 10) = 129000

Scenario: 归档数据包含年度预算

  • WHEN 归档数据中包含年度预算的实际发生金额如1月旅游支出3000
  • THEN 系统将其计入"归档月已实支",不重复计算

Requirement: 明细项计算用金额 - 收入规则

对于收入类预算项,系统 SHALL 根据以下规则计算"计算用金额"

  • 如果实际金额 > 0计算用金额 = 实际金额
  • 如果实际金额 = 0计算用金额 = 预算金额

Scenario: 收入已发生

  • WHEN 工资预算10000实际发生9500
  • THEN 计算用金额 = 9500标注为"使用实际"

Scenario: 收入未发生

  • WHEN 奖金预算5000实际发生0
  • THEN 计算用金额 = 5000标注为"使用预算"

Requirement: 明细项计算用金额 - 支出规则(普通)

对于非硬性支出类预算项,系统 SHALL 计算用金额 = MAX(预算金额, 实际金额)

Scenario: 支出未超预算

  • WHEN 餐饮预算2000实际发生1800
  • THEN 计算用金额 = 2000标注为"使用预算"

Scenario: 支出超预算

  • WHEN 餐饮预算2000实际发生2500
  • THEN 计算用金额 = 2500标注为"使用实际(超支)",高亮显示

Requirement: 明细项计算用金额 - 支出规则(硬性)

对于硬性支出(IsMandatoryExpense = true)且实际金额 = 0 的预算项,系统 SHALL 按天数折算计算用金额,不进行 MAX 比较。

月度折算公式:计算用金额 = 预算金额 / 当月天数 × 当前日期

年度折算公式:计算用金额 = 预算金额 / 当年天数 × 当前天数

Scenario: 硬性支出未发生(月度)

  • WHEN 房租预算3000硬性实际为0当前日期为2月15日2月共28天
  • THEN 计算用金额 = 3000 / 28 × 15 ≈ 1607.14,标注为"按天折算"

Scenario: 硬性支出已发生

  • WHEN 房租预算3000硬性实际发生3000
  • THEN 计算用金额 = MAX(3000, 3000) = 3000标注为"使用实际"

Scenario: 硬性支出超预算

  • WHEN 水电预算500硬性实际发生600
  • THEN 计算用金额 = MAX(500, 600) = 600标注为"使用实际(超支)"

Scenario: 硬性支出按天折算可能超预算

  • WHEN 房租预算3000硬性实际为0当前日期为2月29日2月共28天
  • THEN 计算用金额 = 3000 / 28 × 29 ≈ 3107.14(大于预算),标注为"按天折算"

Requirement: 归档月份数据处理

对于已归档月份的预算数据,系统 SHALL 直接使用归档中的实际金额(BudgetArchive.Content[].Actual),不重新计算。

Scenario: 读取归档数据

  • WHEN 用户在3月查询年度存款1月归档中工资实际10000、房租实际3000
  • THEN 系统使用归档实际值10000和3000不根据当前预算重新计算

Scenario: 归档后预算调整

  • WHEN 1月归档时工资预算10000实际100002月将工资预算调整为12000用户在3月查询年度存款
  • THEN 1月仍使用归档的实际100002月及以后使用新预算12000

Requirement: 闰年和月末边界处理

系统 SHALL 正确处理闰年和月末边界情况:

  • 闰年判断:使用 DateTime.IsLeapYear(year) 判断闰年366天平年365天
  • 月末天数:使用 DateTime.DaysInMonth(year, month) 获取

Scenario: 闰年2月硬性支出折算

  • WHEN 2024年2月29日闰年房租预算3000硬性实际为0
  • THEN 计算用金额 = 3000 / 29 × 29 = 3000

Scenario: 平年2月硬性支出折算

  • WHEN 2026年2月28日平年房租预算3000硬性实际为0
  • THEN 计算用金额 = 3000 / 28 × 28 = 3000

Scenario: 年度硬性支出闰年折算

  • WHEN 2024年闰年第100天年度保险预算12000硬性实际为0
  • THEN 计算用金额 = 12000 / 366 × 100 ≈ 3278.69

Requirement: 不记额预算处理

对于不记额预算(NoLimit = true)的预算项,系统 SHALL 排除在计划存款计算之外,但在明细中显示为"不限额"。

Scenario: 不记额收入

  • WHEN 存在不记额收入预算项如意外收入实际发生1000
  • THEN 该项不计入"收入预算",明细中显示预算为"不限额"实际为1000