#!/usr/bin/env python3 """Seed the sample supplier, import its catalog, price + publish valid products. Idempotent: safe to re-run — supplier/catalog are upserted, prices recalculated. Usage: python3 scripts/seed.py """ import os import sys # allow running from repo root or scripts/ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from decimal import ROUND_HALF_UP, Decimal from app.database import SessionLocal from app.engines.importer import import_feed from app.engines.pricing import calculate_price from app.engines.suppliers.base import build_adapter from app.models import ( AuditLog, PriceHistory, Supplier, SupplierPerformance, SupplierProduct, ) SAMPLE_NAME = "Meridian Distribution" def ensure_supplier(db): supplier = db.query(Supplier).filter(Supplier.name == SAMPLE_NAME).first() if supplier is None: supplier = Supplier( name=SAMPLE_NAME, adapter_type="sample", shipping_regions=["US", "CA"], reliability_score=92.0, status="active", ) db.add(supplier) db.flush() print(f"[seed] created supplier {supplier.id}") else: supplier.status = "active" print(f"[seed] supplier already exists: {supplier.id}") return supplier def ensure_performance(db, supplier): if db.query(SupplierPerformance).filter(SupplierPerformance.supplier_id == supplier.id).first() is None: db.add( SupplierPerformance( supplier_id=supplier.id, fulfillment_rate=98.0, avg_shipping_days=4.0, cancellation_rate=1.0, stock_accuracy=97.0, return_rate=2.0, ) ) db.flush() def price_and_publish(db, supplier): """Price every linked product via the pricing engine; publish valid ones. NEVER publish invalid: products that fail rule lookup or end up with a non-positive retail price stay un-published. """ links = ( db.query(SupplierProduct) .filter(SupplierProduct.supplier_id == supplier.id) .all() ) published = 0 skipped = [] for sp in links: product = sp.product if product is None: continue quote = calculate_price( db, product.cost, shipping=sp.shipping_cost or 0, fees=0, min_price=product.min_price, ) if quote is None: skipped.append({"sku": product.sku, "reason": "no active price rule"}) continue if quote["retail"] <= 0: skipped.append({"sku": product.sku, "reason": "non-positive retail"}) continue product.retail_price = quote["retail"] product.min_price = (quote["retail"] * Decimal("0.90")).quantize( Decimal("0.01"), rounding=ROUND_HALF_UP ) product.max_price = (quote["retail"] * Decimal("1.15")).quantize( Decimal("0.01"), rounding=ROUND_HALF_UP ) product.status = "price_calculated" db.add(PriceHistory(product_id=product.id, price=quote["retail"], reason="auto")) # published only when priced product.status = "published" published += 1 db.add( AuditLog( actor="seed", action="product_published", entity="product", entity_id=str(product.id), detail={"sku": product.sku, "retail_price": float(quote["retail"])}, ) ) db.commit() print(f"[seed] priced + published {published} products; skipped: {skipped}") def main(): db = SessionLocal() try: supplier = ensure_supplier(db) db.commit() ensure_performance(db, supplier) db.commit() summary = import_feed(db, supplier, feed_type="sample", data_or_url="") print( f"[seed] import: received={summary['received']} " f"imported={summary['imported']} updated={summary['updated']} " f"skipped={len(summary['skipped'])}" ) if summary["skipped"]: print(f"[seed] skipped details: {summary['skipped']}") price_and_publish(db, supplier) # quick self-check on a known item ($80-ish cost band) probe = db.query(SupplierProduct).filter( SupplierProduct.supplier_id == supplier.id, SupplierProduct.supplier_sku == "SPL-1006", ).first() if probe and probe.product: p = probe.product print( f"[seed] sanity: {p.sku} cost={p.cost} retail={p.retail_price} " f"status={p.status}" ) print("[seed] done") finally: db.close() if __name__ == "__main__": main()