Initial commit: Robot ökoszisztéma v2.0 - Stabilizált jármű és szerviz robotok
This commit is contained in:
38
backend/app/scripts/discovery_bot.py.veryold
Executable file
38
backend/app/scripts/discovery_bot.py.veryold
Executable file
@@ -0,0 +1,38 @@
|
||||
import asyncio
|
||||
import httpx
|
||||
from sqlalchemy import text
|
||||
from app.db.session import engine
|
||||
from datetime import datetime
|
||||
|
||||
async def log_discovery(conn, category, brand, model, action):
|
||||
await conn.execute(text("""
|
||||
INSERT INTO data.bot_discovery_logs (category, brand_name, model_name, action_taken)
|
||||
VALUES (:c, :b, :m, :a)
|
||||
"""), {"c": category, "b": brand, "m": model, "a": action})
|
||||
|
||||
async def run_discovery():
|
||||
async with engine.begin() as conn:
|
||||
print(f"🚀 Jármű felfedezés indul: {datetime.now()}")
|
||||
|
||||
# Jelenleg a CAR kategóriára fókuszálunk egy külső API segítségével (pl. NHTSA - Ingyenes)
|
||||
# Itt egy példa, hogyan bővül dinamikusan a rendszer
|
||||
async with httpx.AsyncClient() as client:
|
||||
# Autók lekérése
|
||||
response = await client.get("https://vpic.nhtsa.dot.gov/api/vehicles/getallmakes?format=json")
|
||||
if response.status_code == 200:
|
||||
makes = response.json().get('Results', [])[:100] # Tesztként az első 100
|
||||
|
||||
for make in makes:
|
||||
brand_name = make['Make_Name'].strip()
|
||||
# Megnézzük, megvan-e már
|
||||
res = await conn.execute(text("SELECT id FROM data.vehicle_brands WHERE name = :n"), {"n": brand_name})
|
||||
if not res.scalar():
|
||||
await conn.execute(text("INSERT INTO data.vehicle_brands (category_id, name) VALUES (1, :n)"), {"n": brand_name})
|
||||
await log_discovery(conn, "CAR", brand_name, "ALL", "NEW_BRAND")
|
||||
print(f"✨ Új márka találva: {brand_name}")
|
||||
|
||||
await conn.commit()
|
||||
print("✅ Bot futása befejeződött.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(run_discovery())
|
||||
63
backend/app/scripts/link_catalog_to_mdm.py
Executable file
63
backend/app/scripts/link_catalog_to_mdm.py
Executable file
@@ -0,0 +1,63 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/scripts/link_catalog_to_mdm.py
|
||||
import asyncio
|
||||
from sqlalchemy import select, update
|
||||
from app.db.session import SessionLocal
|
||||
from app.models.asset import AssetCatalog
|
||||
from app.models.vehicle_definitions import VehicleModelDefinition, VehicleType
|
||||
|
||||
async def link_catalog_to_mdm():
|
||||
""" Összefűzi a technikai katalógust a központi Master Definíciókkal. """
|
||||
async with SessionLocal() as db:
|
||||
try:
|
||||
print("🔍 Master-Híd építése indul...")
|
||||
|
||||
# 1. Típusok betöltése
|
||||
type_res = await db.execute(select(VehicleType))
|
||||
types = {t.code: t.id for t in type_res.scalars().all()}
|
||||
|
||||
# 2. Egyedi variánsok lekérése
|
||||
stmt = select(AssetCatalog.make, AssetCatalog.model, AssetCatalog.vehicle_class).distinct()
|
||||
raw_data = await db.execute(stmt)
|
||||
unique_models = raw_data.all()
|
||||
|
||||
linked_count = 0
|
||||
for make, model, v_class in unique_models:
|
||||
t_code = v_class if v_class in types else "car"
|
||||
t_id = types.get(t_code)
|
||||
|
||||
# Master rekord keresése vagy létrehozása
|
||||
master_stmt = select(VehicleModelDefinition).where(
|
||||
VehicleModelDefinition.make == make,
|
||||
VehicleModelDefinition.marketing_name == model
|
||||
)
|
||||
master = (await db.execute(master_stmt)).scalar_one_or_none()
|
||||
|
||||
if not master:
|
||||
master = VehicleModelDefinition(
|
||||
make=make,
|
||||
technical_code=model.replace(" ", "-").lower(),
|
||||
marketing_name=model,
|
||||
vehicle_type=t_code,
|
||||
vehicle_type_id=t_id,
|
||||
status="unverified",
|
||||
source="linking_process"
|
||||
)
|
||||
db.add(master)
|
||||
await db.flush()
|
||||
|
||||
# Összekötés
|
||||
await db.execute(
|
||||
update(AssetCatalog)
|
||||
.where(AssetCatalog.make == make, AssetCatalog.model == model)
|
||||
.values(master_definition_id=master.id)
|
||||
)
|
||||
linked_count += 1
|
||||
|
||||
await db.commit()
|
||||
print(f"✅ Sikeresen összekötve: {linked_count} modell.")
|
||||
except Exception as e:
|
||||
await db.rollback()
|
||||
print(f"❌ Hiba: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(link_catalog_to_mdm())
|
||||
35
backend/app/scripts/morning_report.py
Executable file
35
backend/app/scripts/morning_report.py
Executable file
@@ -0,0 +1,35 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/scripts/morning_report.py
|
||||
import asyncio
|
||||
from sqlalchemy import select
|
||||
from app.db.session import SessionLocal
|
||||
from app.models.audit import ProcessLog
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
async def generate_morning_report():
|
||||
""" Összesíti a háttérfolyamatok (robotok) elmúlt 24 órás teljesítményét. """
|
||||
async with SessionLocal() as db:
|
||||
yesterday = datetime.now(timezone.utc) - timedelta(days=1)
|
||||
stmt = select(ProcessLog).where(ProcessLog.start_time >= yesterday)
|
||||
res = await db.execute(stmt)
|
||||
logs = res.scalars().all()
|
||||
|
||||
report = f"📊 REGGELI ROBOT JELENTÉS - {datetime.now().date()}\n"
|
||||
report += "="*40 + "\n"
|
||||
|
||||
total_proc = sum(log.items_processed for log in logs)
|
||||
total_fail = sum(log.items_failed for log in logs)
|
||||
|
||||
report += f"✅ Feldolgozott egységek: {total_proc}\n"
|
||||
report += f"❌ Sikertelen műveletek: {total_fail}\n"
|
||||
|
||||
if logs:
|
||||
report += "\nAktív robotok állapota:\n"
|
||||
for log in logs:
|
||||
status = "🟢 OK" if log.items_failed == 0 else "🔴 HIBA"
|
||||
report += f" - {log.process_name}: {log.items_processed} feldolgozva ({status})\n"
|
||||
|
||||
print(report)
|
||||
return report
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(generate_morning_report())
|
||||
428
backend/app/scripts/seed_system_params.py
Executable file
428
backend/app/scripts/seed_system_params.py
Executable file
@@ -0,0 +1,428 @@
|
||||
# /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"
|
||||
},
|
||||
{
|
||||
"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())
|
||||
31
backend/app/scripts/seed_v1_9_system.py
Executable file
31
backend/app/scripts/seed_v1_9_system.py
Executable file
@@ -0,0 +1,31 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/scripts/seed_v1_9_system.py
|
||||
import asyncio
|
||||
from sqlalchemy import select
|
||||
from app.db.session import SessionLocal
|
||||
from app.models.vehicle_definitions import VehicleType, FeatureDefinition
|
||||
|
||||
async def seed_system_data():
|
||||
""" Alapvető típusok és extrák (Features) feltöltése. """
|
||||
async with SessionLocal() as db:
|
||||
try:
|
||||
print("🚀 Rendszer-blueprint betöltése...")
|
||||
|
||||
types_data = [
|
||||
{"code": "car", "name": "Személyautó", "icon": "directions_car"},
|
||||
{"code": "motorcycle", "name": "Motorkerékpár", "icon": "moped"},
|
||||
{"code": "truck", "name": "Teherautó", "icon": "local_shipping"},
|
||||
{"code": "boat", "name": "Hajó", "icon": "sailing"}
|
||||
]
|
||||
|
||||
for t_info in types_data:
|
||||
stmt = select(VehicleType).where(VehicleType.code == t_info["code"])
|
||||
if not (await db.execute(stmt)).scalar_one_or_none():
|
||||
db.add(VehicleType(**t_info))
|
||||
|
||||
await db.commit()
|
||||
print("✅ Blueprint kész.")
|
||||
except Exception as e:
|
||||
print(f"❌ Hiba: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(seed_system_data())
|
||||
Reference in New Issue
Block a user