轻松聘AI开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

6.0 KiB

salary-history

Purpose

保存求职者每次成功薪资估算的可追溯快照,并提供仅限本人访问的分页查询、详情和物理删除能力。

Requirements

Requirement: 成功计算自动保存历史

The system SHALL 在计算并保存接口成功完成时自动创建一条历史记录,并在响应中返回历史 ID 和创建时间。系统 MUST NOT 要求调用方再调用第二个保存接口。

Scenario: 首次成功计算

  • WHEN STUDENT 提交合法且政策版本一致的计算请求
  • THEN 系统在同一事务中完成计算并保存历史,返回结果及新历史 ID

Requirement: 历史保存完整且可重建的快照

The system SHALL 在历史记录中保存原始输入、城市编码与名称、dataLevel、城市默认参数、用户覆盖项、最终生效参数、完整结果、monthIndex、城市政策版本、政策生效日期、全国税率版本和创建时间。三类 JSON 快照 MUST 能独立重建当时结果。

Scenario: 城市参数后来变化

  • WHEN 历史创建后城市默认参数或政策版本发生变化
  • THEN 历史详情仍返回创建时的输入、政策、覆盖项和完整结果,不重新读取当前城市配置,包括当时的 CITY 或 PROVINCE_FALLBACK 精度标识

Requirement: 计算保存使用幂等键防重

The system SHALL 支持可选 idempotencyKey,最长 64 字符,空白值按未提供处理。同一用户相同幂等键且规范化业务字段相同 MUST 返回原历史;相同幂等键但规范化字段不同 MUST 返回 409/9804。

Scenario: 相同请求网络重试

  • WHEN 客户端使用相同用户、相同幂等键和相同规范化业务字段重试计算
  • THEN 系统返回同一条历史和相同计算结果,不新增数据库行

Scenario: 相同幂等键不同请求体

  • WHEN 客户端复用幂等键但修改税前月薪或政策版本
  • THEN 系统返回 409/9804,且不创建第二条历史

Requirement: 同一幂等键并发只能生成一条历史

The system SHALL 使用事务和数据库唯一约束处理并发。相同用户相同幂等键并发请求 MUST 最多生成一条历史;同键不同请求并发时,一方成功,另一方 MUST 返回 409/9804。

Scenario: 并发相同请求

  • WHEN 两个请求同时提交相同用户、幂等键和规范化业务字段
  • THEN 数据库中最多存在一条历史,两个成功响应指向同一历史 ID

Requirement: 历史列表和详情仅返回本人数据

The system SHALL 提供按创建时间倒序、ID 倒序的分页列表和详情接口。列表 MUST 只返回摘要;详情 MUST 返回完整快照。查询必须同时按当前登录用户和历史 ID 过滤。

Scenario: 查询本人历史

  • WHEN STUDENT 调用历史列表或详情接口
  • THEN 系统只返回该 STUDENT 的历史,按最新创建时间排序

Scenario: 猜测他人历史 ID

  • WHEN STUDENT 请求不属于自己的历史 ID
  • THEN 系统返回 404/9803,不泄露该记录是否存在

Requirement: 历史不可编辑且可以物理删除单条

The system SHALL 不提供历史更新接口。历史创建后不可修改;用户删除本人历史时 MUST 物理删除该行及其幂等键,后续可以为该幂等键创建新历史。

Scenario: 删除本人历史

  • WHEN STUDENT 删除自己的历史记录
  • THEN 系统物理删除该记录并返回成功响应,后续详情查询返回 404/9803

Scenario: 重复删除历史

  • WHEN STUDENT 再次删除已经删除的历史
  • THEN 系统返回 404/9803,不返回成功状态

Requirement: 历史列表采用统一分页且不提供额外筛选

The system SHALL 使用 page=0、size=20 的分页默认值,size 最大为 100;首期 MUST NOT 增加城市、日期范围或薪资范围筛选。

Scenario: 超出分页上限

  • WHEN 客户端请求 size=101
  • THEN 系统返回 400/9802,不返回历史列表

Requirement: 历史数据按用户长期保留

The system SHALL 允许历史记录长期保留直至用户主动删除,不设置自动过期、定时清理或业务数量配额。城市停用、政策更新或历史数量增长 MUST NOT 影响历史详情读取。

Scenario: 城市停用后查看旧历史

  • WHEN 历史所属城市后来被停用
  • THEN STUDENT 仍可查看该历史详情

Requirement: 历史不进入审计日志或个人数据导出

The system SHALL 不因薪资计算或单条历史删除写入业务审计日志,也不得把税前工资、基数、税额、到手工资或 JSON 快照写入应用日志。薪资历史 MUST NOT 纳入现有个人数据导出 ZIP。

Scenario: 计算成功后的日志检查

  • WHEN 系统完成一次薪资计算和历史保存
  • THEN 日志仅包含请求 ID、用户 ID、历史 ID、城市编码、状态和耗时,不包含金额或参数快照

Requirement: 账号注销清理薪资历史

The system SHALL 在账号注销完成事务中物理删除该用户全部薪资历史。注销处于 PENDING 时 MUST 禁止计算和删除写入,COMPLETED 时所有薪资接口 MUST 返回 409/9303。

Scenario: 注销完成后清理历史

  • WHEN 用户账号注销完成
  • THEN 数据库中不存在该用户的 salary_calculation_history 行

Scenario: 注销冷静期尝试计算

  • WHEN 用户处于 PENDING 状态调用计算接口
  • THEN 现有注销守卫返回 409/9302,且不创建历史

Requirement: 数据库迁移保证城市政策和历史完整性

The system SHALL 通过 V40 创建 salary_city_policy 与 salary_calculation_history,通过 V41 写入目标城市种子。城市编码 MUST 唯一,历史幂等键 MUST 按用户唯一,历史快照 MUST 保留且不依赖后续城市更新。

Scenario: 迁移初始化

  • WHEN 在 MySQL 或 H2 MySQL 模式执行 V40 和 V41
  • THEN 城市政策表、历史表、主外键、唯一键和索引创建成功,目标城市种子导入成功