""" seed_db.py, Peuplement de la base de données LivrExpress ========================================================== Réinitialise et peuple livrexpress.db avec des données de démonstration. Usage : uv run python seed_db.py (depuis le dossier code/livexpress/) Ce script illustre concrètement toutes les règles métier de OrderService : RÈGLES (OrderService) ┌─────────────────────────────────────────────────────────────────┐ │ urgency_level → "normal" commande créée il y a < 30min │ │ "light_delay" entre 30 et 45min │ │ "severe_delay" > 45min sans livraison │ │ "delivered" commande livrée │ │ is_late → True si non livrée et créée il y a > 45min │ │ free_delivery → True si total >= 25.0 € │ │ is_premium → True si le client a >= 10 commandes au total │ └─────────────────────────────────────────────────────────────────┘ Le middleware simule l'utilisateur connecté avec customer_id = 1 (Marie). """ import sqlite3 from datetime import datetime, timedelta DB_PATH = "livrexpress.db" NOW = datetime.now() # ───────────────────────────────────────────────────────────────────────────── # Schéma # ───────────────────────────────────────────────────────────────────────────── SCHEMA = """ DROP TABLE IF EXISTS order_dishes; DROP TABLE IF EXISTS orders; DROP TABLE IF EXISTS dishes; DROP TABLE IF EXISTS restaurants; DROP TABLE IF EXISTS customers; CREATE TABLE customers ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL, address TEXT NOT NULL ); CREATE TABLE restaurants ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL ); CREATE TABLE dishes ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, price REAL NOT NULL, restaurant_id INTEGER NOT NULL, FOREIGN KEY (restaurant_id) REFERENCES restaurants(id) ); CREATE TABLE orders ( id INTEGER PRIMARY KEY AUTOINCREMENT, customer_id INTEGER NOT NULL, restaurant_id INTEGER NOT NULL, delivery_address TEXT NOT NULL, created_at TEXT NOT NULL, delivered_at TEXT, FOREIGN KEY (customer_id) REFERENCES customers(id), FOREIGN KEY (restaurant_id) REFERENCES restaurants(id) ); CREATE TABLE order_dishes ( order_id INTEGER NOT NULL, dish_id INTEGER NOT NULL, FOREIGN KEY (order_id) REFERENCES orders(id), FOREIGN KEY (dish_id) REFERENCES dishes(id) ); """ def seed(): conn = sqlite3.connect(DB_PATH) conn.executescript(SCHEMA) c = conn.cursor() # ── Clients ────────────────────────────────────────────────────────────── # Marie : 12 commandes au total → is_premium = True (seuil = 10) # Lucas : 3 commandes au total → is_premium = False c.execute("INSERT INTO customers (name, email, address) VALUES (?, ?, ?)", ("Marie Dupont", "marie@example.com", "12 rue de la Paix, Paris")) marie_id = c.lastrowid c.execute("INSERT INTO customers (name, email, address) VALUES (?, ?, ?)", ("Lucas Martin", "lucas@example.com", "5 avenue Montaigne, Paris")) lucas_id = c.lastrowid # ── Restaurants ────────────────────────────────────────────────────────── c.execute("INSERT INTO restaurants (name) VALUES (?)", ("Chez Mario",)) mario_id = c.lastrowid c.execute("INSERT INTO restaurants (name) VALUES (?)", ("Le Wok d'Or",)) wok_id = c.lastrowid c.execute("INSERT INTO restaurants (name) VALUES (?)", ("Burger Palace",)) burger_id = c.lastrowid # ── Plats ──────────────────────────────────────────────────────────────── dishes = [ ("Margherita", 12.0, mario_id), # d1 ("Quattro Stagioni", 14.5, mario_id), # d2 ("Tiramisu", 6.0, mario_id), # d3 ("Pad Thaï", 13.5, wok_id), # d4 ("Nem croustillants", 8.0, wok_id), # d5 ("Burger Classic", 11.0, burger_id), # d6 ("Burger Double Bacon", 14.0, burger_id), # d7 ("Frites maison", 4.5, burger_id), # d8 ("Cheese Cake", 7.0, burger_id), # d9 ] dish_ids = [] for name, price, rid in dishes: c.execute("INSERT INTO dishes (name, price, restaurant_id) VALUES (?, ?, ?)", (name, price, rid)) dish_ids.append(c.lastrowid) d1, d2, d3, d4, d5, d6, d7, d8, d9 = dish_ids # ── Commandes pour Marie (customer_id=1) ───────────────────────────────── # On couvre tous les cas des règles métier : # # urgency is_late free_del dishes total # -------- ------- -------- ---------------------- ----- # normal False False Margherita 12.0 # normal False True Quattro + Tiramisu 20.5 # light_del False False Nem croustillants 8.0 # light_del False True Pad Thaï + Nem 21.5 # severe_del True False Burger Classic 11.0 # severe_del True True Burger x2 + Frites + CC 40.5 # delivered False True Margherita + Pad Thaï 25.5 order_specs = [ # (label, restaurant_id, created_at_offset_min, delivered_offset_min, dish_list) ("normal / pas chère", mario_id, -10, None, [d1]), ("normal / livraison ok",mario_id, -20, None, [d2, d3]), ("légère alerte", wok_id, -35, None, [d5]), ("légère alerte + gratu",wok_id, -38, None, [d4, d5]), ("retard / pas chère", burger_id, -60, None, [d6]), ("retard / livraison ok",burger_id, -90, None, [d7, d7, d8, d9]), ("livrée", mario_id, -50, -5, [d1, d4]), ] marie_orders = [] for label, rest_id, offset_min, delivered_offset, dish_list in order_specs: created = NOW + timedelta(minutes=offset_min) delivered = (NOW + timedelta(minutes=delivered_offset)).isoformat() if delivered_offset else None c.execute( "INSERT INTO orders (customer_id, restaurant_id, delivery_address, created_at, delivered_at)" " VALUES (?, ?, ?, ?, ?)", (marie_id, rest_id, "12 rue de la Paix, Paris", created.isoformat(), delivered) ) order_id = c.lastrowid for dish_id in dish_list: c.execute("INSERT INTO order_dishes (order_id, dish_id) VALUES (?, ?)", (order_id, dish_id)) total = sum(price for name, price, rid in dishes for did in dish_list if did == dish_ids[dishes.index((name, price, rid))]) marie_orders.append((label, order_id, total, created, delivered, dish_list)) # Commandes historiques pour atteindre order_count >= 10 (Marie est premium) # On en a déjà 7 ci-dessus, on en ajoute 5 dans le passé. for i in range(5): past = NOW - timedelta(days=30 + i) c.execute( "INSERT INTO orders (customer_id, restaurant_id, delivery_address, created_at, delivered_at)" " VALUES (?, ?, ?, ?, ?)", (marie_id, mario_id, "12 rue de la Paix, Paris", past.isoformat(), (past + timedelta(minutes=35)).isoformat()) ) c.execute("INSERT INTO order_dishes (order_id, dish_id) VALUES (?, ?)", (c.lastrowid, d1)) # ── Commandes pour Lucas (customer_id=2), non visibles via /my-orders ── for i in range(3): past = NOW - timedelta(days=5 + i) c.execute( "INSERT INTO orders (customer_id, restaurant_id, delivery_address, created_at, delivered_at)" " VALUES (?, ?, ?, ?, ?)", (lucas_id, burger_id, "5 avenue Montaigne, Paris", past.isoformat(), (past + timedelta(minutes=40)).isoformat()) ) c.execute("INSERT INTO order_dishes (order_id, dish_id) VALUES (?, ?)", (c.lastrowid, d6)) conn.commit() conn.close() # ── Résumé ────────────────────────────────────────────────────────────── print() print("━" * 68) print(" LivrExpress, Base de données peuplée") print("━" * 68) print(f"\n Heure actuelle : {NOW.strftime('%H:%M:%S')}") print(f"\n CLIENTS") print(f" #1 Marie Dupont , 12 commandes au total → 🌟 PREMIUM (seuil ≥ 10)") print(f" #2 Lucas Martin , 3 commandes au total → non premium") print(f"\n Client simulé par le middleware : customer_id = 1 (Marie)") print(f"\n COMMANDES VISIBLES sur /my-orders (Marie, 7 commandes récentes)") print(f"\n {'scénario':<26} {'total':>7} {'créée il y a':>13} {'urgency_level':<14} badges") print(" " + "─" * 66) urgency_labels = { "normal": "normal ", "light_delay": "⚠️ light_delay ", "severe_delay": "🔴 severe_delay", "delivered": "✅ delivered ", } for label, order_id, total, created, delivered, dish_list in marie_orders: elapsed = (NOW - created).total_seconds() / 60 if delivered: ul = "delivered" elif elapsed > 45: ul = "severe_delay" elif elapsed > 30: ul = "light_delay" else: ul = "normal" badges = [] if not delivered and elapsed > 45: badges.append("⏰ is_late") if total >= 25.0: badges.append("🚚 free_delivery") if delivered: badges.append("livrée") age_str = f"{int(elapsed)}min ago" print(f" {label:<26} {total:>6.1f}€ {age_str:>13} " f"{urgency_labels[ul]} {', '.join(badges) if badges else '—'}") print(f"\n + 5 commandes anciennes (livrées, > 30 jours) pour atteindre order_count = 12") print(f"\n COMMANDES Lucas (non visibles) : 3 commandes livrées") print() print(" ✓ Lancez l'app : uv run uvicorn main:app --reload") print(" ✓ Commandes : http://localhost:8000/my-orders") print("━" * 68) print() if __name__ == "__main__": seed()