Files
shanxia2.0/docs/data-migration/05-id-preservation-policy.md
T
2026-07-13 20:26:43 +08:00

95 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 主键 ID 保留策略(全局)
> **决策日期**:2026-07-12
> **适用范围**:`docs/data-migration/` 下全部生产数据同步(CRM、报销、地磅)
> **原则**:原系统业务主键 **原样迁入** 门户库,仅做类型适配(`bigint`/`int` → 同值 `VARCHAR`),**不重新生成 UUID**。
---
## 1. 核心规则
| 项 | 规则 |
|----|------|
| 业务表主键 `id` | `target.id = str(source.id)`(十进制字符串,与源数值一致) |
| 业务外键 `*_id` | 指向业务实体时:`str(source_*_id)`;指向用户时:见 §3 |
| `parent_id` 等树字段 | `0` → `'0'`;非 0 → `str(source_parent_id)` |
| 映射文件 | 仍生成 `*_id_mapping.csv`,多为 **恒等映射**(`source_id` = `new_id`),用于审计与二次移植对账 |
| 脚本实现 | 统一使用 `legacy_id_to_str()`(参考 `migrate_dibang_data.py`、`migrate_crm_product_category.py`) |
**示例**
```
源 crm_product.id = 42 → 目标 "42"
源 crm_product.category_id = 1975766458781167617 → 目标 "1975766458781167617"
源地磅 plan.id = 12 → 目标 "12"
```
---
## 2. 好处
1. **下游表免查 mapping**:产品、客户、报价、合同等子表外键可直接 `str(源值)` 写入。
2. **二次移植简单**:按 `id` 幂等 SKIP/UPDATE,mapping 即对账表。
3. **与地磅策略一致**:三系统同一套心智模型。
4. **问题排查**:门户与旧库对照时 ID 一一对应。
---
## 3. 例外(不保留源 id 或需额外映射)
| 场景 | 处理方式 | 说明 |
|------|----------|------|
| **`sys_user`(P0 已执行)** | 已生成门户 UUID | 以 `mappings/user_mapping_result.csv` 为准;`create_by` / `owner_user_id` / `approver_id` 等 **必须**经用户映射转换 |
| **字典 `sys_dict_data.id`** | 按门户既有主键 | 字典项以 `dict_type` + `dict_value` 对齐,不按 sx 的 `dict_code` 保留 id(见 step-01-dict) |
| **门户已手工录入且 id 冲突** | 步骤文档写明 | 测试库可用 `--truncate`;生产需人工合并,禁止静默覆盖 |
| **源 id 非纯数字** | 原样字符串写入 | 若超长则按目标列宽截断并记 WARNING |
---
## 4. 各阶段适用表(摘要)
| 阶段 | 表 / 实体 | 主键策略 |
|------|-----------|----------|
| P0 | `sys_user` | ❌ 例外:门户 UUID + user_mapping |
| P0 | `sys_dept`、`sys_role` | ✅ 若从 sx 导入,优先保留源 id 字符串 |
| P1 CRM | `crm_product_category` | ✅ 已按本策略实现脚本 |
| P1 CRM | `crm_product`、`crm_customer`、`crm_clue`、商机/报价/合同等 | ✅ 全部 `str(source.id)` |
| P1 CRM | `sys_oss`(附件) | ✅ `str(oss_id)` |
| P2 报销 | `bx_*` 业务表 | ✅ `str(source.id)` |
| P3 地磅 | `db_*` | ✅ 已有脚本,int → 同值字符串 |
---
## 5. 脚本约定
每个 `migrate_*.py` 应:
1. 支持 `--dry-run`
2. 默认:目标已存在同 `id` → **SKIP**;`--update` 可覆盖非主键字段
3. `--mapping-out` 写出恒等或例外映射 CSV
4. 日志与 `phase-*/logs/` 记录「ID 策略:原样保留」
共享工具函数(可复制到各脚本或后续抽到 `scripts/migration_utils.py`):
```python
def legacy_id_to_str(legacy_id) -> str:
if legacy_id is None:
return "0"
return str(int(legacy_id))
```
---
## 6. 与旧文档的关系
- **代码移植 spec** `docs/superpowers/specs/2026-05-30-crm-migration-design.md` §7.1 曾写「bigint → UUID」;**生产数据同步以本文档为准**。
- **OpenSpec / 公共字段** 仍要求目标列类型为 `VARCHAR(64)`;保留源 id 字符串满足类型要求,不要求必须是 UUID 格式。
---
## 7. 相关文档
- [00-master-plan.md](./00-master-plan.md) §2 已确认决策
- [03-process-logging.md](./03-process-logging.md) 映射产物说明
- [phase-1-crm/step-01-product-category.md](./phase-1-crm/step-01-product-category.md) 首版落地示例