init_vehicles_from_history.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #!/usr/bin/env python3
  2. """
  3. 从历史出入库表(inbound_outbound)、地磅单表(weighing_slips)中提取不重复的车牌号,
  4. 初始化写入车牌号基础资料表(vehicles)。
  5. 使用方式(在 backend 目录下执行):
  6. python -m scripts.init_vehicles_from_history
  7. 或:
  8. uv run python -m scripts.init_vehicles_from_history
  9. """
  10. from __future__ import annotations
  11. import asyncio
  12. import sys
  13. from pathlib import Path
  14. # 将 backend 根目录加入 path,以便 import app
  15. backend_root = Path(__file__).resolve().parent.parent
  16. if str(backend_root) not in sys.path:
  17. sys.path.insert(0, str(backend_root))
  18. async def main() -> None:
  19. from sqlmodel import select
  20. from sqlmodel.ext.asyncio.session import AsyncSession
  21. from app.db.session import init_models, AsyncSessionLocal
  22. from app.models.inventory import InboundOutbound
  23. from app.models.master_data import Vehicle
  24. from app.models.weighing import WeighingSlip
  25. # 1. 确保所有表已创建(含 vehicles)
  26. await init_models()
  27. # 2. 从出入库表、地磅单表收集不重复车牌号(去空、去重,按原始大小写保留一个)
  28. seen_normalized: set[str] = set()
  29. vehicle_nos: list[str] = []
  30. async with AsyncSessionLocal() as session:
  31. # 出入库表:未删除记录的车牌号
  32. q_inv = select(InboundOutbound.vehicle_no).where(InboundOutbound.is_deleted == 0)
  33. result_inv = await session.exec(q_inv)
  34. for (v,) in result_inv.all():
  35. v = (v or "").strip()
  36. if not v:
  37. continue
  38. key = v.lower()
  39. if key not in seen_normalized:
  40. seen_normalized.add(key)
  41. vehicle_nos.append(v)
  42. # 地磅单表:未作废记录的车牌号
  43. q_ws = select(WeighingSlip.vehicle_no).where(WeighingSlip.is_voided == 0)
  44. result_ws = await session.exec(q_ws)
  45. for (v,) in result_ws.all():
  46. v = (v or "").strip()
  47. if not v:
  48. continue
  49. key = v.lower()
  50. if key not in seen_normalized:
  51. seen_normalized.add(key)
  52. vehicle_nos.append(v)
  53. if not vehicle_nos:
  54. print("未从出入库/地磅单表中发现任何车牌号,无需导入。")
  55. return
  56. # 3. 写入 vehicles 表(仅插入尚未存在的车牌号)
  57. from datetime import datetime
  58. added = 0
  59. skipped = 0
  60. async with AsyncSessionLocal() as session:
  61. existing = await session.exec(
  62. select(Vehicle.vehicle_no).where(Vehicle.is_deleted == 0)
  63. )
  64. existing_set = {row.lower() for row in existing.all()}
  65. for v in vehicle_nos:
  66. if v.lower() in existing_set:
  67. skipped += 1
  68. continue
  69. vehicle = Vehicle(
  70. vehicle_no=v,
  71. remarks=None,
  72. is_deleted=0,
  73. created_at=datetime.now().isoformat(),
  74. )
  75. session.add(vehicle)
  76. existing_set.add(v.lower())
  77. added += 1
  78. await session.commit()
  79. print(f"历史车牌号统计:共发现 {len(vehicle_nos)} 个不重复车牌号。")
  80. print(f"本次新增写入 vehicles 表:{added} 条;已存在跳过:{skipped} 条。")
  81. if __name__ == "__main__":
  82. asyncio.run(main())