Initial commit: Robot ökoszisztéma v2.0 - Stabilizált jármű és szerviz robotok

This commit is contained in:
Kincses
2026-03-04 02:03:03 +01:00
commit 250f4f4b8f
7942 changed files with 449625 additions and 0 deletions

View File

@@ -0,0 +1,53 @@
# /app/tests_internal/diagnostics/check_api.py
import requests
import json
# THOUGHT PROCESS:
# 1. Az API konténeren belül futva a localhost:8000 a célpont.
# 2. Csak olyan végpontokat tesztelünk, amik szerepelnek a v1/api.py-ben.
# 3. A 401/405 kódokat elfogadjuk 'OK'-nak, mert azt jelentik, hogy a szerver
# látja az útvonalat, csak hitelesítést vagy más HTTP metódust vár.
# 4. A 404 azt jelenti, hogy a router nincs jól regisztrálva.
# 5. A 500 azt jelenti, hogy a kód elszállt (pl. AttributeError a main.py-ban).
base_url = 'http://localhost:8000'
# A valós, api.py-ben definiált útvonalak:
tests = [
('Health Check', '/health', 'GET'),
('Auth Login (Entry)', '/api/v1/auth/login', 'POST'), # Létezik
('Catalog Makes', '/api/v1/catalog/makes', 'GET'), # Létezik
('Service Hunt', '/api/v1/services/hunt', 'POST'), # Létezik
('Admin Health', '/api/v1/admin/health-monitor', 'GET'), # Létezik
('My Organizations', '/api/v1/organizations/my', 'GET') # Létezik
]
print('\n--- 🧪 API VÉGPONT DIAGNOSZTIKA ---')
print(f"{'Végpont neve':20} | {'Útvonal':25} | {'Állapot'}")
print("-" * 65)
for name, endpoint, method in tests:
try:
url = f"{base_url}{endpoint}"
# A POST hívásokhoz üres adatot küldünk, hogy ne 422-t kapjunk a hiányzó body miatt
resp = requests.request(method, url, timeout=5, json={})
# Logika:
# 200: Tökéletes
# 401: Él, de login kell (JÓ)
# 405: Él, de pl. GET helyett POST kell (JÓ - az útvonal létezik)
# 422: Él, de hiányoznak a küldött adatok (JÓ - a validáció működik)
if resp.status_code in [200, 401, 405, 422]:
status_msg = f"✅ OK ({resp.status_code})"
elif resp.status_code == 404:
status_msg = f"❌ HIÁNYZIK (404)"
else:
status_msg = f"🔥 SZERVER HIBA ({resp.status_code})"
print(f"{name:20} | {endpoint:25} | {status_msg}")
except Exception as e:
print(f"{name:20} | {endpoint:25} | 🔌 ELÉRHETETLEN")
print("\n💡 Megjegyzés: Ha a Health Check továbbra is 500, az a main.py-ban lévő elírás miatt van.")

View File

@@ -0,0 +1,66 @@
# /opt/docker/dev/service_finder/backend/app/tests_internal/diagnostics/compare_schema.py
import asyncio
import sys
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import inspect
from app.database import Base
from app.core.config import settings
try:
import app.models
except ImportError as e:
print(f"❌ KRITIKUS IMPORT HIBA: {e}")
sys.exit(1)
async def compare():
""" Diagnosztika minden sémára: identity, data, system. """
print(f"🔗 Kapcsolódás az adatbázishoz...")
engine = create_async_engine(str(settings.SQLALCHEMY_DATABASE_URI))
def get_diff(connection):
inspector = inspect(connection)
# Ezeket a sémákat ellenőrizzük
schemas = ["identity", "data", "system"]
all_db_schemas = inspector.get_schema_names()
mismatches = 0
for sc in schemas:
if sc not in all_db_schemas:
print(f"❌ HIBA: A(z) '{sc}' séma nem létezik!")
continue
db_tables = inspector.get_table_names(schema=sc)
# Begyűjtjük a modelleket, amik ehhez a sémához tartoznak
model_tables = [t.name for t in Base.metadata.sorted_tables if t.schema == sc]
print(f"\n--- 🔍 DIAGNOSZTIKA: '{sc}' séma ({len(db_tables)} tábla a DB-ben) ---")
for mt in model_tables:
if mt not in db_tables:
print(f"❌ HIÁNYZÓ TÁBLA: {sc}.{mt}")
mismatches += 1
else:
db_cols = {c['name']: c for c in inspector.get_columns(mt, schema=sc)}
# Kikeressük a modellt a metadata-ból
table_key = f"{sc}.{mt}"
model_cols = Base.metadata.tables[table_key].columns
missing_cols = [m.name for m in model_cols if m.name not in db_cols]
if missing_cols:
print(f"⚠️ {mt:25} | HIÁNYZÓ OSZLOPOK: {missing_cols}")
mismatches += 1
else:
print(f"{mt:25} | Rendben.")
return mismatches
try:
async with engine.connect() as conn:
err_count = await conn.run_sync(get_diff)
print(f"\n--- Összegzés: {err_count} eltérés található. ---\n")
except Exception as e:
print(f"❌ HIBA: {e}")
finally:
await engine.dispose()
if __name__ == "__main__":
asyncio.run(compare())

View File

@@ -0,0 +1,157 @@
# /opt/docker/dev/service_finder/backend/app/tests_internal/diagnostics/diagnose_system.py
"""
🛰️ SENTINEL SYSTEM DIAGNOSTICS - MB2.0 (2026)
---------------------------------------------
CÉL: A rendszer mélyszintű integritásának és működőképességének auditálása.
FŐBB TESZTEK:
1. Adatbázis Kapcsolat: PostgreSQL aszinkron elérés ellenőrzése.
2. Séma Integritás: Kritikus Master Data táblák és mezők meglétének vizsgálata.
3. Rendszer Paraméterek: A Sentinel központi konfigurációs táblájának ellenőrzése.
4. i18n Motor: Nyelvi gyorsítótár (Cache) és fordítási mechanizmus tesztje.
5. Robot Pipeline: Staging (Hunter) és Gold (Catalog) rekordok számlálása.
FUTTATÁS:
docker compose exec api python -m app.tests_internal.diagnostics.diagnose_system
"""
import asyncio
import sys
import logging
from datetime import datetime
from sqlalchemy import text, select, func
# 🛠️ KRITIKUS IMPORT KÖRNYEZET ELLENŐRZÉSE
try:
from app.core.config import settings
# Megjegyzés: A projekt struktúrájától függően AsyncSessionLocal az app.database-ben van
from app.database import AsyncSessionLocal
from app.services.translation_service import translation_service
from app.models.system import SystemParameter
from app.models.identity import User
from app.models.organization import Organization
from app.models.asset import AssetCatalog
from app.models.vehicle_definitions import VehicleModelDefinition
except ImportError as e:
print(f"\n❌ [KRITIKUS HIBA] Az importálás nem sikerült: {e}")
print("💡 Javaslat: Ellenőrizd a PYTHONPATH-t és a __init__.py fájlok meglétét!")
sys.exit(1)
# SQL logolás némítása a tiszta kimenet érdekében
logging.getLogger('sqlalchemy.engine').setLevel(logging.WARNING)
async def diagnose():
start_time = datetime.now()
print("\n" + ""*70)
print(f"🛰️ SENTINEL SYSTEM DIAGNOSTICS - MB2.0 | {start_time.strftime('%Y-%m-%d %H:%M:%S')}")
print(""*70 + "\n")
async with AsyncSessionLocal() as session:
# --- 1. CSATLAKOZÁS ÉS ADATBÁZIS PING ---
print("1⃣ Kapcsolódási teszt...")
try:
await session.execute(text("SELECT 1"))
print(" [✅ OK] PostgreSQL aszinkron kapcsolat aktív.")
except Exception as e:
print(f" [❌ HIBA] Nem sikerült kapcsolódni az adatbázishoz: {e}")
return
# --- 2. SÉMA INTEGRITÁS (Master Data Audit) ---
print("\n2⃣ Séma integritás ellenőrzése (Kritikus mezők)...")
# Tábla neve (sémával) | Elvárt oszlopok listája
tables_to_check = [
("identity.users", ["preferred_language", "scope_id", "is_active"]),
("data.organizations", ["org_type", "folder_slug", "is_active"]),
("data.assets", ["owner_org_id", "catalog_id", "vin"]),
# "asset_catalog" helyett "vehicle_catalog"
("data.vehicle_catalog", ["make", "model", "factory_data"]),
("data.vehicle_model_definitions", ["status", "raw_search_context"])
]
for table, columns in tables_to_check:
try:
schema_name, table_name = table.split('.')
query = text(f"""
SELECT column_name FROM information_schema.columns
WHERE table_schema = '{schema_name}' AND table_name = '{table_name}';
""")
res = await session.execute(query)
existing_cols = [row[0] for row in res.fetchall()]
if not existing_cols:
print(f" [❌ HIBA] A tábla NEM létezik: {table}")
continue
missing = [c for c in columns if c not in existing_cols]
if not missing:
print(f" [✅ OK] {table:35} (Minden mező rendben)")
else:
print(f" [⚠️ HIÁNY] {table:35} | Hiányzó mezők: {', '.join(missing)}")
except Exception as e:
print(f" [❌ HIBA] Hiba a(z) {table} ellenőrzésekor: {e}")
# --- 3. RENDSZER PARAMÉTEREK (Sentinel Config) ---
print("\n3⃣ System Parameters (Sentinel Config) ellenőrzése...")
try:
res = await session.execute(select(SystemParameter))
params = res.scalars().all()
if params:
print(f" [✅ OK] Talált paraméterek: {len(params)} db")
# Kritikus kulcsok, amiknek illik lenniük
critical_keys = ["SECURITY_MAX_RECORDS_PER_HOUR", "VEHICLE_LIMIT"]
existing_keys = [p.key for p in params]
for ck in critical_keys:
status = "✔️" if ck in existing_keys else "❌ (Hiányzik)"
print(f" {status} {ck}")
else:
print(" [⚠️ FIGYELEM] A system_parameters tábla üres! Futtasd a seedert.")
except Exception as e:
print(f" [❌ HIBA] SystemParameter lekérdezési hiba: {e}")
# --- 4. i18n ÉS CACHE MOTOR ---
print("\n4⃣ Nyelvi motor és i18n Cache ellenőrzése...")
try:
# Gyorsítótár frissítése az adatbázisból
await translation_service.load_cache(session)
test_key = "COMMON.SAVE"
test_val = translation_service.get_text(test_key, "hu")
# Ha a visszakapott érték nem egyezik a kulccsal, akkor van fordítás
if test_val and test_val != f"[{test_key}]":
print(f" [✅ OK] Fordítás sikeres (HU): '{test_key}' -> '{test_val}'")
else:
print(f" [❌ HIBA] Fordítás nem működik. Nincs betöltött adat vagy hibás a cache.")
except Exception as e:
print(f" [❌ HIBA] Nyelvi motor hiba: {e}")
# --- 5. ROBOT ELŐKÉSZÜLETEK (Pipeline MDM) ---
print("\n5⃣ Robot Pipeline (MDM Staging) állapot...")
try:
# Hunter robot eredményei (nyers adatok)
res_hunter = await session.execute(
select(func.count(VehicleModelDefinition.id)).where(VehicleModelDefinition.status == 'unverified')
)
unverified_count = res_hunter.scalar() or 0
# Catalog robot eredményei (tisztított adatok)
res_gold = await session.execute(select(func.count(AssetCatalog.id)))
gold_count = res_gold.scalar() or 0
print(f" [📊 STAT] Feldolgozatlan rekordok (Staging): {unverified_count} db")
print(f" [📊 STAT] Validált arany rekordok (Catalog): {gold_count} db")
except Exception as e:
print(f" [❌ HIBA] Robot-statisztika hiba: {e}")
duration = (datetime.now() - start_time).total_seconds()
print("\n" + ""*70)
print(f"🏁 DIAGNOSZTIKA BEFEJEZŐDÖTT | Időtartam: {duration:.2f} mp")
print(""*70 + "\n")
if __name__ == "__main__":
try:
asyncio.run(diagnose())
except KeyboardInterrupt:
print("\n🛑 Diagnosztika megszakítva a felhasználó által.")
sys.exit(0)