# 01 — 后台资产详情统一展示预计最终到期

**What to build:** 运营人员通过统一资产解析查看卡或设备详情时，可以看到全部有效主套餐按稳定队列连续使用后的“预计套餐到期时间”。系统以统一 Query 计算 `exact`、`waiting_activation`、`none`、`invalid_data` 四种状态，并返回预计日期、上海自然日剩余天数和临期派生结果；后台详情按状态展示明确文案，不再把当前套餐自身到期时间当作资产汇总口径。

**Blocked by:** `.scratch/ur55-package-expiry-base/issues/05-activate-and-queue-from-package-snapshots.md` — 05 — 套餐激活与队列接续只消费购买快照

**Status:** done（后端）

- [x] 架构主通道为 Query，Infrastructure 仅负责 GORM 批量读取、历史套餐兜底和索引；完整收口预计最终到期的读取与投影边界，不迁移套餐激活、购买、退款或队列接续写逻辑。
- [x] 建立可供单资产和批量资产入口共同调用的纯计算核心；两种入口对同一组使用记录返回完全一致的状态、预计日期、剩余自然日和临期标记，卡、设备及各端不得各自实现推算规则。
- [x] 仅纳入未软删除、仍处于当前或排队生命周期且不属于加油包的主套餐；排除已过期、已失效和已退款记录，并按 `priority ASC, created_at ASC, id ASC` 稳定计算。
- [x] 当前生效主套餐的真实到期时间作为游标起点，后续套餐从前一段结束后的下一时刻接续；自然月和按天时长统一使用项目套餐生命周期日期语义，并以 `Asia/Shanghai` 解释业务自然日。
- [x] 排队记录优先使用各自购买时计时快照；仅允许 UR#55 上线前形成的历史缺失快照记录显式回退套餐当前值，非法队列、非法日期或无法安全解析的快照返回 `invalid_data`，不得伪造日期或降级为 `none`。
- [x] 结果完整区分 `exact`、`waiting_activation`、`none`、`invalid_data`；非 `exact` 时预计日期和剩余天数明确序列化为 `null`，不能省略字段表达状态。
- [x] 剩余天数按上海时区日期差计算，允许普通详情返回负数；仅 `exact` 且剩余 0～15 个自然日时 `is_expiring=true`。
- [x] 后台统一资产解析接口为卡和设备返回预计日期、剩余天数、状态、状态中文名称及临期标记；查询失败向上返回统一错误，不得静默返回 `none`。
- [ ] 后台卡和设备详情统一显示“预计套餐到期时间”：精确日期、待激活后起算、—、数据异常分别对应四种状态；当前套餐自身到期时间只保留在套餐明细中。（前端任务，不纳入后端交付）
- [x] 为未软删除主套餐的资产、状态和队列读取建立经开发库 `EXPLAIN ANALYZE` 验证的非唯一或部分索引；索引迁移包含中文注释、可逆向下迁移，代表性查询满足项目性能目标。
- [x] 纯计算测试覆盖无套餐、仅当前套餐、多段队列、自然月、按天、月末、跨年、等待实名激活、历史回退、非法快照、重复优先级、退款、失效、软删除和加油包排除，并明确验证接续边界不多算或少算一天。
- [x] 使用真实开发 PostgreSQL、Redis、JWT 和进程内 Fiber App 完成后台卡/设备详情集成验证；新增、退款或失效排队套餐后无需刷新快照，下一次查询立即返回新结果。
- [x] 补充本功能中文总结文档并同步更新 README；不实现 UR#33 临期列表、Dashboard、提醒，不实现 UR#42 导出，也不维护资产级最终到期快照字段。
