Files
shanxia2.0/docs/data-migration/PRODUCTION_MIGRATION_RUNLOG.md
T
2026-08-03 12:48:52 +08:00

261 lines
21 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.
# 生产数据迁移全过程记录(可续写)
> **用途**:记录本次及后续生产环境「三源 → shanxia2.0」数据迁移的全过程,便于续跑、对账、回滚。
> **权威计划**:[`00-master-plan.md`](./00-master-plan.md)、[`04-execution-order.md`](./04-execution-order.md)
> **勿与代码移植文档混淆**:`docs/crm-migration/`、`bx-migration/`、`db-migration/` 管功能移植;本目录管**数据灌库**。
---
## 0. 环境约定(本次)
| 角色 | 库名 | 说明 |
|------|------|------|
| 目标 | `shanxia2.0` | `backend/.env.production` → `DATABASE_URL`(主机 `121.43.228.102:3306`) |
| CRM + 报销源 | `sx` | 同主机;脚本 `--source-url .../sx`(**不要**把源 URL 写进 `.env.production`,Settings 禁额外字段) |
| 地磅源 | `dibang-test` | 同主机;`--source-url .../dibang-test`(不是 `dibang`) |
| 租户 | `shanxia2.0` | `tenant_no` 统一 |
| **上一次迁移后生产备份** | — | [`docs/sql/shanxia2.0-生产-v1.sql`](../sql/shanxia2.0-生产-v1.sql)(**部门等历史门户主数据以此为准抽取**) |
**策略摘要**
1. 业务主键原样保留:`id = str(源id)`(见 [`05-id-preservation-policy.md`](./05-id-preservation-policy.md));用户表例外(门户 UUID + `user_mapping`)。
2. **逐步清空**:每步只 DELETE/TRUNCATE 该步目标表,禁止一次清全库。
3. 每步:`dry-run` → 清空当步表 → 正式执行 → 本文件追加日志 + `mappings/` / `phase-*/logs/`。
4. 迁移脚本:`backend/scripts/migrate_*.py`(曾在 `bede140d` 删除,已从 `bede140d^` 恢复)。
---
## 1. 第一步:部门数据(P0-2)
### 1.1 权威来源(已确认)
**部门数据不要从 `sx` 迁,而从上一次生产迁移后的备份抽取:**
[`docs/sql/shanxia2.0-生产-v1.sql`](../sql/shanxia2.0-生产-v1.sql) → 表 `sys_dept`(共 **5** 行,`remark` 多为「数据迁移脚本重建」)。
已抽出可复用产物:
| 产物 | 路径 |
|------|------|
| 幂等种子 SQL | [`phase-0-foundation/seed_sys_dept_from_prod_v1.sql`](./phase-0-foundation/seed_sys_dept_from_prod_v1.sql) |
| 映射清单 CSV | [`mappings/dept_from_prod_v1.csv`](./mappings/dept_from_prod_v1.csv) |
### 1.2 v1 备份中的 5 条部门(与 `migrate_users.py` 硬编码一致)
| id | parent_id | dept_name | order_num | remark |
|----|-----------|-----------|-----------|--------|
| `b13c2be2-4e71-11f1-9f47-00163e3bdd96` | `0` | 安庆市山峡化工有限公司 | 0 | 数据迁移脚本重建 |
| `E65CAAE057914CCCAE2A81BE627A43EA` | 根 | 销售部 | 10 | 数据迁移脚本重建 |
| `F65CAAE057914CCCAE2A81BE627A43EF` | 根 | 财务部门 | 15 | 用户迁移前新增 |
| `C65CAAE057914CCCAE2A81BE627A43ED` | 根 | 人力资源部 | 20 | 数据迁移脚本重建 |
| `D65CAAE057914CCCAE2A81BE627A43EE` | 根 | 生产现场部 | 30 | 数据迁移脚本重建(用户默认部门) |
补充说明:
- 不是从 `sx.sys_dept` ETL(sx 快照只有 2 条且主键为 bigint)。
- 当前「测试模型」快照 [`shanxia2.0.sql`](../sql/shanxia2.0.sql) 通常只有根 + 销售,**缺**财务/人力/生产现场 → 必须以 **生产-v1** 补齐,用户 `dept_id` 才不孤立。
### 1.3 执行步骤(续跑时勾选)
- [x] 生产盘点:`SELECT id, parent_id, dept_name, order_num, del_flag FROM sys_dept WHERE del_flag=0 ORDER BY order_num;`
- [x] ~~仅本表 DELETE~~:本次用幂等 UPSERT,未整表 DELETE(原有 2 行被 UPDATE 名称/排序)
- [x] 执行 [`seed_sys_dept_from_prod_v1.sql`](./phase-0-foundation/seed_sys_dept_from_prod_v1.sql)
- [x] 验收:5 行齐全,ID 与 `migrate_users` / roster 一致
- [ ] (可选)补写 `phase-0-foundation/step-02-dept.md`
### 1.4 本步执行日志
| 时间 | 操作 | 结果 | 备注 |
|------|------|------|------|
| 2026-07-31 | 从 `shanxia2.0-生产-v1.sql` 抽取部门 | 5 行;已生成 seed SQL + CSV | |
| 2026-07-31 | 对生产执行 seed SQL | **成功** | 执行前 2 行(山峡化工/销售部门)→ 执行后 5 行齐全;根改名为「安庆市山峡化工有限公司」,销售部 order_num=10;新增财务/人力/生产现场 |
---
## 2. 全过程阶段清单(对照执行)
### P0 基础
| 步 | 内容 | 脚本/方式 | 状态(本次) |
|----|------|-----------|--------------|
| 0-1 | 字典 | 一般无需批量导入 | 历史:已验收跳过 |
| 0-2 | **部门** | 从 [`shanxia2.0-生产-v1.sql`](../sql/shanxia2.0-生产-v1.sql) 抽 5 行种子 | **已完成**(2026-07-31 幂等写入生产) |
| 0-3 | 角色 + 角色菜单 | 从 [`shanxia2.0-生产-v1.sql`](../sql/shanxia2.0-生产-v1.sql) 全量恢复 `sys_role`/`sys_role_menu` | **已完成**(2026-07-31):角色 12 / 菜单关联 452;见 `phase-0-foundation/logs/2026-07-31-sys-role.md` |
| 0-4 | 用户 | **改从** [`shanxia2.0-生产-v1.sql`](../sql/shanxia2.0-生产-v1.sql) 恢复 `sys_user`/`sys_user_role`/`sys_role`(+活跃 role_menu) | **已完成**(2026-07-31):有效用户 26;见 `phase-0-foundation/logs/2026-07-31-sys-user.md` |
### P1 CRM(源 `sx`)
| 步 | 脚本 | 当步清空表 | 状态(本次) |
|----|------|------------|--------------|
| 1-1a | `migrate_crm_product_category.py` | `crm_product_category` | **已完成**;status 曾误为 `1`,**已修复为 `0`(正常)** |
| 1-1b | `migrate_crm_product.py` | `crm_product` | **已完成**(2026-07-31):`--clear-target` 后插入 **247**(与 sx `del_flag=0` 一致);id 如 `'1'` 原样 |
| 1-1c | `renumber_crm_product_no.py --apply` | 不删表,改编号 | **已完成**(2026-07-31):247 条 → `SXWL`+6 位;映射 `crm_product_no_mapping.csv`;下一号 `SXWL000248` |
| 1-2 | `migrate_crm_customer.py` | pool/follow/contact/customer | **已完成**;**2026-07-31 下午再同步**:252 / 119 / 1 / 2(较上次 +1/+1) |
| 1-2b | `migrate_crm_payment_invoice.py` | `crm_invoice_info` | **已完成**(2026-07-31):DELETE 后插入 **201**;id 恒等;回款/发票主表源库 0 行跳过 |
| 1-3a | `migrate_crm_clue.py` | clue_follow/clue | **已完成**(2026-07-31):DELETE 后 clue **1** / follow **0**;id=`'12'` 与 sx 恒等 |
| 1-3b | `migrate_crm_opportunity.py` | opportunity 四表 | **已完成**(2026-07-31):sx 四表均为 **0**;已清空目标残留(opp 2/follow 5/stage 6);映射 CSV 仅表头 |
| 1-4a | `migrate_crm_quote.py` | quote 相关 + supplier | **已完成**;**2026-07-31 下午再同步**:supplier 2 / quote **986** / product **1347** / approval **916**(较上次 +2/+2/+2) |
| 1-4b | `migrate_crm_contract.py` | contract 六表 | **已完成**;**2026-07-31 下午再同步**:contract **962** / product **1338** / approval **440**(较上次 +2/+2) |
| 1-5 | `migrate_crm_sys_oss.py` | 慎清 `sys_oss` | **已提前完成**(2026-07-31):DELETE 291 → 插入 **355**;id 恒等;biz 回填 87 |
### P2 报销(源 `sx`)
| 步 | 命令 | 状态 |
|----|------|------|
| 2-1~2-4 | `migrate_bx_data.py --phase base\|advance\|reimburse\|attachment` | **P2 全部完成**(2026-07-31):base / advance / reimburse / attachment |
### P3 地磅(源 `dibang-test`)
| 步 | 命令 | 状态 |
|----|------|------|
| 3-1 | `db_vehicle` / 源 `vehicles` | 门户无 `db_vehicle` → **跳过**(源 158 辆不迁) |
| 3-2 | `migrate_dibang_data.py --truncate-target --include-deleted` | **已完成**(2026-07-31):plan **109** / IO **2359** / slip **1823**;映射 `dibang_id_mapping.json` |
对账:源/目标三表 COUNT 一致。`--include-deleted` 后仅 1 条孤儿警告:`weighing#84` 引用源库已不存在的 `inbound_outbound.id=94`(目标 `inbound_outbound_id` 置空)。日志见 `phase-3-dibang/logs/`。
### P4 验收
- 源/目标 COUNT 对账、抽样单据、中文名登录、附件 URL — **部分**:地磅三表 COUNT 已对账;其余抽样/登录/附件仍待做
---
## 3. 操作命令模板(密码脱敏)
```bash
cd backend
export PATH="venv/bin:$PATH"
SX_URL='mysql+pymysql://USER:PASS@HOST:3306/sx'
DIBANG_URL='mysql+pymysql://USER:PASS@HOST:3306/dibang-test'
# 用户(示例)
ENV_FILE=.env.production python scripts/migrate_users.py \
--env-file .env.production --source-url "$SX_URL"
# CRM 分类(示例:先 SQL DELETE 当步表,再执行)
ENV_FILE=.env.production python scripts/migrate_crm_product_category.py \
--env-file .env.production --source-url "$SX_URL" \
--user-mapping ../docs/data-migration/mappings/user_mapping_result.csv \
--mapping-out ../docs/data-migration/mappings/crm_product_category_id_mapping.csv
```
逐步 DELETE 示例见计划;子表先于父表。
---
## 4. 批次时间线(追加写,禁止覆盖历史)
### 批次 2026-07-31(中断暂停)
| 时间(约) | 动作 | 结果 |
|------------|------|------|
| 当日上午 | 恢复 `backend/scripts/migrate_*.py`(自 `bede140d^`) | 完成 |
| | 连通校验:`shanxia2.0` / `sx` / `dibang-test` | OK;sx 产品 248、客户 259、报价 1002、合同 995;dibang-test 计划 109 / 出入库 2355 / 地磅单 1821 |
| | 正式 `migrate_users.py`(sx) | 曾新增 25 用户(后被库覆盖/清掉;**已作废,不以本次为准**) |
| | DELETE + `migrate_crm_product_category` | 插入 5 |
| | DELETE + `migrate_crm_product` | 插入 247 |
| | `renumber_crm_product_no` | 仅 DRY-RUN |
| | 用户要求暂停 | 客户及以后 / 报销 / 地磅 **未写** |
| 同日稍后 | 执行部门 seed SQL | 生产 `sys_dept` 5 行齐全 |
| 同日稍后 | **用户改从生产-v1 恢复** | `sys_user` 26 / 活跃 `user_role` 9;刷新 `user_mapping_result.*`(UUID 与上次迁移一致) |
| 同日稍后 | **角色从生产-v1 全量对齐** | `sys_role` 12(有效 6)+ `sys_role_menu` 452;映射 `role_from_prod_v1.csv` |
| 同日稍后 | **6 个新菜单授权给全部角色** | 发票夹×2、改选申请人、主体危化品能力×2、三方驾押人员 → 12 角色均 6/6;见 `logs/2026-07-31-grant-new-menus.md` |
| 同日稍后 | **角色-菜单关系先按生产-v1 重灌** | DELETE 后 INSERT 452;再补授 6 新菜单 +72 → 合计 524;见 `logs/2026-07-31-sys-role-menu-v1.md` |
| 同日稍后 | **产品分类 + 产品从 sx 重灌** | 分类 5(status=1);产品 247;id 与 sx 一致;映射 CSV 已刷新 |
| 同日稍后 | **产品编号统一 SXWL+6 位** | 247 行全部更新;`product_id` 不变;见 `mappings/crm_product_no_mapping.csv` |
| 同日稍后 | **修复分类 status** | 误写成 `1`(停用) → 改回 `0`(正常);脚本已按若依语义回修 |
| 同日稍后 | **恢复** `scripts/migration/minio_url.py` | 客户证照 OSS ID→URL 依赖 |
| 同日稍后 | **客户四表从 sx 重灌** | DELETE 后:customer 251 / contact 118 / follow 1 / pool 2;id 恒等;75 条「未分类」置空;见 `logs/2026-07-31-customer-migrate.md` |
| 同日稍后 | **开票信息 crm_invoice_info** | DELETE 6 → 插入 201;id 恒等;3 条挂已软删客户;见 `logs/2026-07-31-invoice-info.md` |
| 同日稍后 | **线索 crm_clue** | DELETE 残留后:clue 1(id=`12` 陈福威)/ follow 0;见 `logs/2026-07-31-clue.md` |
| 同日稍后 | **商机四表** | sx 全空;DELETE 目标残留后插入 0;见 `logs/2026-07-31-opportunity.md` |
| 同日稍后 | **附件 sys_oss(提前于报价)** | DELETE 门户原 291 → 从 sx 插入 **355**;id 恒等;biz 回填 87 / 未挂业务 268;见 `logs/2026-07-31-sys-oss.md` |
| 同日稍后 | **客户证照 URL 回填** | 41 家客户营业执照/许可证等相对路径已写入;见 `mappings/crm_customer_license_url_backfill.csv` |
| 同日稍后 | **报价四表 + 供应商** | DELETE 残留后:quote 984 / product 1345 / approval 914 / supplier 2;id 恒等;见 `logs/2026-07-31-quote.md` |
| 同日稍后 | **合同六表** | DELETE 残留后:contract 960 / product 1336 / approval 440;id 恒等;见 `logs/2026-07-31-contract.md` |
| 同日稍后 | **OSS biz 回填(合同)** | `--skip-insert`;修好 JSON `ossId` 解析后回填 **189**(合同附件);现 biz:customer 87 + contract ~189 |
| 同日稍后 | **合同附件 ossId→相对路径** | 184 合同 / 188 处替换;门户约定 ossId 存 MinIO key;见 `mappings/crm_contract_attachment_url_backfill.csv` |
| 同日稍后 | **报销 P2-1 基础数据** | expense_item 48(alive 37)/ workflow_def 2(备用金+报销单)/ node 4;审批人已映射;见 `phase-2-bx/logs/2026-07-31-bx-base.md` |
| 同日稍后 | **报销 P2-4 附件** | DELETE 41 → 插入 **155**;file_path 相对路径原样;biz_id 待 advance/reimburse 迁入后对齐;见 `phase-2-bx/logs/2026-07-31-bx-attachment.md` |
| 同日稍后 | **报销 P2-2 备用金** | apply **13** / approval **27**(含发放字段 issue_*);id 恒等;见 `phase-2-bx/logs/2026-07-31-bx-advance.md` |
| 同日稍后 | **报销 P2-3 报销单** | apply **127** / detail **170** / approval **195** / offset **4**;id 恒等;1 条用户字段警告;见 `phase-2-bx/logs/2026-07-31-bx-reimburse.md` |
| 同日稍后 | **用户密码重置** | 25 人恢复为 2026-07-12 `user_import_accounts.md` 首次 4 位密码(bcrypt);见 `phase-0-foundation/logs/2026-07-31-reset-passwords-to-20260712.md` |
| 同日稍后 | **地磅 P3 dry-run** | 仅存活:plan 99 / IO 2044 / slip 1823,孤儿 FK 警告 40;含软删:109 / 2359 / 1823,孤儿仅 1 |
| 同日稍后 | **地磅 P3 正式迁移** | `--truncate-target --include-deleted`:写入 plan 109 / IO 2359 / slip 1823;COUNT 与源一致;见 `phase-3-dibang/logs/2026-07-31-dibang-migrate.md` |
| 同日稍后 | **清空发票夹业务数据** | DELETE:invoice 8 / ledger 8 / summary 2 / reimburse_invoice 1 / attachment(invoice) 1;见 `phase-2-bx/logs/2026-07-31-clear-invoice-wallet.md` |
| 同日下午 | **客户再同步** | DELETE 后:customer **252** / contact **119** / follow 1 / pool 2;证照回填 42;见 `logs/2026-07-31-customer-resync-migrate.md` |
| 同日下午 | **合同再同步(中断后续跑)** | 主表 962 先入;续跑 product **1338** / approval **440**;清掉 18 条非源 UUID 审批残留;附件路径无需再替(migrate 已展开);见 `logs/2026-07-31-contract-resync-migrate-resume.md` |
| 同日下午 | **报价再同步** | DELETE 后:supplier 2 / quote **986** / product **1347** / approval **916**;见 `logs/2026-07-31-quote-resync-migrate.md` |
| 同日下午 | **清空运输管理测试数据** | 全部 `pl_*`(承运商/车辆/人员/计划/出入库/证照等)按租户 DELETE → 0;未动 `db_*`;见 `phase-pl/logs/2026-07-31-clear-pl-test-data.md` |
| 2026-08-01 | **再导入前清空 pl_*** | 残留 plan/product 各 1 → 全部 `pl_*`=0;见 `phase-pl/logs/2026-08-01-clear-pl-before-reimport.md` |
| 2026-08-01 | **产品分类 + 产品再迁移** | `--clear-target`:分类 **5**(status=0)/ 产品 **248**;与 sx 一致;见 `logs/2026-08-01-product-*-migrate.md` |
| 2026-08-01 | **附件 sys_oss 再迁移** | DELETE 355 → 插入 **362**;biz 回填 **281** / 未挂 81;见 `logs/2026-08-01-sys-oss-migrate.md` |
| 2026-08-01 | **客户四表再迁移** | DELETE 后:customer **253** / contact **119** / follow 1 / pool 2;证照回填见 `logs/2026-08-01-customer-*.md` |
| 2026-08-01 | **开票/线索/商机/报价/合同** | invoice_info **203**;clue 1;opp 0;quote 989/1352/919;contract 966/1344/688;中断后续跑审批与合同重灌已对齐 |
| 2026-08-01 | **地磅再迁移** | 源 `dibang-test`,`--truncate-target --include-deleted`:plan **118** / IO **2386** / slip **1840**;见 `phase-3-dibang/logs/2026-08-01-dibang-migrate.md` |
| 2026-08-01 | **报销再迁移** | base→advance→reimburse→attachment:item 48 / wf 2+4 / advance 13+27 / reimburse 127+170+195+4 / att 155;见 `phase-2-bx/logs/2026-08-01-bx-*-migrate.md` |
| 2026-08-02 | **清空运输业务单据(保留主数据)** | 清计划/出入库/运费/ETC/维保等;保留承运商10/车辆13/人员22/证件90/提醒5;见 `phase-pl/logs/2026-08-02-clear-pl-ops-keep-master.md` |
| 2026-08-01 | **地磅再迁移** | `dibang-test` → `--truncate-target --include-deleted`:plan **118** / IO **2386** / slip **1840**;孤儿 weighing#84→IO94;见 `phase-3-dibang/logs/2026-08-01-dibang-migrate.md` |
| 2026-08-02 | **CRM 业务再同步(不含产品)** | 见下节「批次 2026-08-02」 |
### 批次 2026-08-02(CRM 重迁:不含产品分类/产品)
约定:不重迁 `crm_product*`;`sys_oss` **仅增量**(不 DELETE,保留运输等门户附件)。
| 时间(约) | 动作 | 结果 |
|------------|------|------|
| 当日晚 | **sys_oss 增量** | 插入 0 / 更新 362;目标仍 482(sx 362 + 门户约 120);见 `phase-1-crm/logs/2026-08-02-sys-oss-incremental.md` |
| 当日晚 | **客户四表** | DELETE 后:customer **253** / contact **119** / follow 1 / pool 2;id 与 sx 存活集恒等;77 条「未分类」置空;见 `logs/2026-08-02-customer-remigrate.md` |
| 当日晚 | **开票信息** | invoice_info **203**;见 `logs/2026-08-02-invoice-info-remigrate.md` |
| 当日晚 | **客户证照回填** | 43 家至少一证有 URL;见 `logs/2026-08-02-customer-license-backfill.md` |
| 当日晚 | **线索 / 商机** | clue 1 / follow 0;opp 四表 0;见 `logs/2026-08-02-clue-remigrate.md`、`opportunity-remigrate.md` |
| 当日晚 | **报价** | supplier 2 / quote **989** / product **1352** / approval **919**;见 `logs/2026-08-02-quote-remigrate.md` |
| 当日晚 | **合同** | contract **966** / product **1344** / approval **688**;附件回填需更新 0(migrate 已展开路径);见 `logs/2026-08-02-contract-*.md` |
| — | **产品未动** | `crm_product` 仍为门户侧 **367**(与 sx 249 不对齐属预期,本批次刻意跳过) |
对账(`del_flag=0`):客户/联系人/开票/线索/报价/合同与 sx 存活 COUNT 及 id 集合一致。
| 当日晚 | **报价/合同审批批量办结** | 报价 `submitted`→`accepted` **726**;报价审批 pending→approved **824**;合同 `approving`→`approved` **673**;合同审批 pending→approved **682**;见 `logs/2026-08-02-force-approve-quote-contract.md` |
| 当日晚 | **报销 P2 全量重迁** | DELETE 业务表后 `--phase all`:item 48 / wf 2+4 / advance 13+27 / reimburse 127+170+195+4 / att **155**;未动发票夹;见 `phase-2-bx/logs/2026-08-02-bx-all-remigrate.md` |
| 当日晚 | **地磅 P3 全量重迁** | 源 `dibang-test`,`--truncate-target --include-deleted`:plan **118** / IO **2392** / slip **1852**;孤儿 weighing#84→IO94;见 `phase-3-dibang/logs/2026-08-02-dibang-migrate.md` |
| 2026-08-03 | **增量同步 IO#2398** | 出入库 `2398`(UPDATE)+ 地磅单 `1895`(INSERT);车皖H38397 / CRKDH0002048 / 净重 34330;见 `phase-3-dibang/logs/2026-08-03-sync-io-2398.md` |
| 2026-08-03 | **同步当日全部单据** | 源 `dibang-test` 2026-08-03:IO **6**(INSERT 2 UPDATE 4)/ slip **2**(INSERT 1 UPDATE 1);计划 0;见 `phase-3-dibang/logs/2026-08-03-sync-today.md` |
**续跑建议**
1. ~~P1 CRM~~ / ~~审批办结~~ / ~~P2 报销~~ / ~~P3 地磅~~ 已完成。
2. P4 验收:抽样列表页、附件 URL、地磅单据。
---
## 5. 相关产物路径
| 类型 | 路径 |
|------|------|
| 用户映射 | [`mappings/user_mapping_result.csv`](./mappings/user_mapping_result.csv) |
| 用户部门花名册 | [`mappings/user_import_roster.csv`](./mappings/user_import_roster.csv) |
| 初始密码(敏感,勿外传) | [`mappings/user_import_credentials.csv`](./mappings/user_import_credentials.csv) |
| 产品分类/产品映射 | `mappings/crm_product_category_id_mapping.csv`、`crm_product_id_mapping.csv` |
| 客户映射 | `mappings/crm_customer_id_mapping.csv`(251 行,source_id=new_id) |
| 开票信息映射 | `mappings/crm_invoice_info_id_mapping.csv`(201 行,source_id=new_id) |
| 线索映射 | `mappings/crm_clue_id_mapping.csv`(1 行,source_id=new_id=`12`) |
| 商机映射 | `mappings/crm_opportunity_id_mapping.csv`(0 数据行;sx 无商机) |
| 附件 OSS 映射 | `mappings/crm_oss_id_mapping.csv`(355 行);biz:`crm_oss_biz_backfill.csv`;未挂:`crm_oss_unresolved.csv` |
| 报价映射 | `mappings/crm_quote_id_mapping.csv`(984 行,source_id=new_id) |
| 合同映射 | `mappings/crm_contract_id_mapping.csv`(960 行,source_id=new_id) |
| 地磅映射 | [`mappings/dibang_id_mapping.json`](./mappings/dibang_id_mapping.json)(plan 109 / IO 2359 / slip 1823) |
| 阶段日志 | `phase-0-foundation/logs/`、`phase-1-crm/logs/`、`phase-2-bx/logs/`、`phase-3-dibang/logs/` |
| 主键策略 | [`05-id-preservation-policy.md`](./05-id-preservation-policy.md) |
---
## 6. 修订记录
| 日期 | 修订 |
|------|------|
| 2026-07-31 | 建档;回答部门历史结论;记录已执行用户/分类/产品与暂停点 |
| 2026-07-31 | 确认部门权威源为 `shanxia2.0-生产-v1.sql`;抽出 5 行 seed SQL + CSV |
| 2026-07-31 | 用户改为从 `shanxia2.0-生产-v1.sql` 恢复(非 sx migrate_users);完成并留痕 |
| 2026-07-31 | 角色/角色菜单按生产-v1 全量对齐;完成并留痕 |
| 2026-07-31 | 新版 6 菜单授予生产全部 12 角色;完成并留痕 |
| 2026-07-31 | P3 地磅从 `dibang-test` 正式迁入(含软删);三表 COUNT 对账通过 |