ForgeFlow-ERP/backend/app/services/purchase_order_links.py
2026-06-12 16:00:56 +08:00

55 lines
2.0 KiB
Python

from datetime import datetime
from sqlalchemy import inspect, select
from sqlalchemy.orm import Session
from app.models.operations import PurchaseOrderItem, PurchaseOrderSalesOrderLink
from app.models.planning import MaterialDemand
from app.models.sales import SalesOrder, SalesOrderItem
def ensure_purchase_order_sales_link_table(db: Session) -> None:
"""Keep the explicit purchase-sales link table available when DB patches lag behind code."""
if db.info.get("purchase_order_sales_link_table_ensured"):
return
bind = db.connection()
inspector = inspect(bind)
existed = inspector.has_table(PurchaseOrderSalesOrderLink.__tablename__)
PurchaseOrderSalesOrderLink.__table__.create(bind=bind, checkfirst=True)
if not existed:
backfill_purchase_order_sales_links(db)
db.info["purchase_order_sales_link_table_ensured"] = True
def backfill_purchase_order_sales_links(db: Session) -> None:
existing_pairs = {
(int(row.purchase_order_id), int(row.sales_order_id))
for row in db.execute(
select(PurchaseOrderSalesOrderLink.purchase_order_id, PurchaseOrderSalesOrderLink.sales_order_id)
)
}
inferred_rows = db.execute(
select(
PurchaseOrderItem.purchase_order_id.label("purchase_order_id"),
SalesOrder.id.label("sales_order_id"),
)
.join(MaterialDemand, MaterialDemand.id == PurchaseOrderItem.source_demand_id)
.join(SalesOrderItem, SalesOrderItem.id == MaterialDemand.sales_order_item_id)
.join(SalesOrder, SalesOrder.id == SalesOrderItem.sales_order_id)
.distinct()
).all()
now = datetime.now()
for row in inferred_rows:
pair = (int(row.purchase_order_id), int(row.sales_order_id))
if pair in existing_pairs:
continue
db.add(
PurchaseOrderSalesOrderLink(
purchase_order_id=pair[0],
sales_order_id=pair[1],
created_at=now,
updated_at=now,
)
)
existing_pairs.add(pair)