# /opt/docker/dev/service_finder/backend/app/scripts/seed_system_params.py import asyncio import logging from sqlalchemy import select from app.db.session import AsyncSessionLocal from app.models.system import SystemParameter logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s]: %(message)s') logger = logging.getLogger("Seed-System-Params-2.0") async def seed_params(): async with AsyncSessionLocal() as db: # ---------------------------------------------------------------------- # GONDOLATMENET A STRUKTÚRÁHOZ: # Ez a lista tartalmazza a rendszer összes "alapértelmezett" (global) beállítását. # Minden modul innen kapja meg az indulási értékeit. Ha az admin felületen # egy értéket módosítanak, ez a script a következő futáskor NEM írja felül azt, # csak a leírásokat (description) és a kategóriákat frissíti. # ---------------------------------------------------------------------- params = [ # --- 1. KOMMUNIKÁCIÓ (Az EmailManager 2.0 motorja) --- { "key": "email_provider", "value": "smtp", # Lehetőségek: "smtp", "sendgrid", "disabled" "category": "communication", "description": "Aktív e-mail küldő szolgáltató", "scope_level": "global" }, { "key": "emails_from_email", "value": "noreply@profibot.hu", "category": "communication", "description": "A rendszer által küldött levelek feladó címe", "scope_level": "global" }, { "key": "emails_from_name", "value": "Sentinel Master", "category": "communication", "description": "A rendszer által küldött levelek feladó neve", "scope_level": "global" }, { "key": "sendgrid_api_key", "value": "", "category": "communication", "description": "SendGrid API kulcs (ha a provider 'sendgrid')", "scope_level": "global" }, { "key": "smtp_config", "value": { "host": "localhost", "port": 587, "user": "smtp_user", "pass": "smtp_password", "tls": True }, "category": "communication", "description": "SMTP szerver konfiguráció JSON formátumban", "scope_level": "global" }, # --- 2. AUTH & SECURITY (Kapuőr modul) --- {"key": "auth_min_password_length", "value": 8, "category": "security", "description": "Minimum jelszóhossz", "scope_level": "global"}, {"key": "auth_default_role", "value": "user", "category": "auth", "description": "Új regisztrálók alapértelmezett rangja", "scope_level": "global"}, {"key": "auth_registration_hours", "value": 48, "category": "auth", "description": "Regisztrációs link érvényessége", "scope_level": "global"}, {"key": "auth_password_reset_hours", "value": 2, "category": "security", "description": "Jelszóvisszaállító link érvényessége", "scope_level": "global"}, {"key": "asset_auto_transfer_enabled", "value": False, "category": "security", "description": "Autonóm tulajdonosváltás engedélyezése", "scope_level": "global"}, # --- 3. LIMITS & CSOMAGOK (A Billing és Asset korlátok) --- { "key": "VEHICLE_LIMIT", "value": {"free": 1, "premium": 5, "vip": 50, "service_pro": 10}, "category": "limits", "description": "Járműszám korlátok előfizetés szerint", "scope_level": "global" }, { "key": "subscription_packages_matrix", "value": { "free": {"price": 0, "rank": 1, "type": "credit"}, "premium": {"price": 1990, "rank": 5, "type": "credit"}, "vip": {"price": 4990, "rank": 50, "type": "credit"}, "service_pro": {"price": 9990, "rank": 30, "type": "coin", "initial_coin_bonus": 500} }, "category": "billing", "description": "Csomagok, árak és bónuszok központi mátrixa", "scope_level": "global" }, # --- 4. FINANCE (Költségek és Devizák) --- {"key": "finance_default_currency", "value": "HUF", "category": "finance", "description": "Helyi alap deviza", "scope_level": "global"}, {"key": "finance_base_currency", "value": "EUR", "category": "finance", "description": "Központi elszámoló deviza (Statisztikákhoz)", "scope_level": "global"}, {"key": "org_naming_template", "value": "{last_name} Flotta", "category": "system", "description": "Szervezet név sablon", "scope_level": "global"}, # --- 5. DOCUMENT & OCR (Robot 1 vezérlése) --- { "key": "ocr_monthly_limit", "value": {"free": 1, "premium": 10, "vip": 100}, "category": "limits", "description": "Havi ingyenes OCR szkennelések száma", "scope_level": "global" }, { "key": "ocr_auto_trigger_types", "value": ["invoice", "registration_card", "sale_contract"], "category": "robots", "description": "Azonnali OCR feldolgozásra kijelölt típusok", "scope_level": "global" }, # --- 6. GAMIFICATION (A Játékmester) --- {"key": "gamification_kyc_bonus", "value": 500, "category": "gamification", "description": "XP jutalom a KYC után", "scope_level": "global"}, {"key": "xp_multiplier_ocr_cost", "value": 1.5, "category": "gamification", "description": "Bónusz szorzó digitális (OCR) adatrögzítésre", "scope_level": "global"}, { "key": "GAMIFICATION_MASTER_CONFIG", "value": { "xp_logic": {"base_xp": 500, "exponent": 1.5}, "penalty_logic": { "recovery_rate": 0.5, "thresholds": {"level_1": 100, "level_2": 500, "level_3": 1000}, "multipliers": {"L0": 1.0, "L1": 0.5, "L2": 0.1, "L3": 0.0} }, "conversion_logic": {"social_to_credit_rate": 100}, "level_rewards": {"credits_per_10_levels": 50} }, "category": "gamification", "description": "Szintek, büntetések és jutalmak mátrixa", "scope_level": "global" }, # --- 7. ÉRTESÍTÉSEK ÉS KARBANTARTÁS --- { "key": "notif_expiry_threshold_days", "value": 30, "category": "notifications", "description": "Hány nappal az okmányok lejárata előtt küldjön a rendszer automata figyelmeztetést?", "scope_level": "global" }, { "key": "notif_expiry_steps", "value": [30, 7, 1, 0], "category": "notifications", "description": "Hány nappal a lejárat előtt küldjön a rendszer riasztást? (Lista formátum)", "scope_level": "global" }, { "key": "maint_km_alert_threshold", "value": 1000, "category": "maintenance", "description": "Hány kilométerrel a tervezett szerviz előtt küldjön figyelmeztetést a rendszer?", "scope_level": "global" }, { "key": "storage_retention_days", "value": 365, "category": "storage", "description": "Fájlok megőrzési ideje a NAS-on (napokban)", "scope_level": "global" }, { "key": "storage_delete_after_validation", "value": False, "category": "storage", "description": "Törölje-e a rendszer az OCR bizonyítékokat a sikeres hitelesítés után?", "scope_level": "global" }, # --- 8. GEO & LOCALIZATION --- { "key": "geo_default_country_code", "value": "HU", "category": "geo", "description": "Alapértelmezett országkód a címek normalizálásához", "scope_level": "global" }, { "key": "GEO_ADDRESS_FORMAT_TEMPLATE", "value": "{zip} {city}, {street} {type} {number}.", "category": "geo", "description": "Címformázási sablon (Python string format)", "scope_level": "global" }, { "key": "GEO_SUGGESTION_LIMIT", "value": 15, "category": "geo", "description": "Hány találatot adjon vissza az utca-kiegészítő?", "scope_level": "global" }, # --- 9. ÉRTESÍTÉSI MÁTRIXOK (A granuláris szabályozáshoz) --- { "key": "notification_categories_config", "value": { "insurance": {"mandatory": True, "channels": ["email", "internal"], "label": "Biztosítás lejárat"}, "mot_expiry": {"mandatory": True, "channels": ["email", "internal"], "label": "Műszaki vizsga"}, "personal_id": {"mandatory": True, "channels": ["email", "internal"], "label": "Személyi okmányok"}, "service_due": {"mandatory": False, "channels": ["internal"], "label": "Karbantartási emlékeztető"}, "system_alert": {"mandatory": True, "channels": ["email", "internal"], "label": "Rendszerüzenetek"} }, "category": "notifications", "description": "Értesítési típusok és biztonsági szintek mátrixa", "scope_level": "global" }, { "key": "NOTIFICATION_TYPE_MATRIX", "value": { "insurance": [45, 30, 15, 7, 1, 0], # A kötelező biztosítás kiemelt kezelése! "mot": [30, 14, 7, 1, 0], "personal_id": [60, 30, 15, 0], "default": [30, 7, 1] }, "category": "notifications", "description": "Dokumentum alapú riasztási naptár mátrix", "scope_level": "global" }, # --- 10. FLEET & TELEMETRY --- { "key": "FLEET_EVENT_REWARDS", "value": { "refuel": {"xp": 30, "social": 5}, # Tankolás rögzítése "service": {"xp": 150, "social": 30}, # Szerviz látogatás (értékesebb adat!) "repair": {"xp": 100, "social": 20}, # Javítás "tire_change": {"xp": 40, "social": 5}, # Gumicsere "accident": {"xp": 10, "social": 0}, # Baleset "default": {"xp": 20, "social": 2} }, "category": "fleet", "description": "Eseményenkénti gamifikációs jutalom mátrix", "scope_level": "global" }, { "key": "FLEET_ANOMALY_LOGIC", "value": { "odometer_drop_severity": "critical", "excessive_daily_km": 1500, "flag_unverified_providers": True }, "category": "fleet", "description": "Flotta anomália detekciós küszöbértékek", "scope_level": "global" }, # --- 11. KÜLSŐ API-K (DVLA, UK) --- { "key": "dvla_api_enabled", "value": True, "category": "api_keys", "description": "Engedélyezze-e a brit DVLA lekérdezéseket?", "scope_level": "global" }, { "key": "dvla_api_url", "value": "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles", "category": "api_keys", "description": "Hivatalos DVLA Vehicle Enquiry API végpont", "scope_level": "global" }, { "key": "dvla_api_key", "value": "IDE_JÖN_A_VALÓDI_KULCS", "category": "api_keys", "description": "Bizalmas DVLA API kulcs (X-API-KEY)", "scope_level": "global" }, # --- 12. AI & ROBOTOK (Ollama integráció) --- { "key": "ai_model_text", "value": "qwen2.5-coder:32b", "category": "ai", "description": "Fő technikai elemző modell (Ollama)", "scope_level": "global" }, { "key": "ai_model_vision", "value": "llava:7b", "category": "ai", "description": "Látó modell az OCR folyamatokhoz", "scope_level": "global" }, { "key": "ai_temperature", "value": 0.1, "category": "ai", "description": "AI válasz kreativitása (0.1 = precíz, 0.9 = kreatív)", "scope_level": "global" }, { "key": "ai_prompt_ocr_invoice", "value": "FELADAT: Olvasd ki a számla adatait. JSON válasz: {amount, currency, date, vendor, vat}.", "category": "ai", "description": "Robot 1 - Számla OCR prompt", "scope_level": "global" }, # --- 13. SOCIAL & VERIFIED REVIEWS (Epic 4.1 - #66) --- { "key": "REVIEW_WINDOW_DAYS", "value": 30, "category": "social", "description": "Értékelési időablak napokban a tranzakció után", "scope_level": "global" }, { "key": "TRUST_SCORE_INFLUENCE_FACTOR", "value": 1.0, "category": "social", "description": "Trust‑score súlyozási tényező a szerviz értékeléseknél", "scope_level": "global" }, { "key": "REVIEW_RATING_WEIGHTS", "value": { "price": 0.25, "quality": 0.35, "time": 0.20, "communication": 0.20 }, "category": "social", "description": "Értékelési dimenziók súlyai az összpontszám számításához", "scope_level": "global" }, { "key": "ai_prompt_gold_data", "value": "Készíts technikai adatlapot a(z) {make} {model} típushoz a megadott adatok alapján: {context}. Csak hiteles JSON-t adj!", "category": "ai", "description": "Robot 3 - Technikai dúsító prompt", "scope_level": "global" } ] # <-- ITT HIÁNYZOTT A ZÁRÓJEL! # ---------------------------------------------------------------------- # HIERARCHIKUS KERESÉSI MÁTRIXOK (A SearchService 2.4-hez) # Ezek az értékek felülbírálják az alapértelmezéseket a megfelelő "scope" esetén. # ---------------------------------------------------------------------- # 1. GLOBÁLIS ALAP (Free usereknek) params.append({ "key": "RANKING_RULES", "scope_level": "global", "scope_id": None, "value": { "ad_weight": 8000, "partner_weight": 1000, "trust_weight": 5, "dist_penalty": 40, "can_use_prefs": False, "search_radius_km": 25 }, "category": "search", "description": "Alapértelmezett (Free) rangsorolási szabályok" }) # 2. PREMIUM CSOMAG SZINTŰ BEÁLLÍTÁS (Közepes szint) params.append({ "key": "RANKING_RULES", "scope_level": "package", "scope_id": "premium", "value": { "pref_weight": 10000, "partner_weight": 2000, "trust_weight": 50, "ad_weight": 500, "dist_penalty": 20, "can_use_prefs": True, "search_radius_km": 50 }, "category": "search", "description": "Prémium csomag rangsorolási szabályai" }) # 3. VIP CSOMAG SZINTŰ BEÁLLÍTÁS params.append({ "key": "RANKING_RULES", "scope_level": "package", "scope_id": "vip", "value": { "pref_weight": 20000, # A kedvenc mindent visz "partner_weight": 5000, "trust_weight": 100, # A minőség számít "ad_weight": 0, # VIP-nek nem tolunk hirdetést az élre "dist_penalty": 5, # Alig büntetjük a távolságot "can_use_prefs": True, "search_radius_km": 150 }, "category": "search", "description": "VIP csomag rangsorolási szabályai" }) # 4. EGYÉNI CÉGES FELÜLBÍRÁLÁS (Pl. ProfiBot Flotta Co.) params.append({ "key": "RANKING_RULES", "scope_level": "user", "scope_id": "99", "value": { "pref_weight": 50000, # Nekik csak a saját szerződött partnereik kellenek "can_use_prefs": True, "search_radius_km": 500 # Az egész országot látják }, "category": "search", "description": "Egyedi flotta-ügyfél keresési szabályai" }) logger.info("🚀 Rendszerparaméterek szinkronizálása a 2.0-ás modell szerint...") added_count = 0 updated_count = 0 for p in params: # GONDOLATMENET A JAVÍTÁSHOZ: # Muszáj a scope_level-t és scope_id-t is vizsgálni, különben az SQLAlchemy # összeomlik (MultipleResultsFound), mert ugyanaz a 'key' (pl. RANKING_RULES) # több sorban is szerepel a hierarchia miatt! s_level = p.get("scope_level", "global") s_id = p.get("scope_id", None) stmt = select(SystemParameter).where( SystemParameter.key == p["key"], SystemParameter.scope_level == s_level, SystemParameter.scope_id == s_id ) res = await db.execute(stmt) existing = res.scalar_one_or_none() if not existing: # Új rekord létrehozása new_param = SystemParameter( key=p["key"], value=p["value"], category=p["category"], description=p["description"], scope_level=s_level, scope_id=s_id, last_modified_by=None ) db.add(new_param) added_count += 1 # Azonnali commit, hogy a következő körben már lássa a DB! await db.commit() else: # Csak frissítés, ha szükséges existing.description = p["description"] existing.category = p["category"] updated_count += 1 await db.commit() logger.info(f"✅ Kész! Új: {added_count}, Frissített meta: {updated_count}") if __name__ == "__main__": asyncio.run(seed_params())