95 lines
3.9 KiB
Markdown
95 lines
3.9 KiB
Markdown
# 主键 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) 首版落地示例
|