All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 10m49s
52 lines
3.1 KiB
Markdown
52 lines
3.1 KiB
Markdown
## Context
|
||
|
||
现有 step2 依据旧套餐的类型、状态、生效时间和到期时间分类生命周期;分类后只要同一资产有多条 `active` 就阻断。奇成数据中的少量续费记录缺少生效时间且仍标为正常,无法从通用字段推断先后关系。
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
- 用映射配置表达经运营确认的逐卡裁决。
|
||
- 在生成 SQL 前验证裁决完整性,确保不静默丢失或重复迁移套餐。
|
||
- 将覆盖后的状态写入现有审核产物,保持可追溯性。
|
||
|
||
**Non-Goals:**
|
||
- 不修改奇成老库记录。
|
||
- 不依据到期时间、创建时间或套餐时长引入全局自动裁决规则。
|
||
- 不改变未覆盖资产的现有分类和阻断逻辑。
|
||
|
||
## Decisions
|
||
|
||
### 使用 ICCID 与生命周期 ID 的显式覆盖
|
||
在 `mapping.yaml` 增加 `package_lifecycle_overrides`。每项包含完整 ICCID、一个 `active_life_id`、可选的 `pending_life_ids` 与 `skipped_life_ids`。
|
||
|
||
生命周期 ID 是老库主键,避免到期时间存在 UTC/本地时区展示差异或同日期重复时的歧义。完整 ICCID 与 step2 的资产键一致。
|
||
|
||
未采用“最早到期记录为当前”的规则:已确认的第三张异常卡表明未来记录并不必然均应作为待生效迁移。
|
||
|
||
### 覆盖在冲突检测前重分类
|
||
先获取老库原始生命周期及既有通用分类,再按 ICCID 应用覆盖,最后执行现有映射、唯一 active 校验与 SQL 生成。覆盖只改变配置明确列出的记录状态;同卡其他通用分类为 `active` 或 `pending` 的正式套餐必须也被覆盖明确裁决,否则报配置错误并阻断该资产。
|
||
|
||
### 配置与运行时双重校验
|
||
加载时校验字段格式、同一覆盖内 ID 不重复且状态集合不重叠。读取老库后校验每个被引用 ID 都属于该 ICCID 的 `tbl_card_life` 记录、active 恰好一个、覆盖未遗漏其他原本可迁移记录。错误沿用 step2 的错误 CSV,且不生成该资产套餐 SQL。
|
||
|
||
### 本批已确认裁决
|
||
实现时将下列裁决写入迁移配置:
|
||
|
||
| ICCID | active | pending | skipped |
|
||
|---|---|---|---|
|
||
| `89860624630055027529` | `DD74BA52EC8242FF94815532DC19389B` | `AB77C853EEF444E2AF20A8475F61CFA7` | 无 |
|
||
| `89860624630055035589` | `4ACDBC19027A4E90BF500F515093E0A3` | `2D247EF7877C4CE18E74EF9B139B7FCD` | 无 |
|
||
| `89860624590009246403` | `186B9062F3904AACB4A231041B6B5E98` | 无 | `EB006800000D49EB9A18024922657680` |
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- [运营裁决填写错误] → 覆盖按老库主键校验,并在审核 CSV 输出覆盖后的每条记录状态。
|
||
- [老库后续新增套餐记录] → 完整性校验拒绝遗漏的可迁移记录,要求重新确认配置。
|
||
- [覆盖配置被误用于常规数据] → 不提供全局或通配符规则,覆盖仅作用于单一完整 ICCID。
|
||
|
||
## Migration Plan
|
||
|
||
1. 发布包含覆盖能力与上述三项配置的迁移脚本。
|
||
2. 在隔离环境重新生成 step2,核对三张卡各一条 active,前两张各一条 pending,第三张无额外套餐。
|
||
3. 线上仅执行经审核的生成 SQL;若需回退,移除对应覆盖后重新生成,不写老库。
|