migrate_qc_material_stock_check_requisition.py 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #!/usr/bin/env python3
  2. """执行质检物料盘点登记相关 DB 迁移(requisition_status + usage_id/batch_id)。
  3. 用法(在 backend 目录):
  4. source venv/bin/activate
  5. python scripts/migrate_qc_material_stock_check_requisition.py
  6. """
  7. from __future__ import annotations
  8. from sqlalchemy import text
  9. from app.core.database import engine
  10. MIGRATIONS = [
  11. (
  12. "biz_qc_material_usage.requisition_status",
  13. """ALTER TABLE `biz_qc_material_usage`
  14. ADD COLUMN `requisition_status` varchar(16) NOT NULL DEFAULT 'open'
  15. COMMENT '领用状态:open-待登记/有剩余 closed-已使用完'
  16. AFTER `purpose`""",
  17. """UPDATE `biz_qc_material_usage`
  18. SET `requisition_status` = 'open'
  19. WHERE `source_type` = 'manual_out'
  20. AND `change_type` = 'use'
  21. AND (`requisition_status` IS NULL OR `requisition_status` = '')""",
  22. ),
  23. (
  24. "biz_qc_material_stock_check_unused_line.usage_id",
  25. """ALTER TABLE `biz_qc_material_stock_check_unused_line`
  26. ADD COLUMN `usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(biz_qc_material_usage.id)' AFTER `check_id`""",
  27. None,
  28. ),
  29. (
  30. "biz_qc_material_stock_check_unused_line.batch_id",
  31. """ALTER TABLE `biz_qc_material_stock_check_unused_line`
  32. ADD COLUMN `batch_id` varchar(64) DEFAULT NULL COMMENT '关联入库批次ID(手工登记批次检索)' AFTER `usage_id`""",
  33. None,
  34. ),
  35. (
  36. "idx_qc_check_unused_line_usage",
  37. """ALTER TABLE `biz_qc_material_stock_check_unused_line`
  38. ADD KEY `idx_qc_check_unused_line_usage` (`usage_id`, `del_flag`)""",
  39. None,
  40. ),
  41. ]
  42. def _run(conn, sql: str, label: str) -> None:
  43. try:
  44. conn.execute(text(sql))
  45. print(f"OK {label}")
  46. except Exception as e:
  47. msg = str(e)
  48. if "Duplicate column name" in msg or "1060" in msg:
  49. print(f"SKIP {label} (column exists)")
  50. elif "Duplicate key name" in msg or "1061" in msg:
  51. print(f"SKIP {label} (index exists)")
  52. else:
  53. raise
  54. def main() -> None:
  55. with engine.begin() as conn:
  56. for label, ddl, follow_up in MIGRATIONS:
  57. _run(conn, ddl, label)
  58. if follow_up:
  59. _run(conn, follow_up, f"{label} data backfill")
  60. print("Migration completed.")
  61. if __name__ == "__main__":
  62. main()