Add Polaris FastAPI backend: models/schemas, pricing+scoring+order router, importer, Celery tasks, API routers, seed script

This commit is contained in:
drjones
2026-08-25 20:37:58 -07:00
parent 8573554bf9
commit 96b4fcaac9
32 changed files with 2211 additions and 0 deletions

159
backend/scripts/seed.py Normal file
View File

@@ -0,0 +1,159 @@
#!/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 = "Sample Home & Gadgets"
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()