73 lines
2.7 KiB
Python
73 lines
2.7 KiB
Python
"""Inventory sync engine.
|
|
|
|
Refreshes supplier_products inventory from each adapter, writes inventory_history,
|
|
and flags zero/unavailable stock (pauses published products + audit log alert).
|
|
"""
|
|
from datetime import datetime, timezone
|
|
|
|
from app.engines.suppliers.base import build_adapter
|
|
from app.models import AuditLog, InventoryHistory, Supplier, SupplierProduct
|
|
|
|
|
|
def sync_inventory(db, supplier=None):
|
|
if supplier is not None:
|
|
suppliers = [supplier]
|
|
else:
|
|
suppliers = db.query(Supplier).filter(Supplier.status == "active").all()
|
|
|
|
stats = {"suppliers": len(suppliers), "checked": 0, "changed": 0, "zeroed": 0}
|
|
|
|
for s in suppliers:
|
|
try:
|
|
adapter = build_adapter(s)
|
|
current = {r["supplier_sku"]: int(r["inventory"]) for r in adapter.get_inventory()}
|
|
except Exception as exc: # noqa: BLE001 — log and continue to next supplier
|
|
db.add(
|
|
AuditLog(
|
|
actor="inventory",
|
|
action="sync_failed",
|
|
entity="supplier",
|
|
entity_id=str(s.id),
|
|
detail={"supplier": s.name, "error": str(exc)},
|
|
)
|
|
)
|
|
continue
|
|
|
|
for sp in db.query(SupplierProduct).filter(SupplierProduct.supplier_id == s.id).all():
|
|
stats["checked"] += 1
|
|
new_value = current.get(sp.supplier_sku)
|
|
if new_value is None:
|
|
continue
|
|
|
|
if sp.supplier_inventory != new_value:
|
|
stats["changed"] += 1
|
|
sp.supplier_inventory = new_value
|
|
sp.last_updated = datetime.now(timezone.utc)
|
|
db.add(InventoryHistory(supplier_product_id=sp.id, inventory=new_value))
|
|
|
|
if new_value <= 0:
|
|
stats["zeroed"] += 1
|
|
db.add(
|
|
AuditLog(
|
|
actor="inventory",
|
|
action="inventory_zero",
|
|
entity="supplier_product",
|
|
entity_id=str(sp.id),
|
|
detail={"supplier_sku": sp.supplier_sku, "inventory": 0},
|
|
)
|
|
)
|
|
if sp.product is not None and sp.product.status == "published":
|
|
sp.product.status = "paused"
|
|
db.add(
|
|
AuditLog(
|
|
actor="inventory",
|
|
action="product_paused_zero_inventory",
|
|
entity="product",
|
|
entity_id=str(sp.product.id),
|
|
detail={"sku": sp.product.sku},
|
|
)
|
|
)
|
|
|
|
db.commit()
|
|
return stats
|