21 KiB
生产数据迁移全过程记录(可续写)
用途:记录本次及后续生产环境「三源 → shanxia2.0」数据迁移的全过程,便于续跑、对账、回滚。
权威计划:00-master-plan.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(部门等历史门户主数据以此为准抽取) |
策略摘要
- 业务主键原样保留:
id = str(源id)(见05-id-preservation-policy.md);用户表例外(门户 UUID +user_mapping)。 - 逐步清空:每步只 DELETE/TRUNCATE 该步目标表,禁止一次清全库。
- 每步:
dry-run→ 清空当步表 → 正式执行 → 本文件追加日志 +mappings//phase-*/logs/。 - 迁移脚本:
backend/scripts/migrate_*.py(曾在bede140d删除,已从bede140d^恢复)。
1. 第一步:部门数据(P0-2)
1.1 权威来源(已确认)
部门数据不要从 sx 迁,而从上一次生产迁移后的备份抽取:
docs/sql/shanxia2.0-生产-v1.sql → 表 sys_dept(共 5 行,remark 多为「数据迁移脚本重建」)。
已抽出可复用产物:
| 产物 | 路径 |
|---|---|
| 幂等种子 SQL | phase-0-foundation/seed_sys_dept_from_prod_v1.sql |
| 映射清单 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_deptETL(sx 快照只有 2 条且主键为 bigint)。 - 当前「测试模型」快照
shanxia2.0.sql通常只有根 + 销售,缺财务/人力/生产现场 → 必须以 生产-v1 补齐,用户dept_id才不孤立。
1.3 执行步骤(续跑时勾选)
- 生产盘点:
SELECT id, parent_id, dept_name, order_num, del_flag FROM sys_dept WHERE del_flag=0 ORDER BY order_num; 仅本表 DELETE:本次用幂等 UPSERT,未整表 DELETE(原有 2 行被 UPDATE 名称/排序)- 执行
seed_sys_dept_from_prod_v1.sql - 验收: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 抽 5 行种子 |
已完成(2026-07-31 幂等写入生产) |
| 0-3 | 角色 + 角色菜单 | 从 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 恢复 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. 操作命令模板(密码脱敏)
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 |
续跑建议
P1 CRM/审批办结/P2 报销/P3 地磅已完成。- P4 验收:抽样列表页、附件 URL、地磅单据。
5. 相关产物路径
| 类型 | 路径 |
|---|---|
| 用户映射 | mappings/user_mapping_result.csv |
| 用户部门花名册 | mappings/user_import_roster.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(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 |
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 对账通过 |