"""Seed DB with admin + demo customer + categories + 12 clothing products.""" from __future__ import annotations from core.db import SessionLocal from core.events import event_bus from core.security import hash_password from core.settings_service import set_setting from apps.auth.models import User from apps.catalog.models import Category, Product from apps.catalog.projector import rebuild_all CATEGORIES = [ {"slug": "oberteile", "name": {"de": "Oberteile", "en": "Tops"}, "sort_order": 1}, {"slug": "hosen", "name": {"de": "Hosen", "en": "Pants"}, "sort_order": 2}, {"slug": "schuhe", "name": {"de": "Schuhe", "en": "Shoes"}, "sort_order": 3}, {"slug": "accessoires", "name": {"de": "Accessoires", "en": "Accessories"}, "sort_order": 4}, ] def _placeholder(color_hex: str, label: str) -> str: # Simple SVG data URL — zero external dependencies from urllib.parse import quote svg = ( f"" f"" f"{label}" f"" ) return "data:image/svg+xml;utf8," + quote(svg) PRODUCTS = [ { "sku": "PULLI-GRUEN-M", "name": {"de": "Grüner Kuschelpulli", "en": "Green Cozy Sweater"}, "description": { "de": "Weicher grüner Pullover aus Bio-Baumwolle, ideal für kühle Tage.", "en": "Soft green sweater made of organic cotton, perfect for chilly days.", }, "price": 49.90, "stock": 20, "cat": "oberteile", "color": "green", "img": ("2e7d32", "Grüner Pulli"), }, { "sku": "PULLI-BLAU-L", "name": {"de": "Blauer Rundhalspullover", "en": "Blue Crewneck Sweater"}, "description": { "de": "Klassischer blauer Pullover mit Rundhalsausschnitt.", "en": "Classic blue crewneck sweater.", }, "price": 42.00, "stock": 15, "cat": "oberteile", "color": "blue", "img": ("1565c0", "Blauer Pulli"), }, { "sku": "TSHIRT-WHITE-M", "name": {"de": "Weißes Basic T-Shirt", "en": "White Basic T-Shirt"}, "description": { "de": "Leichtes Basic-Shirt aus 100% Bio-Baumwolle.", "en": "Light basic shirt made of 100% organic cotton.", }, "price": 14.90, "stock": 80, "cat": "oberteile", "color": "white", "img": ("f5f5f5", "Weißes Shirt"), }, { "sku": "TSHIRT-BLACK-L", "name": {"de": "Schwarzes T-Shirt", "en": "Black T-Shirt"}, "description": { "de": "Klassisches schwarzes Shirt, regular fit.", "en": "Classic black shirt, regular fit.", }, "price": 15.90, "stock": 80, "cat": "oberteile", "color": "black", "img": ("212121", "Schwarzes Shirt"), }, { "sku": "JACKE-OUTDOOR-M", "name": {"de": "Warme Outdoor-Jacke", "en": "Warm Outdoor Jacket"}, "description": { "de": "Wasserabweisende, wärmende Jacke zum Wandern und Radeln im Herbst.", "en": "Water-repellent, warm jacket for hiking and cycling in autumn.", }, "price": 129.00, "stock": 10, "cat": "oberteile", "color": "olive", "img": ("556b2f", "Outdoor-Jacke"), }, { "sku": "JEANS-BLAU-32", "name": {"de": "Blaue Jeans Straight", "en": "Blue Straight Jeans"}, "description": { "de": "Gerade geschnittene klassische Jeans in Dunkelblau.", "en": "Straight-cut classic jeans in dark blue.", }, "price": 69.00, "stock": 40, "cat": "hosen", "color": "blue", "img": ("0d47a1", "Blaue Jeans"), }, { "sku": "JEANS-SCHWARZ-34", "name": {"de": "Schwarze Slim Jeans", "en": "Black Slim Jeans"}, "description": { "de": "Slim-Fit-Jeans in tiefem Schwarz, leicht elastisch.", "en": "Slim-fit jeans in deep black, slightly stretchy.", }, "price": 74.00, "stock": 25, "cat": "hosen", "color": "black", "img": ("1b1b1b", "Schwarze Jeans"), }, { "sku": "HOSE-WANDER-L", "name": {"de": "Wanderhose robust", "en": "Robust Hiking Pants"}, "description": { "de": "Robuste Wanderhose für alle Jahreszeiten, wasserabweisend.", "en": "Robust hiking pants for all seasons, water-repellent.", }, "price": 89.00, "stock": 18, "cat": "hosen", "color": "khaki", "img": ("6b8e23", "Wanderhose"), }, { "sku": "SNEAKER-WEISS-42", "name": {"de": "Weiße Sneaker", "en": "White Sneakers"}, "description": { "de": "Zeitlose weiße Sneaker für den Alltag.", "en": "Timeless white sneakers for everyday use.", }, "price": 79.00, "stock": 30, "cat": "schuhe", "color": "white", "img": ("eeeeee", "Weiße Sneaker"), }, { "sku": "WANDERSCHUH-43", "name": {"de": "Wanderschuhe warm", "en": "Warm Hiking Boots"}, "description": { "de": "Warme Wanderschuhe mit guter Dämpfung und rutschfester Sohle.", "en": "Warm hiking boots with great cushioning and slip-resistant sole.", }, "price": 149.00, "stock": 12, "cat": "schuhe", "color": "brown", "img": ("6d4c41", "Wanderschuhe"), }, { "sku": "MUETZE-WOLLE", "name": {"de": "Wollmütze grün", "en": "Green Wool Beanie"}, "description": { "de": "Warme grüne Wollmütze für kalte Tage.", "en": "Warm green wool beanie for cold days.", }, "price": 19.90, "stock": 50, "cat": "accessoires", "color": "green", "img": ("388e3c", "Mütze"), }, { "sku": "SCHAL-GRAU", "name": {"de": "Grauer Schal", "en": "Grey Scarf"}, "description": { "de": "Weicher grauer Schal aus Merinowolle.", "en": "Soft grey scarf made of merino wool.", }, "price": 29.00, "stock": 35, "cat": "accessoires", "color": "grey", "img": ("757575", "Grauer Schal"), }, ] def seed() -> None: db = SessionLocal() try: # Shop name setting if not db.query(User).filter_by(email="admin@example.com").first(): set_setting(db, "core.shop_name", "Demo Shop") # Users if not db.query(User).filter_by(email="admin@example.com").first(): admin = User( email="admin@example.com", password_hash=hash_password("admin123"), role="admin", name="Admin", locale="de", ) db.add(admin) if not db.query(User).filter_by(email="kunde@example.com").first(): customer = User( email="kunde@example.com", password_hash=hash_password("kunde123"), role="customer", name="Demo Kunde", locale="de", ) db.add(customer) db.commit() # Categories cats_by_slug: dict[str, Category] = {} for c in CATEGORIES: row = db.query(Category).filter_by(slug=c["slug"]).first() if not row: row = Category(slug=c["slug"], name=c["name"], sort_order=c["sort_order"]) db.add(row) db.commit() db.refresh(row) event_bus.publish("category.created", {"id": row.id}, db=db) cats_by_slug[c["slug"]] = row # Products for pd in PRODUCTS: if db.query(Product).filter_by(sku=pd["sku"]).first(): continue image = _placeholder(*pd["img"]) p = Product( sku=pd["sku"], name=pd["name"], description=pd["description"], price=pd["price"], currency="EUR", stock=pd["stock"], active=True, image_url=image, category_id=cats_by_slug[pd["cat"]].id, attributes={"color": pd["color"]}, ) db.add(p) db.commit() db.refresh(p) event_bus.publish("product.created", {"id": p.id, "sku": p.sku}, db=db) # Rebuild Redis cache (idempotent) rebuild_all(db) print("Seed complete.") finally: db.close() if __name__ == "__main__": seed()