JhHardwareWRS_BackPoint/scripts/migrate_cleaning_to_stamping_method.py
2026-06-24 15:19:14 +08:00

129 lines
4.7 KiB
Python

from pathlib import Path
import re
import sys
from sqlalchemy import select, text
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from app.database import SessionLocal, engine # noqa: E402
from app.models import DeviceQRCode, Product, ProductionReportItem, WorkSessionDevice # noqa: E402
from app.services.cleaning import CLEANING_STAMPING_METHOD, LEGACY_CLEANING_PROCESS_NAME # noqa: E402
def _column_exists(conn, table_name: str, column_name: str) -> bool:
return bool(conn.execute(
text("""
SELECT COUNT(*)
FROM information_schema.columns
WHERE table_schema = DATABASE()
AND table_name = :table_name
AND column_name = :column_name
"""),
{"table_name": table_name, "column_name": column_name},
).scalar_one())
def _sequence_number(process_name: str) -> int | None:
matched = re.search(r"\d+", str(process_name or ""))
return int(matched.group(0)) if matched else None
def _next_process_name(products: list[Product]) -> str:
existing = {str(product.process_name or "").strip() for product in products}
max_number = max(
(number for number in (_sequence_number(value) for value in existing) if number is not None),
default=0,
)
number = max_number + 1
while f"{number}" in existing:
number += 1
return f"{number}"
def main() -> None:
with engine.begin() as conn:
if not _column_exists(conn, "production_report_items", "stamping_method"):
conn.execute(text("""
ALTER TABLE production_report_items
ADD COLUMN stamping_method VARCHAR(128) NULL AFTER process_name
"""))
with SessionLocal() as db:
cleaning_products = db.scalars(
select(Product).where(Product.process_name == LEGACY_CLEANING_PROCESS_NAME)
).all()
migrated_products = 0
for product in cleaning_products:
old_process_name = product.process_name
siblings = db.scalars(
select(Product).where(
Product.project_no == product.project_no,
Product.product_name == product.product_name,
Product.device_no == product.device_no,
)
).all()
next_process_name = _next_process_name(siblings)
old_qr = db.get(DeviceQRCode, {
"device_no": product.product_name,
"process_name": old_process_name,
})
if old_qr is not None:
old_qr.process_name = next_process_name
for session_device in db.scalars(
select(WorkSessionDevice).where(
WorkSessionDevice.device_no == product.product_name,
WorkSessionDevice.process_name == old_process_name,
)
).all():
session_device.process_name = next_process_name
for report_item in db.scalars(
select(ProductionReportItem).where(
ProductionReportItem.project_no == product.project_no,
ProductionReportItem.product_name == product.product_name,
ProductionReportItem.process_name == old_process_name,
)
).all():
report_item.process_name = next_process_name
report_item.stamping_method = CLEANING_STAMPING_METHOD
report_item.standard_beat = 0
report_item.standard_workload = 0
report_item.allocated_minutes = 0
product.process_name = next_process_name
product.stamping_method = CLEANING_STAMPING_METHOD
product.standard_beat = 0
product.standard_workload = 0
migrated_products += 1
for product in db.scalars(
select(Product).where(Product.stamping_method == CLEANING_STAMPING_METHOD)
).all():
product.standard_beat = 0
product.standard_workload = 0
for report_item in db.scalars(select(ProductionReportItem)).all():
if report_item.stamping_method:
continue
product = db.scalar(
select(Product).where(
Product.project_no == report_item.project_no,
Product.product_name == report_item.product_name,
Product.process_name == (report_item.process_name or ""),
Product.device_no == "",
)
)
if product is not None:
report_item.stamping_method = product.stamping_method
db.commit()
print(f"cleaning migrated to stamping_method, products={migrated_products}")
if __name__ == "__main__":
main()