# P1-1:CRM 产品分类 > **前置**:P0-4 用户;全局 ID 策略见 [05-id-preservation-policy.md](../05-id-preservation-policy.md) > **设计**:[superpowers 设计](../../superpowers/specs/2026-07-12-crm-product-category-data-migration-design.md) > **计划**:[superpowers 计划](../../superpowers/plans/2026-07-12-crm-product-category-data-migration.md) > **下游**:P1-1b 产品(`crm_product.category_id` 依赖本步 mapping) --- ## 1. 目标 将 sx `crm_product_category` 写入门户 `crm_product_category`,并生成: `docs/data-migration/mappings/crm_product_category_id_mapping.csv` --- ## 2. 源数据快照(docs/sql/sx.sql) | source_id | category_name | parent_id | sort | status | |-----------|---------------|-----------|------|--------| | 1975766404158746625 | 有机原料 | 0 | 0 | 0 | | 1975766458781167617 | 无机原料 | 0 | 1 | 0 | | 1975766539550879745 | 水处理溶剂 | 0 | 2 | 0 | | 1975766588632625154 | 其他 | 0 | 3 | 0 | | 1975766650771238913 | 未分类 | 0 | 4 | 0 | 生产执行前须在** live sx 库**再 `COUNT(*)` 核对(快照可能滞后)。 --- ## 3. 执行前检查 ```sql -- 目标:应为空 SELECT COUNT(*) FROM crm_product_category WHERE tenant_no='shanxia2.0' AND del_flag=0; -- 源 SELECT id, category_name, parent_id, sort, status, del_flag FROM crm_product_category ORDER BY sort; -- 用户映射文件存在 -- docs/data-migration/mappings/user_mapping_result.csv ``` 确认门户 admin 存在: ```sql SELECT id, user_no FROM sys_user WHERE user_no='admin' AND del_flag=0; ``` --- ## 4. 执行步骤 | 步骤 | 操作 | 状态 | |------|------|------| | 1 | 备份目标库 `mysqldump shanxia2.0` | 跳过(执行前 0 行) | | 2 | `migrate_crm_product_category.py --dry-run` | ✅ 2026-07-12 | | 3 | 审阅 dry-run 输出(5 行映射、admin create_by) | ✅ | | 4 | 正式执行 + `--mapping-out` | ✅ 插入 5 行 | | 5 | SQL + 界面验收 | SQL ✅;界面待人工 | | 6 | 追加 `logs/` 批次记录 | ✅ `logs/2026-07-12-2051-product-category.md` | ### 4.1 命令(脚本就绪后) ```bash cd backend && source venv/bin/activate # 预览 ENV_FILE=.env.production python scripts/migrate_crm_product_category.py \ --dry-run \ --source-url "$SX_SOURCE_DATABASE_URL" \ --user-mapping ../docs/data-migration/mappings/user_mapping_result.csv # 正式 ENV_FILE=.env.production python scripts/migrate_crm_product_category.py \ --source-url "$SX_SOURCE_DATABASE_URL" \ --user-mapping ../docs/data-migration/mappings/user_mapping_result.csv \ --mapping-out ../docs/data-migration/mappings/crm_product_category_id_mapping.csv ``` --- ## 5. 字段映射速查 | 源 | 目标 | 说明 | |----|------|------| | id | id | **原样保留** `str(source_id)` | | parent_id | parent_id | 0→'0',否则 `str(source_parent_id)` | | sort | order_num | 直接 | | status | status | **0/1 不反转**(sys_normal_disable) | | tenant_id | tenant_no | `shanxia2.0` | | create_by | create_by | user_mapping;1→admin | --- ## 6. 验收标准 - [x] 目标有效行数 = 源有效行数(5) - [x] 5 个分类名称、排序与源一致 - [x] 全部为顶级 `parent_id='0'`,`level=1` - [x] 状态均为 `0`(正常) - [x] mapping CSV 5 行,`source_id` = `new_id` - [ ] 产品分类页树形列表正常展示(待人工登录确认) --- ## 7. 二次移植说明 再次移植时: 1. 保留历史 `logs/` 与 mapping CSV,**新批次只追加** 2. 默认脚本 **skip 已映射 source_id**;若源数据有变更,使用 `--update` 3. 若目标库已有手工新增分类,勿 `--force` 清库;增量只迁源库有而 mapping 无的行 --- ## 8. 执行日志模板 执行后在 `logs/` 新建 `YYYY-MM-DD-HHMM-product-category.md`: ```markdown ## 批次:YYYY-MM-DD HH:MM ### 环境 - 目标库: - 源库 sx: - 操作人: ### 执行命令 (脱敏) ### 行数对比 | 表 | 源 | 执行前 | 执行后 | ### mapping 抽样 | source_id | new_id | category_name | ### 界面验收 - 路径:/#/crm/product-category - 结果: ### 问题与处理 ```