# UR#33 套餐临期提醒功能总结 ## 交付范围 - 新增 `GET /api/admin/expiring-assets`,平台与代理共用当前后台认证和店铺层级权限。 - 仅返回预计最终到期状态为 `exact`、剩余 0 至 15 个上海自然日的卡和设备。 - 返回卡、设备及合计数量,提供 `pink/purple/red` 高亮等级和 0 至 3 天优先标识。 - 每日上海时间 03:00 扫描 15、7、3 天节点,向资产关联个人客户写入站内通知 Outbox。 - C 端继续复用既有通知列表、未读数和弹窗机制,不新增营销、短信或企业微信提醒。 ## 数据与幂等 - 临期时间复用 `internal/query/packageexpiry` 的最终到期算法,不建立临期状态快照。 - 列表候选使用当前主套餐到期时间预筛,再批量计算当前与排队主套餐的最终到期时间。 - 通知事件 ID 固化资产类型、资产 ID、到期日、节点和个人客户 ID;定时任务、Outbox Relay 和通知消费者重复执行均不会重复通知。 - `000183_add_package_expiry_scan_indexes` 仅增加卡、设备主套餐到期扫描索引,不新增外键。 ## 权限和异常边界 - 平台与超级管理员读取全局范围;代理只读取当前认证上下文的下级店铺范围。 - 代理权限范围为空时查询固定返回空集,不能因空切片退化为全局读取。 - `shop_id` 只缩小既有权限范围;企业账号禁止调用。 - 无关联个人客户的资产正常跳过通知,不影响临期列表事实。 ## 联调与回滚 - 前端按 `expiry_level` 渲染颜色,按 `is_priority` 置顶,不自行重算阈值。 - 回滚应用版本后可删除迁移新增的两个扫描索引;已产生的通知和 Outbox 事实不得清表。 - 本 Change 未运行测试、完整构建、LSP 和迁移;按用户后续明确要求已运行 OpenAPI 生成器,另执行 `gofmt`、只读一致性检查和 `git diff --check`。