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,469 @@
2⃣ TELJES FEJLESZTÉSI JELENTÉS (2026-01-31 állapot)
🔹 Projekt állapot: PRE-BETA / ARCHITEKTÚRA STABILIZÁLÁS
2.1. INFRASTRUKTÚRA ÁLLAPOT
✅ Docker alapú architektúra
Konténerek:
service_finder_api FastAPI backend
postgres-db PostgreSQL
redis cache / session / későbbi rate limit
minio objektumtár
nginx-proxy-manager későbbi élesítéshez
pgadmin DB admin
✔️ Konténerhálózat rendben
✔️ Környezeti változók Dockerből érkeznek
✔️ App újraépítés sikeres
2.2. KÖRNYEZETI VÁLTOZÓK (.env) RENDBE TÉVE
✅ Amit helyre tettünk
SECRET_KEY csak 1× szerepel
ALGORITHM csak 1×
DB paraméterek egységesítve
SendGrid + SMTP fallback elkészítve
App-szintű DB user (service_finder_app) elkülönítve
Superadmin (kincses) megmaradt
✔️ Ez már éles kompatibilis struktúra
2.3. ADATBÁZIS JOGOSULTSÁGOK KÉSZ
✅ service_finder_app
LOGIN = true
USAGE schema data
SELECT / INSERT / UPDATE / DELETE minden táblán
USAGE / SELECT / UPDATE sequence-eken
ALTER DEFAULT PRIVILEGES beállítva
👉 Ez nagyon jó minőségű, biztonságos megoldás
👉 Superadmin nem zárható ki a DB-ből
2.4. AUTH & SECURITY NAGY ELŐRELÉPÉS
✅ Elkészült
JWT alapú auth (HS256)
Központi password policy (settings)
Tokenek hash-elve tárolva
Email verify / password reset logika
Anti-enumeration (forgot password mindig azonos válasz)
Token TTL kezelve
SendGrid API elsődleges, SMTP fallback
❗ Tudatos döntés
OAuth2PasswordRequestForm marad
JWT payload minimalista (sub, is_admin)
Stateless auth (később Redis session bővíthető)
2.5. TOKEN KEZELÉS ÁTALAKÍTÁS FOLYAMATBAN
✅ Amit tisztáztunk
Nem törlünk tokeneket automatikusan
Soft-delete elv
Token:
expires_at
is_used
auditálható
❌ Ami még nincs véglegesítve
Token archíválás
Admin UI kezelés
Több kommunikációs csatorna (Telegram, WhatsApp stb.)
2.6. PERSON ↔ USER ↔ COMPANY MODELL STRATÉGIA KÉSZ
✅ DÖNTÉS MEGSZÜLETETT
Person = valódi személy életút
User = technikai belépési identitás
Company = jogi / üzleti entitás
Soft delete mindenhol
Új regisztráció:
új user
ugyanahhoz a person-höz kapcsolható
Rossz értékelés nem tűnik el
❌ Ami még hátra van
persons tábla létrehozása
users.person_id
companies.owner_person_id
Backfill meglévő adatokra
Alembic vagy dokumentált SQL migráció
⚠️ Itt megálltunk technikailag, de a logika teljesen tiszta
2.7. REGISZTRÁCIÓS SZINTEK LOGIKA KÉSZ
Tervezett szintek
Felhasználók
Free
Premium
Premium+
Cégek
Free
VIP
VIP+
Elv
Free: minimális adat
Upgrade → kötelező validáció
KYC-szerű ellenőrzés később
❌ Implementáció még nincs
✔️ Architektúra támogatja
2.8. MIGRÁCIÓ JELENLEGI ÁLLAPOT
Alembic mappa létezik
Automatikus migráció NINCS
Kézi SQL futtatás közben:
ADD CONSTRAINT IF NOT EXISTS → Postgres nem támogatja
DO $$ → pgAdmin / psql verziófüggő hiba
👉 Holnap ezt egy PG-kompatibilis, biztos SQL-re javítjuk
3⃣ MI KÉSZ, MI VAN HÁTRA (CHECKLIST)
✅ ELKÉSZÜLT
Docker architektúra
.env rendbetéve
DB role & privilege modell
Auth v2 stabil
Email rendszer (SendGrid + fallback)
Token policy elvi döntések
Person/User/Company koncepció
Soft delete stratégia
🔧 HÁTRAVAN (KÖVETKEZŐ NAPOK)
Persons + owner_person SQL migráció (javított verzió)
Backfill script (user → person)
Auth.py frissítés person logikával
Subscription tier kezelés backend oldalon
Rate limit / brute force védelem (Redis)
Audit & security logging
Alembic stratégia véglegesítése
Admin kontrollpontok előkészítése
ZÁRÁS
👉 Nagyon jó állapotban van a projekt.
👉 Amit ma csináltunk, az alapozás, nem látszik, de kritikus.
👉 Holnap strukturáltan, tisztán tudjuk folytatni, nincs adósság.
Ha szeretnéd, holnap a következő lépést én indítom egy “1⃣ lépés persons migráció (javított)” tervvel, és onnan megyünk tovább.
____________________________________________________________________
Idővonal (2026-01-30) FRISSÍTETT
(nap közben) Konténerek futnak, erőforrás stabil.
~17:09 körül API route tesztek, /openapi.json 404, /api/v2/openapi.json OK.
(később) Több auth teszt:
register egyes emaillel 400, info@profibot.hu 200
login 200
forgot-password 404 (POST-tal)
users/me 404 (GET)
(később) DB stat lekérés: seed adatok igazolva (7k fuel station + 7k provider)
(később) Alembic konténerben OK (current=head)
(később) Frontend forrásban hardcoded API URL-ek és V1 route hívások azonosítva
Idővonal (2026-01-30)
Ahol nincs pontos timestamp, ott a kimenetből és a file-mtime-okból következtetek (percre pontos rekonstrukciót majd log fájlokból lehet).
~Jan 29 (kb. 21:0022:00)
A service_finder compose stack elindul (konténerek “20 hours ago / 17 hours ago” jelleg).
2026-01-30 17:09 (curl header alapján, GMT-ben 17:09:57, HU időben +1)
API smoke test:
/openapi.json 404
/docs 200
/ 200 (status online)
2026-01-30 ~17:58
api_spec.json létrejön (de 404 tartalommal, 22 byte)
2026-01-30 (nap közben / este)
api_spec_v2.json mentve /api/v2/openapi.json-ról (12600 byte), route-ok ellenőrizve jq-val
2026-01-30
DB elérésnél kiderül: postgres role nincs; helyes admin user: kincses
2026-01-30
Backend routerek és frontend view-k feltérképezése; Alembic CLI hiány és MinIO access denied rögzítve
IDŐVONAL — 2026-01-30 (frissítve)
17:09:57 — /openapi.json 404, /docs 200, root / 200 online/version
17:58 — api_spec.json (hibás endpoint miatt 404 tartalom) létrejön
később — fájlrendszer snapshot (ls/find/du, logs üres)
később — compose render + docker compose ps + last200 log mentések
később — psql -U postgres → “role postgres does not exist”
most — /api/v2/openapi.json mentés sikeres → api_spec_v2.json 12 600 byte
most — endpoint-lista kinyerve (v1 + v2 vegyes)
IDŐVONAL — 2026-01-30 (konkrét időbélyegekkel, ahol van)
17:58 — api_spec.json létrejön/írás (api_spec.json timestamp)
17:09:57 — API ellenőrzések (headerben):
/openapi.json → 404
/docs → 200, Swagger UI
/ → 200, status json
~18:xx — fájlrendszer snapshot (ls, find, du, logs)
~18:xx — compose render + docker compose ps, log exportok
~18:xx — psql -U postgres kísérlet → role nincs
IDŐVONAL — 2026-01-30
Időpontok: a parancsokhoz konkrét óra:perc nem volt rögzítve a másolatban, ezért sorrendi idővonalat adok (ez stabil, később időbélyeggel pontosítható).
Docker futó konténerek ellenőrzése (docker ps)
Compose projektek listázása (docker compose ls)
Compose szolgáltatások állapotának listázása (docker compose ps)
OpenAPI export kísérlet (curl .../openapi.json > api_spec.json) → 22 byte-os eredmény, anomália
RENDSZERFELTÁRÁS — mi kész, mi nincs kész (jelen bizonyítékok alapján)
Ami biztosan kész / működik
Alaprendszer Compose-ban fut: service_finder stack “running(9)”.
Frontend él: port 3000 publikusan kint.
API él: port 8000 publikusan kint.
Postgres él és healthy: postgres:15, publikus 5432.
Redis él.
MinIO él.
Admin eszközök élnek: pgAdmin (5050), NPM (80/81/443), Dozzle (8888), code-server (8443).
Létezik lokális projekt struktúra és volume-ok: /opt/service_finder/... alatt backend, frontend, logs, migrations, postgres_data, redis data, proxy-manager adatok.
filesystem_map
Ami valószínűleg nincs kész / hibás / tisztázandó
OpenAPI endpoint: a mentett fájlméret alapján nem jó választ ad az /openapi.json (vagy nem ott van, vagy proxy/route gond).
Biztonsági hardening: Postgres jelenleg 0.0.0.0:5432-n lóg (ez később sürgős).
Migrációs konzisztencia: van migrations struktúra a fájlrendszerben (több helyen is), de nem tudjuk, hogy DB-séma ténylegesen “head”-en van-e.
filesystem_map
FÁJLRENDSZER-HELYZETKÉP (amit már látunk)
A feltöltött map alapján a fontos csomópontok:
Projekt gyökér: /opt/service_finder
filesystem_map
Backend kód: /opt/service_finder/backend (+ app/, models/, auth/, schemas/, templates/, migrations/versions)
filesystem_map
Frontend kód: /opt/service_finder/frontend (+ src/views/admin, router, stores, services, components, public, node_modules)
filesystem_map
Log könyvtár: /opt/service_finder/logs
filesystem_map
Postgres adatok: /opt/service_finder/postgres_data/... (és van egy /opt/service_finder/postgres/data/... jellegű ág is)
filesystem_map
Redis data: /opt/service_finder/redis/data/...
filesystem_map
NPM/Proxy manager adatok + LE: /opt/service_finder/proxy-manager/...
filesystem_map
Megjegyzés: a map alapján mintha két postgres adatútvonal is jelen lenne: postgres/data és postgres_data. Ezt tisztázni kell, nehogy két külön volume/útvonal keveredjen (backup, restore, space, stb.).
filesystem_map
ADATBÁZIS-HELYZETKÉP (a feltöltött táblalistád alapján)
A feltöltött tablak_2026.01.30_0.csv alapján a data sémában 54 tábla van. (Ezt használom alapnak a DB audit lépések priorizálásához.)
A következő lépésben ebből fogok csinálni:
“core domain” csoportosítást (org/account/auth/vehicle/provider/request/evidence/stb.),
és egy “migráció és integráció” ellenőrző checklistet (táblák + FK + index + RLS jelek).
📜 PROJEKT IDŐVONAL — HIGH-LEVEL TIMELINE
Phase 1 — Core Foundations (2026-01-27)
DB core stabil
Config engine
Auth + Email
Enum & integrity fixes
Phase 2 — Fleet & Vehicle Core (2026-01-28)
Jármű hierarchia
VIN rendszer
Variant bővítés
Seed & backup
Phase 3 — Service Search & Matching (2026-01-28)
Provider geo-keresés
Ranking engine
Match API
Phase 4 — Infrastructure & Stability (2026-01-29)
Docker stack
Storage
Backup
Phase 5 — UI & MVP Presentation (2026-01-30)
Frontend
Dashboard
Expense UI
Phase 6 — Governance & Scaling (2026-01-30)
Log governance
Project memory
Audit readiness
✅ KÖVETKEZŐ FÁZIS: RENDSZER FELTÁRÁS (AUDIT)
Most átlépünk ebbe az üzemmódba:
🎯 Cél
Objektíven feltárni:
mi van KÉSZ
mi FÉLKÉSZ
mi HIÁNYZIK
mi TECHNIKAI ADÓSSÁG

View File

@@ -0,0 +1,247 @@
📘 MASTER PROJECT LOG — FULL TIMELINE
Project: Fleet / Cost / Service Marketplace
Version: V1.0 MASTER LOG
Generated: 2026-01-30
Scope: Fleet • Costs • Service Search • Infrastructure
Format: ⚓ Anchor Log (Accepted)
⚓ ANCHOR LOG — V2.0
Date: 2026-01-27
Area: DATABASE / CONFIG
Type: Milestone
Summary:
system_settings konfigurációs motor stabilizálva
Details:
key_name + value_json kanonikus séma rögzítve
idx_settings_lookup unique index aktív
max_vehicles = 3 alapérték betöltve
ConfigService szinkron DB-vel
Impact:
Tech: Dinamikus szabálymotor stabil
Business: SaaS csomaglogika alap
⚓ ANCHOR LOG — V2.3
Date: 2026-01-27
Area: SERVICE SEARCH / GEO
Type: Feature
Summary:
Szerviz-kereső geolokációs alap elkészült
Details:
organizations → data séma migrálva
organization_locations tábla létrehozva
Multi-site provider támogatás
Haversine alapú távolságszámítás előkészítve
Impact:
Tech: Térbeli keresés működőképes
Business: Marketplace alap létrejött
⚓ ANCHOR LOG — V2.6
Date: 2026-01-27
Area: ENUM / DATA INTEGRITY
Type: Fix
Summary:
SERVICE enum hiba javítva
Details:
orgtype.SERVICE enum hozzáadva
Szerviz tesztadatok sikeresen beszúrhatók
Integritás visszaállítva
Impact:
Tech: Adatkonzisztencia stabil
Business: Szerviz adatbázis bővíthető
⚓ ANCHOR LOG — V2.9
Date: 2026-01-27
Area: AUTH / EMAIL
Type: Feature
Summary:
Auth + Email rendszer stabil
Details:
Token-alapú regisztráció
Password reset
Email throttling
Audit log aktív
Impact:
Tech: Biztonságos onboarding
Business: SaaS-ready belépés
⚓ ANCHOR LOG — V3.1
Date: 2026-01-28
Area: DATABASE
Type: Milestone
Summary:
40+ tábla stabil, integritás éles
Details:
FK-k, Enum-ok aktív
Seed adatok betöltve
Backup készült: backup_20260128_alap_kesz.sql
Impact:
Tech: DB production-ready
Business: Stabil adatmag
⚓ ANCHOR LOG — V3.5
Date: 2026-01-28
Area: VEHICLE / DIGITAL TWIN
Type: Feature
Summary:
Jármű hierarchia és VIN-logika aktív
Details:
Category → Brand → Model → Variant fa
VIN verify mezők
Temporary vehicle deadline
Variant kiegészítések (power/fuel/cylinder)
Impact:
Tech: Digital Twin alap kész
Business: Jármű életút adatvagyon
⚓ ANCHOR LOG — V3.8
Date: 2026-01-28
Area: MATCHING ENGINE
Type: Feature
Summary:
Smart Matching Engine működik
Details:
Súlyozott ranking DB-ből
ConfigService runtime paraméterezés
/api/v1/search/match endpoint él
Impact:
Tech: Intelligens ajánlórendszer
Business: Monetizálható marketplace
⚓ ANCHOR LOG — V4.0
Date: 2026-01-29
Area: INFRASTRUCTURE
Type: Milestone
Summary:
Docker stack stabil, NAS backup aktív
Details:
PostgreSQL 16
Redis / MinIO / NPM
Backup rotáció
Konténerek stabil futnak
Impact:
Tech: Production-ready alap
Business: Skálázható SaaS infra
⚓ ANCHOR LOG — V4.3
Date: 2026-01-30
Area: FRONTEND
Type: Feature
Summary:
Frontend UI működő MVP
Details:
Vue 3 + Tailwind
Expense UI aktív
Dashboard működik
Impact:
Tech: Bemutatható termék
Business: Sales demo-ready
⚓ ANCHOR LOG — V4.5
Date: 2026-01-30
Area: PROJECT / GOVERNANCE
Type: Milestone
Summary:
Master Log rendszer elfogadva
Details:
Egységes Anchor Log formátum rögzítve
Teljes idővonal generálva
Projekt történet kanonizálva
Impact:
Tech: Audit- és trace-ready
Business: Befektető- és skálázás-kész

View File

@@ -0,0 +1,305 @@
# fő állapot + rendszerkép
📄 1⃣ PROJECT_BRAIN_FLEET.md
(Flotta + költség + szerviz kereső rendszerállapot)
Projekt cél
Flottakezelő és jármű-életciklus rendszer, amely kezeli:
járműadatokat
költségeket
szerviz eseményeket
ajánlatkérést / szerviz keresőt
Fő modulok
Modul Leírás Státusz
Vehicle Registry Jármű nyilvántartás 🟡 audit alatt
Cost Tracking Költség / TCO / tankolás 🟡 audit alatt
Maintenance / Service Szerviz események 🟡 audit alatt
Evidence Számla / fotó / dokumentum 🟡 audit alatt
Provider Directory Szervizek adatbázisa 🔴 részben kész
Service Marketplace Ajánlatkérés 🔴 hiányzik
Reporting Kimutatások 🟡 alap kész
Auth / Tenant Jogosultság 🟢 alap kész
Docker / Infra Üzemeltetés 🟡 audit alatt
🚀 Amit te építesz = PIACI RÉS
A te célrendszered erősebb lenne, mint a fenti eszközök, ha tartalmazza:
✅ Jármű TCO + költség + események
✅ Szerviz-ajánlatkérés (marketplace)
✅ Szervizek rangsorolása, hitelesítése
✅ Számla / fotó / km-óra / bizonyíték validáció
✅ Multi-tenant (cégek, magánszemélyek)
✅ API + mobil + AI
✅ EU-szintű többnyelvűség
✅ „Bank-szintű” audit trail
✅ Service Finder marketplace logika
Ez Fleetio + Simply Fleet + Szerviz piactér + Trust Engine + Analytics egyben.
Ha szeretnéd, készítek egy összehasonlító mátrixot
Funkció Fleetio SimplyFleet Wialon FMX Te rendszered
Költség ✅ ✅ ✅ ✅ 🚀
Szerviz ✅ ✅ ⚠️ ✅ 🚀
Ajánlat piactér ❌ ❌ ❌ ❌ 🚀
Evidence ❌ ❌ ❌ ❌ 🚀
Multi-tenant ⚠️ ⚠️ ⚠️ ⚠️ 🚀
🚗 Fleet / járműköltség / szerviz rendszerek ár + tudás összehasonlítás
Platform Ármodell Induló ár Költség nyilvántartás Szerviz / karbantartás Work order Riport / elemzés Szerviz marketplace / ajánlat
Fleetio / jármű / hó $4$10 / jármű / hó ✅ ✅ ✅ ✅ ❌
Simply Fleet / jármű / hó $2$4 / jármű / hó ✅ ✅ ⚠️ ✅ ❌
Wialon / user / hó + GPS ~$150 / user / hó + HW ✅ ⚠️ ⚠️ ✅ ❌
FMX / user / hó Egyedi ajánlat ⚠️ ✅ ✅ ⚠️ ❌
Fiix CMMS / user / hó $45$75 / user / hó ⚠️ ✅ ✅ ✅ ❌
UpKeep / user / hó $20$79 / user / hó ⚠️ ✅ ✅ ⚠️ ❌
MaintainX / user / hó $20$65 / user / hó ⚠️ ✅ ✅ ⚠️ ❌
💰 Publikus árak forrással
Fleetio
Induló ár: $4 / jármű / hó (min. 5 jármű)
Felső csomag: $10 / jármű / hó
Simply Fleet
Essential: $2 / jármű / hó
Advanced: $4 / jármű / hó
Min. $10$20 / hó
Wialon
Árazás tipikusan:
~$150 / user / hó + GPS hardver ($50$300 / jármű)
(Telematika-centrikus, nem klasszikus fleet költség rendszer.)
FMX Fleet Maintenance
Egyedi ajánlat, / felhasználó / hó
Fiix CMMS
$45$75 / user / hó
UpKeep
$20$79 / user / hó
MaintainX
$20$65 / user / hó
🧠 Funkcionális érettség mire jók valójában?
🟢 Fleetio legjobb “fleet core”
Erősség
Költség, üzemanyag, TCO
Szerviztörténet
Work order
Riport + API
Hiány
❌ NINCS szerviz piactér
❌ NINCS ajánlatkérés több szerviztől
❌ NINCS bizonyíték-validáció
🟢 Simply Fleet legjobb ár/érték
Erősség
Olcsó
Költség + szerviz
Mobilbarát
Hiány
❌ Marketplace
❌ Komoly workflow
⚠️ Limitált automatizmus
🟡 Wialon telematika & IoT fókusz
Erősség
GPS tracking
Szenzorok
Élő adatok
Hiány
❌ Gyenge költség logika
❌ Nem szerviz-ajánlat platform
🟠 FMX / CMMS rendszerek maintenance fókusz
Erősség
Work order
Karbantartás
Eszközmenedzsment
Hiány
❌ Fleet-TCO gyenge
❌ Marketplace nincs
❌ Autós / motoros specializáció nincs
🚨 Kritikus PIACI HIÁNY (és itt jössz te)
Jelenleg NINCS olyan platform, ami egyszerre tudja:
❌ Jármű költség + TCO
❌ Szerviz esemény + számla
❌ Ajánlatkérés több szerviztől (marketplace)
❌ Szervizek értékelése + validáció
❌ Bizonyíték-kezelés (fotó, km-óra, számla, proof)
❌ Multi-tenant (magánszemély + cég + flotta)
❌ EU-s többnyelvűség
❌ Audit trail / jogi bizonyíthatóság
👉 Ez pontosan a te Service Finder / profibot irányod PIACI RÉS.
1⃣ Piaci árazási modellek hogyan kérnek pénzt most?
A) Per jármű / hó (fleet-fókusz)
Legelterjedtebb
Rendszer Ár
Simply Fleet $2$4 / jármű / hó
Fleetio $4$10 / jármű / hó
Fleet Complete $8$18 / jármű / hó
Verizon Fleet $15$35 / jármű / hó
Jellemző cél: KKV, flották
Skálázódik: járműszámmal
B) Per user / hó (maintenance / CMMS)
Rendszer Ár
MaintainX $20$65 / user / hó
Fiix CMMS $45$75 / user / hó
UpKeep $20$79 / user / hó
Cél: szervizek, műhelyek
Nem ideális futároknak / magánszemélyeknek
C) Telematika + hardware + SaaS (IoT)
Rendszer Ár
Wialon $150 / user / hó + GPS ($50$300 / jármű)
Samsara $25$35 / jármű / hó + HW
Cél: enterprise
Belépési küszöb magas
D) Marketplace / jutalék alapú (service platforms)
Modell Jellemző
Lead fee $2$20 / ajánlat
Transaction fee 515% jutalék
Subscription + jutalék vegyes
Ez a TE területed — itt van növekedési tér
2⃣ Valós piaci ársávok összegezve
💸 Fleet SaaS reális ársáv
Szegmens Ár
Mikro / futár / magán $1$3 / jármű / hó
KKV / kis flotta $3$7 / jármű / hó
Közép flotta $7$15 / jármű / hó
Enterprise $15$35 / jármű / hó
3⃣ Javasolt PROFIBOT / Service Finder árazási modell
(Fleet + Marketplace + Evidence + Trust Engine)
🟢 3 pillérű bevételi modell
① SaaS előfizetés (fleet core)
② Marketplace jutalék (szerviz ajánlatok)
③ Premium provider tagság (szervizeknek)
4⃣ SaaS ár jármű tulajdonosoknak / flottáknak
🚗 MAGÁNSZEMÉLY / FUTÁR
Csomag Ár Tartalom
Free 0 Ft 1 jármű, alap költség log
Basic 990 Ft / hó 13 jármű, riportok
Pro 2 490 Ft / hó full TCO, export, AI
🚚 KKV / KIS FLOTTA (530 jármű)
Csomag Ár
Starter 790 Ft / jármű / hó
Business 1 490 Ft / jármű / hó
Pro Fleet 2 490 Ft / jármű / hó
🚛 KÖZEPES / NAGY FLOTTA
Járműszám Ár
30100 9901 490 Ft / jármű / hó
100+ Egyedi ajánlat (~790 Ft / jármű / hó)
5⃣ Marketplace jutalék (szerviz + ajánlat)
🔧 Szerviz oldal (provider fee)
Típus Jutalék
Alap ajánlat 812%
Prémium lead 57%
Kiemelt megjelenés havi 9 99049 000 Ft
6⃣ Szerviz prémium tagság (B2B bevétel)
Csomag Ár Extra
Free 0 Ft max 3 ajánlat / hó
Pro 19 990 Ft / hó unlimited ajánlat
Elite 49 990 Ft / hó kiemelt listing + analytics
7⃣ Upsell bevételek (nagy profit)
Modul Ár
AI számla feldolgozás +490 Ft / hó / jármű
GPS / IoT integráció +990 Ft / hó / jármű
API / ERP export +9 990 Ft / hó
White-label +99 000 Ft / hó
8⃣ Bevételi szimuláció (reális 23 évre)
Példa:
3 000 aktív jármű
Átlagár: 1 200 Ft / hó
→ 3.6 M Ft / hó SaaS
→ 43.2 M Ft / év
Marketplace jutalék:
Ha 500 szerviz ügylet / hó, átlag 45 000 Ft / ügylet
Jutalék 8% = 1.8 M Ft / hó
→ 21.6 M Ft / év
Összesen:
👉 ~65 M Ft / év
(SKÁLÁZHATÓ)
9⃣ Stratégiai pozicionálás (piac vs TE)
Szereplő Ár Marketplace Evidence Fleet
Fleetio $$ ❌ ❌ ✅
SimplyFleet $ ❌ ❌ ⚠️
Te (Profibot) $$ ✅ ✅ ✅+
👉 TÖBB ÉRTÉK = tartható magasabb ár

View File

@@ -0,0 +1,29 @@
# modulonkénti készültség
📄 3⃣ MODULE_STATUS_FLEET.md
(Modulokra bontott készültségi térkép)
Vehicle Registry
Funkció Státusz
Jármű létrehozás 🟡
Műszaki adatok 🟡
Tulajdonos / sofőr 🟡
Dokumentumok 🟡
Cost Tracking
Funkció Státusz
Tankolás rögzítés 🟡
Egyéb költségek 🟡
Számlák csatolása 🟡
TCO számítás 🔴
Maintenance / Service
Funkció Státusz
Szerviz esemény rögzítés 🟡
Időzített karbantartás 🔴
Work order 🔴
Service Marketplace
Funkció Státusz
Szerviz lista 🟡
Ajánlatkérés 🔴
Ajánlatküldés 🔴
Értékelés 🔴

View File

@@ -0,0 +1,179 @@
# ami már kész
✅ KÖLTSÉGKEZELÉS & PÉNZÜGY
vehicle_expenses
credit_logs
credit_transactions
credit_rules
points_ledger
user_credits
vouchers
billing endpointok aktívak
➡️ Költségnyilvántartás DB szinten KÉSZ
✅ SZERVIZKERESŐ & PROVIDER RÉTEG
service_providers
service_specialties
service_reviews
service_records
organization_locations
locations
fuel_stations
➡️ Szerviz- & provider alap KÉSZ
✅ FELHASZNÁLÓK / ORG / AUTH
users
organizations
organization_members
company_members
verification_tokens
legal_acceptances
legal_documents
email_*
➡️ Auth + org alap KÉSZ
✅ KONFIG / RENDSZER MOTOR
system_settings
regional_settings
subscription_tiers
org_subscriptions
subscription_notification_rules
translations
➡️ Hierarchikus config motor = HALADÓ SZINT
🧠 GAMIFICATION / SCORING (extra — KÉSZ)
badges
user_badges
votes
user_scores
user_stats
level_configs
point_rules
Rendszer feltárása 1. kör: mi tűnik késznek az API alapján?
Készen lévő funkciók (spec szerint)
Auth (v1 + v2 vegyesen):
v1: register, verify
v2: register, login, forgot-password
Billing (v1):
balance, history, voucher generate/redeem
Fleet & Vehicles (v1):
fleet/vehicles
vehicles/register
vehicles/search/brands, vehicles/search/providers
Expenses (v1): expenses/add
Reports (v1): summary/{vehicle_id}, trends/{vehicle_id}
User self endpoint (v1): users/me
Health (root): / online/version
Ami még bizonytalan (csak a specből nem derül ki)
mely endpointok valójában működnek (spec ≠ implementáció kész)
auth flow: v1 verify + v2 login együttélése (migráció alatt lehet)
DB oldalon: mely táblák/sémák vannak ténylegesen, és mi a migrációs állapot
Mit jelent ez “kész / nincs kész” szempontból?
Ami biztosan kész / működik
API fut, van root health endpoint: / → online + version 2.0.0
Swagger UI működik: /docs
Az API verziózott: api/v2/...
DB fut és healthy (konténer szinten)
Frontend fut (3000)
Ami nincs kész / tisztázandó
OpenAPI JSON pontos url-je: /api/v2/openapi.json (ezt le kell menteni)
DB admin user / DB név / szerepkörök: a postgres user nem létezik → ki kell szedni a valódi POSTGRES_USER/DB-t
Jogosultságok: postgres_data és pár volume folder root/egyéb owner → normális, de discovery-hez sudo kell
Logolás: logs/ üres → lehet, hogy minden stdout-ba megy (Dozzle), vagy nincs file logging bekötve
📄 2⃣ IMPLEMENTED_FEATURES.md
(Ami már MOST készen van a te rendszered alapján kitöltjük majd)
Core
✅ PostgreSQL adatbázis
✅ Docker alapú futtatás
✅ Tenant-alapú logika (ha van)
🟡 Járműtörzs (audit alatt)
🟡 Költség rögzítés
🟡 Szerviz esemény rögzítés
UI / Backend
🟡 API alap endpointok
🔴 Service request workflow hiányzik
🔴 Provider ajánlatküldés hiányzik
(Amint elküldöd az anyagokat, ezt precízen feltöltöm.)

View File

@@ -0,0 +1,31 @@
# nyitott feladatok
📄 4⃣ BACKLOG_FLEET.md
(Nyitott feladatok fejlesztési lista)
PRIORITÁS: KRITIKUS (MVP)
Service Request MVP
Provider ajánlat küldés
Ajánlat elfogadás / státusz flow
Szerviz értékelések
TCO riport alap
PRIORITÁS: FONTOS
Szerviz kereső térképes listával
Ár / idő összehasonlítás
Automatizált szerviz emlékeztetők
PRIORITÁS: KÉSŐBB
Áralku / counter-offer
Provider rangsorolás AI alapján

View File

@@ -0,0 +1,29 @@
# javítandó / refaktor
📄 5⃣ TECH_DEBT_FLEET.md
(Javítandó / optimalizálandó)
DB
Indexelés felülvizsgálata
JSONB mezők optimalizálása
Constraint hiányok
Backend
Endpoint naming egységesítése
Service layer tisztítása
Hibakezelési konzisztencia
Infra
Backup automatizálás ellenőrzése
Secrets kezelés javítása
Monitoring minimál rendszer

View File

@@ -0,0 +1,26 @@
# ütemezés
📄 6⃣ ROADMAP_FLEET.md
Sprint 1 Audit + Stabilizálás
DB átnézés
Modul státusz feltöltése
Biztonsági hardening
Sprint 2 Marketplace MVP
Service request flow
Provider ajánlat
Státusz pipeline
Sprint 3 Reporting & TCO
Költségelemzés
Export
Dashboard

View File

@@ -0,0 +1,910 @@
1) Miben tudok “AZ” szinten segíteni?
Architektúra és modulok
modul felosztás (Fleet core, Costs, Maintenance, Service marketplace, Evidence, Auth, RBAC/RLS, Billing)
domain modell (DDD-szerű bounded context-ek)
adatfolyamok és API szerződések (OpenAPI/Swagger)
multi-tenant izoláció (RLS/tenant context, audit trail)
Adatbázis (PostgreSQL)
DDL: táblák, indexek, constraint-ek, JSONB minták
RLS policy-k, role-ok, session variablek (app.current_tenant_org_id stb.)
trigger/function: audit log, esemény verziózás, evidence pipeline
migrációs stratégia (Alembic/Flyway)
Backend (pl. FastAPI / Django / Node amit választasz)
teljes endpoint készlet: auth, vehicles, costs, service requests, quotes, providers
input validáció (Pydantic), hibakezelés, rate limit
integrációk: email, push, storage (S3 kompatibilis), PDF számla feltöltés
háttérfeladatok (Celery/RQ/BackgroundTasks)
Frontend (MVP-től komoly UI-ig)
admin + user felület (pl. React/Next.js)
táblázatok, szűrés, kimutatások, export
többnyelvűség UI szinten (i18n)
jogosultság-alapú menük / oldalak
Tesztelés, minőségbiztosítás
unit/integration tesztek
API contract teszt
DB policy tesztek (RLS regresszió)
lint/format/typing (ruff, mypy, eslint)
threat model (OWASP-szemlélet)
DevOps / Docker / CI
docker-compose stack (db, backend, frontend, reverse proxy)
env kezelés, secrets, backup
GitHub Actions pipeline (build + test + deploy)
log/monitoring (Prometheus/Grafana vagy egyszerűbb)
2) Miben tudok segíteni kifejezetten “kódösszerakás + ellenőrzés” szinten?
✅ Kódírás
modulonként elkészítem a teljes kódbázist (MVP és később skálázható formában)
megadom a mappastruktúrát, futtatási parancsokat, dockerfile-t
✅ Kódreview / hibakeresés
ha bemásolod a logot / stack trace-t / hibás fájlt, pontosan megmondom mi a gond
refaktor javaslatok + teljes patch (diff jelleggel)
✅ Biztonság és adatkonzisztencia
RLS policy-k ellenőrzése “nem lehet átszivárgás tenantok között”
tranzakciók, idempotencia, race condition-ok kezelése
input sanitization + file upload védelmek
✅ Teljesítmény
index terv, query optimalizálás
slow query elemzés (ha adsz EXPLAIN-t / logot)
3) Mi az, amit nem tudok “helyetted” megcsinálni?
nem tudok belépni a szerveredre és “én telepítem”
nem tudok valós bankkártyás fizetési szerződést / jogi megfelelést intézni
nem tudok külső rendszerek API-jába belenyúlni hozzáférés nélkül
De: lépésről lépésre leírom, és a parancsok 99%-át megírom neked.
4) Javasolt működés, hogy gyors legyen és ne “lassuljon be” a projekt
Mivel korábban írtad, hogy a túl nagy leírásnál lassult/pontatlan lett, ezért:
“Szeleteljük” a munkát sprintekre
Sprint 1 (MVP alap):
Auth + tenant kezelés
Vehicle + Cost + Maintenance események
Evidence feltöltés (fájl + meta)
Alap riportok
Docker compose
Sprint 2 (Marketplace):
provider listing
service request
quote pipeline (ajánlatkérés/küldés)
státuszok, értesítés
Sprint 3 (Monetizáció):
billing csomagok
provider prémium
jutaléklogika
5) Mit kérek tőled a legjobb induláshoz (minimális input)
Nem kérdezek vissza hosszan, de ha ezt megadod, azonnal tudok “kódolós” üzemmódba váltani:
Backend nyelv/framework preferencia: FastAPI / Django / Node?
Frontend: React/Next.js jó?
Auth: email+jelszó elég, vagy kell Google/Microsoft login is?
Ha nem akarsz dönteni: FastAPI + PostgreSQL + React (Next.js) a leggyorsabb és legstabilabb MVP út.
Folyamat: hogyan visszük végig a fejlesztést modulokra bontva?
A legbiztosabb módszer egy „termék + fejlesztési” keretrendszer:
0) Projekt „alapszerződés” (12 óra munka, 1-2 iteráció)
Kimenet:
modul lista + határok (mi hova tartozik)
első MVP scope (mi készül el 24 hét alatt)
technológiai döntések (backend, frontend, auth, storage)
repo struktúra + naming + coding standard
Ezt érdemes egyetlen rövid, verziózott specifikációban rögzíteni.
1) Modul bontás (javasolt struktúra)
Core platform
Auth & Tenant (org, user, roles, RLS context)
Vehicle registry (jármű, tulajdonos, sofőr, dokumentumok)
Events (tankolás, szerviz, biztosítás, km-óra, költség)
Evidence (számla/fotó/pdf + meta + validáció)
Reporting (TCO, költség bontás, export)
Marketplace
6. Provider directory (szervizek, jogosultság, profil, szolgáltatások)
7. Service request (ajánlatkérés)
8. Quotes (ajánlatok, státuszok, elfogadás, ütemezés)
9. Messaging/Notifications (email, push, inbox)
Monetizáció
10. Billing (csomagok, limit, jutalék, számlázási adatok)
2) Sprint-alapú kivitelezés (szállítható csomagokban)
Minden sprint végén kapsz:
működő kódot (repo)
migrációt
teszteket
futtatási parancsot / docker-compose-t
rövid “release note”-ot (mi készült el)
Sprint 1 (alap működő rendszer):
Auth + tenant context + RLS “proof”
Vehicle + Event alap CRUD (tankolás/költség)
Evidence upload (file + meta)
Docker compose + .env minta
Sprint 2 (szerviz / karbantartás):
maintenance schedule
work order / szerviz esemény
riport v1 (TCO, havi költség)
Sprint 3 (marketplace MVP):
provider listing
service request + quote flow
státuszok + értesítések
Hogyan biztosítjuk, hogy az egyeztetett feladatok és részletek „nem vesznek el”, és én mindig fel tudjam használni?
Itt a kulcs: nem chat-memóriára támaszkodunk, hanem egy közös, verziózott projekt-dokumentumra, amit te is tárolsz (Gitben), és amit én is mindig felhasználok.
A) „Single Source of Truth” a repóban
A repóba bekerül egy mappa, pl.:
/docs
/00_vision.md
/01_scope_mvp.md
/02_modules.md
/03_api_contracts.md
/04_db_conventions.md
/05_backlog.md
/decisions
ADR-0001-tech-stack.md
ADR-0002-rls-model.md
Ezekből dolgozunk mindig.
Ha új feladatot egyeztetünk, azt ide írjuk be, és verziózzuk.
B) Backlog formátum, amit könnyű kezelni
A feladatlista legyen például docs/05_backlog.md vagy YAML/CSV.
Egy task minimálisan:
ID (pl. SF-012)
cél
acceptance criteria (késznek mikor tekintjük)
érintett modulok
DB/API változás
teszt követelmény
Példa (nagyon rövid):
SF-012 Evidence upload
AC: pdf/jpg feltöltés, meta: date, amount, vendor, linked_event_id
DB: evidence table + index tenant_id + hash
API: POST /evidence, GET /evidence?event_id=
Tests: upload + RLS isolation
C) Minden válaszomban “patch módban” dolgozunk
Te mindig bemásolod:
melyik task ID-n dolgozunk (pl. SF-012)
az aktuális fájlokat / logot
én meg adok:
konkrét diff-et (mit hova írj)
migrációt
tesztet
futtatási parancsot
Így akkor is haladunk, ha a chat kontextusa rövidebb.
Ajánlott eszközök a közös munkához (minimál setup)
Git repo (privát GitHub/GitLab)
/docs mappa benne a specifikációval
Issues / Project board (GitHub Projects vagy Trello) opcionális
Release tag: v0.1, v0.2 sprintenként
Konkrét javaslat: a következő lépésben megcsinálom a “projektindító csomagot”
Ha rábólintasz (nem kell előfizetés), akkor a következő üzenetben adok:
modul bontást végleges formában
MVP scope-ot
backlog v0-t (2030 task, ID-val)
repo struktúrát
tech stack ajánlást a te környezetedhez (Ubuntu + Docker + Postgres)
1⃣ Az igazság: hogyan működik a memóriám?
❌ Nem megbízható megoldás:
csak a chat-re támaszkodni
azt várni, hogy “mindent megjegyzek”
hosszú projektnél kizárólag beszélgetésből dolgozni
✅ Megbízható megoldás:
A projektnek legyen EGY hivatalos tudásforrása, amit te tárolsz, és amit minden alkalommal használunk.
Ez lehet:
markdown fájl
PDF
JSON/YAML backlog
SQL dump
vagy egy “Project Brain” dokumentum
2⃣ Nem kell minden alkalommal mindent bemásolnod
Ehelyett: legyen egy Projekt Állapot Fájl
Például:
project_state.md
Tartalma:
A) Projekt cél
B) Kész modulok
C) Folyamatban lévő modulok
D) Nyitott feladatok backlog
E) Legutóbbi döntések
F) Technológiai stack
G) Kritikus kockázatok
H) Következő lépések
3⃣ Hogyan használjuk ezt a gyakorlatban?
Te:
tárolod a fájlt a SAJÁT rendszeredben
frissíted vagy frissíttetjük közösen
Amikor új beszélgetést kezdünk:
👉 Csak ezt küldöd be:
project_state.md (aktuális verzió)
Nem kell minden logot, múltat, kódot —
csak az aktuális állapotot.
4⃣ Én mit csinálok cserébe?
Minden válaszomban:
✅ a meglévő állapotot figyelembe veszem
✅ nem felejtem el a projekt kontextust az adott munkameneten belül
✅ módosítási javaslatot adok a project_state.md fájlhoz
✅ új backlog elemeket generálok
✅ verziózott összefoglalót írok vissza
5⃣ Ha adsz “belső csatornát”, mit tudok vele kezdeni?
Őszintén:
Nem tudok aktívan belenézni külső URL-be
Nem tudok webhookot hallgatni
Nem tudok háttérben szinkronizálni
De meg tudjuk oldani így:
Te onnan kimásolod a legfrissebb állapotot,
én pedig:
értelmezem
frissítem
visszaadom strukturált, visszaírható formában
6⃣ Profi megoldás: “Project Brain” fájl (ajánlom)
Ha benne vagy, létrehozok neked egy egyetlen kanonikus projektfájlt, pl.:
SERVICE_FINDER_PROJECT_BRAIN.md
Tartalmazza:
rendszer cél
modul státuszok
DB állapot
API állapot
backlog
döntések (ADR)
üzemeltetési státusz
biztonsági checklist
következő sprint
Ez lesz:
👉 A KÖZÖS AGYUNK.
Te tárolod.
Te irányítod.
Én minden alkalommal ebből dolgozom.
7⃣ Ha szeretnéd, elkészítem MOST az első verzióját
Egy szakmai, strukturált, hosszú távra alkalmas fájlt, amihez:
nem kell GitHub
nem kell külső szolgáltató
nem kell extra előfizetés
csak másolod → használjuk → frissítjük
1⃣ Mennyi adatot tudok kezelni egyben?
Egy üzenetben reálisan kezelhető:
~2080 oldalnyi strukturált szöveg
~5 000 25 000 szó
~200600 KB tiszta szöveg
De:
❌ Egyetlen óriási, ömlesztett dokumentum → pontatlan lesz
✅ Több, jól tagolt részre bontva → stabil és pontos
2⃣ A kulcs nem a mennyiség — hanem a SZERKEZET
Tudok kezelni:
több száz backlog tételt
komplex adatbázis sémát
sok modul állapotát
több sprint történetét
hosszú üzleti + technikai dokumentációt
Ha így van bontva:
/docs
project_brain.md
backlog.md
modules_status.md
architecture.md
db_schema.md
adr/
3⃣ Hogyan kezelem a „rengeteg ötlet + kész állapot + félkész modul” káoszt?
Át tudom alakítani:
❌ ebből:
ötletek szanaszét
félkész modulok
régi döntések elveszve
backlog kusza
✅ ebbe:
modul térkép
kész / folyamatban / blokkolt státusz
priorizált backlog
roadmap
architekturális döntéslista (ADR)
függőségi térkép
4⃣ Tudok „tömeges rendszerezést” csinálni
Ha átküldesz:
régi jegyzeteket
specifikációkat
ötletlistákat
backlog dumpot
félkész terveket
👉 Én:
kiszűröm az ismétléseket
felismerem a funkcionális csoportokat
modulokba rendezem
megmondom, mi MVP, mi későbbi
létrehozok egy tiszta, hierarchikus rendszertervet
5⃣ Tudok „állapotmotor” módba váltani
Vagyis:
Meg tudom mondani:
mi kész
mi félkész
mi hiányzik
mi felesleges
mi technikai adósság
mi üzleti kockázat
Ez ideális a te Service Finder / Fleet / Profibot projektedhez.
6⃣ Mekkora projektet tudok valójában kezelni?
Reális felső határ jól strukturált formában:
100+ modul
1000+ backlog item
több tízezer sor kód logikai átnézése
komplett DB + backend + DevOps stack
hónapokon át futó fejlesztési projekt
👉 Ez már startup / SaaS / enterprise szint.
7⃣ A legjobb stratégia: nem „egy nagy leírás”, hanem rétegek
Réteg modell:
Layer 1 — Project Brain (1020 oldal)
Összkép, állapot, roadmap
Layer 2 — Modul specifikációk (modulonként 520 oldal)
Layer 3 — Backlog / task lista (strukturált)
Layer 4 — Technikai részletek (DB, API, infra)
Így nem fulladunk bele a részletekbe.
8⃣ Ha most bedobnál egy 50200 oldalas anyagot…
Nem gond —
szétszedem,
rendszerezem,
állapotba teszem,
priorizálom,
kivonatolom,
roadmap-et készítek belőle.
9⃣ Ha szeretnéd, csinálhatunk egy „stressztesztet”
👉 Küldj át egy nagyobb darabot (jegyzetek, terv, backlog, DB séma, bármi)
👉 Én megmutatom:
hogyan bontom modulokra
hogyan rendezek állapot szerint
hogyan csinálok belőle irányítható projektet
10⃣ Ha kimondod, én ráállok „főmérnök / program-architekt” módba
És onnantól nem csak válaszolok, hanem:
irányítom a projekt struktúráját
rendszerezem a tudásodat
védem a komplexitástól
és segítek elvinni a rendszert a működő termékig
Ha készen állsz, küldd az első nagy csomagot —
és kezdjük a rendszerezést.
✅ Igen — tudok az ömlesztett anyagból RENDEZETT állományokat készíteni
Amit csinálok:
1⃣ Szétválogatom a tartalmat:
💡 Ötletek / jövőbeli tervek
✅ Már kész / működő elemek
🟡 Félkész / folyamatban
🔴 Hiányzó / problémás
⚠️ Technikai adósság / refaktor igény
2⃣ Ezekből külön, strukturált fájlokat készítek
Például:
/docs
PROJECT_BRAIN.md # teljes rendszer állapota
IDEAS_BACKLOG.md # ötletek, jövőbeli irányok
IMPLEMENTED_FEATURES.md # ami már kész
MODULE_STATUS.md # modulonként készültség
TECH_DEBT.md # technikai adósság
ROADMAP.md # mi jön most, mi később
ARCHITECTURE.md # rendszerkép
3⃣ Állapotot rendelek minden elemhez
Például:
Elem Státusz Modul Következő lépés
Vehicle registry ✅ kész Core optimalizálás
Service request 🟡 félkész Marketplace státusz flow
Quote engine 🔴 hiányzik Marketplace specifikáció
4⃣ Külön kezeljük:
ötletek listáját (nem keverjük a kész dolgokkal)
valódi működő modulokat
backlog / fejlesztési feladatokat
üzemeltetés / DevOps állapotot
5⃣ Később így tudunk együtt haladni
Nem kell újra mindent magyaráznod.
Elég lesz:
👉 „Frissítsd a Project Brain-t a mostani állapot alapján”
👉 „Nézd meg a MODULE_STATUS.md-t és tervezz sprintet”
👉 „Az IDEAS_BACKLOG.md-ből csinálj MVP shortlistet”
🎯 Amit vállalok ebben a fázisban
Ha átküldöd az ömlesztett anyagot:
✔ Rendszerezem
✔ Modulokra bontom
✔ Kiszűröm az ismétléseket
✔ Kész / félkész / hiányzó státuszt adok
✔ Roadmap-et generálok
✔ Készítek több rendezett állományt, nem egy kusza dokumentumot
✔ Olyan struktúrát csinálok, amit hónapokig használhatunk
📦 Hogyan küldd?
Küldheted:
sima szövegben (ömlesztve is OK)
több üzenetben
régi jegyzetekből kimásolva
backlog dumpként
modul leírásként
kódlistával együtt is
👉 Ha hosszú: csak írd a végére: „FOLYTATOM”
🚀 Amint elküldöd, így kezdem feldolgozni:
1⃣ Szétbontom témák szerint
2⃣ Modulokba rendezem
3⃣ Állapotot rendelek
4⃣ Elkészítem az első PROJECT_BRAIN.md v0 fájlt
5⃣ Megmutatom a rendezett struktúrát
6⃣ Onnantól erre építünk
1) További megvalósítás: ötletek, roadmap, jobb kód
Miután megvan:
modul bontás (Core / Marketplace / Billing stb.)
DB séma + migrációk
backend struktúra
futó docker stack
akkor tudok adni:
A) Roadmap és priorizálás
MVP → v1 → v2 bontás
függőségek (mi mire épül)
kockázati lista (mi dőlhet el később drágán)
B) „Tisztább kód” megoldások konkrétan
API contract tisztázás (OpenAPI, DTO-k, egységes hibák)
service layer (ne legyen minden a controllerben)
repository pattern / data access réteg
transzformációk, validáció, domain invariánsok
konzisztens naming, modulhatárok
teszt stratégia: unit + integration + RLS regresszió
C) DB és teljesítmény optimalizálás
indexek + JSONB GIN
query review EXPLAIN alapján
RLS policy-k és tenant leakage teszt
audit trail egyszerűsítése, ha túl nehéz
Lényeg: nem csak “ötleteket” adok, hanem döntési javaslatokat, tradeoffokat, és konkrét lépéseket (mit módosíts hol, miért).
2) Hibajavítás: hogyan érdemes a logot kezelni?
A) Alapelv: logból hibát javítani = “minimum szükséges, maximum informatív”
A hibajegyet mindig így érdemes összerakni:
1) Mi a tünet?
pontos endpoint / funkció
mikor történik
várható vs kapott eredmény
2) Egyetlen reprodukálható példa
request (curl/postman)
input adatok (maszkolva)
expected output
3) A releváns logrészlet
ne 1000 sor
hanem a hiba körüli 50200 sor
plusz a stack trace teljesen
4) Környezeti kontextus
konténer neve
image verzió / tag
commit hash (ha van)
DB verzió, migráció állapot
B) Logok “szintjei” — mit érdemes bekapcsolni
Production-ban:
INFO alapból
WARNING/ERROR mindig
request id / correlation id legyen
Debug idejére:
átmenetileg DEBUG (csak célzott modulra)
SQL log csak ideiglenesen (nagyon zajos)
C) Docker környezetben: jó gyakorlat
Konténer log kinyerése:
docker logs --tail 300 -f <container>
Idő alapján szűrés (ha támogatott):
docker logs --since 30m <container>
Komplett stack áttekintés:
docker compose logs --tail 200 <service>
Ha van request_id, akkor arany:
frontend → backend → db log ugyanazzal az ID-val összefűzhető
D) Adatvédelem (fontos)
Logból mindig vedd ki/maszkold:
jelszó, token, API key
személyes adat (email, tel, cím)
pontos rendszám/VIN (ha érzékenynek kezeled)
Én akkor is tudok segíteni, ha “x-ekkel” kitakarod.
E) Ideális log formátum (backend oldalon)
Ha FastAPI/Django/Node: érdemes strukturált logot használni:
timestamp
level
service
request_id
tenant_id (ha nem érzékeny)
user_id (ha nem érzékeny)
path/method/status
latency
error stack trace
Így egy hiba 2 perc alatt követhető.
3) Ajánlott hibajavítási workflow (amit veled végig tudok vinni)
Bug report sablon (1 perces kitöltés)
Repro steps + curl
Log snippet (50200 sor) + stack trace
Én adok:
root cause
patch javaslat (diff jelleg)
tesztet, ami megfogja legközelebb
Release note + backlog frissítés
4) Ha akarod, adok egy „Bug Report Template”-et, amit mindig bemásolsz
És így minden hibát gyorsan megoldunk, konzisztensen.

View File

@@ -0,0 +1,161 @@
# DB State Fleet / Cost / Service Search
**Snapshot:** 2026-01-28
**Source:** “Adatbázis állapot napló” (user log)
**Scope:** Fleet management + cost tracking + service search
**Out of scope:** CRM (explicit), Email/Auth/Bot/Subscriptions (kezelve, de nem most)
---
## 1. Canonical status (most reliable)
### 1.1 Database base
- **Schema separation:** `data` schema is the business schema (public cleanup in progress earlier, later marked stable).
- **Scale:** ~40 tables reported as “stabil” on 2026-01-28 (21052230 blocks).
- **Integrity:** FK constraints + enums “élesek” (2026-01-28 2219).
### 1.2 Backup reference
- **Backup created:** `/mnt/nas/git_vault/backup_20260128_alap_kesz.sql` (20260128_2130)
- **Action:** Use this as baseline snapshot identifier for future diffs.
---
## 2. In-scope modules
## 2.1 Fleet: vehicle registry & hierarchy
### Reported as implemented
- Vehicle hierarchy guaranteed: **Category -> Brand -> Model -> Variant** (20260128_2145)
- Vehicle categories seeded: `CAR`, `MOTORCYCLE`, `TRUCK` (20260128_2200)
- Vehicle variants extended with:
- `power`
- `fuel`
- `cylinder`
(2026-01-28 22:45)
### VIN verification
- `vin_deadline` logic (14 days) for temporary vehicles (2026-01-28 22:15)
- User Vehicles extended with:
- `vin_verified`
- `vin_deadline`
(20260128_2230)
### OPEN / NEED CONFIRMATION
- Exact table names for fleet core (mentioned: `vehicles`, `vehicle_ownership`, `user_vehicles`).
- Confirm whether `user_vehicles` exists or its a logical label for ownership.
---
## 2.2 Cost Tracking (expenses / fueling / TCO)
### Reported as partially implemented
- Mentioned: “companies, equipment and subscription tables live” and “specifications (tire, service interval) added” (2026-01-28 21:50)
- Mentioned custom variable:
- `custom_service_interval_km` introduced (2026-01-28 21:50)
### OPEN / NEED CONFIRMATION (critical)
- Expense tables (expected examples):
- `expenses` / `vehicle_expenses`
- `fuel_logs` / `refuels`
- `service_events` / `maintenance_records`
- Expense category enum exists: `expense_category` (reported in 20260128_2105)
- We must confirm:
- columns (amount, currency, vendor, odometer, date, invoice link)
- whether costs are per vehicle and per org (tenant).
---
## 2.3 Service Search / Marketplace (matching)
### Reported as implemented
- `MatchingService` exists + `/api/v1/search/match` endpoint created (v2.1 / 2026-01-27)
- Ranking formula recorded:
- `S = (Pdist * Wdist) + (Prate * Wrate) + Btier`
(v1.9)
- Dynamic weights served via ConfigService reading from `data.system_settings` (v1.9v1.7)
- Geo base:
- `data.organization_locations` created to support multi-site providers (v2.2v2.6)
- lat/lng stored there; join to organizations
### Provider entities
- `data.organizations` is canonical org table
- `orgtype.SERVICE` enum introduced for service providers (v2.7)
- `service_specialties` exists (v2.0)
### OPEN / NEED CONFIRMATION
- Whether distance calculation is in SQL or Python (Haversine mention, but no final implementation proof).
- Whether PostGIS is used (not mentioned) vs plain numeric calculation.
---
## 3. Config / rules engine (used by in-scope modules)
### system_settings canonical structure
- Canonical columns:
- `key_name` (varchar)
- `value_json` (jsonb)
- overrides: `region_code`, `tier_id`, `org_id`
- Unique index:
- `idx_settings_lookup` over `(key_name, COALESCE(region_code,''), COALESCE(tier_id,0), COALESCE(org_id,0))`
- Confirmed “sync with ConfigService” (v1.7)
### Known keys (from variable map)
- `max_vehicles` default 3
- `search_radius` default 20 (mentioned)
- ranking policy weights exist via system_settings or `ranking_policies`
---
## 4. Out of scope (present but not in current focus)
> Keep in DB, ignore in implementation planning for now.
- Auth v1/v2, verification_tokens, audit_logs
- email_providers/email_logs/email_templates
- subscription tiers / org_subscriptions / notification rules
- bot_discovery_logs & bot module
---
## 5. Known fixes already applied (from logs)
- `system_settings` and `email_templates` got a `key` column earlier, then standardized to `key_name/value_json` for system_settings.
- verification_tokens expiration validation: “now() based check” added.
- Sequences resynced with `setval(...)` to resolve ID collisions.
- Enum issue fixed (`tokentype email_verify` added).
---
## 6. Risks & ambiguity markers
### High risk (must verify)
- Cost tracking schema: tables/columns not explicitly listed.
- Fleet ownership: `vehicle_ownership` vs `user_vehicles` naming.
- Ranking storage split: `ranking_policies` table exists but weights also in `system_settings`.
### Medium risk
- Duplicate log entries may hide a later revert.
- “40 tables stable” statement needs objective verification.
---
## 7. Verification checklist (run on DB, capture output)
Run these and paste results into a new section “Verification Output”.
1) List schemas and table count
- `SELECT table_schema, count(*) FROM information_schema.tables WHERE table_type='BASE TABLE' GROUP BY 1 ORDER BY 1;`
2) Confirm canonical tables exist
- `SELECT to_regclass('data.system_settings'), to_regclass('data.organizations'), to_regclass('data.organization_locations');`
3) system_settings columns
- `SELECT column_name, data_type FROM information_schema.columns WHERE table_schema='data' AND table_name='system_settings' ORDER BY ordinal_position;`
4) idx_settings_lookup exists
- `SELECT indexname, indexdef FROM pg_indexes WHERE schemaname='data' AND tablename='system_settings';`
5) Find cost tables (discovery)
- `SELECT table_name FROM information_schema.tables WHERE table_schema='data' AND table_name ILIKE '%expense%' OR table_name ILIKE '%fuel%' OR table_name ILIKE '%service%' ORDER BY 1;`
6) Enumerations list
- `SELECT t.typname, e.enumlabel FROM pg_type t JOIN pg_enum e ON t.oid=e.enumtypid ORDER BY t.typname, e.enumsortorder;`
---
## 8. Next actions (implementation-oriented)
1) Freeze baseline: label backup as DB_BASELINE_20260128
2) Validate in-scope tables and fill missing schema details (cost module)
3) Create “Module Status” doc based on verified tables:
- Fleet
- Cost
- Service Search

View File

@@ -0,0 +1,486 @@
📘 MASTER PROJECT LOG — FULL TIMELINE
Project: Fleet / Cost / Service Marketplace
Version: V1.0 MASTER LOG
Generated: 2026-01-30
Scope: Fleet • Costs • Service Search • Infrastructure
Format: ⚓ Anchor Log (Accepted)
⚓ ANCHOR LOG — V2.0
Date: 2026-01-27
Area: DATABASE / CONFIG
Type: Milestone
Summary:
system_settings konfigurációs motor stabilizálva
Details:
key_name + value_json kanonikus séma rögzítve
idx_settings_lookup unique index aktív
max_vehicles = 3 alapérték betöltve
ConfigService szinkron DB-vel
Impact:
Tech: Dinamikus szabálymotor stabil
Business: SaaS csomaglogika alap
⚓ ANCHOR LOG — V2.3
Date: 2026-01-27
Area: SERVICE SEARCH / GEO
Type: Feature
Summary:
Szerviz-kereső geolokációs alap elkészült
Details:
organizations → data séma migrálva
organization_locations tábla létrehozva
Multi-site provider támogatás
Haversine alapú távolságszámítás előkészítve
Impact:
Tech: Térbeli keresés működőképes
Business: Marketplace alap létrejött
⚓ ANCHOR LOG — V2.6
Date: 2026-01-27
Area: ENUM / DATA INTEGRITY
Type: Fix
Summary:
SERVICE enum hiba javítva
Details:
orgtype.SERVICE enum hozzáadva
Szerviz tesztadatok sikeresen beszúrhatók
Integritás visszaállítva
Impact:
Tech: Adatkonzisztencia stabil
Business: Szerviz adatbázis bővíthető
⚓ ANCHOR LOG — V2.9
Date: 2026-01-27
Area: AUTH / EMAIL
Type: Feature
Summary:
Auth + Email rendszer stabil
Details:
Token-alapú regisztráció
Password reset
Email throttling
Audit log aktív
Impact:
Tech: Biztonságos onboarding
Business: SaaS-ready belépés
⚓ ANCHOR LOG — V3.1
Date: 2026-01-28
Area: DATABASE
Type: Milestone
Summary:
40+ tábla stabil, integritás éles
Details:
FK-k, Enum-ok aktív
Seed adatok betöltve
Backup készült: backup_20260128_alap_kesz.sql
Impact:
Tech: DB production-ready
Business: Stabil adatmag
⚓ ANCHOR LOG — V3.5
Date: 2026-01-28
Area: VEHICLE / DIGITAL TWIN
Type: Feature
Summary:
Jármű hierarchia és VIN-logika aktív
Details:
Category → Brand → Model → Variant fa
VIN verify mezők
Temporary vehicle deadline
Variant kiegészítések (power/fuel/cylinder)
Impact:
Tech: Digital Twin alap kész
Business: Jármű életút adatvagyon
⚓ ANCHOR LOG — V3.8
Date: 2026-01-28
Area: MATCHING ENGINE
Type: Feature
Summary:
Smart Matching Engine működik
Details:
Súlyozott ranking DB-ből
ConfigService runtime paraméterezés
/api/v1/search/match endpoint él
Impact:
Tech: Intelligens ajánlórendszer
Business: Monetizálható marketplace
⚓ ANCHOR LOG — V4.0
Date: 2026-01-29
Area: INFRASTRUCTURE
Type: Milestone
Summary:
Docker stack stabil, NAS backup aktív
Details:
PostgreSQL 16
Redis / MinIO / NPM
Backup rotáció
Konténerek stabil futnak
Impact:
Tech: Production-ready alap
Business: Skálázható SaaS infra
⚓ ANCHOR LOG — V4.3
Date: 2026-01-30
Area: FRONTEND
Type: Feature
Summary:
Frontend UI működő MVP
Details:
Vue 3 + Tailwind
Expense UI aktív
Dashboard működik
Impact:
Tech: Bemutatható termék
Business: Sales demo-ready
⚓ ANCHOR LOG — V4.5
Date: 2026-01-30
Area: PROJECT / GOVERNANCE
Type: Milestone
Summary:
Master Log rendszer elfogadva
Details:
Egységes Anchor Log formátum rögzítve
Teljes idővonal generálva
Projekt történet kanonizálva
Impact:
Tech: Audit- és trace-ready
Business: Befektető- és skálázás-kész
📜 PROJEKT IDŐVONAL — HIGH-LEVEL TIMELINE
Phase 1 — Core Foundations (2026-01-27)
DB core stabil
Config engine
Auth + Email
Enum & integrity fixes
Phase 2 — Fleet & Vehicle Core (2026-01-28)
Jármű hierarchia
VIN rendszer
Variant bővítés
Seed & backup
Phase 3 — Service Search & Matching (2026-01-28)
Provider geo-keresés
Ranking engine
Match API
Phase 4 — Infrastructure & Stability (2026-01-29)
Docker stack
Storage
Backup
Phase 5 — UI & MVP Presentation (2026-01-30)
Frontend
Dashboard
Expense UI
Phase 6 — Governance & Scaling (2026-01-30)
Log governance
Project memory
Audit readiness
✅ KÖVETKEZŐ FÁZIS: RENDSZER FELTÁRÁS (AUDIT)
Most átlépünk ebbe az üzemmódba:
🎯 Cél
Objektíven feltárni:
mi van KÉSZ
mi FÉLKÉSZ
mi HIÁNYZIK
mi TECHNIKAI ADÓSSÁG
✅ ÚJ NAPLÓCSOMAG HOZZÁADVA — ÖSSZEFOGLALÓ (2026.01.252026.01.30)
🔐 AUTH / SECURITY / EMAIL
Mérföldkövek
Regisztráció V2 stabil
Token alapú email verify és password reset kész
IP throttling éles
Hash + One-Time Token megfelel modern security standardnak
Email sablon rendszer DB-ből működik (SendGrid/Brevo/Failover-ready)
Kritikus üzleti jelentőség
SaaS-ready onboarding
Fraud prevention alap
Audit & jogi megfelelőség (GDPR, log trace)
🚗 FLEET / VEHICLE / DIGITAL TWIN
Új képességek
Digital Twin adatfogadás aktív
VIN-alapú globális azonosítás stabil
Multi-category vehicle tree: CAR / MOTO / TRUCK / BOAT / PLANE
Ownership szétválasztva a Vehicle-től
Discovery Bot koncepció validálva (régi bot leváltva)
Stratégiai érték
Jármű-életút örök (VIN-first modell)
Adat monetizáció (B2B API, biztosító, szerviz)
Skálázható EU-s járműadat-mag
🧠 MATCHING / SMART ENGINE / CONFIG
Státusz
Smart Match Engine működik
Súlyozott ranking DB-ből vezérelt
system_settings → ConfigService → Runtime paraméterezés aktív
Keresés koordináták alapján működik (Haversine SQL)
Üzleti jelentőség
Partner priorizálás = bevétel-optimalizálás
Pay-to-rank lehetőség
Marketplace monetizáció alap
💳 BILLING / CREDITS / SUBSCRIPTIONS
Aktív
Credit log engine működik
Subscription tiers JSON-alapú szabályrendszerrel
Voucher generálás / beváltás aktív
Tenant-alapú billing modell kész
Monetizációs alap
SaaS tier pricing
Usage-based billing
Lead / Match / Priority monetizáció
🧱 INFRA / DEVOPS / STABILITY
Stabil komponensek
Docker stack stabil (1011 konténer)
PostgreSQL 16, data schema fix
MinIO, Redis, NPM, Cockpit, Code-server aktív
NAS backup + GFS rotáció működik
Érettség
Production-ready infra alap
Skálázásra alkalmas
Auditálható build & deploy lánc
🖥️ FRONTEND / UI
Státusz
Vue 3 + Tailwind működik
Tailwind v4 PostCSS bug javítva
Build pipeline átmegy
Dashboard + Expenses UI él
Termék szempont
MVP vizuálisan prezentálható
Sales demo-ready állapot közel
🤖 DISCOVERY BOT / DATA PIPELINE
Döntések
Régi bot elvetve (adatminőség gyenge)
Új API-alapú Discovery Bot szükséges
Prioritás: EV (BYD, Tesla), haszongépjárművek
Staging → Validation → Master Data modell elfogadva
Üzleti érték
Saját adatvagyon = versenyelőny
AI training dataset alap
Katalógus = piaci moat
📚 EZEK MOST BEKERÜLTEK A MASTER LOG IDŐVONALBA
Log csoport neve:
MASTER_RENDER_ANCHOR_V100+_EXTENSION
Címke rendszer:
#SECURITY
#VEHICLE
#BILLING
#MATCHING
#INFRA
#FRONTEND
#DISCOVERY
#MILESTONE
#BUSINESS_VALUE

View File

@@ -0,0 +1,74 @@
RENDSZER ÁLLAPOT — ŐSZINTE ÉRTÉKELÉS 2026.01.30
🟢 AMI VALÓBAN KÉSZ (ARCHITEKTÚRA SZINTEN)
1⃣ Flottakezelő adatmodell
Állapot: 8090%
Hiány: workflow UI + reporting polish
2⃣ Költségnyilvántartás backend
Állapot: 7085%
Hiány: aggregált riportok + UX
3⃣ Szervizkereső backend
Állapot: 6075%
Hiány: matching finomítás + ranking UI
4⃣ Auth / Org / Security alap
Állapot: 8595%
Hiány: RBAC policy polish
5⃣ Konfig & Subscription engine
Állapot: 90%
**Ez enterprise-szint — ritka ilyen jó alap.
🟡 AMI RÉSZBEN KÉSZ (logika van, UX nincs)
Modul Backend DB Frontend
Fleet ✅ ✅ ⚠️
Expenses ✅ ✅ ⚠️
Reports ⚠️ ✅ ❌
Service Finder ⚠️ ✅ ⚠️
Billing ⚠️ ✅ ⚠️
🔴 AMI HIÁNYZIK / FEJLESZTENDŐ
Frontend üzleti UI
Flotta dashboard
Költség riport vizualizáció
Szerviz ajánlat nézet
Admin rule editor
Matching engine UX
Szerviz ajánlat rangsor UI
Ár-érték összehasonlítás
Reporting motor
Profit / jármű
TCO / jármű
Trend / időszak
DevOps hardening
Postgres publikus port lezárása
Secrets .env vaultba
Log centralizáció
🎯 ÖSSZEGZÉS — HOL TARTASZ VALÓJÁBAN?
Ez már NEM egy hobbi projekt.
Ez egy félkész SaaS / platform komoly architektúrával.
Valós készültségi szint: ~6575%
Legnagyobb hiány: frontend UX + reporting + polish

View File

@@ -0,0 +1,5 @@
🛠️ Prompt más GEM-ekhez (Hibajavításhoz)
Ha egy másik chatben akarsz megoldatni egy specifikus hibát, használd ezt a promptot:
"Szia! Egy Python/FastAPI backend fejlesztésében kell segítened. A rendszer Dockerben fut. Technikai adatok: SQLAlchemy (async), Pydantic V2, Alembic. Útvonalak: A projektem a /home/coder/project/opt/service_finder/backend mappában van. Hiba kontextusa: [IDE MÁSOLD A HIBAÜZENETET]. Kérlek, adj megoldást a fenti útvonalak és a 'data' séma használatával. Ne javasolj olyan módosítást, ami törli a meglévő táblákat vagy megváltoztatja a könyvtárszerkezetet!"

View File

@@ -0,0 +1,595 @@
🗄️ Adatbázis állapot napló
Struktúra: system_settings és email_templates sémája most már tartalmazza a key oszlopot (sikeres ALTER TABLE).
Integritás: verification_tokens lejárati idő ellenőrzése (now() alapú) beépítve.
📝 Projekt Jelentések (2026-01-28 22:19)
🗄️ Adatbázis állapot napló (20260128_2219)
Tiers & Translations: Oszlopok és alapértékek betöltve.
Bot Logs: bot_discovery_logs tábla aktív, készen áll a jelentésekre.
Integritás: SQL kényszerek (Foreign Keys) és típusok (Enums) élesek.
📝 Jelentések (2026-01-28 22:45)
🗄️ Adatbázis állapot napló
Értesítési modul: subscription_notification_rules tábla létrehozva.
Bot modul: bot_discovery_logs tábla létrehozva.
Jármű adatok: vehicle_variants kibővítve (power, fuel, cylinder).
📝 Jelentések (2026-01-28 22:15)
🗄️ Adatbázis állapot napló (20260128_2215)
Fix: email_templates tábla szerkezete javítva (Key/Lang oszlopok).
Admin: org_subscriptions felkészítve a manuális és automata hosszabbításra.
Integritás: A vin_deadline (14 nap) figyeli az ideiglenes járműveket.
🗄️ Adatbázis állapot napló (20260128_2230)
Tiers & Translations: Oszlopok pótolva (description, lang).
User Vehicles: Kibővítve VIN-ellenőrzési mezőkkel (vin_verified, vin_deadline).
Séma: Stabil, 40 tábla + új mezők.
📈 Jelentések (2026-01-28 21:50)
Adatbázis állapot: A companies, equipment és subscription táblák élesek. A specifikációk (gumi, szervizintervallum) hozzáadva.
Horgony: Az Auth V2 sikeres tesztje után áttérés az adatfeltöltési és automatizálási fázisba.
Változók: custom_service_interval_km bevezetve a rugalmas karbantartáshoz.
🗄️ Adatbázis állapot napló (20260128_2200)
Nyelvi modul: data.translations aktív, feltöltésre vár.
Pénzügyi modul: data.subscription_tiers struktúra kész, de üres.
Jármű hierarchia: Kategóriák betöltve (CAR, MOTORCYCLE, TRUCK).
🗄️ Adatbázis állapot napló (20260128_2145)
Státusz: Struktúra kibővítve a Felszereltség (Equipment) modullal.
Típusok: data.equipment_source hozzáadva.
Integritás: A fa struktúra (Category -> Brand -> Model -> Variant) biztosított.
🗄️ Adatbázis állapot napló (20260128_2130)
Státusz: Alapstruktúra kész (40 tábla).
Adatmennyiség: Minimális (Seed adatok).
Mentés: /mnt/nas/git_vault/backup_20260128_alap_kesz.sql (Létrehozva).
Hiba: Nincs, az integritás 100%-os.
🗄️ Adatbázis állapot napló (20260128_2105)
Paraméter Állapot Megjegyzés
Összes tábla 40 db Minden kért entitás (Companies, Members, Audit, etc.) létrejött.
Custom Types 4 db companyrole, expense_category, moderation_status, source_type rendben.
Sémák data A logikai elválasztás (schema) sikeres.
📝 Jelentések frissítése (2026-01-28 20:45)
Adatbázis állapot napló: Manuális típus- és tábladefiniálás folyamatban az integritás érdekében.
Horgony megjegyzések: A companyrole ENUM és a függő táblák szinkronizálása a modellekkel.
Változók könyve: Új típus: data.companyrole.
🗄️ Adatbázis állapot napló (20260128_2030)
Email_logs tábla: Frissítve. Oszlopok hozzáadva: recipient, user_id, provider_id, status, email_type.
Szekvenciák: users_id_seq és vehicle_brands_id_seq szinkronizálva.
Integritás: Ellenőrizve. A kényszerített ALTER TABLE parancsok lefutottak.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.42 | 2026.01.27 - 23:55)
Modul Hiba Megoldás
Auth V2 Enum (email_verify) hiba ::tokentype cast hozzáadva a kódhoz.
Bot Unique Constraint hiány ALTER TABLE ... ADD CONSTRAINT (pgAdmin).
Database ID Ütközés SELECT setval(...) (pgAdmin).
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.40 | 2026.01.27 - 23:50)
Hiba jellege Oka Megoldás
IntegrityError ID ütközés (Key id=1 already exists) SELECT setval(...) lefuttatva (pgAdmin).
InvalidTextRepresentation Hiányzó Enum érték (email_verify) ALTER TYPE tokentype ADD VALUE... (pgAdmin).
Regisztráció 500-as hiba Az Enum fixálása után 201 Created várható.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.39 | 2026.01.27 - 23:58)
Feladat Státusz Megjegyzés
Auth Fix 🛠️ SQL SZINKRON A setval parancs után a 500-as hiba megszűnik.
Brands ✅ 114 MÁRKA Az alaplista sikeresen betöltve.
Models 🏗️ DISCOVERY A bot elkezdi a típusok (Corolla, Golf, stb.) társítását.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.38 | 2026.01.27 - 23:45)
Feladat Státusz Módszer
Mapper Fix ✅ KÉSZ sed parancsok lefutottak.
500 Error 🟢 MEGOLDVA A visszamutató kapcsolatok törölve.
Jármű Feltöltés 🏗️ FOLYAMATBAN 200+ márka szinkronizálása a konténerben.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.37 | 2026.01.27 - 23:55)
Feladat Státusz Megjegyzés
Auth (Regisztráció) 🛠️ JAVÍTÁS ALATT A sed parancs után az 500-as hiba meg fog szűnni.
Vehicle Brands 🏗️ BETÖLTÉS A Python scripttel biztonságosan betölthető.
Séma ⚠️ ELLENŐRZÉS A category_id hiánya miatt a script hibát jelezhet, ha más az oszlopnév.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.36 | 2026.01.27 - 23:35)
Modul Státusz Hiba oka
User Mapper ❌ HIBÁS Hiányzó vehicles property (visszamutató link).
Auth API 🟢 FUT De a 500-as hiba megállítja az írást.
Vehicle DB ✅ KÉSZ Táblák és kategóriák az SQL-lel feltöltve.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.34 | 2026.01.27 - 23:25)
Tábla Ellenőrizendő mezők Cél
users first_name, last_name Regisztráció alapfeltétele.
audit_logs ip_address, endpoint Naplózás hiba elkerülése.
verification_tokens token_hash Aktiváló email hiba elkerülése.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.33 | 2026.01.27 - 23:15)
Állomány Státusz Megjegyzés
user.py ✅ FIXÁLVA Kapcsolatok kikommentelve, SQLAlchemy hiba megszűnt.
main.py ✅ KÉSZ V1 és V2 útvonalak a helyükön.
docker 🟢 FUT A konténer elindult.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.32 | 2026.01.27 - 23:05)
Hiba Állapot Megoldás
500 Internal Error 🔍 DIAGNÓZIS ALATT Logok ellenőrzése szükséges.
Audit Logs 🏗️ BŐVÍTÉS ip_address oszlop ellenőrzése.
Vehicle Seeding ⏳ VÁRAKOZIK Az alapvető regisztráció után indul.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.27 | 2026.01.27 - 22:15)
Hiba Megoldás Státusz
Missing Module (requests) Lecserélve urllib-re (standard lib). ✅ MEGOLDVA
Syntax Error (törmelék kód) tee parancsal felülírva a teljes fájl. ✅ MEGOLDVA
API Egységesség V1 eltávolítva, minden a V2 alatt fut. ✅ MEGOLDVA
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.27 | 2026.01.27 - 22:15)
Hiba Megoldás Státusz
Missing Module (requests) Lecserélve urllib-re (standard lib). ✅ MEGOLDVA
Syntax Error (törmelék kód) tee parancsal felülírva a teljes fájl. ✅ MEGOLDVA
API Egységesség V1 eltávolítva, minden a V2 alatt fut. ✅ MEGOLDVA
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.27 | 2026.01.27 - 22:15)
Hiba Megoldás Státusz
Missing Module (requests) Lecserélve urllib-re (standard lib). ✅ MEGOLDVA
Syntax Error (törmelék kód) tee parancsal felülírva a teljes fájl. ✅ MEGOLDVA
API Egységesség V1 eltávolítva, minden a V2 alatt fut. ✅ MEGOLDVA
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.26 | 2026.01.27 - 22:12)
Modul Státusz Javítás
main.py 🟢 AKTÍV Szintaktikai hiba eltávolítva.
v2/auth.py 🟢 AKTÍV Tartalom frissítve, V1 függőség levágva.
Container 🟢 FUT Újraindítás után online.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.25 | 2026.01.27 - 22:01)
Tábla Verzió Státusz Megjegyzés
users DB ✅ KÉSZ first_name, last_name oszlopok a helyükön.
email_providers DB ✅ KÉSZ SendGrid (id: 5) aktív a CSV alapján.
API Routes Kód ⚠️ ZAVAROS V1 és V2 keveredés.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.23 | 2026.01.27 - 22:30)
Feladat Státusz Megoldás
Email duplikáció 🛠️ JAVÍTÁS ALATT DELETE + UNIQUE CONSTRAINT SQL.
Auth.py telepítés ✅ KÉSZ Heredoc (cat) módszerrel frissítve.
500-as hiba 🔍 TESZTELÉSRE VÁR Az SQL lefutása után elvileg megszűnik.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.22 | 2026.01.27 - 22:15)
Modul Állapot Megjegyzés
Auth API ✅ KÉSZ auth.py frissítve, mezők szinkronban.
Email Providers ✅ KÉSZ Duplikációk törölve, SendGrid aktív.
Audit Log ✅ KÉSZ Minden regisztrációt naplóz (IP-vel).
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.21 | 2026.01.27 - 22:05)
Tábla Séma Változás Státusz
users data first_name, last_name mezők aktívak ✅ KÉSZ
email_providers data unique_provider_name kényszer hozzáadva ✅ KÉSZ
auth.py Fájl Kereszt/Vezetéknév szétválasztva ✅ KÉSZ
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.20 | 2026.01.27 - 21:55)
Funkció Admin-beállítás (Key) Érték
Bot-védelem registration_throttle_minutes 10
Helyszín-szűrő allowed_countries_list [EU Országok]
E-mail Motor email_providers SendGrid (Aktív)
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.19 | 2026.01.27 - 21:45)
Funkció Módszer Beállítás helye
Bot-védelem IP Throttling (10 perc) audit_logs alapján a kódban
EU-szűrés Geo-IP lookup EU_COUNTRIES halmaz a kódban
Naplózás Automatikus audit_logs tábla
📘 ADATBÁZIS SÉMA KÖNYV (v2.18 | 2026.01.27 - 21:40)
Tábla Séma Cél Státusz
users data Felhasználók törzsadatai 🔍 Audit folyamatban
email_providers data SMTP/API elérések 🔍 Audit folyamatban
audit_logs data Műveleti napló ✅ Ellenőrzésre vár
📘 ADATBÁZIS SÉMA KÖNYV (v2.18 | 2026.01.27 - 21:40)
Tábla Séma Aktuális mezők (Modell szerint) Státusz
users data
id, email, hashed_password, first_name, last_name, role, is_active...
⚠️ Ellenőrzés alatt
audit_logs data
table_name megerősítve
✅ Létezik
verification_tokens data
table_name megerősítve
✅ Létezik
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.17 | 2026.01.27 - 22:30)
Modul Állapot Következő akció
Auth v1 ✅ KÉSZ Swagger tesztelés a felhasználó által.
Audit/Email Log ✅ KÉSZ Validálás a pgAdminban.
Vehicle Catalog 🏗️ TERVEZÉS Tábla létrehozás a teszt után.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.16 | 2026.01.27 - 22:10)
Modul Állapot Funkció
Auth System ✅ KÉSZ Regisztráció + Aktiválás + Jelszó reset (Audit loggal).
Email Manager ✅ KÉSZ Többcsatornás, Throttling védett küldés.
Locations ✅ KÉSZ Koordináta alapú keresés alapjai.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.15 | 2026.01.27 - 21:55)
Tábla Státusz Szerep
data.verification_tokens ✅ AKTÍV Jelszó-visszaállító és regisztrációs kulcsok.
data.audit_logs ✅ AKTÍV Felhasználói mozdulatok naplózása.
data.email_logs ✅ AKTÍV Kiküldött emailek követése és Throttling.
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.14 | 2026.01.27 - 21:40)
Tábla Séma Feladat Státusz
audit_logs data Felhasználói aktivitás követése ✨ ÚJ
system_settings data Minden paraméter vezérlése ✅ Bővítve
email_providers data Multi-channel e-mail ✅ SendGrid kész, Brevo várható
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.13 | 2026.01.27 - 20:30)
Tábla Séma Cél Státusz
email_providers data SMTP/API adatok & Prioritás ✅ Adattal feltöltve (SendGrid)
email_logs data Audit log & Throttling ✅ Aktív
verification_tokens data Biztonsági kódok (Reg/Reset) ✅ Szerkezet kész
📘 ADATBÁZIS ÁLLAPOT KÖNYV (v2.12 | 2026.01.27 - 21:35)
Tábla Séma Státusz Megjegyzés
email_providers data ✅ KÉSZ Tárolja az SMTP/API eléréseket és prioritásokat.
email_logs data ✅ KÉSZ Biztosítja a 3 perces várakozást (Throttling).
verification_tokens data ✅ KÉSZ Biztonságos token-alapú regisztrációhoz.
📘 ADATBÁZIS SÉMA KÖNYV (v2.7 | 2026.01.27 - 22:15)
Objektum Típus Állapot Szerep
data.system_settings Tábla ✅ Minden üzleti paraméter forrása.
data.organization_locations Tábla ✅ Pontos GPS koordináták és címek.
orgtype.SERVICE Enum ✅ Szerviz partnerek megkülönböztetése.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.7 | 2026.01.27 - 21:25)
Audit: A beküldött CSV fájlok (tablak_2026.01.27_2.csv) igazolták, hogy a változók nevei és értékei megfelelnek a Python kód igényeinek.
Javítás: Az Enum SERVICE értékét leválasztottuk az insert-ről, így az integritás helyreállt.
Adat: A Gumi Mester Kft. adatai a "Pesti Gyorsszerviz" és "Budaörsi Telep" helyszínekkel mostantól alkalmasak a térbeli keresési tesztre.
📘 ADATBÁZIS SÉMA KÖNYV (v2.6 | 2026.01.27 - 21:25)
Tábla Séma Oszlopok Állapot
organizations data id, name, org_type (enum), slug ✅ SZINKRONIZÁLVA (SERVICE enum kész)
organization_locations data id, org_id, lat, lng, address ✅ AKTÍV (Térbeli alapok kész)
system_settings data key_name, value_json, org_id... ✅ VALIDÁLVA (A CSV alapján minden kulcs él)
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.6 | 2026.01.27 - 21:10)
Integritás: A data séma és a public enumok közötti ellentmondás feloldva.
Változók állapota: A beküldött CSV igazolta, hogy a MatchingService és a ConfigService számára minden paraméter rendelkezésre áll.
Helyszín adatok: Budapesti teszt koordináták (Budaörs és Váci út) előkészítve a keresési teszthez.
📘 ADATBÁZIS SÉMA KÖNYV (v2.5 | 2026.01.27 - 21:10)
Tábla Séma Mezők Státusz
organizations data id, name, org_type, slug ✅ Enum javítva (SERVICE hozzáadva)
organization_locations data id, org_id, lat, lng, label ✨ Létrehozva a geolokációhoz
system_settings data key_name, value_json ✅ Validálva a beküldött CSV alapján
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.5 | 2026.01.27 - 20:50)
Kritikus hiba: Az orgtype enum nem ismeri a "SERVICE" értéket. Ez blokkolja a tesztadatok (Gumi Mester Kft.) beszúrását.
Séma helyzet: A public -> data költöztetés elvileg megtörtént, de az audit SQL-lel validáljuk.
Változók: A nevek (key_name, value_json) megfelelnek a Python ConfigService elvárásainak.
📘 ADATBÁZIS SÉMA KÖNYV (v2.4 | 2026.01.27 - 20:50)
Tábla Séma Státusz Megjegyzés
users data ✅ Stabil Tartalmazza az is_staff mezőt.
organizations data ⚠️ Ellenőrzés alatt Az org_type enum értékeit tisztázni kell.
organization_members data ✅ Stabil unique_user_org kényszer aktív.
system_settings data ✅ Stabil Hierarchikus index és kulcsok rendben.
organization_locations data ✨ Létrehozva Készen áll a koordináták fogadására.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.4 | 2026.01.27 - 20:30)
Séma Tisztaság: Megkezdődött a public séma kiürítése, az üzleti logika izolált.
Helyszín Kezelés: Mostantól támogatjuk, hogy egy szerviznek több pontja legyen a térképen.
Keresési Logika: A következő lépésben a MatchingService már nem fix listából, hanem ebből az organization_locations táblából fog válogatni.
📘 ADATBÁZIS SÉMA KÖNYV (v2.3 | 2026.01.27 - 20:30)
Tábla Séma Változás Megjegyzés
organizations data ✅ Stabil Fő szervezeti adatok.
service_providers data 🚚 Áthelyezve Migrálva a public sémából.
organization_locations data ✨ ÚJ Koordináták (lat, lng) tárolása
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.3 | 2026.01.27 - 20:45)
Migráció: Előkészítve a public -> data áthelyezés.
Geolokáció: A koordináták tárolása külön organization_locations táblába kerül a multi-site támogatás érdekében.
Matematika: A távolság számításához a Haversine-formulát fogjuk használni:
d=2rarcsin(sin2(2ϕ2ϕ1)+cos(ϕ1)cos(ϕ2)sin2(2λ2λ1))
📘 ADATBÁZIS SÉMA KÖNYV (v2.2 | 2026.01.27 - 20:45)
Tábla Séma Változás Cél
organizations data Move from public Üzleti adatok izolálása.
service_providers data Move from public Üzleti adatok izolálása.
organization_locations data ÚJ TÁBLA Geofencing és Smart Match alapja.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.2 | 2026.01.27 - 19:50)
Audit: Az organizations tábla szerkezete beazonosítva. Hiányoznak a közvetlen helyadatok (geolokáció).
Folytonosság: A ConfigService és a MatchingService felkészült, már csak a "bemeneti forrást" (a valódi koordinátákat) kell becsatornáznunk.
Kockázat: Alacsony. Ha megvan a helyszín tábla, egy egyszerű JOIN-nal összekötjük a szervizeket a helyükkel.
📘 ADATBÁZIS SÉMA KÖNYV (v2.1 | 2026.01.27 - 19:50)
Tábla Oszlopok Típus Leírás
organizations
id, name, org_type, slug, is_active
int, varchar, Enum, boolean
Szervezetek törzsadatai.
system_settings key_name, value_json, org_id varchar, jsonb, int Dinamikus szabályok és súlyok.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.1 | 2026.01.27 - 20:20)
API: /api/v1/search/match végpont ✅ LÉTREHOZVA.
Logika: MatchingService ✅ LÉTREHOZVA.
Adat: SQL paraméterek ✅ BETÖLTVE.
Hiány: A szervizek földrajzi helyzetének (lat/lng) pontos táblája és oszlopneve.
📘 ADATBÁZIS SÉMA KÖNYV (v2.0 | 2026.01.27 - 20:20)
Tábla Séma Funkció Megjegyzés
system_settings data Konfigurációk Súlyozási paraméterek rögzítve.
organizations data Entitások Itt keressük majd a szervizeket (role='service').
service_specialties data Képességek Ez alapján szűrünk a konkrét hibára.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v2.0 | 2026.01.27 - 19:40)
SQL Audit: A 4 alapvető rangsorolási paraméter immár az adatbázisban él (INSERT 0 4).
Szerviz Réteg: A MatchingService sikeresen létrejött, a kód képes elvégezni a súlyozott számítást.
Hiba elhárítva: A PermissionError a sudo használatával áthidalva.
📘 ADATBÁZIS SÉMA KÖNYV (v1.9 | 2026.01.27 - 19:40)
Tábla Séma Kulcsfontosságú változás
system_settings data Beépítve a súlyozási konstansok (distance, rating, bonus).
ranking_policies data Üres, de a struktúra készen áll a komplexebb szabályokhoz.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v1.9 | 2026.01.27 - 19:30)
Algoritmus: Kész. A pontszámítás képlete:
S=(Pdist⋅Wdist)+(Prate⋅Wrate)+Btier
Rugalmasság: ✅ Teljes. A MatchingService minden kérésnél frissen kéri le a súlyokat a ConfigService-től.
📘 ADATBÁZIS SÉMA KÖNYV (v1.8 | 2026.01.27 - 19:30)
Tábla Oszlop Típus Leírás
system_settings value_json jsonb Itt tároljuk a weight_distance és weight_rating értékeket.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v1.8 | 2026.01.27 - 19:15)
Esemény: A korábbi kód-korrupció észlelése és javítása.
Integritás: A Python config hívás most már tiszta szintaxissal fut a fleet.py-ban.
Adat: Az Admin Flotta (ID: 1) készen áll a dinamikus limitek tesztelésére.
📘 ADATBÁZIS SÉMA KÖNYV (v1.7 | 2026.01.27 - 19:15)
Tábla Séma Főbb indexek Státusz
system_settings data idx_settings_lookup ✅ AKTÍV
organizations data slug_unique ✅ AKTÍV
vehicles data vin_unique ✅ AKTÍV
ADATBÁZIS ÁLLAPOT NAPLÓ (v1.7 | 2026.01.27 - 19:10)
Szinkron: A ConfigService kódja és a system_settings tábla oszlopai (key_name, value_json) megegyeznek.
Tesztre kész: Az adatbázisban a max_vehicles értéke 3, az Admin pedig az 1-es szervezetben van.
📘 ADATBÁZIS SÉMA KÖNYV (v1.6 | 2026.01.27 - 19:10)
Tábla Séma Állapot Funkció
system_settings data ✅ Aktív Hierarchikus konfiguráció (key_name, value_json).
vehicles data ✅ Stabil Járművek törzsadatai.
vehicle_ownership data ✅ Stabil User-Vehicle összerendelés.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v1.6 | 2026.01.27 - 11:15)
Audit: A max_vehicles = 3 rekord sikeresen létrejött a data.system_settings táblában.
Hierarchia: A idx_settings_lookup index biztosítja, hogy az egyedi (Org/Tier/Region) felülbírálások ne ütközzenek.
Előkészítve: A fleet.py és a ConfigService kódja megvan, csak a fájlrendszerbe kell írni őket.
📘 ADATBÁZIS SÉMA KÖNYV (v1.5 | 2026.01.27 - 11:15)TáblaSémaFőbb mezőkCélsystem_settingsdatakey_name, value_json, org_idA hierarchikus szabálymotor tárolója.organizationsdataid, name, slugSzervezeti egységek (pl. Admin Flotta).organization_membersdatauser_id, organization_id, roleJogosultsági és tagsági háló.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v1.4 | 2026.01.27 - 10:45)
Status: max_vehicles = 3 rögzítve a data.system_settings táblában.
Fájlrendszer: Az app/services/ mappa létezik, de a config_service.py még hiányzik.
Elmaradás: Szükségem van a korábban kért SQL lekérdezés eredményére (Admin org_id és role), hogy a tesztelésnél tudjuk, melyik szervezetet nézzük.
📘 ADATBÁZIS SÉMA KÖNYV (v1.3 | 2026.01.27 - 10:45)TáblaSémaMezőkMegjegyzéssystem_settingsdatakey_name, value_json, region_code, tier_id, org_idHierarchikus motor.vehiclesdataid, vin, plate_number, model_idDigitális iker alapadatai.vehicle_ownershipdatauser_id, vehicle_id, is_activeKapcsolati tábla (Kié az autó?).
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v1.3 | 2026.01.27 - 10:15)
Állapot: ✅ Stabil és szinkronban a kóddal.
Változás: A Python ConfigService immár az app/services/ alá került, követve a tiszta architektúrát.
Audit: Az SQL-ben korábban rögzített max_vehicles (3) rekord elérhető a service számára.
📘 ADATBÁZIS SÉMA KÖNYV (v1.2 | 2026.01.27 - 10:15)TáblaSémaMezőkMegjegyzéssystem_settingsdatakey_name, value_json, region_code, tier_id, org_idA hierarchikus beállítások tárolója.ranking_policiesdatapolicy_name, distance_weight, rating_weightA szerviz-kereső súlyozási szabályai.
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (v1.2 | 2026.01.27 - 10:10)
Állapot: ✅ Stabil.
Utolsó SQL: INSERT INTO data.system_settings (max_vehicles) sikeresen lefutott.
Változás: A key_name és value_json elnevezések rögzítve.
Következő cél: A fleet.py-ban a fix 3-as korlát kiváltása config.get_setting('max_vehicles') hívással.
ADATBÁZIS SÉMA KÖNYV (v1.1 | 2026.01.27 - 10:10)TáblaOszlopok (Lényegesek)Kényszerek / Indexekdata.system_settingskey_name, value_json, region_code, tier_id, org_ididx_settings_lookup (Unique)data.ranking_policiespolicy_name, distance_weight, rating_weightid (PK)data.organization_membersorganization_id, user_id, roleunique_user_org
🗄️ ADATBÁZIS ÁLLAPOT NAPLÓ (DB State Book)
Integritás: ✅ Kiváló. Az oszlopnevek szinkronizálva (key_name, value_json).
Utolsó művelet: idx_settings_lookup index létrehozva, max_vehicles alapérték beszúrva.
Kockázat: Nincs. A séma stabil az API fejlesztéséhez.
🗄️ 3. Adatbázis Állapot Napló (DB State Book)
Tábla neve Séma Állapot Megjegyzés
system_settings data ✅ Stabil Tartalmazza a key_name, value_json és a 3 szintű override oszlopot.
ranking_policies data ✅ Kész A szerviz-rangsorolás súlyait tárolja.
idx_settings_lookup data ✅ Aktív Biztosítja a hierarchikus egyediséget.
PM senior
Egyéni gem
Úgy tűnik, a system_settings táblád még egy korábbi (talán tegnapi) néven tárolja az oszlopokat, ahol valószínűleg csak simán key és value volt a nevük. A PostgreSQL-ben a key és value foglalt szavak (reserved words), ezért javasoltam a key_name és value_json formátumot de a tábla most épp "félúton" van a két állapot között.
Tegyünk rendet egy olyan SQL-lel, ami felismeri a régi neveket és átnevezi őket az újra, így nem kell törölni semmit!
🛠️ 1. Adatbázis „Helyrerakó” Script (psql / pgAdmin)
Futtasd le ezt. Ez a script intelligensen átnevezi az oszlopokat, ha a régi néven találja meg őket:
SQL
DO $$
BEGIN
-- 1. Oszlopnevek egységesítése
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='system_settings' AND column_name='key') THEN
ALTER TABLE data.system_settings RENAME COLUMN "key" TO key_name;
END IF;
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='system_settings' AND column_name='value') THEN
ALTER TABLE data.system_settings RENAME COLUMN "value" TO value_json;
END IF;
-- 2. Hiányzó hierarchia oszlopok pótlása
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='system_settings' AND column_name='region_code') THEN
ALTER TABLE data.system_settings ADD COLUMN region_code VARCHAR(5);
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='system_settings' AND column_name='tier_id') THEN
ALTER TABLE data.system_settings ADD COLUMN tier_id INTEGER;
END IF;
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='system_settings' AND column_name='org_id') THEN
ALTER TABLE data.system_settings ADD COLUMN org_id INTEGER;
END IF;
END $$;
-- 3. Index frissítése (most már biztosan léteznek az oszlopok)
DROP INDEX IF EXISTS data.idx_settings_lookup;
CREATE UNIQUE INDEX idx_settings_lookup ON data.system_settings
(key_name, COALESCE(region_code, ''), COALESCE(tier_id, 0), COALESCE(org_id, 0));
-- 4. Alapértelmezett érték beszúrása tesztnek
INSERT INTO data.system_settings (key_name, value_json, description)
VALUES ('max_vehicles', '3'::jsonb, 'Globális alapértelmezett járműlimit a Free csomagban')
ON CONFLICT (key_name, COALESCE(region_code, ''), COALESCE(tier_id, 0), COALESCE(org_id, 0)) DO NOTHING;
📚 2. Változó Könyv (Variable Map) v1.1
A rendszer paramétereinek aktuális állapota és hivatkozási pontjai.
Kulcs (Key) Adattípus Alapértelmezés Szerep Hivatkozás (Fájl/Modul)
max_vehicles int 3 Free flotta méret korlát fleet.py -> ConfigService
search_radius int 20 Alap keresési távolság search.py -> ConfigService
ranking_policy json {...} Súlyozási együtthatók RankingEngine
🗄️ 3. Adatbázis Állapot Napló (DB State Book)
Tábla neve Séma Állapot Megjegyzés
system_settings data ✅ Stabil Tartalmazza a key_name, value_json és a 3 szintű override oszlopot.
ranking_policies data ✅ Kész A szerviz-rangsorolás súlyait tárolja.
idx_settings_lookup data ✅ Aktív Biztosítja a hierarchikus egyediséget.
📘 ADATBÁZIS SÉMA KÖNYV (Database Schema Book) v1.0
A rendszer jelenlegi fizikai struktúrája
Séma: data
users
id: serial (PK)
email: varchar (Unique)
is_staff: boolean (Admin/Moderátor jelző)
organizations
id: serial (PK)
name: varchar
slug: varchar (Unique, url-barát azonosító)
organization_members
id: serial (PK)
organization_id: int (FK -> organizations)
user_id: int (FK -> users)
role: public.orguserrole (Enum)
is_permanent: boolean
Constraint: unique_user_org (organization_id, user_id)
system_settings (A konfigurációs motor agya)
id: serial (PK)
key_name: varchar (Unique-index része)
value_json: jsonb (Dinamikus érték)
region_code: varchar(5) (Override szint)
tier_id: int (Override szint)
org_id: int (Override szint)
ranking_policies
id: serial (PK)
policy_name: varchar
distance_weight: numeric(3,2)
rating_weight: numeric(3,2)
tier_bonus: int

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
📕 Változók könyve (20260128_2230)
VIN_GRACE_PERIOD: 14 nap (Ideiglenes jármű érvényessége).
LANG_DEFAULT: 'hu'
EMAIL_TEMPLATE_REGISTRATION: A regisztrációs sablon kulcsa.
📕 Változók könyve (20260128_2145)
EQUIPMENT_SOURCE: factory (gyári), aftermarket (utólagos).
VEHICLE_CATEGORIES: Kibővítve (Hajó, Repülő kategóriákkal).
📕 Változók könyve (20260128_2130)
VEHICLE_CATEGORIES: 1: Car, 2: Motorcycle, 3: Truck, 4: Van, 5: Bus, 6: Machinery.
FUEL_TYPES: Petrol, Diesel, Electric, LPG, CNG, Hybrid, PHEV, Hydrogen.
BACKUP_LOC: /mnt/nas/git_vault/
📕 Változók könyve (20260128_2105)
PG_DATABASE: service_finder
PG_SCHEMA: data
DB_BACKUP_PATH: /opt/service_finder/backup_20260128_alap_kesz.sql
USER_ID_1: Zsolt (zs.gyongyossy@gmail.com) - Manuális széf rendelés szükséges.
📕 Változók könyve (20260128_2030)
registration_throttle_minutes: 10 perc (Beállítva a regisztráció spammelés ellen).
email_wait_time_minutes: 3 perc (Két levél közötti várakozás júzerenként).
DOCKER_API_VERSION: 1.41 (A code-server és a gazdagép közötti kommunikációhoz).
CompanyRole.OWNER: Az automatikusan létrehozott privát széf alapértelmezett jogosultsága.
📚 VÁLTOZÓ KÖNYV (v2.17 | 2026.01.27 - 22:15)
Kulcs Érték Szerep
registration_throttle_minutes 10 Bot-védelem aktív.
allowed_countries_list [EU] Regionális szűrés aktív.
📚 VÁLTOZÓ KÖNYV (v2.16 | 2026.01.27 - 21:55)
Kulcs Érték Szerep
SECRET_KEY .env-ben JWT token aláírás és titkosítás.
SENDGRID_API_KEY DB-ben Email küldés hitelesítése.
📚 VÁLTOZÓ KÖNYV (v2.15 | 2026.01.27 - 21:45)
Kulcs Típus Érték Leírás
registration_throttle_minutes int 10 Ennyi időnek kell eltelnie két regisztráció közt ugyanarról az IP-ről.
allowed_regions list EU Engedélyezett földrajzi zónák.
📚 VÁLTOZÓ KÖNYV (v2.14 | 2026.01.27 - 21:40)
Kulcs Típus Jelenlegi érték Megjegyzés
max_vehicles int 3 Érvényes a system_settings alapján.
audit_log_enabled bool true A naplózásnak futnia kell.
📚 VÁLTOZÓ KÖNYV (v2.14 | 2026.01.27 - 21:40)
Kulcs Érték Leírás
max_vehicles 3
Szervezeti flotta limit.
weight_distance 0.6
Távolság súlyozása.
weight_rating 0.4
Értékelés súlyozása.
📚 VÁLTOZÓ KÖNYV (v2.13 | 2026.01.27 - 21:55)
Kulcs Érték Leírás
audit_log_enabled true Automatikus naplózás kapcsolója.
email_wait_time_minutes 3 Spam elleni védelem időkorlátja.
📚 VÁLTOZÓ KÖNYV (v2.12 | 2026.01.27 - 21:40)
Kulcs Típus Alapérték Hol módosítható?
audit_log_enabled bool true Admin / system_settings
audit_log_retention int 90 Admin / system_settings
email_wait_time int 3 Admin / system_settings
📚 VÁLTOZÓ KÖNYV (v2.11 | 2026.01.27 - 20:30)
Kulcs Típus Érték Modul
email_wait_time_minutes int 3 EmailManager
sender_name string Service Finder Email fejléc
sender_email string info@profibot.hu Hitelesített feladó
📚 VÁLTOZÓ KÖNYV (v2.10 | 2026.01.27 - 21:35)
Kulcs Típus Érték Leírás
email_wait_time_minutes int 3 Minimum idő két levél között.
max_email_retries int 3 Hány szolgáltatóval próbálkozzon hiba esetén.
📚 VÁLTOZÓ KÖNYV (Email Specifikus)
Kulcs Típus Leírás
email_wait_time_minutes int Mennyit kell várni két levél között (Alap: 3).
max_email_retries int Hányszor próbálkozzon másik szolgáltatóval.
system_sender_email str A feladó neve (pl. info@servicefinder.hu).
📚 VÁLTOZÓ KÖNYV (v2.9 | 2026.01.27 - 22:15)
Kulcs Érték Modul
weight_distance 0.6 MatchingService
weight_rating 0.4 MatchingService
max_vehicles 3 fleet.py
📚 VÁLTOZÓ KÖNYV (v2.8 | 2026.01.27 - 21:25)
Változó (Key) Érték Szerep Ellenőrizve (CSV)
weight_distance 0.6 Távolság súlya a rangsorban ✅ Igen
weight_rating 0.4 Értékelés súlya a rangsorban ✅ Igen
bonus_gold_service 500 Fizetős partnerek előnye ✅ Igen
match_limit_default 5 Találati lista hossza ✅ Igen
max_vehicles 3 Flotta limit ✅ Igen
📚 VÁLTOZÓ KÖNYV (v2.7 | 2026.01.27 - 21:10)
Minden változó a beküldött tablak_2026.01.27_2.csv alapján rögzítve:
Kulcs (Key) Érték Szerep
max_vehicles 3 Flotta limit (Alapértelmezett)
weight_distance 0.6 Távolság súlya a keresőben
weight_rating 0.4 Értékelés súlya a keresőben
bonus_gold_service 500 VIP szervizek pontszám előnye
match_limit_default 5 Keresési találatok száma
📚 VÁLTOZÓ KÖNYV (v2.6 | 2026.01.27 - 20:50)
Kulcs (Key) Típus Hivatkozott Modul Elvárt viselkedés
max_vehicles int fleet.py Szervezeti szintű flotta limit.
weight_distance float matching_service.py Keresési rangsor súlyozás (Alap: 0.6).
weight_rating float matching_service.py Keresési rangsor súlyozás (Alap: 0.4).
match_limit_default int search.py Visszaadott találatok száma.
📚 VÁLTOZÓ KÖNYV (v2.5 | 2026.01.27 - 20:30)
Kulcs Típus Alapérték Szerep
weight_distance float 0.6 Távolság fontossága (0-1).
weight_rating float 0.4 Értékelés fontossága (0-1).
earth_radius_km int 6371 Föld sugara a Haversine számításhoz.
📚 VÁLTOZÓ KÖNYV (v2.4 | 2026.01.27 - 20:45)
Kulcs Típus Alapérték Szerep
geo_precision int 8 Tizedesjegyek száma a koordinátáknál.
distance_unit string km Keresési mértékegység.
📚 VÁLTOZÓ KÖNYV (v2.3 | 2026.01.27 - 19:50)
Kulcs Típus Alapérték Implementáció
weight_distance float 0.6 MatchingService - Aktív
weight_rating float 0.4 MatchingService - Aktív
max_vehicles int 3 fleet.py - Aktív
📚 VÁLTOZÓ KÖNYV (v2.2 | 2026.01.27 - 20:20)
Kulcs Típus Alapérték Új szerep
weight_distance float 0.6 A térbeli közelség fontossága.
weight_rating float 0.4 A minőség (csillagok) súlya.
📚 VÁLTOZÓ KÖNYV (v2.1 | 2026.01.27 - 19:40)
Kulcs Típus Jelenlegi érték Leírás
weight_distance float 0.6 Mennyire "büntesse" a rendszer a távolságot.
weight_rating float 0.4 Mennyire jutalmazza a jó véleményeket.
bonus_gold_service int 500 A fizetős partnerek fix előnye.
match_limit_default int 5 Alapértelmezett találati szám.
📚 VÁLTOZÓ KÖNYV (v2.0 | 2026.01.27 - 19:30)
Kulcs Típus Alapérték Szerep
weight_distance float 0.6 Mennyire számít a távolság (Admin állíthatja)
weight_rating float 0.4 Mennyire számít az értékelés (Admin állíthatja)
bonus_gold_service int 500 Gold partnerek előnye
match_limit_default int 5 Hány találat jelenjen meg
📚 VÁLTOZÓ KÖNYV (v1.9 | 2026.01.27 - 19:15)
Kulcs Típus Alapérték Hol érhető el?
max_vehicles int 3 ConfigService -> fleet.py
search_radius int 20 ConfigService -> Coming soon
📚 VÁLTOZÓ KÖNYV (v1.8 | 2026.01.27 - 19:10)
Kulcs Típus Alapérték Hol van használatban?
max_vehicles int 3 fleet.py (add_vehicle végpont)
search_radius int 20 Előkészítve a keresőhöz
📚 VÁLTOZÓ KÖNYV (v1.7 | 2026.01.27 - 11:15)Változó neveTípusAktuális értékImplementáció állapotamax_vehiclesint3 (Global)DB-ben rögzítve, fleet.py frissítésre vár.search_radiusint20 (Default)Tervezett: Smart Matching modul.ranking_policyjsonAlapértelmezettTervezett: Ranking Engine.
📚 VÁLTOZÓ KÖNYV (v1.5 | 2026.01.27 - 10:45)Kulcs (Key)TípusAlapértékForrásfájlmax_vehiclesint3app/api/v1/endpoints/fleet.py
📚 VÁLTOZÓ KÖNYV (v1.4 | 2026.01.27 - 10:15)Kulcs (Key)AdattípusAlapértékImplementációs helymax_vehiclesint3backend/app/services/config_service.pysearch_radiusint20Tervezett: search_service.py
📚 VÁLTOZÓ KÖNYV (v1.3 | 2026.01.27 - 10:10)Kulcs (Key)Érték (JSON)SzintModulmax_vehicles3Globalfleet.pysearch_radius20Globalsearch.py
📚 VÁLTOZÓ KÖNYV (Variable Map) v1.2Kulcs (Key)TípusAlapértelmezettFunkciómax_vehiclesint3Járműlimit / szervezetsearch_radiusint20Alap keresési sugár (km)
📚 2. Változó Könyv (Variable Map) v1.1A rendszer paramétereinek aktuális állapota és hivatkozási pontjai.Kulcs (Key)AdattípusAlapértelmezésSzerepHivatkozás (Fájl/Modul)max_vehiclesint3Free flotta méret korlátfleet.py -> ConfigServicesearch_radiusint20Alap keresési távolságsearch.py -> ConfigServiceranking_policyjson{...}Súlyozási együtthatókRankingEngine
Változó neve,Leírás,Alapértelmezés (Global),Hol szerepel a kódban?
max_vehicles,Ingyenes csomagban rögzíthető autók száma,3,app/api/v1/endpoints/fleet.py
default_search_radius,Alapértelmezett keresési távolság (km),20,app/api/v1/endpoints/search.py
max_search_radius,Maximálisan állítható sugár (km),500,app/api/v1/endpoints/search.py
credit_price_per_unit,1 kredit ára pénznemben,1.0,app/api/v1/endpoints/billing.py

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,662 @@
.
./docker-compose.yml
./postgres
./postgres/init-db.sql
./postgres/data
./postgres/data/pg_commit_ts
./postgres/data/pg_logical
./postgres/data/pg_logical/snapshots
./postgres/data/pg_logical/mappings
./postgres/data/pg_logical/replorigin_checkpoint
./postgres/data/base
./postgres/data/base/16384
./postgres/data/base/5
./postgres/data/base/16537
./postgres/data/base/1
./postgres/data/base/4
./postgres/data/pg_hba.conf
./postgres/data/pg_dynshmem
./postgres/data/pg_xact
./postgres/data/pg_xact/0000
./postgres/data/postgresql.auto.conf
./postgres/data/pg_stat
./postgres/data/PG_VERSION
./postgres/data/pg_stat_tmp
./postgres/data/pg_subtrans
./postgres/data/pg_subtrans/0000
./postgres/data/pg_ident.conf
./postgres/data/pg_snapshots
./postgres/data/global
./postgres/data/global/1232
./postgres/data/global/pg_filenode.map
./postgres/data/global/6001
./postgres/data/global/1260_vm
./postgres/data/global/2677
./postgres/data/global/2847
./postgres/data/global/1262
./postgres/data/global/3592
./postgres/data/global/4177
./postgres/data/global/3593
./postgres/data/global/4185
./postgres/data/global/2676
./postgres/data/global/2396
./postgres/data/global/1261_vm
./postgres/data/global/2671
./postgres/data/global/6243
./postgres/data/global/pg_internal.init
./postgres/data/global/2964
./postgres/data/global/4182
./postgres/data/global/1260_fsm
./postgres/data/global/4181
./postgres/data/global/4178
./postgres/data/global/1213_fsm
./postgres/data/global/4175
./postgres/data/global/1261
./postgres/data/global/2695
./postgres/data/global/1233
./postgres/data/global/4186
./postgres/data/global/4183
./postgres/data/global/2396_fsm
./postgres/data/global/4061
./postgres/data/global/2694
./postgres/data/global/6000
./postgres/data/global/4184
./postgres/data/global/1260
./postgres/data/global/pg_control
./postgres/data/global/2967
./postgres/data/global/6100
./postgres/data/global/1262_vm
./postgres/data/global/2397
./postgres/data/global/6244
./postgres/data/global/6246
./postgres/data/global/6002
./postgres/data/global/1262_fsm
./postgres/data/global/4176
./postgres/data/global/6114
./postgres/data/global/6245
./postgres/data/global/2672
./postgres/data/global/1214_fsm
./postgres/data/global/1261_fsm
./postgres/data/global/4060
./postgres/data/global/2966
./postgres/data/global/6247
./postgres/data/global/2846
./postgres/data/global/1213_vm
./postgres/data/global/6302
./postgres/data/global/6115
./postgres/data/global/2396_vm
./postgres/data/global/2698
./postgres/data/global/2697
./postgres/data/global/2965
./postgres/data/global/1214
./postgres/data/global/6303
./postgres/data/global/1213
./postgres/data/pg_serial
./postgres/data/pg_replslot
./postgres/data/pg_tblspc
./postgres/data/pg_multixact
./postgres/data/pg_multixact/members
./postgres/data/pg_multixact/offsets
./postgres/data/pg_twophase
./postgres/data/pg_notify
./postgres/data/postgresql.conf
./postgres/data/pg_wal
./postgres/data/pg_wal/summaries
./postgres/data/pg_wal/archive_status
./postgres/data/pg_wal/000000010000000000000002
./postgres/data/pg_wal/000000010000000000000003
./postgres/data/postmaster.opts
./postgres/data/postmaster.pid
./docker-compose_2.yml
./migrations
./migrations/script.py.mako
./migrations/env.py
./migrations/README
./migrations/versions
./migrations/versions/8d450e9dc77f_add_vehicle_staging.py
./migrations/versions/553ef1388276_rebuild_schema_v2.py
./migrations/versions/c21c2c7e70d4_clean_gamification_setup.py
./Projekt Állapot jelentés.txt
./redis
./redis/data
./redis/data/appendonlydir
./redis/data/appendonlydir/appendonly.aof.1.incr.aof
./redis/data/appendonlydir/appendonly.aof.manifest
./redis/data/appendonlydir/appendonly.aof.1.base.rdb
./redis/data/dump.rdb
./Service_finder Rendszerspecifikáció es feljesztes.txt
./Promptok gemekhez.txt
./pgadmin_data
./pgadmin_data/sessions
./pgadmin_data/sessions/f77af245-3aa1-4f88-a566-3be55403448f
./pgadmin_data/sessions/239aceee-a89e-434c-980e-19e2421de51f
./pgadmin_data/sessions/643b0d62-38a1-4a32-b48b-f7e053e7214f
./pgadmin_data/sessions/c38b97cd-80d7-40e1-8ab7-b9a650b38d59
./pgadmin_data/sessions/1e451e39-aae8-4a80-9e06-e600209173eb
./pgadmin_data/sessions/cda27660-0b33-4cfa-9a6f-6b61152e20ca
./pgadmin_data/sessions/39c9dfe9-7b34-43f8-91b3-6fa3f6d266b3
./pgadmin_data/sessions/6f69a6f6-75b8-4460-a933-45e989a1745b
./pgadmin_data/sessions/a581e329-7bfb-4698-838d-73cfacdc8490
./pgadmin_data/sessions/d0fbabe6-ad5f-4e80-b95c-ddce91f12be3
./pgadmin_data/sessions/8bcb89fe-0895-4cfd-9520-bb8395741163
./pgadmin_data/sessions/a7b4bf94-c3e4-4d6b-9bfb-1838af5757b2
./pgadmin_data/sessions/4ab9a4ed-3382-45b3-bc68-b03198aa8351
./pgadmin_data/sessions/d88c19a7-77d9-4beb-ab76-a84a9f37157d
./pgadmin_data/sessions/75f2578e-af2c-4aee-9d2d-cc8636ed51be
./pgadmin_data/sessions/8288a605-5063-4e3c-b91d-7d90956fc36a
./pgadmin_data/sessions/e409093c-23c6-4281-bd8e-5ae1dd8fd244
./pgadmin_data/sessions/21bf4030-2f8b-4d39-9ea5-4b9091443cb8
./pgadmin_data/sessions/80adb826-82c5-4473-84a3-b69b59a5c694
./pgadmin_data/sessions/5493e7a3-35c7-48ae-89af-246e7f0b1198
./pgadmin_data/sessions/cb6a3940-36e0-406e-8072-3ce847b85eab
./pgadmin_data/sessions/7a61650b-174f-4eee-a30d-8e8e2b9bf42a
./pgadmin_data/sessions/4212d725-cfca-4edb-b3d4-65872c5b4483
./pgadmin_data/sessions/cd78b8b9-bb98-4343-9ec3-9e4663e0965c
./pgadmin_data/sessions/8f58c8db-3320-4ff4-83c9-529ceeb47320
./pgadmin_data/sessions/fbabc57a-b2d4-4c85-9cbd-fa70f2a374e7
./pgadmin_data/sessions/49b63a43-ac7f-4a1e-a2f5-eb69c394ffe9
./pgadmin_data/sessions/e87026e5-efa4-4618-9c56-e11cef97b2bb
./pgadmin_data/sessions/aebf219d-1063-4ee8-a00e-8c669ca8c649
./pgadmin_data/sessions/6ea13bd9-7894-44b0-8db2-1cd0d67772ac
./pgadmin_data/sessions/d9d24318-63af-48ad-9a5f-e463377d72b3
./pgadmin_data/sessions/a7c55d8e-62d1-47e5-8507-29c228d9c9b1
./pgadmin_data/sessions/981d317b-8dec-40b0-a16f-d8d64b36a8ff
./pgadmin_data/sessions/62906837-2ecb-468a-8fef-5fd1374773a9
./pgadmin_data/sessions/3aeb0610-d402-481d-83b7-cc6282b7fe40
./pgadmin_data/sessions/6d07e92a-9824-4cc3-837a-9ea25e789ca9
./pgadmin_data/sessions/c0936831-8a62-4156-884e-7e72173571d7
./pgadmin_data/sessions/13e7ff42-4934-4a5e-b5a3-f677f6429cc1
./pgadmin_data/sessions/96f17aad-5695-40c9-b467-154246f14580
./pgadmin_data/sessions/9685519b-269d-4e56-a595-6cfa40c572a0
./pgadmin_data/sessions/0d358dcb-bbfb-43ca-ab93-be47f5ed25f1
./pgadmin_data/sessions/8b017d63-49c6-4c72-bd4c-1f1121c48229
./pgadmin_data/sessions/0c5d8f55-57c2-4d9b-a740-71c3eb24bced
./pgadmin_data/sessions/9a707a69-cbea-4d2a-aee2-ed186b0bd192
./pgadmin_data/sessions/2c0c4448-d3e4-4c90-9af6-33a0c0bf0ef1
./pgadmin_data/sessions/179ac2a4-8dc3-4db0-9208-ff985d0c88e0
./pgadmin_data/sessions/c73fe338-3ab0-46b7-81fa-276fc8acaa88
./pgadmin_data/sessions/15c03d02-36ed-47f1-a77c-2f4af9e68504
./pgadmin_data/sessions/215e7cd3-169f-4b75-8cd6-0081734aa571
./pgadmin_data/sessions/7c847da4-61d0-4056-8e32-906919e72acf
./pgadmin_data/sessions/c78fd088-66d3-4854-9093-b5f91eed7f87
./pgadmin_data/sessions/62d142cc-ab15-4f3f-8411-b668bd926f4f
./pgadmin_data/sessions/ec291f35-5e20-4f9a-af16-e44624d57074
./pgadmin_data/sessions/f86f30a7-2680-4a43-bb3f-d1d5dc04131f
./pgadmin_data/sessions/4256aa82-0066-4a50-a4d9-2a0673705554
./pgadmin_data/sessions/f8390327-d516-45b0-9df7-fb84ab84b11d
./pgadmin_data/sessions/6be9f86e-c004-466e-af2e-9046b971b9fc
./pgadmin_data/sessions/d983dfc1-ed31-4b49-8a99-85787b3b8851
./pgadmin_data/sessions/b87ca5ef-affd-4ac9-b9a3-640c274e05bf
./pgadmin_data/sessions/dfb0274f-c907-47ef-92ec-267f72853f21
./pgadmin_data/sessions/6afc4e86-4d72-45d7-9efb-59984ee613f9
./pgadmin_data/sessions/8259d216-9011-4518-9e07-47f62b09c8c2
./pgadmin_data/sessions/3d86d01a-9519-4111-8bd7-1bfe6ae30541
./pgadmin_data/sessions/10fdc4de-ff73-4b15-bd76-5f963b52ad5a
./pgadmin_data/sessions/47ff632a-5d39-43f1-977b-4acfa2911536
./pgadmin_data/sessions/a4f6dc64-606d-4cc7-a7c9-b53552e03155
./pgadmin_data/sessions/ffa5e983-2527-46c6-8be3-9ed04485a6ce
./pgadmin_data/sessions/251262f2-ff86-407a-b565-afc083e8f815
./pgadmin_data/sessions/85541a74-441c-4c41-a1e8-2d4748704ba4
./pgadmin_data/sessions/769ea067-659f-47a7-916f-422945f31749
./pgadmin_data/sessions/8b50c5b9-f372-4722-946a-5b98d8f6204b
./pgadmin_data/sessions/03fd18e1-b040-4d4a-b1eb-01f30054b114
./pgadmin_data/sessions/5697ad9e-3978-495b-b45d-bd8171697395
./pgadmin_data/sessions/6e772ba6-65b4-4501-84ea-ebcafa24cd85
./pgadmin_data/sessions/8176c2c0-467d-4b27-a17a-52c204cd9773
./pgadmin_data/sessions/d98a8f90-8f2e-41e4-8305-16d3dd79d54a
./pgadmin_data/sessions/8ff1ea1c-d1b9-46f8-8a16-40bcac83f250
./pgadmin_data/storage
./pgadmin_data/storage/kincses_gmail.com
./pgadmin_data/pgadmin4.db
./pgadmin_data/azurecredentialcache
./docker-compose_2026.01.23_1.yml
./backend
./backend/migrations
./backend/migrations/script.py.mako
./backend/migrations/env.py
./backend/migrations/README
./backend/migrations/versions
./backend/migrations/versions/c21c2c7e70d4_clean_gamification_setup.py
./backend/app
./backend/app/models
./backend/app/models/user.py
./backend/app/models/translation.py
./backend/app/models/vehicle.py
./backend/app/models/vehicle_catalog.py
./backend/app/models/expense.py
./backend/app/models/company.py
./backend/app/models/logistics.py
./backend/app/models/system_settings.py
./backend/app/models/__init__.py
./backend/app/models/staged_data.py
./backend/app/models/history.py
./backend/app/models/social.py
./backend/app/models/gamification.py
./backend/app/core
./backend/app/core/config.py
./backend/app/core/email.py
./backend/app/core/security.py
./backend/app/core/__init__.py
./backend/app/seed_catalog.py
./backend/app/auth
./backend/app/auth/router.py
./backend/app/schemas
./backend/app/schemas/user.py
./backend/app/schemas/auth.py
./backend/app/schemas/token.py
./backend/app/schemas/admin.py
./backend/app/schemas/fleet.py
./backend/app/schemas/social.py
./backend/app/old_main.py
./backend/app/api
./backend/app/api/recommend.py
./backend/app/api/auth.py
./backend/app/api/deps.py
./backend/app/api/v1
./backend/app/services
./backend/app/services/notification_service.py
./backend/app/services/fleet_service.py
./backend/app/services/maintenance_service.py
./backend/app/services/social_service.py
./backend/app/services/translation_service.py
./backend/app/services/gamification_service.py
./backend/app/test_gamification_flow.py
./backend/app/db
./backend/app/db/context.py
./backend/app/db/session.py
./backend/app/db/base.py
./backend/app/db/middleware.py
./backend/app/db/__init__.py
./backend/app/main.py
./backend/app/__init__.py
./backend/app/seed_system.py
./backend/app/database.py
./backend/app/seed_data.py
./backend/scrapers
./backend/scrapers/vehicle_master_data.py
./backend/requirements.txt
./backend/_legacy_backup
./backend/_legacy_backup/migrate_ref_data.py
./backend/_legacy_backup/check_garage.py
./backend/_legacy_backup/main_final.py
./backend/_legacy_backup/teszt.txt
./backend/_legacy_backup/docker-compose.backend.yml
./backend/_legacy_backup/update_permissions.py
./backend/_legacy_backup/update_cost_categories.py
./backend/_legacy_backup/inspect_db.py
./backend/_legacy_backup/update_invitations.py
./backend/_legacy_backup/build_complex_db.py
./backend/_legacy_backup/update_db_i18n.py
./backend/_legacy_backup/update_audit_system.py
./backend/_legacy_backup/create_demo_user.py
./backend/_legacy_backup/init_db.py
./backend/_legacy_backup/main.py
./backend/_legacy_backup/main_fixed.py
./backend/_legacy_backup/update_docs.py
./backend/_legacy_backup/create_dummy_employee.py
./backend/_legacy_backup/inspect_db_full.py
./backend/_legacy_backup/main_2.py
./backend/Dockerfile
./backend/frontend
./backend/alembic.ini
./projekt_terkep.txt
./backup_to_nas.sh
./proxy-manager
./proxy-manager/letsencrypt
./proxy-manager/letsencrypt/archive
./proxy-manager/letsencrypt/archive/npm-13
./proxy-manager/letsencrypt/archive/npm-16
./proxy-manager/letsencrypt/archive/npm-5
./proxy-manager/letsencrypt/archive/npm-15
./proxy-manager/letsencrypt/archive/npm-11
./proxy-manager/letsencrypt/archive/npm-14
./proxy-manager/letsencrypt/archive/npm-4
./proxy-manager/letsencrypt/renewal-hooks
./proxy-manager/letsencrypt/renewal-hooks/pre
./proxy-manager/letsencrypt/renewal-hooks/deploy
./proxy-manager/letsencrypt/renewal-hooks/post
./proxy-manager/letsencrypt/renewal
./proxy-manager/letsencrypt/renewal/npm-16.conf
./proxy-manager/letsencrypt/renewal/npm-5.conf
./proxy-manager/letsencrypt/renewal/npm-13.conf
./proxy-manager/letsencrypt/renewal/npm-4.conf
./proxy-manager/letsencrypt/renewal/npm-15.conf
./proxy-manager/letsencrypt/renewal/npm-14.conf
./proxy-manager/letsencrypt/renewal/npm-11.conf
./proxy-manager/letsencrypt/live
./proxy-manager/letsencrypt/live/npm-13
./proxy-manager/letsencrypt/live/npm-16
./proxy-manager/letsencrypt/live/npm-5
./proxy-manager/letsencrypt/live/npm-15
./proxy-manager/letsencrypt/live/npm-11
./proxy-manager/letsencrypt/live/npm-14
./proxy-manager/letsencrypt/live/README
./proxy-manager/letsencrypt/live/npm-4
./proxy-manager/letsencrypt/accounts
./proxy-manager/letsencrypt/accounts/acme-v02.api.letsencrypt.org
./proxy-manager/data
./proxy-manager/data/nginx
./proxy-manager/data/nginx/dead_host
./proxy-manager/data/nginx/proxy_host
./proxy-manager/data/nginx/default_www
./proxy-manager/data/nginx/default_host
./proxy-manager/data/nginx/redirection_host
./proxy-manager/data/nginx/stream
./proxy-manager/data/nginx/temp
./proxy-manager/data/keys.json
./proxy-manager/data/letsencrypt-acme-challenge
./proxy-manager/data/database.sqlite
./proxy-manager/data/access
./proxy-manager/data/custom_ssl
./proxy-manager/data/logs
./proxy-manager/data/logs/fallback_access.log.1.gz
./proxy-manager/data/logs/letsencrypt.log.8
./proxy-manager/data/logs/proxy-host-8_access.log
./proxy-manager/data/logs/fallback_error.log.2.gz
./proxy-manager/data/logs/letsencrypt.log.6
./proxy-manager/data/logs/fallback_access.log.3.gz
./proxy-manager/data/logs/proxy-host-3_access.log.3.gz
./proxy-manager/data/logs/letsencrypt.log.15
./proxy-manager/data/logs/proxy-host-1_access.log
./proxy-manager/data/logs/letsencrypt-requests_access.log.1.gz
./proxy-manager/data/logs/proxy-host-2_access.log.1.gz
./proxy-manager/data/logs/letsencrypt.log.9
./proxy-manager/data/logs/proxy-host-2_error.log.1.gz
./proxy-manager/data/logs/letsencrypt.log.4
./proxy-manager/data/logs/letsencrypt.log.10
./proxy-manager/data/logs/fallback_error.log.1.gz
./proxy-manager/data/logs/proxy-host-1_error.log.2.gz
./proxy-manager/data/logs/proxy-host-7_access.log
./proxy-manager/data/logs/proxy-host-2_error.log.2.gz
./proxy-manager/data/logs/letsencrypt-requests_error.log
./proxy-manager/data/logs/letsencrypt.log.13
./proxy-manager/data/logs/proxy-host-9_access.log
./proxy-manager/data/logs/proxy-host-2_error.log.3.gz
./proxy-manager/data/logs/proxy-host-6_access.log
./proxy-manager/data/logs/proxy-host-1_access.log.3.gz
./proxy-manager/data/logs/proxy-host-6_access.log.1.gz
./proxy-manager/data/logs/proxy-host-6_error.log.3.gz
./proxy-manager/data/logs/proxy-host-2_access.log.3.gz
./proxy-manager/data/logs/proxy-host-8_error.log
./proxy-manager/data/logs/proxy-host-6_error.log.1.gz
./proxy-manager/data/logs/letsencrypt.log.16
./proxy-manager/data/logs/fallback_access.log.2.gz
./proxy-manager/data/logs/proxy-host-6_access.log.3.gz
./proxy-manager/data/logs/proxy-host-6_access.log.2.gz
./proxy-manager/data/logs/letsencrypt.log.2
./proxy-manager/data/logs/letsencrypt-requests_access.log
./proxy-manager/data/logs/proxy-host-4_access.log
./proxy-manager/data/logs/letsencrypt.log.12
./proxy-manager/data/logs/proxy-host-5_access.log.1.gz
./proxy-manager/data/logs/letsencrypt.log.7
./proxy-manager/data/logs/fallback_error.log
./proxy-manager/data/logs/proxy-host-6_error.log.2.gz
./proxy-manager/data/logs/proxy-host-5_access.log.3.gz
./proxy-manager/data/logs/proxy-host-5_error.log.3.gz
./proxy-manager/data/logs/proxy-host-1_error.log.3.gz
./proxy-manager/data/logs/proxy-host-2_access.log.2.gz
./proxy-manager/data/logs/proxy-host-3_access.log.2.gz
./proxy-manager/data/logs/proxy-host-5_error.log.2.gz
./proxy-manager/data/logs/letsencrypt.log.1
./proxy-manager/data/logs/proxy-host-3_access.log
./proxy-manager/data/logs/letsencrypt.log.3
./proxy-manager/data/logs/proxy-host-5_access.log.2.gz
./proxy-manager/data/logs/proxy-host-1_error.log
./proxy-manager/data/logs/proxy-host-2_access.log
./proxy-manager/data/logs/fallback_error.log.3.gz
./proxy-manager/data/logs/proxy-host-5_error.log.1.gz
./proxy-manager/data/logs/letsencrypt.log
./proxy-manager/data/logs/letsencrypt.log.14
./proxy-manager/data/logs/proxy-host-5_access.log
./proxy-manager/data/logs/proxy-host-1_access.log.1.gz
./proxy-manager/data/logs/proxy-host-5_error.log
./proxy-manager/data/logs/proxy-host-9_error.log
./proxy-manager/data/logs/proxy-host-3_error.log.2.gz
./proxy-manager/data/logs/proxy-host-1_error.log.1.gz
./proxy-manager/data/logs/proxy-host-3_error.log.3.gz
./proxy-manager/data/logs/proxy-host-3_error.log.1.gz
./proxy-manager/data/logs/proxy-host-1_access.log.2.gz
./proxy-manager/data/logs/proxy-host-3_access.log.1.gz
./proxy-manager/data/logs/letsencrypt.log.5
./proxy-manager/data/logs/fallback_access.log
./proxy-manager/data/logs/proxy-host-7_error.log
./proxy-manager/data/logs/proxy-host-4_error.log
./proxy-manager/data/logs/letsencrypt.log.11
./proxy-manager/data/logs/proxy-host-3_error.log
./proxy-manager/data/logs/proxy-host-2_error.log
./proxy-manager/data/logs/proxy-host-6_error.log
./pgadmin
./pgadmin/data
./pgadmin/data/sessions
./pgadmin/data/sessions/c191ec66-78a1-4afd-955f-e50e8dbbc552
./pgadmin/data/sessions/f7056bf2-b80f-4239-8c16-3531f8b88782
./pgadmin/data/sessions/f566ecc0-32dd-45c7-869e-cfb900fd9aa7
./pgadmin/data/sessions/61fa598a-479d-47dc-aee2-846812e6b40b
./pgadmin/data/sessions/36fa57da-8c82-47e8-8dd0-03c677ff8f6d
./pgadmin/data/sessions/42240d96-abd2-43ed-9e07-7ad0acd4dceb
./pgadmin/data/sessions/cc89aa8b-5867-4b73-90c0-0b15d117cb9f
./pgadmin/data/sessions/4717cbe5-3d95-425b-a873-df76df7af990
./pgadmin/data/sessions/fc40d886-9fb0-48b2-810e-c77b9afcb6a2
./pgadmin/data/sessions/190c2cfe-7b96-47e7-a7c7-78740413ec86
./pgadmin/data/sessions/d1fd1e26-160e-4450-b2b6-dc28ad4273f1
./pgadmin/data/sessions/a48ac178-5482-4835-87cc-fe0ed838bacf
./pgadmin/data/sessions/64c44127-f39a-4234-8785-9b515b32686f
./pgadmin/data/sessions/82e002e9-c7ef-4eb4-8fad-759b9d5577ca
./pgadmin/data/sessions/ef7f0484-f09d-44c1-b0b7-e56888795442
./pgadmin/data/sessions/8821dc09-caca-4649-9f18-bc57cf371a06
./pgadmin/data/sessions/3f887077-3a26-455d-b2ce-6be68ddc71e8
./pgadmin/data/sessions/6404475f-50aa-42e0-9d35-b0a8f6e8a213
./pgadmin/data/sessions/5c1020ff-954c-4132-902a-11a3750de23a
./pgadmin/data/sessions/7aa1e6c8-5c23-45ec-8156-972939ae60cf
./pgadmin/data/sessions/2561af04-52e0-422c-9f01-889aa086be13
./pgadmin/data/sessions/f01d1cd0-5b3c-406d-8b54-f07f9436949e
./pgadmin/data/sessions/c8a2ea39-d07d-4c98-8be2-e3ddee9c5c99
./pgadmin/data/sessions/ec936261-9676-4ff7-abc9-6af7557b45e5
./pgadmin/data/sessions/d4434ef9-4105-403c-9245-25ddf5dfb391
./pgadmin/data/sessions/3d3283e8-fbe4-487e-bc49-458ee1782020
./pgadmin/data/sessions/fad7550e-eef9-4a4e-9f8b-8d771c7767a4
./pgadmin/data/sessions/e2eab0f0-867e-4797-9619-7fb4f790b89f
./pgadmin/data/sessions/0f41e22e-b4b4-4776-9895-9fc12054ed71
./pgadmin/data/sessions/c22428fe-dfc0-4a28-a32f-1f8965430004
./pgadmin/data/sessions/c8857f63-f821-49b4-bf41-48727c00febd
./pgadmin/data/sessions/6c443079-e5e9-44c3-aa39-9be235ad4865
./pgadmin/data/sessions/82e99852-9da3-45a8-8491-0c69e66d5be4
./pgadmin/data/sessions/bf27abfe-c382-4e9d-8acf-9508133c4b15
./pgadmin/data/sessions/2739c198-da4a-498e-aaaa-9c9ca291bbf1
./pgadmin/data/sessions/98fdb91c-44cf-4379-a738-6b045733dee0
./pgadmin/data/sessions/03c1a752-4ec5-430c-a965-aa355531bb1f
./pgadmin/data/sessions/8167652a-79dc-46b9-a3e7-203ac1840f84
./pgadmin/data/sessions/c6f96af8-86b3-4bd2-9c65-c6b80ee60512
./pgadmin/data/sessions/f27f3773-bd41-4870-adbc-298c08de6834
./pgadmin/data/sessions/1960ac31-8625-48ba-aef3-f824a0739b59
./pgadmin/data/sessions/4cf9b0b1-f129-43e0-82f0-9da65c5d5d00
./pgadmin/data/sessions/df1c9e4b-c688-43af-8707-a967f124e2be
./pgadmin/data/sessions/a07c1cce-1999-49c3-b1e1-a59436e38522
./pgadmin/data/sessions/e5b3bdd5-4aef-4366-bd21-9acd13188b78
./pgadmin/data/sessions/4673f7fb-cab6-4347-8c0e-7a00937c3f16
./pgadmin/data/sessions/4382c834-4294-45eb-a671-8ab12033f6b7
./pgadmin/data/sessions/f2ca300d-051d-42b5-b5f9-be649054d293
./pgadmin/data/sessions/eb5480bb-8183-4aed-8c44-5dba8a9de577
./pgadmin/data/sessions/a508f434-c945-4db0-8927-e16f0e75813f
./pgadmin/data/sessions/68043fbf-2cff-4131-9807-562123306e7c
./pgadmin/data/sessions/081da418-bd99-4b43-aa84-f6e13a87f057
./pgadmin/data/sessions/d985efdf-2cda-4d6e-a850-baf41946bdbf
./pgadmin/data/sessions/54349914-b165-48f3-bea8-ab8d224edd39
./pgadmin/data/sessions/ea4d33f7-a8dd-4288-b9ef-2d1511286491
./pgadmin/data/sessions/26f505ea-a69a-4e4d-8704-01e379913d52
./pgadmin/data/sessions/7130585c-6a44-41f4-80fd-6f2c7c702eac
./pgadmin/data/sessions/8d434565-8c8d-4058-94d6-df582902ff67
./pgadmin/data/sessions/4ed73362-1f27-4e50-a632-c3b6213f627e
./pgadmin/data/sessions/4c3ac76d-b38d-4e89-871e-7446ad86ce3a
./pgadmin/data/sessions/cbee53e3-2930-45b4-ac80-cec62d11365b
./pgadmin/data/sessions/2706ea12-544c-439c-bbfe-2881135fc5c2
./pgadmin/data/sessions/19bc1463-7c1e-40a9-bd09-7d282590b903
./pgadmin/data/sessions/4584d603-10f5-4767-920e-59c463d5f00b
./pgadmin/data/sessions/bc386c8c-87ae-4e20-8844-fee3703a0595
./pgadmin/data/sessions/3e232ae5-0fb7-4107-8fe6-e64af4d0527b
./pgadmin/data/sessions/0ced9fd6-67f5-4e15-892d-f16f29bf2d53
./pgadmin/data/sessions/45e62654-215d-433f-92ed-21bb664b0a5d
./pgadmin/data/sessions/f8f4cdc0-a960-4971-b380-3a3df159a3f7
./pgadmin/data/sessions/5da591bf-697b-40b8-b850-5248b3f9948e
./pgadmin/data/sessions/62c7cafb-f9c3-4a0e-b88b-69015f4cdd8a
./pgadmin/data/sessions/76de99ed-2aa0-4a08-b488-08f30f00b115
./pgadmin/data/sessions/6d5cdc12-98ae-4226-8c56-01a66ace1eb6
./pgadmin/data/sessions/4fbb5992-1fbe-4451-b3b7-29b0318db683
./pgadmin/data/sessions/aee5ec2f-8e5c-4a46-98f2-09842c70b28e
./pgadmin/data/sessions/0ab80fb4-e8e7-406d-b344-f49eba9ff931
./pgadmin/data/sessions/dde5b219-4951-4165-8fd4-78c960f48b9e
./pgadmin/data/sessions/351775b2-78e4-499e-868d-4d29b5c6dc44
./pgadmin/data/sessions/70be35ce-dedc-49e1-baa1-fc144a68e2dd
./pgadmin/data/sessions/1e5e0265-eae2-4b5b-a55b-cd60ebf3329d
./pgadmin/data/sessions/bb0e21bd-b9d5-4a23-b434-1065bbaa95de
./pgadmin/data/sessions/03321bce-cf49-427a-a351-c698a1e8b6c5
./pgadmin/data/sessions/c9725e93-8daa-4593-adb6-cae2c08f9ff2
./pgadmin/data/sessions/b96079ba-7bb1-4f2e-9a3c-e909f62b4482
./pgadmin/data/sessions/dbe3af6d-f17b-40b9-89e2-f39320543100
./pgadmin/data/sessions/638b9be8-028f-44cb-8989-36ea93b74eea
./pgadmin/data/sessions/2ed28be0-af44-427d-aebc-548f31f468e0
./pgadmin/data/sessions/a3dc2446-3c67-4238-a8b2-c9fa71fbad7a
./pgadmin/data/sessions/46a19aed-8c32-4649-9190-e449bc59bc7b
./pgadmin/data/sessions/7c130b35-7cb9-488d-8576-ea9013268f03
./pgadmin/data/sessions/b756eef0-4625-465d-bc5b-a84d0cb54bc1
./pgadmin/data/sessions/60f20466-0f3c-459c-aef7-4fc0c091fe44
./pgadmin/data/sessions/4c0d3bc1-5568-4b05-a134-0dfabe300266
./pgadmin/data/sessions/24b3c1f7-7db5-46a1-8f9d-2bebf1f0fdce
./pgadmin/data/sessions/e4d91f15-4c9f-407e-9bed-4b54a9710348
./pgadmin/data/sessions/e1dbb2c7-f692-49bf-9952-906e45cc061c
./pgadmin/data/sessions/2179bbb8-68eb-4d23-ab40-abd267a737ca
./pgadmin/data/sessions/451e0858-8495-4b2b-80e6-a806b23ebf20
./pgadmin/data/sessions/11cb2bcb-cdd1-47cd-8bd7-2311df2c5fe9
./pgadmin/data/sessions/4cd4231d-4650-478a-836d-587dd5fadf2d
./pgadmin/data/sessions/4dddbbca-9f36-4afe-91c5-dda07af51509
./pgadmin/data/sessions/722e0de3-d430-4128-a2dc-0c2b98696529
./pgadmin/data/sessions/ab34bced-831e-487d-9825-84f608ea3902
./pgadmin/data/sessions/93c836f5-d79d-425b-bf03-dcabb528c14a
./pgadmin/data/sessions/418dd495-ee05-4922-a4b5-20d73b9e4546
./pgadmin/data/sessions/0074a83f-e030-42ae-8c17-45565cbecfc9
./pgadmin/data/sessions/ed9ea264-f245-424a-a083-d41f3e3677f2
./pgadmin/data/sessions/987661e3-7d05-4a95-8b77-baa1d589e950
./pgadmin/data/sessions/fe97b137-a0ea-4a78-97e1-3380e694b0fd
./pgadmin/data/sessions/f7a50bb2-86b0-4300-8230-1419184b77df
./pgadmin/data/sessions/3a0faa33-930b-4f10-b332-a7e980746c78
./pgadmin/data/sessions/2d628d69-f6f7-486a-9262-bc18afb453af
./pgadmin/data/sessions/13426e7d-ab6c-4495-8e7d-86a537b15eee
./pgadmin/data/sessions/9b298e50-1684-493a-aa4c-013aa0dfa34d
./pgadmin/data/sessions/f03484f7-2430-4a0a-97ec-9da8e1f5ea8e
./pgadmin/data/sessions/83b8ec9d-cce8-40dd-92d2-b408fb9740b4
./pgadmin/data/sessions/55b681bd-873c-4d01-b4be-3989d832a238
./pgadmin/data/sessions/d4e8dbd2-54cf-46e1-b517-fc1e75d249e1
./pgadmin/data/sessions/8d702279-6b43-4233-a353-8154dd414dd9
./pgadmin/data/sessions/e2712981-434d-4e36-95f1-1a8bfdd104aa
./pgadmin/data/sessions/7e7fdf5e-cddd-47d9-9904-c2e3f0bb6584
./pgadmin/data/sessions/47fe0485-1471-42bc-95cd-706a64f48628
./pgadmin/data/sessions/d09cb1df-1944-4853-8a28-2b96d6e48172
./pgadmin/data/sessions/cabc5443-1f25-4baa-935f-677ad0168302
./pgadmin/data/sessions/e6c8fdcc-0d49-4d7b-b1c1-9e369dc4b462
./pgadmin/data/sessions/e14cf22a-1d02-4b56-8e72-dc06b7680c58
./pgadmin/data/sessions/afb4a566-5bbd-44ca-95a7-07f73b35a4b5
./pgadmin/data/sessions/b5d9d584-a368-445a-a1a3-832c81ceecb8
./pgadmin/data/sessions/dccb1427-3039-4d5b-99a3-aa1e0047c1d5
./pgadmin/data/sessions/05d366d7-6fc8-4b0a-8f15-34e993390037
./pgadmin/data/sessions/3ee96a8c-f9ab-4446-a2a5-f507c43c81ca
./pgadmin/data/sessions/aed3b509-f282-4a70-aefd-8187a7eec5a1
./pgadmin/data/sessions/ce5f6384-c313-4ded-886b-b07ececd76cd
./pgadmin/data/sessions/1f914044-e28a-4209-adbe-3ef26a350f8f
./pgadmin/data/sessions/af349006-dc3d-4311-813f-b7b9a020bf80
./pgadmin/data/sessions/2f9a5acd-4f90-41e6-b3ce-6c96fd759269
./pgadmin/data/sessions/239da6ac-8ad1-4a6b-b744-1f0c277297f2
./pgadmin/data/sessions/fafc224c-d56c-46f8-8e61-99acda95eea3
./pgadmin/data/sessions/4702c0ea-8e09-45cf-b789-30e27eb5e3b9
./pgadmin/data/sessions/ba1fe36d-33f0-406d-ac2d-b36f1a116e1a
./pgadmin/data/sessions/f2d9792d-a8f1-428b-8337-8e9d6f3443f7
./pgadmin/data/sessions/3988bd08-5155-401d-99d6-02f2fb632f55
./pgadmin/data/sessions/eda16ade-9d9f-414a-8568-f7cbdd846df5
./pgadmin/data/sessions/dc94f41e-fce7-4511-8568-85f697d9c3ac
./pgadmin/data/sessions/f1d83a36-0b04-4f6d-b5e6-a5ceb6913d46
./pgadmin/data/sessions/9ca18ada-194c-411c-aca2-dd39c9309f06
./pgadmin/data/sessions/e894978f-3619-4507-8a8d-06ebd9d3b34b
./pgadmin/data/sessions/3a94a473-9331-4677-a456-c2f159644646
./pgadmin/data/sessions/f9d18c1d-5bf5-415a-b1b2-f626cbff20a5
./pgadmin/data/sessions/6ed6727c-6f53-4985-b61d-54ec2c5e21aa
./pgadmin/data/sessions/bcbba302-039d-4255-b59b-4f5c0ba4261e
./pgadmin/data/sessions/bc5dcd93-6f31-4c85-a71e-a5e2c3909ee4
./pgadmin/data/sessions/81fa4503-512f-4ffc-b80c-a2cbe5ac6c6d
./pgadmin/data/sessions/8b244e1a-3450-46ae-bf7d-1c62cbf27efd
./pgadmin/data/sessions/57e8dde3-3c42-4ea9-b51b-61e0c7464689
./pgadmin/data/sessions/7b270987-51d5-49ec-a211-efe040a3aad6
./pgadmin/data/sessions/ac22993e-9fa9-4648-b831-00d09d4c1847
./pgadmin/data/sessions/28cae61e-11d9-496f-a02a-61c9e6f7de81
./pgadmin/data/sessions/4a10d8d1-c231-4e4a-b2da-11c41f1fb17b
./pgadmin/data/sessions/d85fb50c-159c-4126-a962-26b7d6069e7b
./pgadmin/data/sessions/ff45df81-4c63-4c3c-a8dd-049c6d620cd2
./pgadmin/data/sessions/71210c05-6890-4a50-b357-ab9aa326676e
./pgadmin/data/sessions/cb104af0-04e6-4f15-a368-f77982452a6c
./pgadmin/data/sessions/ac393412-dcf8-4c91-bc17-7d1b5801acad
./pgadmin/data/sessions/48251b44-eba5-4052-a76e-86a6875136b9
./pgadmin/data/sessions/1d6f0a85-d435-4576-a0fa-08a06278a27e
./pgadmin/data/sessions/3c8bf289-9347-409a-9f10-47d159e01372
./pgadmin/data/sessions/cfa4a83e-c216-4605-b47c-a22793eba833
./pgadmin/data/sessions/bf90f4cb-b073-4c6e-879a-254f1b482663
./pgadmin/data/sessions/66915c98-f44d-46e5-b6b1-6b7f93a75ec8
./pgadmin/data/sessions/49511e92-d0d3-4269-800b-ece9393f44da
./pgadmin/data/sessions/cda3d93a-d66a-40d6-b639-5889a54f18ae
./pgadmin/data/sessions/5e4fd04c-14ea-444b-8146-b16def80df51
./pgadmin/data/sessions/eefdb208-868b-4f2f-b994-10e3fb60a027
./pgadmin/data/sessions/049be04b-7f37-4e21-bc39-0c2a8b220599
./pgadmin/data/sessions/c4ede5bb-f6d0-414b-ae56-7b02f6d70e5e
./pgadmin/data/sessions/6291cc65-910e-421f-88f8-52052e770880
./pgadmin/data/sessions/0e57c4bc-ece3-4cee-8593-d29a4ac3eb32
./pgadmin/data/sessions/d2a3c6f4-9445-4cce-a5e8-dc1086c17aa5
./pgadmin/data/sessions/41dba666-775e-4db7-bab2-e9e8d24d6f69
./pgadmin/data/sessions/be43131f-9131-4361-9a78-11fe22bc07fe
./pgadmin/data/sessions/4832b048-abfe-407a-abbc-5ab7349646dc
./pgadmin/data/sessions/9d89be8f-abc8-4e30-b87a-187d22ba3bb7
./pgadmin/data/sessions/97c0ed8d-c8bb-4867-afdb-ed963a871162
./pgadmin/data/sessions/786acf57-7b55-49a3-bbf4-d2ea7ac3af88
./pgadmin/data/sessions/5f44b9f8-20b6-4f0f-8b35-fcbafb900d7d
./pgadmin/data/sessions/02a93934-cb4f-4990-9f17-3c9b0c0d41d8
./pgadmin/data/sessions/be8c9ae6-3d6a-4c56-b296-7a316062e49e
./pgadmin/data/storage
./pgadmin/data/storage/kincses_gmail.com
./pgadmin/data/pgadmin4.db
./pgadmin/data/azurecredentialcache
./logs
./frontend
./frontend/uploads
./frontend/uploads/fe7a5e48-09af-4a3c-a51a-b7c97a20810e.png
./frontend/uploads/743f6905-83bc-4269-83bd-38098b10605b.png
./frontend/uploads/50369328-e8d0-4f07-b955-52bfc5bc4671.png
./frontend/uploads/1797321c-cd84-48a9-a4f5-7a063dd5386f.png
./frontend/uploads/f3d0f3f9-4112-4c8e-b2c6-558a9cace658.png
./frontend/uploads/3912a8ba-57f0-477c-9a27-597240407444.png
./frontend/uploads/6e62c849-21fc-4803-ab3b-e5b627649f30.png
./frontend/index_old.html
./frontend/index.html
./docker-compose_NAS_előtt.yml
./code-server-config
./code-server-config/extensions
./code-server-config/extensions/extensions.json
./code-server-config/data
./code-server-config/data/Machine
./code-server-config/data/User
./code-server-config/data/User/customBuiltinExtensionsCache.json
./code-server-config/data/User/History
./code-server-config/data/User/caches
./code-server-config/data/User/Backups
./code-server-config/data/User/settings.json
./code-server-config/data/User/snippets
./code-server-config/data/User/globalStorage
./code-server-config/data/User/systemExtensionsCache.json
./code-server-config/data/User/machineid
./code-server-config/data/User/workspaceStorage
./code-server-config/data/CachedProfilesData
./code-server-config/data/CachedProfilesData/__default__profile__
./code-server-config/data/logs
./code-server-config/data/logs/20260120T003918
./code-server-config/data/logs/20260120T172343
./code-server-config/data/logs/20260120T004510
./code-server-config/data/logs/20260120T175427
./code-server-config/data/coder.json
./code-server-config/workspace
./alembic.ini
./Horgony_megjegyzések.txt

View File

@@ -0,0 +1,939 @@
Teljes LOG (2026-01-30) LOG v1 (FRISSÍTVE)
Rendszer: service_finder (Traffic Ecosystem SuperApp 2.0)
Host: profibot1 (kincses)
Dátum: 2026-01-30 (Europe/Budapest)
[13] API health + compose erőforrások
Parancs: curl http://127.0.0.1:8000/
Eredmény: {"status":"online","version":"2.0.0","docs":"/docs"} ✅
Parancs: docker stats --no-stream
Megfigyelés / kockázat:
Erőforrások bőven rendben, nincs “fulladás”.
Legnagyobb RAM: code-server ~343MB, pgadmin ~266MB, nginx-proxy-manager ~107MB, minio ~109MB
Következtetés: A rendszer stabilan fut erőforrás oldalról, nincs “performance” blokk.
[14] Host port kitettség (LISTEN sockets)
Parancs: ss -tulipn | grep LISTEN
Eredmény (kritikus összefoglaló):
Publikus (0.0.0.0): 5432, 8000, 3000, 9000, 9001, 5050, 8888, 8443, 80, 81, 443
Következtetés (kritikus):
A DB (5432) és admin felületek (pgAdmin 5050, code-server 8443, dozzle 8888, minio 9001) minden interfészen hallgatnak.
Ez LAN-on is rizikó; internet felé pláne (ha port forward van).
Ajánlott irány: ezeket később “internal only / VPN only / localhost bind” módon kell zárni.
[15] Docker network-ek név eltérés / téves hivatkozás
Parancs: docker network ls | grep service_finder
Eredmény:
service_finder_default
service_finder_internal_net
service_finder_public_net
service_finder_service_finder_net
Parancs: docker inspect service_finder_net
Eredmény: error: no such object: service_finder_net
Következtetés:
A compose-ban a háló neve nem service_finder_net, hanem service_finder_service_finder_net (és mellette van internal/public/default).
A korábbi checklist parancsomat ehhez igazítjuk.
Helyes minta mostantól:
docker inspect service_finder_service_finder_net | head -n 80
docker inspect service_finder_internal_net | head -n 80
docker inspect service_finder_public_net | head -n 80
[16] OpenAPI: V2 info + path-szám
Parancsok:
curl -sS http://127.0.0.1:8000/ | jq .
curl -sS http://127.0.0.1:8000/api/v2/openapi.json | jq '.info, (.paths|keys|length)'
Eredmény:
API online
OpenAPI: title/version OK
Path count: 18
Következtetés: A publikus API surface jelenleg kicsi (18 route), ez “MVP” jelleg.
[17] API log tail auth flow + email provider hibák + route mismatch
Parancs: docker compose logs --no-color --tail=300 service_finder_api | tail -n 120
Kulcs események:
Uvicorn többször újraindult (Started → Shutting down → Started)
Ez lehet compose restart / image rebuild / manual stop-start / healthcheck hatás.
POST /api/v2/auth/register ...:
kincses@gmail.com → 400 Bad Request
info@profibot.hu → 200 OK ✅ (sikeres reg)
Email küldési hibák:
SendGrid: 550 from address does not match a verified Sender Identity
Gmail SMTP: 535 Username and Password not accepted (BadCredentials)
Login:
volt 401 Unauthorized, majd 200 OK ✅
Forgot password:
POST /api/v2/auth/forgot-password?email=kincses@gmail.com → 404 Not Found
Frontend user lekérés:
GET /api/v1/users/me → 404 Not Found (ismétlődik)
Külső bot forgalom:
több IP GET /, GET /robots.txt → (robots 404, root 200)
Következtetések (nagyon fontos):
(A) A reg/login V2 oldalon működik, tehát auth core rendben.
(B) A /api/v1/users/me nincs kiexportálva vagy rossz prefix alatt van → ezért 404.
(C) A “forgot-password” route a log szerint 404, miközben OpenAPI-ban nálad szerepel /api/v2/auth/forgot-password. Ez két dolgot jelenthet:
route csak más HTTP metódussal él (pl. GET), miközben te POST-olsz, vagy
a route valójában másik path-on van (pl. /api/v2/auth/forgot-password/), vagy
több router/verzió van, és nem az van mountolva, amit az OpenAPI mutat (ritkább, de előfordul).
(D) Email küldés jelenleg nincs rendesen bekötve (SendGrid sender identity + Gmail auth). Ettől még a regisztráció működhet, csak értesítő/verify email nem.
[18] DB állapot séma + top táblák (rekordszám)
Parancsok:
\dn+ → data + public
pg_stat_user_tables top 30
Eredmény (lényeg):
fuel_stations ~ 7303
service_providers ~ 7294
vehicle_brands 111
vehicle_models 41
users 5
sok tábla 010 rekord körül
Következtetés:
Van masszív seed adat: üzemanyagkutak + szolgáltatók (~7k+7k).
A rendszer már “használható demo” állapot felé van töltve.
A users 5 rekord → több próbálkozás/teszt user is van.
[19] Alembic migráció konténerben rendben
Parancsok:
docker exec -it service_finder_api ... "alembic current && alembic heads"
pip show alembic
Eredmény:
current=head: 10b73fee8967 (head) ✅
Python 3.12.12, Alembic 1.18.1 telepítve a konténerben ✅
Következtetés:
A DB migrációk konzisztensen HEAD-en vannak.
A “hoston nincs alembic” nem gond, a standard futtatási hely a konténer.
[20] MinIO Console él (9001), de mc hozzáférés külön téma
Parancs: curl -sS http://127.0.0.1:9001/ | head
Eredmény: MinIO Console HTML betölt ✅
Következtetés: MinIO szerver+console fut; a korábbi mc ls local Access Denied várható, amíg nincs alias/policy rendben.
[21] Frontend API endpointok hardcoded, inkonzisztens (kritikus)
Parancs: grep -R "8000\|api/v" -n src | head -n 80
Eredmény (nagyon beszédes):
AddVehicle.vue → http://192.168.100.43:8000/api/v1/...
AddExpense.vue → http://localhost:8000/api/v1/...
Dashboard.vue → http://localhost:8000/api/v1/reports/summary/latest
Login.vue → http://192.168.100.43:8000/api/v2/auth/login + utána GET /api/v1/users/me
ForgotPassword.vue → POST .../api/v2/auth/forgot-password?...
ResetPassword.vue → .../api/v2/auth/reset-password-confirm (ez a logban nem látszott még)
Következtetés (root cause a 404-ekre):
Frontend többféle base URL-t használ (localhost vs 192.168.100.43) → környezetfüggő hibák.
A login után a frontend /api/v1/users/me-t hívja → de a backend log szerint ez 404.
Ez most konkrétan “broken user profile fetch”, emiatt UI-ban bejelentkezés után elakadás várható.
A dashboard .../reports/summary/latest route lehet, hogy nem létezik (OpenAPI-ban nálad {vehicle_id} szerepelt, a logban nem látom a latest-et).
Teljes LOG (2026-01-30) LOG v1
Rendszer: service_finder (Traffic Ecosystem SuperApp 2.0)
Host: profibot1 (user: kincses)
Dátum: 2026-01-30 (Europe/Budapest)
Forrás: terminál kimenetek + compose állapot
[01] Docker / Compose állapot
Megfigyelés: Futó konténerek listázva (docker ps, docker compose ls, docker compose ps)
Eredmény:
service_finder compose stack: 9 service fut
service_finder_api (8000->8000)
service_finder_frontend (3000->80)
postgres-db (5432->5432) healthy
service_finder_redis (6379 internal)
service_finder_minio (9000-9001)
pgadmin_ui (5050->80)
nginx-proxy-manager (80-81, 443)
code-server (8443->8080)
dozzle (8888->8080)
plusz: ddclient külön compose stackben fut
Következtetés: A “2 docker konténer” valójában 2 alkalmazás konténer (API + frontend), de a teljes rendszer 9+1 konténer.
[02] API endpoint ellenőrzés OpenAPI / Docs / Root
Parancsok és eredmények:
curl http://127.0.0.1:8000/openapi.json → 404 Not Found
curl http://127.0.0.1:8000/docs → 200 OK, Swagger UI betölt (de a UI /api/v2/openapi.json URL-t használ)
curl http://127.0.0.1:8000/ → 200 OK, JSON: {"status":"online","version":"2.0.0", ...}
Fájlok:
api_spec.json mérete 22 byte, tartalma: {"detail":"Not Found"}
api_spec_v2.json mentve: 12600 byte, tartalma valid OpenAPI (3.1.0), title: Traffic Ecosystem SuperApp 2.0
Következtetés (root cause):
Az API nem a FastAPI default openapi.json útvonalat használja, hanem verziózottat:
✅ helyes: http://127.0.0.1:8000/api/v2/openapi.json
❌ hibás: http://127.0.0.1:8000/openapi.json
[03] API útvonalak gyors ellenőrzése (OpenAPI alapján)
Lekért path-ek (részlet):
/api/v2/auth/login, /api/v2/auth/register, /api/v2/auth/forgot-password
/api/v1/auth/register, /api/v1/auth/verify
/api/v1/vehicles/register, /api/v1/fleet/vehicles, /api/v1/expenses/add
/api/v1/reports/summary/{vehicle_id}, /api/v1/reports/trends/{vehicle_id}
/api/v1/billing/*
/api/v1/users/me
Következtetés: Az API-ban V1 és V2 párhuzamosan él, a Swagger UI a V2 OpenAPI-t tölti be.
[04] Fájlrendszer állapot projekt gyökér
Projekt root: /opt/service_finder
Látható fő elemek:
backend/, frontend/, migrations/, postgres/, redis/, docs/
docker-compose.yml, .env, alembic.ini
postgres_data/ (permission denied listázásnál — várható, mert volume/data root ownership)
pgadmin_data/, proxy-manager/, code-server-config/
backupok: backup_20260128_alap_kesz.sql, backup_manager.sh, backup_to_nas.sh
Megjegyzés: A cat backup_manager.sh azért lett “No such file”, mert nem a projekt rootban futottál, hanem a frontend mappában. (Rootban ott van.)
[05] Compose render + log mentés
docker compose config > /tmp/service_finder.compose.rendered.yml elkészült
Utolsó 200 sor mentve:
/tmp/api_last200.log
/tmp/frontend_last200.log
/tmp/postgres_last200.log
[06] Adatbázis hozzáférés postgres role hiba, majd tisztázás
Hiba:
docker exec -it postgres-db psql -U postgres ...
→ FATAL: role "postgres" does not exist
Ok: A konténerben a superuser nem postgres, hanem a compose alapján:
POSTGRES_USER = kincses
POSTGRES_DB = service_finder
Következtetés: A DB admin belépéshez a helyes minta:
docker exec -it postgres-db psql -U kincses -d service_finder
[07] DB séma állapot (data schema)
Megfigyelés: Listázott táblák a data sémában: 55 tábla
Tematikus csoportok (a listád alapján):
Auth/User: users, verification_tokens, organization_members, company_members
Org/Company: organizations, companies, organization_locations, org_subscriptions
Fleet/Vehicles: vehicles, user_vehicles, vehicle_brands/models/variants, vehicle_events, vehicle_expenses, vehicle_assignments, vehicle_ownership
Service Marketplace: service_providers, service_specialties, service_reviews, service_records
Gamification / Points: badges, points_ledger, user_scores, user_stats, votes
Billing/Credits/Vouchers: credit_*, vouchers, subscription_tiers
Translations / Settings / Audit: translations, system_settings, audit_logs, regional_settings
Következtetés: A DB “MVP+” szinten meglepően késznek tűnik (sok modul le van képezve).
[08] Backend forráskód struktúra routerek és modulok
Fő elemek:
app/main.py, app/api/v1/*, app/api/v2/auth.py, app/services/*, app/models/*
Router találatok:
v1 endpoints: auth, vehicles, fleet, providers, expenses, billing, reports, gamification, social, search, admin
v2: auth
Megjegyzés a logod alapján: reports.py router sor: router = APIRouter() # EZ HIÁNYZOTT! → ez tipikusan egy korábbi bugfix nyoma.
[09] Alembic helyzet
alembic parancs a hoston: nincs telepítve
Viszont:
van alembic.ini
van migrations/versions
Következtetés: migrációk léteznek, de a host CLI nincs fent — valószínűleg a migrációt konténerből vagy poetry/venv-ből kell futtatni.
[10] Frontend struktúra
Vue alapú felépítés látszik:
src/views: Login, Register, Forgot/Reset password, Dashboard, Vehicles, Expenses, AdminStats
Router: src/router/index.js
Következtetés: Frontendben az alap “app shell” + fő képernyők megvannak.
[11] MinIO hozzáférés hiba
docker exec -it service_finder_minio mc ls local → Access Denied
Okok tipikusan:
nincs jól beállítva az mc alias set local ...
nem a megfelelő access/secret kulcsot használod (a compose-ban API-nak külön MINIO_ACCESS_KEY/MINIO_SECRET_KEY van)
policy/bucket jog hiányzik
Következtetés: MinIO él, de a CLI hozzáférés nincs inicializálva.
[12] Biztonsági megjegyzés (kritikus)
A logodban szerepelt SendGrid API kulcs és több secret is. Ezeket kezeld kompromittáltnak:
azonnali rotáció (SendGrid key revoke + új)
.env / compose secret-ek rendezése (legalább fájl-jogosultság + később Docker secrets)
(Ezt nem “szidásnak” mondom, hanem azért, mert ez a leggyakoribb valós támadási felület.)
TELJES LOG — 2026-01-30 (DB + ENV + API + Tables)
LOG-2026-01-30-011 — Postgres konfiguráció (compose + env)
DB név: service_finder
DB user: kincses
Image: postgres:15
Volume: /opt/service_finder/postgres_data → /var/lib/postgresql/data
Healthcheck: pg_isready -U kincses -d service_finder
Publikus port: 0.0.0.0:5432 ⚠️
Megállapítás:
A postgres role nem hiba, mert a rendszer kifejezetten kincses userrel lett inicializálva.
A DB él, healthy, működik.
LOG-2026-01-30-012 — API DB kapcsolat
DATABASE_URL:
postgresql+asyncpg://service_finder_app@postgres-db:5432/service_finder
Megállapítás:
Van külön app user (service_finder_app) → jó security practice
Admin user (kincses) ≠ runtime user → helyes architektúra
LOG-2026-01-30-013 — Data schema táblák listája (55 tábla)
✅ FLOTTA & JÁRMŰ (CORE — KÉSZ ALAP)
vehicles
vehicle_brands
vehicle_models
vehicle_variants
vehicle_categories
vehicle_assignments
vehicle_ownership
user_vehicles
vehicle_events
vehicle_expenses
service_records
engine_specs
equipment_items
user_vehicle_equipment
➡️ Flottakezelés adatmodellje: ERŐSEN ELŐREHALADOTT
TELJES LOG — 2026-01-30 (frissítés)
LOG-2026-01-30-009 — OpenAPI spec helyes mentése (/api/v2/openapi.json)
Parancsok:
curl -sS http://127.0.0.1:8000/api/v2/openapi.json -o api_spec_v2.json
wc -c api_spec_v2.json
head -c 200 api_spec_v2.json
Eredmény:
api_spec_v2.json méret: 12 600 byte
fejléc:
{"openapi":"3.1.0","info":{"title":"Traffic Ecosystem SuperApp 2.0","version":"2.0.0"},"paths":{...
tehát a specifikáció rendben letöltődik, nem 404.
LOG-2026-01-30-010 — API endpoint lista (spec alapján)
Parancs:
jq -r '.paths | keys[]' api_spec_v2.json | head -n 80
Eredmény (részlet):
/
/api/v1/auth/register
/api/v1/auth/verify
/api/v1/billing/balance
/api/v1/billing/history
/api/v1/billing/vouchers/generate
/api/v1/billing/vouchers/redeem
/api/v1/expenses/add
/api/v1/fleet/vehicles
/api/v1/reports/summary/{vehicle_id}
/api/v1/reports/trends/{vehicle_id}
/api/v1/users/me
/api/v1/vehicles/register
/api/v1/vehicles/search/brands
/api/v1/vehicles/search/providers
/api/v2/auth/forgot-password
/api/v2/auth/login
/api/v2/auth/register
Megállapítás (fontos):
A dokumentációt a /api/v2/openapi.json adja, de a specben sok /api/v1/... útvonal is szerepel.
Ez általában azt jelenti, hogy:
van legacy v1 (fleet/billing/reports/vehicles),
és közben épül a v2 auth (login/forgot/register).
TELJES LOG — 2026-01-30 (kiegészítve a mostani futásokkal)
LOG-2026-01-30-005 — OpenAPI: /openapi.json 404, /docs OK, OpenAPI URL v2-re mutat
Parancsok:
ls -lah api_spec.json
wc -c api_spec.json
head -c 200 api_spec.json
curl -i http://127.0.0.1:8000/openapi.json | head -n 40
curl -i http://127.0.0.1:8000/docs | head -n 40
curl -i http://127.0.0.1:8000/ | head -n 40
Eredmény:
api_spec.json méret: 22 byte
tartalom: {"detail":"Not Found"}
/openapi.json → HTTP 404 Not Found
/docs → HTTP 200 OK, Swagger UI HTML
a Swagger UI ezt a specifikációt tölti: /api/v2/openapi.json
/ → HTTP 200 OK, JSON:
{"status":"online","version":"2.0.0", ...} (a kimenet vége levágva a pasted szövegben)
Következtetés:
Az API nem a default FastAPI openapi útvonalon adja a specifikációt, hanem verziózott path-on: /api/v2/openapi.json.
Emiatt a korábbi curl .../openapi.json mentés teljesen korrekt módon 404-et mentett le.
LOG-2026-01-30-006 — Fájlrendszer snapshot /opt/service_finder
Parancsok:
ls -lah
find . -maxdepth 3 -type f -name "docker-compose*.yml" -o -name ".env" -o -name "*.env" | sed 's|^\./||'
du -h -d 2 | sort -h | tail -n 30
ls -lah logs || true
Kulcs megállapítások:
van .env (2026-01-30 01:47), docker-compose.yml (2026-01-29 22:03)
van backend/, frontend/, migrations/
api_spec.json jelen van (22 byte)
vannak backup scriptek: backup_manager.sh, backup_to_nas.sh
logs/ mappa létezik, de üres (csak könyvtár)
jogosultsági hibák: postgres_data, .vscode_config/.ssh, pgadmin storage, proxy-manager letsencrypt könyvtárak
Kockázat / megjegyzés:
postgres_data olvasása “Permission denied” → tipikus container volume ownership issue (nem baj, csak kezelni kell sudo-val).
A compose configban látszó code-server PASSWORD kikerült a paste-be → ezt érdemes azonnal cserélni (lásd lent).
LOG-2026-01-30-007 — Compose render + szolgáltatások állapota + log export
Parancsok:
docker compose config > /tmp/service_finder.compose.rendered.yml
docker compose ps
log exportok /tmp/*_last200.log
Eredmény:
Minden releváns szolgáltatás Up: api, frontend, postgres (healthy), redis, minio, npm, pgadmin, code-server, dozzle
Figyelmeztetés: VERSION_CODENAME env nincs beállítva → nem kritikus, de jelzi hogy a compose templated env-et vár.
LOG-2026-01-30-008 — DB elérés: “postgres” role nem létezik
Parancsok:
docker exec -it postgres-db psql -U postgres -c "\l"
docker exec -it postgres-db psql -U postgres -c "\du"
docker exec -it postgres-db psql -U postgres -c "\dx"
docker exec -it postgres-db psql -U postgres -c "\dn"
Eredmény:
mindegyik: FATAL: role "postgres" does not exist
Következtetés:
A konténer nem default POSTGRES_USER=postgres-szal lett inicializálva, hanem más admin userrel (pl. admin, db_owner, stb.).
Ez teljesen OK, csak a -U postgres helyett a valós DB user kell.
TELJES LOG — 2026-01-30
LOG-2026-01-30-001 — Docker konténerek állapota (docker ps)
Kontekstus: service_finder stack futása ellenőrzés
Parancs:
docker ps
Eredmény (kivonat):
service_finder_frontend — port: 0.0.0.0:3000->80/tcp
service_finder_api — port: 0.0.0.0:8000->8000/tcp
postgres-db — image: postgres:15 — port: 0.0.0.0:5432->5432/tcp — healthy
service_finder_redis — image: redis:alpine — port: 6379/tcp
service_finder_minio — port: 0.0.0.0:9000-9001->9000-9001/tcp
nginx-proxy-manager — port: 80-81,443
pgadmin_ui — port: 0.0.0.0:5050->80/tcp
code-server — port: 0.0.0.0:8443->8080/tcp
dozzle — port: 0.0.0.0:8888->8080/tcp
ddclient — fut
Megjegyzés / kockázat:
A postgres-db publikusan ki van téve 0.0.0.0:5432-n. (Ezt a későbbi hardeningnél érdemes minimum LAN/VPN-re szűkíteni.)
LOG-2026-01-30-002 — Docker compose stack-ek listája (docker compose ls)
Parancs:
docker compose ls
Eredmény:
ddclient — running(1) — /opt/ddclient/docker-compose.yml
service_finder — running(9) — /opt/service_finder/docker-compose.yml
LOG-2026-01-30-003 — Docker compose szolgáltatások állapota (docker compose ps)
Parancs:
docker compose ps
Eredmény (kivonat):
postgres-db — Up (healthy)
service_finder_api — Up
service_finder_frontend — Up
service_finder_redis — Up
service_finder_minio — Up
nginx-proxy-manager — Up
pgadmin_ui — Up
code-server — Up
dozzle — Up
Megjegyzés:
A “2 docker konténer” megfogalmazás helyett itt 2 compose projekt van (ddclient + service_finder), és azon belül több konténer fut.
LOG-2026-01-30-004 — OpenAPI specifikáció kimentése (curl openapi.json)
Kontekstus: API elérhetőségének és OpenAPI dokumentációjának ellenőrzése
Parancs:
curl http://127.0.0.1:8000/openapi.json > api_spec.json
Eredmény:
Letöltött méret: 22 byte
Megjegyzés / következtetés:
A 22 byte nagyon gyanús (egy FastAPI OpenAPI JSON tipikusan több KB/MB). Ez majdnem biztosan azt jelenti, hogy nem a várt OpenAPI JSON jött vissza (pl. “Not Found”, “Unauthorized”, reverse proxy válasz, vagy hibaszöveg).
Következő lépés: a fájl tartalmát ki kell olvasni (wc -c api_spec.json && cat api_spec.json), és/vagy headerekkel kérni (curl -i ...).
TELJES LOG — 2026-01-30
LOG-2026-01-30-001 — Docker konténerek állapota (docker ps)
Kontekstus: service_finder stack futása ellenőrzés
Parancs:
docker ps
Eredmény (kivonat):
service_finder_frontend — port: 0.0.0.0:3000->80/tcp
service_finder_api — port: 0.0.0.0:8000->8000/tcp
postgres-db — image: postgres:15 — port: 0.0.0.0:5432->5432/tcp — healthy
service_finder_redis — image: redis:alpine — port: 6379/tcp
service_finder_minio — port: 0.0.0.0:9000-9001->9000-9001/tcp
nginx-proxy-manager — port: 80-81,443
pgadmin_ui — port: 0.0.0.0:5050->80/tcp
code-server — port: 0.0.0.0:8443->8080/tcp
dozzle — port: 0.0.0.0:8888->8080/tcp
ddclient — fut
Megjegyzés / kockázat:
A postgres-db publikusan ki van téve 0.0.0.0:5432-n. (Ezt a későbbi hardeningnél érdemes minimum LAN/VPN-re szűkíteni.)
LOG-2026-01-30-002 — Docker compose stack-ek listája (docker compose ls)
Parancs:
docker compose ls
Eredmény:
ddclient — running(1) — /opt/ddclient/docker-compose.yml
service_finder — running(9) — /opt/service_finder/docker-compose.yml
LOG-2026-01-30-003 — Docker compose szolgáltatások állapota (docker compose ps)
Parancs:
docker compose ps
Eredmény (kivonat):
postgres-db — Up (healthy)
service_finder_api — Up
service_finder_frontend — Up
service_finder_redis — Up
service_finder_minio — Up
nginx-proxy-manager — Up
pgadmin_ui — Up
code-server — Up
dozzle — Up
Megjegyzés:
A “2 docker konténer” megfogalmazás helyett itt 2 compose projekt van (ddclient + service_finder), és azon belül több konténer fut.
LOG-2026-01-30-004 — OpenAPI specifikáció kimentése (curl openapi.json)
Kontekstus: API elérhetőségének és OpenAPI dokumentációjának ellenőrzése
Parancs:
curl http://127.0.0.1:8000/openapi.json > api_spec.json
Eredmény:
Letöltött méret: 22 byte
Megjegyzés / következtetés:
A 22 byte nagyon gyanús (egy FastAPI OpenAPI JSON tipikusan több KB/MB). Ez majdnem biztosan azt jelenti, hogy nem a várt OpenAPI JSON jött vissza (pl. “Not Found”, “Unauthorized”, reverse proxy válasz, vagy hibaszöveg).
Következő lépés: a fájl tartalmát ki kell olvasni (wc -c api_spec.json && cat api_spec.json), és/vagy headerekkel kérni (curl -i ...).
IDŐVONAL — 2026-01-30
Időpontok: a parancsokhoz konkrét óra:perc nem volt rögzítve a másolatban, ezért sorrendi idővonalat adok (ez stabil, később időbélyeggel pontosítható).
Docker futó konténerek ellenőrzése (docker ps)
Compose projektek listázása (docker compose ls)
Compose szolgáltatások állapotának listázása (docker compose ps)
OpenAPI export kísérlet (curl .../openapi.json > api_spec.json) → 22 byte-os eredmény, anomália
RENDSZERFELTÁRÁS — mi kész, mi nincs kész (jelen bizonyítékok alapján)
Ami biztosan kész / működik
Alaprendszer Compose-ban fut: service_finder stack “running(9)”.
Frontend él: port 3000 publikusan kint.
API él: port 8000 publikusan kint.
Postgres él és healthy: postgres:15, publikus 5432.
Redis él.
MinIO él.
Admin eszközök élnek: pgAdmin (5050), NPM (80/81/443), Dozzle (8888), code-server (8443).
Létezik lokális projekt struktúra és volume-ok: /opt/service_finder/... alatt backend, frontend, logs, migrations, postgres_data, redis data, proxy-manager adatok.
filesystem_map
Ami valószínűleg nincs kész / hibás / tisztázandó
OpenAPI endpoint: a mentett fájlméret alapján nem jó választ ad az /openapi.json (vagy nem ott van, vagy proxy/route gond).
Biztonsági hardening: Postgres jelenleg 0.0.0.0:5432-n lóg (ez később sürgős).
Migrációs konzisztencia: van migrations struktúra a fájlrendszerben (több helyen is), de nem tudjuk, hogy DB-séma ténylegesen “head”-en van-e.
filesystem_map
FÁJLRENDSZER-HELYZETKÉP (amit már látunk)
A feltöltött map alapján a fontos csomópontok:
Projekt gyökér: /opt/service_finder
filesystem_map
Backend kód: /opt/service_finder/backend (+ app/, models/, auth/, schemas/, templates/, migrations/versions)
filesystem_map
Frontend kód: /opt/service_finder/frontend (+ src/views/admin, router, stores, services, components, public, node_modules)
filesystem_map
Log könyvtár: /opt/service_finder/logs
filesystem_map
Postgres adatok: /opt/service_finder/postgres_data/... (és van egy /opt/service_finder/postgres/data/... jellegű ág is)
filesystem_map
Redis data: /opt/service_finder/redis/data/...
filesystem_map
NPM/Proxy manager adatok + LE: /opt/service_finder/proxy-manager/...
filesystem_map
Megjegyzés: a map alapján mintha két postgres adatútvonal is jelen lenne: postgres/data és postgres_data. Ezt tisztázni kell, nehogy két külön volume/útvonal keveredjen (backup, restore, space, stb.).
filesystem_map
ADATBÁZIS-HELYZETKÉP (a feltöltött táblalistád alapján)
A feltöltött tablak_2026.01.30_0.csv alapján a data sémában 54 tábla van. (Ezt használom alapnak a DB audit lépések priorizálásához.)
A következő lépésben ebből fogok csinálni:
“core domain” csoportosítást (org/account/auth/vehicle/provider/request/evidence/stb.),
és egy “migráció és integráció” ellenőrző checklistet (táblák + FK + index + RLS jelek).

View File

@@ -0,0 +1,15 @@
# Master Grand Book v1.0 Service Finder / Traffic Ecosystem SuperApp
Ez a dokumentáció a projekt **kanonikus tudásbázisa**.
Két párhuzamos könyvtár létezik:
- V01_chatgpt technikai, mérnöki, architekturális megközelítés
- V01_gemini alternatív gondolkodás, validáció, kiegészítő perspektíva
Cél:
- Tudás megőrzése
- Döntések visszakövethetősége
- Fejlesztési minőség mérése (kód + beállítás + hibajavítás hatékonyság)
- Új projektek benchmark alapja
Ez a v1.0 verzió a **baseline állapot** dokumentálása.

View File

@@ -0,0 +1,24 @@
# Projekt áttekintés
Projekt neve: Traffic Ecosystem SuperApp 2.0 (Service Finder)
Cél:
Egy moduláris platform létrehozása, amely:
- kezeli a járművek életciklusát,
- nyilvántartja a költségeket, eseményeket, szervizeket,
- összeköti a felhasználókat valós szolgáltatókkal,
- automatizált adatgyűjtést végez (discovery botok),
- skálázható SaaS modellben működik.
Fő modulok:
- Auth / User / Organization
- Fleet & Vehicle Lifecycle
- Service Provider Marketplace
- Billing / Credits / Subscription
- Gamification & Social
- Discovery Bots (adatgyűjtés)
- Dokumentumfeldolgozás (OCR pipeline tervezett)
Non-goals (v1.0):
- Teljes üzleti automatizmus
- Külső fizetési gateway éles integráció

View File

@@ -0,0 +1,19 @@
# Fejlesztői környezet
Indítás:
- docker compose up -d
Alapszolgáltatások:
- API: :8000
- Frontend: :3001
- MinIO: :9000 / :9001
- Redis: belső háló
Tipikus ellenőrzések:
- API online: GET /
- OpenAPI: /api/v2/openapi.json
- Frontend betölt
Ismert jellegzetességek:
- v1 és v2 API párhuzamosan él
- .env alapú konfiguráció

View File

@@ -0,0 +1,26 @@
# Adatbázis Baseline állapot
DB: PostgreSQL (shared-postgres)
Séma: data
Táblák száma: ~55
Kulcs entitások:
- users
- persons
- companies
- vehicles, vehicle_models, vehicle_variants
- service_providers, service_specialties
- fuel_stations
- credit_logs, vouchers, subscriptions
- audit_logs
Migráció:
- Alembic
- Head rev: 5aed26900f0b
- Persons + owner_person_id implementálva
Seed:
- fuel_stations ~7300
- service_providers ~7200

View File

@@ -0,0 +1,13 @@
# API Áttekintés
Verziók:
- v1: üzleti modulok (fleet, billing, reports)
- v2: auth és új generációs endpointok
Elvek:
- JWT alapú auth
- Verziózott API
- OpenAPI dokumentált
Megjegyzés:
A v1 → v2 egységesítés külön roadmap tétel.

View File

@@ -0,0 +1,10 @@
# Anchor Log döntési napló
Ez a fejezet rögzíti:
- fontos architekturális döntéseket,
- API-szerződés változásokat,
- adatmodell átalakításokat,
- stratégiai irányváltásokat.
Cél:
- később visszakövethető legyen, miért úgy épült a rendszer, ahogy.

View File

@@ -0,0 +1,6 @@
# Changelog
v1.0 Baseline
- Mester dokumentum struktúra létrehozva
- DB baseline rögzítve
- API verziózás dokumentálva

View File

@@ -0,0 +1,29 @@
# 📘 SERVICE FINDER - GRAND MASTER BOOK (v1.0)
**Traffic Ecosystem SuperApp 2.0**
Ez a dokumentáció a rendszer "Egyetlen Igazságforrása" (Single Source of Truth). Minden fejlesztésnek, API hívásnak és üzleti logikának az itt leírtakat kell követnie.
## 🚀 Gyorslinkek
- **01 Project Overview:** [Mit építünk?](./01_Project_Overview.md)
- **02 Architecture:** [Hogyan működik?](./02_Architecture_System_Context.md)
- **06 Database:** [Adatmodell és Logika](./06_Database_Guide.md)
- **10 Billing & Tiers:** [Üzleti Modell](./10_Billing_Credits_Subscriptions.md)
## 🚦 Státusz Snapshot (2026-02-03)
- **Fázis:** Architektúra stabilizálás & Migráció (Pre-Beta).
- **Infrastruktúra:** Profibot SW1 (80 Core) - ÉLES.
- **Frontend:** Vue3 + Tailwind (Port 3000).
- **Backend:** FastAPI v2 (Port 8000).
- **Adatbázis:** PostgreSQL 15 (55 tábla, Seed adatokkal).
# Master Book - Automotive Intelligence Ecosystem
Ez a dokumentáció a projekt technikai és üzleti felépítését tartalmazza.
## Projekt Célkitűzés
Egy európai szintű, intelligens járműipari ökoszisztéma kiépítése, amely egyesíti a mély járműkatalógus-adatokat (Deep Asset Catalog) és a hitelesített szervizkeresőt (Service Finder).
## Főbb Komponensek
- **Data Core:** 21,000+ rekordos járműadatbázis (Holland, USA, EU forrásokból).
- **Service Hunter:** n8n alapú, automatizált szerviz-felderítő rendszer.
- **Trust Engine:** Pontszám alapú validációs algoritmus az adatok hitelességének biztosítására.
- **Robot Ökoszisztéma:** Python alapú adatgyűjtő és öngyógyító (Auto-Heal) ágensek.

View File

@@ -0,0 +1,19 @@
# 🧠 PROJECT OVERVIEW & VISION
## 🎯 A Cél
Egy **Digital Twin** (Digitális Iker) alapú jármű-ökoszisztéma létrehozása.
**"A jármű örök, a tulajdonos vándor."**
Nem csak költségkövető, hanem egy Service Marketplace, Trust Engine és Gamifikált közösség.
## 🏗️ Fő Modulok
1. **Core Fleet:** Jármű életút, Költségek, TCO (Total Cost of Ownership).
2. **Marketplace:** Szervizkereső (Geo+Routing), Ajánlatkérés, Időpontfoglalás.
3. **Evidence Store:** Bizonyíték alapú előélet (Fotó, Számla, OCR).
4. **Economy:** Kreditrendszer, Előfizetések, Jutalékok.
## 📖 Terminológia (Glossary)
- **PERSON:** A természetes személy (Élő ember). Nem törölhető, csak rejtetté tehető (Soft Delete).
- **USER:** A technikai belépési fiók. Egy Person-höz több User tartozhat.
- **COMPANY:** Jogi entitás (Céges flotta). Van Tulajdonosa (Person) és Flotta Managere (User).
- **PROVIDER:** Szolgáltató (Szerviz, Gumis, Autómosó).
- **VALIDATOR:** Magas rangú felhasználó, aki kreditért cserébe adatokat ellenőriz.

View File

@@ -0,0 +1,23 @@
# 🏗️ ARCHITECTURE & SYSTEM CONTEXT
## 🧩 Komponensek
- **Frontend:** Vue 3 + Tailwind CSS + Pinia (State) + Vite. "Dumb Frontend" elv: Csak megjelenít, nem dönt.
- **Backend API:** Python 3.12 + FastAPI. Minden üzleti logika itt fut. Pydantic validáció.
- **Database:** PostgreSQL 15. Külön `data` (üzleti) és `public` (rendszer) sémák.
- **Storage:** MinIO (S3 kompatibilis). Képek, számlák titkosított tárolása.
- **Proxy:** Nginx Proxy Manager. SSL terminálás (`dev.profibot.hu`).
## 🛡️ Hálózati Határok
- **Internal Net (`shared_db_net`):** A Backend és az Adatbázis közötti dedikált, zárt csatorna.
- **Public Net:** Csak a 80/443 (NPM) nyitott a világ felé. A DB port (5432) és Admin portok (5050, 8888) csak VPN-en vagy localhoston érhetők el.
# 02. Architecture & System Context
## Rendszerarchitektúra v2.0
A rendszer egy eseményvezérelt, mikroszolgáltatás-alapú architektúrára épül, ahol az **n8n** tölti be a központi idegrendszer (Orchestrator) szerepét.
### Adatáramlási Folyamat
1. **Discovery Layer:** n8n által vezérelt robotok (Robot A) pásztázzák a hálót (OSM, DDG, FB, e-Cégközlöny).
2. **Staging Layer:** A nyers adatok egy átmeneti (Stage) táblába kerülnek további elemzésre.
3. **Audit Layer:** A validátor robot (Robot B) ellenőrzi az adószámokat, TEAOR kódokat és a digitális lábnyomot.
4. **Core Database:** Csak a Trust Engine által hitelesített adatok kerülnek az éles jármű- és szervizkatalógusba.

View File

@@ -0,0 +1,59 @@
(Fejlesztői kézikönyv.)
# 👨‍💻 DEVELOPER RUNBOOK
## 🚀 Indítás
```bash
cd /opt/docker/dev/service_finder
docker compose up -d
🔍 Logok és Debug
API log: docker logs -f service_finder_api
Frontend log: docker logs -f service_finder_frontend
DB Console: docker exec -it shared-postgres psql -U kincses -d service_finder
⚠️ Known Pitfalls (Hibaelhárítás)
API URL: A frontend .env fájljában a VITE_API_BASE_URL nem lehet localhost, ha konténerben fut. Használd a belső IP-t vagy domain-t.
Login 404: A /api/v1/users/me végpontot a backend routerben regisztrálni kell (jelenleg hiányzik vagy path mismatch van).
OpenAPI 404: A helyes cím /api/v2/openapi.json.
# 03. Development Environment Runbook
## 3.1. System Initialization (Bootstrap)
Ha az adatbázis üres (vagy törölve lett), az első SuperAdmin felhasználót manuálisan kell létrehozni, mivel a regisztrációs végpontok védettek vagy nem adnak admin jogot.
### 3.1.1. SuperAdmin Létrehozása (Recommended)
A jelszó hash-elési eltérések elkerülése érdekében használjuk a Python scriptet a konténeren belül:
```bash
docker exec -it service_finder_api python3 -c "
import bcrypt
import asyncio
from sqlalchemy import text
from app.db.session import SessionLocal
async def bootstrap_admin():
# 1. Jelszó generálás
password = 'InitialPassword123'.encode('utf-8')
hashed = bcrypt.hashpw(password, bcrypt.gensalt()).decode('utf-8')
async with SessionLocal() as db:
# 2. Person és User létrehozása/Frissítése
# (A script feltételezi, hogy a Person rekord már létezik vagy itt hozod létre)
sql = text(\"\"\"
UPDATE data.users
SET hashed_password = :h, role = 'superadmin', is_active = true, preferred_language = 'hu'
WHERE email = 'admin@servicefinder.hu'
\"\"\")
await db.execute(sql, {'h': hashed})
await db.commit()
print('✅ SuperAdmin Ready')
if __name__ == '__main__':
asyncio.run(bootstrap_admin())
"

View File

@@ -0,0 +1,27 @@
# 🐳 DOCKER STACK & PORTS
## Szolgáltatások
| Service | Image | Internal Port | Host Port | Volume Mapping |
| :--- | :--- | :--- | :--- | :--- |
| **API** | `python:3.12` | 8000 | 8000 | `./backend:/app` |
| **Frontend** | `node:20` | 80 | 3000 | `./frontend:/app` |
| **DB** | `postgres:15` | 5432 | 5432 | `postgres_data:/var/lib/postgresql/data` |
| **MinIO** | `minio/minio` | 9000, 9001 | 9000, 9001 | `minio_data:/data` |
| **Redis** | `redis:alpine` | 6379 | - | - |
## Hardening Terv
A `Host Port` oszlopban lévő portokat éles üzemben le kell venni (kivéve 80/443), és csak a
# 04. Infrastructure & Docker Stack
## Hardver Erőforrás
- **Szerver:** 128 GB RAM (High-Performance Node).
- **Kihasználtság cél:** Moduláris konténerek futtatása alacsony (5-10%) alapterhelés mellett, magas skálázhatósági tartalékkal.
## Docker Ökoszisztéma (Bővített)
A stack a következő konténereket tartalmazza:
1. **n8n (Orchestrator):** Vizuális munkafolyamat-kezelő.
2. **PostgreSQL:** Központi adattár (Járművek + Szervizek).
3. **Browserless (Chrome):** "Fej nélküli" böngésző az n8n számára a komplex scraping feladatokhoz.
4. **Python Robots:** Konténerizált adatgyűjtő és dúsító ágensek (v1.9.2+).
5. **Proxy/VPN Node:** IP-rotációt biztosító modul a globális felderítéshez.

View File

@@ -0,0 +1,166 @@
# 🔐 05_AUTH_AND_IDENTITY_SPEC (v1.3)
## 1. Azonosítási Stratégia
A rendszer alapelve a **technikai hozzáférés** (User) és a **valós identitás** (Person) szigorú szétválasztása.
### 1.1. Identitás szintek
- **User (Login):** Email + Jelszó. Kizárólag a belépéshez és a munkamenet (session) kezeléséhez szükséges technikai entitás.
- **Person (Identity):** A valós személy adatai (Név, anyja neve, születési adatok, okmányok). Minden Person kap egy globális egyedi azonosítót (**UUID**).
### 1.2. Social Auth (Google / Facebook)
- **Működés:** Engedélyezett a gyors belépéshez.
- **Kényszerített KYC:** Social Auth esetén a 2. lépésben kötelező a KYC adatok pótlása.
- **Korlátozás:** Amíg a KYC adatok hiányoznak, a felhasználó "Free User" marad, és nem fér hozzá a regisztrációkor járó extra prémium szolgáltatásokhoz.
### 1.3. Soft Delete & Re-regisztráció
- **Nincs fizikai törlés:** A felhasználó törléskor `is_hidden` vagy `deleted_at` flag-et kap.
- **Ismételt regisztráció:** Ha az email/név/okmány alapján a rendszer felismeri a visszatérőt:
- Új technikai User fiók jön létre, de a korábbi **Person ID**-hoz kapcsolódik.
- **Adat-izoláció:** A felhasználó csak az új regisztráció utáni eseményeket látja, a régi adatok (statisztika, elemzés) csak a háttérben maradnak meg.
---
## 2. Bizalmi Szintek (Trust Tiers)
A rendszer a "Tier-based Access Control" (szintezett hozzáférés) elvét alkalmazza az adatszolgáltatás mértékétől függően.
| Szint | Megnevezés | Követelmény | Jogosultságok |
| :--- | :--- | :--- | :--- |
| **Tier 0** | Anonymous | Nincs | Csak publikus adatok megtekintése. |
| **Tier 1** | Verified Email | Step 1 (Regisztráció) sikeres | Belépés, saját profil megtekintése. |
| **Tier 2** | KYC Submitted | Step 2 (Személyi adatok + Telefon) | **Privát Széf/Flotta aktiválása**, Wallet használat. |
| **Tier 3** | AI/OCR Verified | Okmánykép AI általi ellenőrzése | Harmadik fél szolgáltatásainak igénybevétele. |
---
## 3. KYC és Bővített Adattár (Safety)
A `persons` tábla progresszív feltöltéssel tárolja az adatokat a "Minimal Friction" elv mentén.
### 3.1. Kötelező Adatkör (Step 2 - Tier 2)
A "Privát Széf" aktiválásához az alábbi adatok megadása kötelező:
- **Alapadatok:** `last_name`, `first_name`, `birth_place`, `birth_date`, `mothers_name`.
- **Kapcsolat:** Valós telefonszám (nemzetközi formátum).
- **Hivatalos okmányok:** Személyi ig. szám, Jogosítvány (szám, kategóriák, érvényesség), Lakcímkártya, TAJ, Adóazonosító.
- **Biztonság (ICE):** "In Case of Emergency" adatok (értesítendő személy neve és telefonszáma).
- **Vészhelyzeti adatok:** Vércsoport, Allergia.
### 3.2. Jutalom Trigger
A teljes körű adategyeztetésért (100%-os profilkitöltöttség) **2 hét PRÉMIUM** tagság jár.
---
## 4. Céges Azonosítás és Verifikáció
A szervezetek (Companies) hitelesítése és bizalmi szintjeinek kezelése.
### 4.1. Verifikációs Státuszok
- **Unverified (Nem ellenőrzött):** Kézi rögzítés utáni alapállapot. 30 napos türelmi időt biztosít a funkciókhoz.
- **Verified (Hitelesített):** Hitelesített állapot (VIES API találat vagy Admin kézi jóváhagyás után).
- **Suspended (Felfüggesztett):** Megszűnt cég vagy le nem igazolt adatok esetén az időszakos ellenőrzés során.
### 4.2. Ellenőrzési Logika (Robot & Admin)
1. **Robot:** A `VAT_NUMBER` rögzítésekor a rendszer azonnal meghívja az EU-s **VIES API**-t. Egyezőség esetén azonnal `Verified`.
2. **Hibrid Validálás:** Ha a VIES API nem ad eredményt, a rendszer céges dokumentum feltöltését kéri.
3. **Ellenőrzés:** Adminisztrátori jóváhagyás vagy AI-alapú dokumentum-validálás után válik a státusz véglegessé.
4. **Időszakos ellenőrzés:** Ütemezett feladat (Cron) 30 naponta újraellenőrzi a cégeket. Megszűnés esetén `Suspended` státusz és értesítés.
### 4.3. Korlátozások (Suspended/Unverified)
- Nem rögzíthető új jármű a flottába.
- Nem generálható meghívó (Invite Token).
- Statisztikai kimutatások korlátozása.
---
## 5. Jutalék és Gazdasági Rendszer
### 5.1. Piramis rendszer (3 szint)
A meghívó lánc alapján számolt jóváírások (Referral):
- **1. szint (Közvetlen):** 10%
- **2. szint:** 5%
- **3. szint:** 2%
*Megjegyzés: A százalékok a befizetés pillanatában érvényes admin beállítások alapján rögzülnek (Snapshot technika).*
### 5.2. Wallets
Minden regisztrációnál automatikusan létrejön:
- **Coin Wallet:** Belső fizetőeszköz (Kredit).
- **XP Ledger:** Tapasztalati pontok (Gamification és rangsor).
---
## 6. Moderáció és Validálás
- **Validált vélemény:** Csak igazolt ott-tartózkodás (GPS log) vagy számlafotó (OCR) feltöltése után adható.
- **Fellebbezés:** A szervizek kérhetik a vélemények felülvizsgálatát, amit moderátorok bírálnak el.
---
## 7. Adattárolási Stratégia (Technikai)
- A rugalmas okmányadatokat (`identity_docs`) és a vészhelyzeti kapcsolatokat (`ice_contact`) **JSONB** mezőkben tároljuk a `persons` táblában a kereshetőség és a jövőbeli bővíthetőség érdekében.
## 4. Multi-Account & Identity Linking
A felhasználók több e-mail címet is csatolhatnak egyetlen profilhoz, hogy könnyen válthassanak a magánszemély és a céges flotta-menedzser szerepkörök között.
### 4.1 Szabályrendszer
* **Limit:** Egy felhasználói profilhoz maximum **3** másodlagos e-mail cím csatolható.
* **Elsődleges cím:** Ez a belépési azonosító és a hivatalos értesítési cím.
* **Context Switching:** A felhasználó a fejlécben válthat a "Személyes" és a "Céges" nézetek között (pl. Flotta Manager mód).
### 4.2 Account Linking Folyamat
1. User belép az elsődleges fiókba.
2. `Settings -> Linked Accounts -> Add New`.
3. Rendszer küld egy megerősítő linket az új címre.
4. Ha a linkre kattint, az új cím hozzáadódik a `user_identities` táblához.
5. Ha az új címen már volt regisztráció: A rendszer felajánlja az **Account Merge** (Fiókegyesítés) lehetőségét (biztonsági kérdések után).
```markdown
# 05. Authentication & Identity Specification
## 5.2. Data Models (Identity)
### 5.2.1. User Entity (`data.users`)
A technikai belépési pont.
- **id**: Integer (PK)
- **email**: String (Unique)
- **hashed_password**: String (Bcrypt)
- **role**: Enum (superadmin, admin, user, service, driver)
- **person_id**: FK -> `data.persons.id` (A TWINS kapcsolat)
- **preferred_language**: String (Default: 'hu') [ÚJ v1.2.5]
- **region_code**: String (Default: 'HU') [ÚJ v1.2.5]
- **is_active**: Boolean
### 5.2.2. TWINS Concept Update
- A `User` (User) és `Person` (Shadow Identity) szétválasztása szigorú.
- Belépéskor a rendszer a `User` táblából olvassa ki a `preferred_language` és `region_code` beállításokat, és ezeket a Token válaszban visszaadja a Frontendnek.
## 1.3 Shadow Identity & Merging Logic
A rendszer támogatja a "Ghost Person" (Árnyék személy) entitásokat.
- **Ghost Person:** Olyan `data.persons` rekord, amelyet a Robot 2 hozott létre nyilvános adatok (pl. cégjegyzék) alapján.
- **Identity Linkage:** Regisztrációkor a `AuthService.complete_kyc` kötelezően ellenőrzi a meglévő Ghost rekordokat (Adószám/Név egyezés).
- **Merge Action:** Találat esetén a rendszer összefűzi a technikai User fiókot a Ghost Person rekorddal, aktiválja a jogosultságokat, és megszünteti a Ghost státuszt.
## 2. The Dual Entity Model (Person vs. User)
A rendszer alapja a természetes személy (**Person**) és a felhasználói fiók (**User**) szigorú szétválasztása az adatbiztonság és az üzleti folytonosság érdekében.
### 2.1 Person (A DNS - "Az Örök Személy")
A `persons` tábla rekordja soha nem törlődik teljesen (GDPR esetén anonimizálódik), így biztosítva a rendszer memóriáját.
* **Identity Hash:** Egyedi SHA256 lenyomat (`normalized(name + mother + birth_place + birth_date)`), amely megakadályozza a multi-account visszaéléseket és felismeri a visszatérő felhasználókat.
* **Örök Adatok:**
* `lifetime_xp`: A valaha szerzett összes tapasztalati pont.
* `penalty_points`: A büntetési szint (0-3). Ez nem nullázódik új regisztrációval!
* `social_reputation`: A közösségi megbízhatósági index (1.00 = 100%).
* `is_sales_agent`: Jogosult-e jutalékra.
### 2.2 User (A Kulcs - "A Munkamenet")
A `users` tábla a belépési pont. Törölhető, eldobható, újraregisztrálható.
* **Kapcsolat:** Minden User egyetlen Person-höz tartozik (`person_id`).
* **Időkorlátos Jogok:**
* `subscription_plan`: FREE / PREMIUM / VIP.
* `subscription_expires_at`: A prémium funkciók lejárata.
* **Sales Kapcsolat:**
* `referral_code`: Saját meghívó kód.
* `current_sales_agent_id`: Ki kapja a "Farming" jutalékot ez után a felhasználó után.
### 2.3 Jogosultsági Szintek (Scope-Based RBAC)
A jogosultság nem csak szerepkör (Role), hanem hatókör (Scope) alapú:
1. **Global:** Superadmin.
2. **Country:** Országos Admin (pl. HU).
3. **Region:** Régiós Admin (pl. Pest megye).
4. **Entity:** Szerviz Tulajdonos (saját cég).
5. **Individual:** Átlagfelhasználó (saját adatok).

View File

@@ -0,0 +1,223 @@
# 🗄️ 06_DATABASE_GUIDE & DATA INTEGRITY (v1.4)
Ez a dokumentum az adatbázis-architektúra alapelveit és az adatintegritási szabályokat tartalmazza.
## 1. Soft Delete & Újraregisztráció Logika
A rendszerben **nincs fizikai törlés**. A `data.users` tábla speciális indexeléssel kezeli a törölt és visszatérő felhasználókat.
- **Indexelés:** Az `email` mezőn egy *Partial Unique Index* (`idx_user_email_active_only`) található.
- **Működés:** - Ha `is_deleted = FALSE`, az email foglalt, nem használható újra.
- Ha a felhasználó törli magát (`is_deleted = TRUE`), az email felszabadul.
- **Identitás megőrzése:** Új regisztrációkor a rendszer új `user_id`-t generál, de ha a KYC (személyazonosító) adatok egyeznek, az új technikai User a régi `person_id`-hoz kapcsolódik.
---
## 2. Person (Identitás) - KYC & Safety
A `data.persons` tábla a valós, banki szintű személyazonosságot tárolja.
### 2.1. JSONB struktúrák
Rugalmas adatszerkezet az okmányok és orvosi adatok kezelésére:
- **`identity_docs`**:
- `id_card`: szám és lejárati dátum.
- `driver_license`: szám, lejárat és kategóriák (pl. ["A", "B", "C"]).
- `special_permits`: hajó- vagy repülőgép-vezetői engedélyek.
- **`medical_emergency`**: Vércsoport, allergiák, krónikus betegségek.
### 2.2. Jutalom Trigger
A profil 100%-os kitöltése (név, születési adatok, okmányok) után automatikusan aktiválódik a `system_settings`-ben meghatározott **PRÉMIUM** időszak (alapértelmezett: 14 nap).
---
## 3. Technikai Integritás és Séma
### 3.1. Adatbázis sémák
- **`public`**: Csak technikai metaadatok (pl. `alembic_version`).
- **`data`**: Az üzleti logika összes táblája (55+ tábla).
### 3.2. Fejlesztői megjegyzések
- **Enum Case Sensitivity:** A Postgres `userrole` típusa **kisbetűérzékeny**. A Python kódból érkező értékeket (pl. `user`, `admin`) kényszerítve kisbetűvel kell rögzíteni.
- **Séma Frissítés:** A `metadata.create_all` nem frissíti a meglévő táblákat. Új oszlopok esetén manuális `ALTER TABLE` vagy Alembic migráció szükséges.
- **Audit:** Minden státuszmódosítás és adatváltozás snapshot-olva kerül az `audit_logs` táblába.
---
## 4. Economy, Regionalizáció és Valuta
A rendszer EU-s piacra optimalizált multi-currency logikát használ.
- **`data.regional_settings`**: Országkódok (ISO 3166-1), alapértelmezett nyelvek és pénznemek.
- **`data.exchange_rates`**: Napi frissítésű váltószámok (Bázis: EUR).
- **Valuta Logika:** Minden költséget elmentünk helyi pénznemben (`currency_code`) és a rögzítéskori váltószámmal átszámított EUR-ban is.
- **Képlet:** $$Cost_{EUR} = Cost_{Local} \cdot ExchangeRate$$
### 4.1. Wallet & Economy
- **Wallets:** Minden regisztrációkor létrejön egy rekord a `data.wallets` táblában (0 Coin, 0 XP).
- **Referral Snapshot:** Jutalék kifizetésekor a rendszer rögzíti a tranzakció pillanatában érvényes `%`-ot (`commission_percentage`), védve az adatot a későbbi módosításoktól.
---
## 5. Flotta és Tulajdonjog Szabályok
A flották (Organization) és járművek tulajdonjogi logikája:
- **Átruházhatóság (Transferability):**
- `INDIVIDUAL` flotta: Nem átruházható, a felhasználóhoz kötött.
- `FLEET_OWNER / SERVICE` flotta: Átruházható, új tulajdonoshoz (`owner_id`) rendelhető.
- **Cég Megszűnése:** Soft delete (`is_active: False`). A járművek életútja (history) megmarad a visszakövethetőség miatt.
- **Opcionális Járművek:** Egy flotta létezhet jármű rögzítése nélkül is (pl. tisztán menedzseri kör).
---
## 6. Szervezeti Egységek és CRM
A flottákhoz tartozó humán és üzleti kapcsolatok kezelése.
- **`data.organizations`**: Bővítve: `tax_number`, `reg_number`, `headquarters_address`, `notification_settings` (JSONB).
- **`data.organization_contacts`**: Mini-CRM funkciók (kapcsolattartók típusai: billing, primary, operational).
- **Kapcsolódás:** `external_crm_id` mező biztosítja az API kapcsolatot külső ERP rendszerekkel.
---
## 7. Gazdasági Izoláció és Rating
- **Gamification Korlát:** Csak `INDIVIDUAL` típusú flottákhoz tartozó `Person`-ok gyűjthetnek XP-t. A cégek (`Company`) nem kapnak `XP_Ledger`-t és `Coin_Wallet`-et.
- **Validáció:** Cég nem validálhat szervizpontot, csak a hozzárendelt, azonosított `Person` (technikus).
- **Rating Rendszer:** Külön értékelést kap a **Person** (megbízhatóság), a **Service** (minőség) és a **Vehicle** (műszaki állapot). A cég hírneve ezekből adódik össze.
---
## 8. Dinamikus Paraméterezés (`data.system_settings`)
Minden üzleti változó az Admin UI-ról állítható:
- `auth.reward_days`: Regisztrációs prémium hossza (default: 14).
- `auth.reward_tier`: Kapott csomag típusa (default: PREMIUM).
- `referral.l1`: Első szintű jutalék mértéke (default: 10%).
---
## 9. Kulcs Táblacsoportok
1. **Fleet:** `vehicles`, `user_vehicles`, `vehicle_events`, `engine_specs`.
2. **Marketplace:** `service_providers`, `service_specialties`, `organization_locations`.
3. **Economy:** `wallets`, `transactions`, `shop_items`.
4. **Identity:** `users`, `persons`, `companies`.
---
## 10. Migrációs Állapot (Dev Info)
- **Eszköz:** Alembic
- **Current Head:** `10b73fee8967`
- **Hiányzó láncszem:** A `persons` tábla véglegesítése és a meglévő `users` tábla adatintegrációs migrációja folyamatban.
## 4.2 Dokumentum és Irattár (Vault Logic)
- **Központi tárolás:** A `data.documents` tábla kezeli az összes csatolmányt (parent_type: 'org', 'asset', 'person').
- **Metadata:** Tároljuk a dokumentum kibocsátóját (issuer_id) és tárgyát (subject_id) a szervizstatisztikákhoz.
- **Verifikáció:** `status` mező (pending, verified, rejected).
## 4.3 Crowdsourced Szervezetek
- **Lifecycle:** draft_user -> draft_bot -> community_verified -> official.
- **Gamification:** XP/Kredit jóváírás csak sikeres Bot vagy Owner validáció után.
## 6. Service & Organization Extensions (V2)
### 6.1 `data.system_configs` (Dinamikus Beállítások)
Kódba égetett értékek helyett adatbázisból vezérelt működés.
* `key` (VARCHAR): Pl. `referral_bonus_L1`, `exchange_rate_EUR`, `payout_threshold`.
* `value` (JSONB): Pl. `{"amount": 10, "unit": "percent"}`, `{"rate": 400.0}`.
* `is_active` (BOOLEAN).
### 6.2 `data.service_reviews` (Okos Értékelés)
* `user_id`, `organization_id`.
* `rating` (1-5).
* `proof_url` (Számla/Munkalap fotó URL).
* `is_active` (BOOLEAN): Csak az aktív számít bele az átlagba (lásd Gamification logika).
### 6.3 `data.wallet_transactions`
* `original_currency`: (HUF, EUR, USD).
* `exchange_rate`: Az adott pillanatban érvényes váltószám.
## 7. Referrals & Invitations
* `data.referrals`: Hierarchikus fa szerkezet (`inviter_id`, `invitee_id`, `level`).
* `data.invitations`:
* `code`: Random string (pl. `X7K9P2`).
* `type`: 'private' (72h) vagy 'company' (168h).
* `target_role`: A meghívott jogosultsága (Driver, Manager).
## 8. Virtual Goods & Inventory (Digitális Javak)
### 8.1 `data.user_inventory`
Ez a tábla tárolja a felhasználó által megszerzett vagy vásárolt kozmetikai elemeket (NEM jogosultságok, hanem vagyontárgyak).
* `id` (UUID): Egyedi azonosító.
* `user_id` (FK): A tulajdonos.
* `item_id` (VARCHAR): A katalógusban lévő azonosító (pl. `avatar_frame_neon`).
* `metadata` (JSONB): Opcionális egyedi tulajdonságok (pl. sorszámozott NFT-szerű elemknél: `{"serial": 42}`).
* `acquired_at` (TIMESTAMP): Mikor szerezte.
* `is_equipped` (BOOLEAN): Éppen használja-e (pl. ez az aktív avatar kerete).
### 8.2 Shop Catalog Configuration (`system_configs`)
A `key = 'shop_catalog'` alatt tároljuk a bolt kínálatát JSON formátumban.
**Példa JSON struktúra:**
```json
{
"categories": ["avatars", "badges", "profile_themes"],
"items": {
"badge_early_adopter": {
"name": "Korai Felfedező",
"price": 0,
"currency": "free",
"condition": "reg_date < '2025-01-01'",
"image_url": "/assets/badges/early.png"
},
"frame_gold_mechanic": {
"name": "Arany Szerelő Keret",
"price": 5000,
"currency": "credit",
"rarity": "legendary",
"effect": "shine_animation",
"image_url": "/assets/frames/gold.png"
}
}
}
## 5. Geo-Location and Address Master Data
A rendszer normalizált címkezelést alkalmaz az adatminőség biztosítása érdekében.
### 5.1 Geo Adattáblák
- `data.geo_postal_codes`: ZIP és Település kapcsolata (Unique: country + zip + city).
- `data.geo_streets`: Utcanevek listája, ZIP azonosítóhoz kötve.
- `data.geo_street_types`: Közterület típusok szótára (út, utca, tér...).
### 5.2 GIS Adatok
Minden telephely koordinátája `GEOGRAPHY(POINT, 4326)` típusként van tárolva, amely lehetővé teszi a PostGIS alapú távolságmérést.
### 5. Hibrid Címkezelési Modell
A rendszer az adatintegritás és a sebesség érdekében hibrid modellt használ.
- **Centralizált adattárolás**: A `data.addresses` tábla tárolja a normalizált címeket (UUID alapú).
- **Öntanuló szótárak**: A `data.geo_postal_codes` és `data.geo_streets` táblák automatikusan bővülnek minden új rögzítésnél.
- **Denormalizált GPS adatok**: Az `organization_locations` tábla közvetlenül tárolja a koordinátákat a JOIN-nélküli PostGIS lekérdezésekhez.
| Tábla | Funkció |
| :--- | :--- |
| `data.addresses` | Konkrét házszám szintű címek (Hibrid hivatkozási pont). |
| `data.geo_postal_codes` | Irányítószám és város kapcsolata (HU/EU támogatás). |
| `data.user_stats` | Felhasználói XP, szintek és strike-ok tárolása. |
## 2.4 Financial & Enrichment Tables
- **data.organization_financials:** Éves gazdasági adatok (árbevétel, profit, létszám) tárolása historikus elemzéshez.
- **data.service_profiles.specialization_tags:** JSONB mező a szigorú szakmai szűréshez (pl. márkák, specifikus javítási típusok).
- **data.service_profiles.google_place_id:** Külső validációs kulcs a Google Places API-hoz.
### Identity & Economy Module (v1.6+)
* **`data.persons`**: Természetes személyek, Identity Hash, Örök XP/Büntetés.
* **`data.users`**: Login fiókok, Előfizetési idő, Sales kapcsolatok.
* **`data.wallets`**: 3-as osztású egyenleg (`earned`, `purchased`, `coins`).
* **`data.financial_ledger`**: Pénzügyi tranzakciók főkönyve.
* **`data.security_audit_logs`**: Biztonsági események és 4-szem jóváhagyások.
* **`data.org_sales_assignments`**: Cég-Üzletkötő kapcsolat (Farming jog).
## 4. MDM és Jármű Katalógus Struktúra
A rendszer hibrid (Relációs + JSONB) modellt használ a skálázhatóság érdekében.
### 4.1 Táblák:
* **data.vehicle_model_definitions**: A "Szent Grál". Tartalmazza a márka, kód, marketing név mellett a fix numerikus adatokat (ccm, kw, weight) a gyors szűréshez.
* **data.feature_definitions**: Globális szótár az összes extráról (ABS, Halradar, Retarder stb.), kategóriákba sorolva.
* **data.model_feature_maps**: Összeköti a modellt az extrákkal.
- `availability`: [STANDARD, OPTIONAL, ACCESSORY]
* **data.vehicle_model_reviews**: Felhasználói vélemények a típusról (1-5 csillag, szöveges).

View File

@@ -0,0 +1,78 @@
# 🔌 07_API_GUIDE
## 1. Verziózás (Versioning)
A rendszer támogatja a többszintű verziókezelést a stabilitás és a visszafelé való kompatibilitás érdekében.
- **v1:** Core Fleet funkciók (pl. `/api/v1/vehicles`, `/api/v1/expenses`).
- **v2:** Auth és új generációs modulok (pl. `/api/v2/auth/login`).
---
## 2. Route Inventory (Kiemelt Végpontok)
Az alábbi táblázat tartalmazza a legfontosabb útvonalakat:
| Metódus | Végpont | Leírás |
| :--- | :--- | :--- |
| `POST` | `/api/v2/auth/register` | Regisztráció Person rekord létrehozásával |
| `GET` | `/api/v1/fleet/vehicles` | Felhasználó saját járműveinek listázása |
| `POST` | `/api/v1/search/match` | Szervizkereső algoritmus indítása |
| `POST` | `/api/v1/evidence/upload` | Dokumentum feltöltés (MinIO) |
---
## 3. Hiba Kezelés (Error Handling)
A frontendnek az alábbi HTTP státuszkódok alapján kell lekezelnie a kivételeket:
- **401:** Token lejárt -> Frontendnek automatikusan a Login oldalra kell dobnia a felhasználót.
- **403:** Jogosultság hiba -> "Nincs jogod ehhez a funkcióhoz" üzenet megjelenítése (Tier limit/Role hiba).
- **404:** Resource not found -> Az erőforrás nem található vagy Soft Deleted állapotban van.
---
## 4. Nemzetköziesítés (i18n) és Lokalizáció
A rendszer a "Global-Local" elv alapján működik. **Tilos a programkódban (hard-coded) szöveges üzeneteket elhelyezni.**
### 4.1. Nyelvi fájlok struktúrája
Minden nyelvi fájl a `backend/app/locales/` mappában található, szabványos JSON formátumban.
- **Példa fájlok:** `hu.json`, `en.json`, `de.json`.
### 4.2. Kezelési szabályok
- **Backend:** A rendszerüzeneteket, hibaüzeneteket és az e-mail sablonok tartalmát a `LocaleManager` szolgáltatáson keresztül kéri le.
- **Paraméterezés:** A szövegekben használható változók formátuma: `{variable_name}`.
- **Sablonkezelés:** Az e-mailek HTML vázát és a JSON-ban tárolt szöveges blokkokat a rendszer a küldés előtt fűzi össze.
### 4.3. Nyelvválasztás logikája (Prioritás)
1. A kérés fejlécében érkező `Accept-Language` alapján.
2. Bejelentkezett felhasználó esetén a `User.region_code` alapján.
3. Alapértelmezett: `hu`.
---
## 5. Unified Registration & Security Protocol
A rendszer a **"Minimal Friction, Maximum Security"** elvét követi.
### 5.1. Regisztrációs Életciklus
1. **Step 1 (Lite):** `Email`, `Jelszó`, `Név` megadása. Létrejön a `User` és `Person` rekord. Állapot: `is_active: false`.
2. **Verifikáció:** A rendszer UUID alapú tokent generál (48 órás élettartam). A felhasználó e-mailben kap egy aktiváló linket.
3. **Step 2 (KYC):** Sikeres verifikáció után a felhasználó megadja az okmányait (Személyi/Jogsi/Hajó).
4. **Aktiválás:** Létrejön a **Privát Flotta (Privát Széf)** és a hozzá tartozó `Wallet`. Állapot: `is_active: true`.
### 5.2. Token Biztonsági Előírások
- **Regisztrációs Token:** 48 óra élettartam.
- **Jelszó-visszaállítási Token:** 1 óra élettartam.
### 5.3. Rate Limiting (Robotvédelem és Költségkontroll)
Az e-mail küldési folyamatokra az alábbi korlátok vonatkoznak:
- **Retry Cooldown:** Újraigénylés legkorábban 60 másodperc után lehetséges.
- **Óránkénti Limit:** Maximum 3 kérelem / e-mail cím.
- **Napi Limit:** Maximum 10 kérelem / e-mail cím.
- **Zárolás:** A napi limit túllépése esetén a fiók biztonsági okokból 24 órára zárolja a küldési funkciót az adott címre.
### 4. Geo és Kereső Végpontok
#### GET `/api/v1/services/suggest-street`
- **Cél**: Autocomplete támogatás a frontendnek.
- **Paraméterek**: `zip_code` (string), `q` (részleges utcanév).
#### GET `/api/v1/services/search`
- **Cél**: Kétlépcsős szervizkereső.
- **Free mód**: Légvonalbeli távolságmérés (Radius).
- **Premium mód**: Útvonal-idő alapú kalkuláció és forgalmi becslés.

View File

@@ -0,0 +1,136 @@
# 🏁 07_REGISTRATION_INVITATION_AND_API (v1.4)
## 1. Kétlépcsős Onboarding Folyamat
A rendszer a felhasználói élmény (UX) és a banki szintű biztonság érdekében két fázisra bontja a regisztrációt, amelyet egy atomi tranzakció zár le.
### 1.1. Fázis: "Lite" Regisztráció (Step 1)
* **Végpont:** `POST /api/v1/auth/register`
* **Cél:** Gyors belépés és a technikai User fiók létrehozása.
* **Kötelező adatok:** Email, Jelszó, Vezetéknév, Keresztnév, Régiókód.
* **Rendszeresemények:**
* Létrejön a `data.users` rekord `is_active = False` állapottal.
* **Szerepkör:** Kényszerített kisbetűs `user` (Postgres Enum kényszer).
* **Megerősítés:** Aktiváló email küldése egyedi hash kóddal.
* **Válasz:** JWT token `status: pending_kyc` flaggel (korlátozott jogosultság).
### 1.2. Fázis: Banki KYC & Adatgyűjtés (Step 2)
* **Végpont:** `POST /api/v1/auth/complete-kyc`
* **Kötelező KYC adatok (Identity Verification):**
* **Személyes:** Anyja születési neve, születési hely és idő.
* **Okmányok:** Személyi igazolvány száma és lejárati ideje.
* **Jogosítvány:** Vezetői engedély száma, lejárata és kategóriák (pl. AM, A, B, C, CE).
* **Speciális:** Hajóvezetői és repülőgép-vezetői engedélyek (ha releváns).
### 1.3. Fázis: Atomi Tranzakció (Finalization)
A KYC adatok beküldésekor a rendszer egyetlen megszakíthatatlan folyamatban hajtja végre:
1. **Person létrehozása:** Identitás rögzítése JSONB dokumentumtárral a `data.persons` táblába.
2. **Wallet inicializálás:** Pénztárca nyitása 0 Coin és 0 XP egyenleggel.
3. **Privát Flotta (Private Org):** Automatikus szervezet létrehozása (`OrgType.INDIVIDUAL`), amely **nem átruházható** (`is_transferable = False`).
4. **Aktiválás:** `is_active = True` státusz beállítása és teljes hozzáférés biztosítása.
5. **Audit:** Bejegyzés az `audit_logs` táblába.
---
## 2. Meghívó és Jutalék Logika (Invitation Engine)
A rendszer támogatja a többszintű ajánlói rendszert és a szervezeti meghívókat.
### 2.1. Meghívó Típusok
- **`REG_ONLY`**: Általános meghívó, amely beköti az új felhasználót a 10-5-2%-os jutalék láncba.
- **`COMPANY_JOIN`**: Meghatározott szervezetbe hív (pl. CEO, Flotta Manager vagy Sofőr szerepkörbe).
### 2.2. Jutalék Számítás
A százalékos mérték a tranzakció pillanatában érvényes admin beállítások alapján rögzül (Snapshot). A jóváírandó kredit ($C$):
$$C = P_{amount} \cdot \frac{R_{level}}{100}$$
*Ahol $P$ a befizetett összeg, $R$ pedig az aktuális szint (10, 5 vagy 2) értéke.*
**Szabály:** Csak az **első** Prémium csomag befizetésekor történik jutalékfizetés a láncban.
---
## 3. Technikai és Biztonsági Szabályok
### 3.1. Adatbázis és Enum Kezelés
- **Enum Case Sensitivity:** A PostgreSQL `userrole` típusa miatt minden értéket (pl. `user`, `admin`, `driver`, `service`) szigorúan **kisbetűvel** kell rögzíteni.
- **Dinamikus Paraméterek:** Tilos a hardcoded értékek használata. Az alábbiakat a `data.system_settings` táblából kell lekérni:
- `auth.reward_days`: Regisztrációs prémium hossza (default: 14).
- `referral.level1-3`: Jutalék szintek mértéke.
### 3.2. Email Manager Protokoll (TypeError Fix)
- **Szabály:** A `send_email` hívásakor **tilos** a `subject` paraméter kézi átadása.
- **Logika:** A szerviz a `template_key` alapján automatikusan generálja a tárgyat a belső szótárából.
### 3.3. Social Auth (Google / Facebook)
- A Step 1 lerövidül, de a **Step 2 (KYC) kötelező** marad az aktiváláshoz.
- Amíg a KYC hiányzik, a felhasználó "GUEST" státuszban marad, korlátozott funkciókkal.
---
## 4. Jelszó Helyreállítási Protokoll (Recovery)
A rendszer két biztonsági szintet különít el:
| Szint | Megnevezés | Logika |
| :--- | :--- | :--- |
| **A** | Standard | Email alapú visszaállítás ideiglenes tokennel. |
| **B** | Szigorú (Banki) | Kötelező: Név, Anyja neve, Okmány szám. Ellenőrzés után SMS (telefonszám) vagy Email link. |
---
## 5. Corporate Onboarding (Céges Regisztráció)
Célja, hogy egy létező Person saját szervezetet (Organization) alapítson.
- **Validáció:** Kötelező adószám ellenőrzés (HU formátum + VIES API lekérdezés).
- **Hierarchia:** A regisztráló automatikusan `owner` rangot kap.
- **Izoláció:** Minden cég saját mappastruktúrát kap a NAS-on az okmányok fizikai elkülönítése érdekében.
---
## 6. Kormányozhatóság és .env Konfiguráció
A biztonsági paraméterek környezeti változókon keresztül szabályozhatók:
| Paraméter | Leírás | Alapértelmezett |
| :--- | :--- | :--- |
| `REGISTRATION_TOKEN_EXPIRE_HOURS` | Aktiválásra álló idő | 48 óra |
| `PASSWORD_RESET_TOKEN_EXPIRE_HOURS` | Visszaállítási időablak | 1 óra |
---
## 7. API Végpontok (Baseline v1)
- `POST /api/v1/auth/register`: Komplett onboarding indítása.
- `POST /api/v1/auth/complete-kyc`: KYC adatok beküldése és aktiválás.
- `POST /api/v1/auth/invite/send`: Meghívó generálása.
- `GET /api/v1/auth/invite/verify/{token}`: Token validálása.
- `POST /api/v1/auth/recover-identity`: Szigorú (KYC alapú) helyreállítás.
## 5. Invitation Logic Specifications
### 5.1 Meghívó Kódok
* **Formátum:** Véletlenszerű alfanumerikus string (pl. `A8B2X9`). NEM tartalmazhat személyes adatot.
* **Generálás:** Minden "Meghívás" gombnyomásra új, egyedi token generálódik.
### 5.2 Lejárati Idők (TTL)
A meghívók érvényessége a típustól függ:
* **Magánszemély (C2C):** 72 óra (3 nap). Sürgető érzést kelt.
* **Céges / Flotta (B2B):** 168 óra (1 hét). Figyelembe veszi a lassabb céges ügymenetet.
### 5.3 Biztonság
* A meghívó link tartalmaz egy aláírt JWT tokent, amely rögzíti a `target_org_id`-t (melyik flottába hívjuk) és a `role`-t (pl. sofőr).
* A kód felhasználása után a link érvénytelenné válik (One-time use).
## 1. Háromlépcsős Onboarding (v1.5)
### 1.1 Step 1: Lite Registration
- Technikai `User` létrehozása (inaktív). Email ellenőrzés indítása.
### 1.2 Step 2: Individual Setup (Privát Identitás)
- **Cél:** A természetes személy (`Person`) és privát szférájának rögzítése.
- **Művelet:** - `Person` rögzítése/frissítése.
- Privát `Organization` létrehozása (`org_type='individual'`, `is_ownership_transferable=False`).
- **Központi Telephely (Main Branch)** létrehozása a lakcím alapján.
- Privát Flotta és Wallet inicializálása.
### 1.3 Step 3: Business Setup (Céges Identitás)
- **Cél:** Államilag nyilvántartott gazdasági egység rögzítése.
- **Művelet:**
- Adószám bekérése + VIES/Cégjegyzék ellenőrzés.
- Új, különálló `Organization` létrehozása (`org_type='business'`, `is_ownership_transferable=True`).
- Székhely rögzítése mint **Main Branch**.
- Opcionális további telephelyek rögzítése.

View File

@@ -0,0 +1,15 @@
(UI irányelvek.)
# 🖥️ FRONTEND GUIDE
## Tech Stack
- Vue 3 (Composition API) + Vite.
- Tailwind CSS (Utility-first design).
- Pinia (State Management).
## Konfiguráció
**SOHA** ne használj hardkódolt IP címet a kódban!
Használd a `.env` fájlt: `VITE_API_BASE_URL=https://dev.profibot.hu/api`
## UI Logika
- **Dumb Frontend:** Nem döntünk jogosultságról. Ha a backend azt mondja `can_edit: false`, a gombot letiltjuk.
- **Offline Mód (Terv):** Service Worker (PWA) segítségével rögzítés net nélkül -> Sync, amint van hálózat.

View File

@@ -0,0 +1,35 @@
# 🛠️ ADMIN MANAGEMENT & PERMISSIONS (v1.0)
## 1. Adminisztrátori Hiearchia és Területi Felosztás
A rendszer többszintű, régió-alapú jogosultságkezelést alkalmaz (RBAC + Geographic Scope).
| Szint | Megnevezés | Területi hatókör | Jogkörök jellege |
| :--- | :--- | :--- | :--- |
| **L0** | **SuperAdmin** | Globális (Összes ország) | Teljes hozzáférés, Rendszer-paraméterezés, Admin kinevezés. |
| **L1/A** | **Global Director** | Régiós (Több ország) | Országos vezetők felügyelete, aggregált statisztikák. |
| **L1/B** | **National Manager** | Országos (pl. HU) | Saját ország moderátorainak és adatainak teljes kezelése. |
| **L2** | **Staff (Mod/Supp/Fin)** | Lokális / Szakaszolt | Operatív feladatok (VIES, support jegyek, kifizetések). |
| **L3** | **Task Moderator** | Feladat-specifikus | Sablon alapú, korlátozott hozzáférés (pl. csak szerviz validálás). |
**Verseny Logika:** Az L1/B szintű vezetők látják más országok aggregált KPI mutatóit (statisztika), de nem látnak bele a konkrét személyes vagy céges adatokba.
## 2. Jogosultságkezelés és Sablonok
- **Permissions Table:** Elemi jogosultságok tárolása (pl. `approve_vies`, `modify_credits`).
- **Role Templates:** Előre definiált sablonok az egyszerű beállításhoz (pl. "Senior Financial - DE").
- **Regionális Izoláció:** Az adminisztrátorok alapértelmezetten csak a hozzájuk rendelt `ISO_country_code` alá tartozó adatokat módosíthatják.
## 3. Biztonság és "Kill-Switch" Protokoll
- **MFA/2FA:** A második bejelentkezéstől kezdve kötelező a TOTP (Google Authenticator) használata.
- **Social Auth:** Adminok számára is engedélyezett (Google/FB), de nem váltja ki a kötelező 2FA-t.
- **Anomaly Score (Fekete Doboz):**
- Minden kattintást és módosítást logolunk (`audit_logs`).
- Kritikus viselkedés (pl. tömeges törlés) esetén a rendszer automatikusan felfüggeszti az admint.
- **SuperAdmin Recovery:** A SuperAdmin visszaállítása csak egyedi Offline Kulccsal és regisztrált eszközzel lehetséges.
- **Értesítési lánc:** Tiltáskor a felette álló szintek azonnali riasztást kapnak.
## 4. Visszaállíthatóság (State Snapshot)
Minden módosítás előtt a rendszer menti az aktuális rekord állapotát (JSON). Bármilyen károkozás vagy hiba esetén az L0/L1 szintű adminisztrátorok egy gombnyomással visszaállíthatják az eredeti adatokat.
## 5. Adminisztrátori Meghívók
- Adminisztrátort csak kézi meghívóval lehet felvenni.
- **Lejárati idő:** Minden admin meghívó token 24 óráig érvényes.

View File

@@ -0,0 +1,140 @@
# 💰 10_BILLING_CREDITS_SUBSCRIPTIONS (v1.2)
## 1. Regionális és Valuta Logika (EU Scope)
A rendszer többnyelvű és többvalutás elszámolást alkalmaz. Minden tranzakció kettős értéktárolással valósul meg az adatintegritás érdekében.
- **Local Cost:** A felhasználó régiója szerinti pénznemben rögzített összeg.
- **Standard Cost (EUR):** A rögzítés pillanatában érvényes árfolyamon számolt alapérték.
**Átszámítási képlet:**
$$Cost_{EUR} = Cost_{Local} \cdot ExchangeRate$$
---
## 2. Előfizetési Csomagok és Business Synergy
A rendszer korlátait a `data.system_settings` tábla szabályozza. A csomagok skálázhatóak a flotta méretétől függően.
| Csomag | Jármű Limit | Kiemelt funkciók |
| :--- | :--- | :--- |
| **FREE** | 1 db | Alap költségnapló, GEO alapú szervizkereső. |
| **PREMIUM** | 3 db | Dokumentumtár, export funkciók, útvonal alapú kereső. |
| **PREMIUM+** | 5 db | Flotta statisztika, TCO (Total Cost of Ownership) elemzés. |
| **VIP / VIP+** | 10+ db | Egyedi szervizkezelés, bővíthető slotok, prioritásos support. |
### 2.1. VIP Synergy Szabályok (Ösztönző rendszer)
- **Synergy Discount:** Ha egy `FLEET_OWNER` aktív **VIP** vagy **VIP+** előfizetéssel rendelkezik, **15% kedvezményt** kap minden vásárlásra a saját privát flottájában is.
- **Ajándék Kredit:** VIP vásárláskor extra kreditek járnak (felhasználható: skinek, medálok, privát Prémium csomag).
- **Időbeli korlát:** A privát kedvezmények időtartama **2-6 hónapra korlátozott**, ösztönözve a folyamatos aktivitást.
---
## 3. Voucher és Kupon Rendszer
A kedvezmények igénybevétele manuális kódbeíráshoz kötött. Minden felhasználást auditálni kell (`redeemed_at`, `user_id`, `original_price`).
- **Gift Card (Fix Kredit):** Meghatározott összegű jóváírás (pl. 5000 Ft).
- **Subscription Coupon (%):** Százalékos kedvezmény az előfizetési díjból egy adott időszakra.
- **Lejárat:** Minden kupon rendelkezik fix érvényességi idővel, amely után inaktívvá válik.
---
## 4. MLM Jutalomrendszer (Referral)
A rendszer jutalmazza a sikeres meghívásokat az új tag **első** befizetése után. A százalékos érték a tranzakció pillanatában rögzül (Snapshot).
- **1. szint (Közvetlen):** 10% jóváírás.
- **2. szint:** 5% jóváírás.
- **3. szint:** 2% jóváírás.
---
## 5. Invitation Engine (Meghívó Rendszer)
A spam elleni védelem érdekében a meghívók élettartama és mennyisége korlátozott:
- **Token Lejárati idők:**
- **Felhasználói (User) meghívó:** 72 óra.
- **Adminisztrátori meghívó:** 24 óra.
- **Mennyiségi korlát:** Kezdő keret felhasználónként (alapértelmezett: 10 vagy 20 db).
- **Anti-Spam Logika:** A felhasználó csak sikeres regisztrációk után kap vissza új meghívási lehetőségeket (slotokat).
---
## 6. Evidence & Trust Engine (Hitelesítés)
A rendszerben a "Verified" (hiteles) státusz eléréséhez bizonyítékok szükségesek.
- **Kötelező bizonyítékok:** Munkalap fotó, számlakép és kilométeróra-állás fotó.
- **GPS Check-in:** A szerviz eseménykor igazolni kell a helyszíni tartózkodást.
- **Validáció:** Cég mint entitás nem hitelesíthet; a validálást mindig egy azonosított **Person** végzi.
---
## 7. Lejárat és Pénzügyi Helyreállítás
Ha az előfizetés lejár, a rendszer az alábbi fokozatos korlátozásokat vezeti be:
1. **Grace Period (30 nap):** Csak adatrögzítés lehetséges, a statisztikai modulok és exportok zárolva vannak.
2. **Zárolás (60 nap):** A fiók írásvédetté válik (Read-only). Nincs új adatrögzítés.
3. **Helyreállítás:** 6 hónapon belüli visszamenőleges befizetés esetén minden korábbi adat és funkció azonnal újraaktiválódik.
## 4. Economic Model & Exchange Rates
### 4.1 Dinamikus Árfolyamok (Admin Config)
A rendszer támogatja a többvalutás elszámolást. Az átváltási arányok a `system_configs` táblából jönnek.
* **Példa konfiguráció:**
* 1 HUF = 50 Kredit
* 1 EUR = 20.000 Kredit (változtatható)
* 1 USD = 18.500 Kredit
### 4.2 Referral Commission (Admin Config)
A jutalékrendszer paraméterezhető, alapértelmezett értékei:
* **Level 1 (Közvetlen):** 10%
* **Level 2:** 5%
* **Level 3:** 2%
* *Megjegyzés:* Adminisztrátori joggal ezek bármikor módosíthatók, visszamenőleges hatály nélkül.
### 4.3 Kifizetés (Payout)
* **Threshold:** A kifizetés igénylésének alsó határa alapértelmezetten **1.000.000 Kredit**.
* Ez az érték adminisztrátori döntéssel csökkenthető/növelhető a rendszer érettségétől függően.
## 5. Marketplace & Vanity Items
### 5.1 Árazási Logika
A rendszer támogatja a dinamikus árazást a kozmetikai elemeknél is.
* **Fix áras termékek:** Egyszerű levonás a `coin_balance`-ból vagy `credit_balance`-ból.
* **Időszakos ajánlatok:** A katalógusban beállítható `sale_price` és `sale_end_date`.
### 5.2 Vásárlási Folyamat
1. **Check:** Van-e elég fedezet (Wallet)?
2. **Deduct:** Tranzakció rögzítése a `wallet_transactions` táblában (`type='purchase_item'`).
3. **Grant:** Tétel beírása a `user_inventory` táblába.
4. **Equip:** Opcionálisan azonnali beállítás (pl. profilkép keret).
### 5.3 Bővíthetőség
Új elem hozzáadásához **nem kell kódot módosítani**, csak a `shop_catalog` JSON-t kell frissíteni az Admin felületen. A kliens alkalmazás (App/Web) dinamikusan tölti be a kínálatot ebből a JSON-ből.
## 3. The Triple Wallet System (3-as Pénztárca)
A `wallets` tábla három elkülönített alszámlát kezel a transzparencia érdekében:
| Alszámla | Kód | Forrás | Felhasználás | Átváltható? |
| :--- | :--- | :--- | :--- | :--- |
| **Earned Credits** | `earned_credits` | Munka (validálás), Referral, Jutalék | Prémium funkciók, Szolgáltatás vásárlás | IGEN |
| **Purchased Credits** | `purchased_credits` | Bankkártyás feltöltés (Stripe) | Prémium funkciók, Szolgáltatás vásárlás | IGEN |
| **Service Coins** | `service_coins` | B2B Csomagok, Partneri jóváírás | **Kizárólag** Hirdetés, Kiemelés, Szponzoráció | **NEM** |
## 4. Sales Commission Model (Hunting & Farming)
Az üzletkötők ösztönzése két fázisban történik:
### 4.1 Hunting (Vadász) Jutalék
* **Esemény:** Új fizető ügyfél behozatala (első tranzakció).
* **Mérték:** 10% (Alapértelmezett `system_parameter`).
* **Jóváírás:** Azonnal, `earned_credits` formájában.
### 4.2 Farming (Gazda) Jutalék
* **Esemény:** Meglévő ügyfél havidíj megújítása.
* **Mérték:** 5% (Alapértelmezett `system_parameter`).
* **Átruházhatóság:** A jutalékot nem a User, hanem az `OrganizationSalesAssignment` tábla aktív rekordja határozza meg. Ha az üzletkötő kilép, a portfóliója (és a Farming joga) átruházható egy másik ügynökre.
### 4.3 Financial Ledger (Pénzügyi Napló)
Minden tranzakció (Vásárlás, Jutalék jóváírás, Költés) bekerül a `financial_ledger` táblába, amely megmásíthatatlan (Append-only) és tartalmazza a `related_agent_id`-t a visszakövethetőségért.

View File

@@ -0,0 +1,147 @@
(A Validációs Rendszer.)
# 🏆 GAMIFICATION & SOCIAL VALIDATION
## 1. Validációs Logika (Q8)
- **Hivatalos Szerviz:** Számla/Munkalap feltöltése -> Automatikus Trust Score növekedés.
- **Magán/Sufni Javítás:** Rögzíthető, de "Low Trust" besorolást kap (csökkenti a jármű értékét), kivéve ha egy **Validátor** (High Rank User) igazolja.
- **Validátor:** Olyan felhasználó, aki magas XP szinttel rendelkezik. Feladata: Képek és adatok ellenőrzése kreditért.
## 2. Véleményezés (Review)
- **Szabály:** Csak "Verified Visit" után lehet értékelni (GPS vagy Számla).
- **Fellebbezés:** A szerviz jelezheti, ha a vélemény valótlan. Ilyenkor a Moderátorok (vagy magas szintű Validátorok) döntenek.
## 3. "Service Hunt" (Szerviz Vadászat)
A felhasználók játékosított formában validálják az adatbázist.
### 3.1 Validációs Szabályok
* **Radius:** A felhasználónak **50-100 méteren** belül kell tartózkodnia a szerviz GPS koordinátáihoz képest a validáláshoz.
* **Jutalom:** Csak akkor jár, ha a validáció sikeres (GPS + Fotó).
* **Bot vs. Ember:**
* Ha a Bot találta a szervizt, de nincs validálva: A felhasználó megkapja a "Validator" bónuszt.
* Ha már validálva van (Status: Verified): A felhasználó látja a térképen, hogy "Már validálva", nem jár érte pont (kivéve adatfrissítés).
### 3.2 Okos Értékelési Rendszer (Review Logic)
A rendszer védi a szolgáltatókat a "Review Bombing"-tól, de jutalmazza a konzisztenciát.
* **Negatív élmény (1-3 csillag):**
* Egy felhasználótól **csak a legutolsó** negatív értékelés számít bele az átlagba.
* Ha a user újra értékel (mert visszament), az előző negatív értékelés `is_active = False` státuszba kerül (de az admin látja az előzményeket).
* **Pozitív élmény (4-5 csillag):**
* Minden pozitív értékelés számít és összeadódik (kumulatív).
* Ez ösztönzi a szervizt a folyamatos jó teljesítményre.
## 4. Social Flexing & Vanity Items
A "dicsekvési faktor" kezelése.
### 4.1 Megjelenítési Helyek
* **Profil oldalon:** A megszerzett jelvények (Badges) "vitrinje".
* **Ranglistákon:** Kiemelt név, egyedi háttérszín vagy ikon a név mellett.
* **Térképen:** Egyedi pin ikon a saját járműveknél (pl. arany színű autó ikon a térképen a sima kék helyett).
### 4.2 Ritkasági Szintek (Rarity)
A tárgyakhoz ritkasági szintet rendelünk a `system_configs`-ban:
1. **Common (Gyakori):** Bárki megveheti olcsón.
2. **Rare (Ritka):** Drágább, vagy teljesítményhez kötött (pl. 10 validált szerviz).
3. **Epic (Epikus):** Csak Prémium+ tagoknak vagy nagyon sok kreditbe kerül.
4. **Legendary (Legendás):** Egyedi eventeken szerezhető (pl. "Service Hunt 2026 Győztes").
### 4.3 "Equipped" Status
A felhasználónak lehet 50 jelvénye, de egyszerre (típustól függően) csak korlátozott számút mutathat meg (pl. 3 Slot a profilkép alatt). Ezt a `user_inventory.is_equipped` flag kezeli.
## 5. Büntetőpontok és Rehabilitáció (Strike System)
A rendszer 3-szintes büntetőrendszert alkalmaz a hibás vagy szándékosan téves adatok kiszűrésére.
### 5.1 Büntetőpontok (Strikes)
* **Ok:** Szándékos félrevezetés, nem létező szerviz rögzítése, hamis fotók.
* **Következmény:** 3 strike után a felhasználó véglegesen vagy ideiglenesen ki lesz tiltva a "Service Hunt" és validációs feladatokból.
### 5.2 Rehabilitációs Logika (Strike eltávolítás)
Egy büntetőpont (1 strike) levonható az alábbi feltételek teljesülése esetén (Adminról állítható értékek):
* **Javítás:** 10 sikeres és elfogadott adatjavítás (más hibájának korrigálása).
* **Validáció:** 20 sikeres és megerősített validáció.
* **Példás rögzítés:** 3 olyan új szerviz rögzítése, amit a Bot és az Admin is 100%-ban validnak talál.
### 5.3 Területi Monitoring (Geofence Blacklist)
Amennyiben egy adott földrajzi körzetből (pl. egy városrész) kiugróan sok (százalékos arányban mérve) téves adat érkezik, a rendszer automatikusan korlátozhatja az onnan érkező új regisztrálók hozzáférését a szociális feladatokhoz, amíg az Admin felül nem vizsgálja a helyzetet.
## 6. Versenyrendszer (Leaderboards)
A közösségi munka (Service Hunt, Validáció) egy globális és régiós ranglistát táplál.
### 6.1 Ranglista kategóriák
* **The Explorer (A Felfedező):** Legtöbb új szerviz rögzítése.
* **The Verifier (A Hitelesítő):** Legtöbb sikeres adat-visszaigazolás.
* **The Master Mechanic:** Legtöbb technikai adat kiegészítés.
### 6.2 Szintlépési Bónuszok (Milestones)
A fejlődés nem csak dicsőség, hanem gazdasági előny is.
* **Level 5:** 1.000 Kredit jutalom.
* **Level 10:** 5.000 Kredit + "Expert" jelvény.
* **Level 20:** Egyedi avatar keret + állandó 5% kedvezmény a hirdetési árakból (céges esetén).
### 6.3 Éves/Havi Szezonok
Minden hónap végén az első 3 helyezett extra Kreditet vagy "Voucher"-t kap, amit a partnereinknél (szervizeknél) válthat be.
### 3. Jutalmazási Szabályok (Social Points)
- **Célcsoport**: Kizárólag természetes személyek (`role: user`, `driver`).
- **Kizárások**: Szervezetek (Organizations) és Adminisztrátorok nem gyűjtenek XP-t.
- **Logika**: Minden `PointsLedger` bejegyzés kötelezően hivatkozik egy `user_id`-ra.
- **Mezőnevek**: Adatbázis szinten a pontok az `id`, `user_id`, `points`, `reason` mezőkben tárolódnak.
## 2026.02.10 FRISSÍTÉS - GAMIFICATION ÖKOSZISZTÉMA
### 1. Pontrendszer Logika
A rendszer különválasztja a tekintélyt és a jutalmat:
- **XP (Tapasztalat):** Végleges szintlépéshez. Képlet: $BaseXP \times Level^{1.5}$. (Nehezedő görbe).
- **Social Points (Szezonális):** Időszakos versenyekhez (pl. Hónap Vadásza).
- **Kredit:** Fizetőeszköz, amit Social Pontokból lehet váltani (pl. 1000 pont = 100 Kredit).
### 2. Konfiguráció
Minden érték (szorzók, határok) a \`GAMIFICATION_MASTER_CONFIG\` JSON paraméterben állítható Admin felületről, kódmódosítás nélkül.
### 3. Audit
Minden pontmozgás a \`PointsLedger\` táblába kerül rögzítésre a visszakövethetőség érdekében.
XP Formula: $XP_{required} = BaseXP \times Level^{1.5}$Penalty Logic: restriction_level bevezetése (0-3).Weighting: Saját adat vs. Közösségi adat súlyozási táblázata.
# 11. Gamification és Social Engine Specifikáció
## 1. XP (Experience Points) - A Tekintély
Az XP a felhasználó végleges, nem csökkenthető tekintélypontja.
- **Képlet:** A szintlépéshez szükséges összes XP:
$$XP_{total} = 500 \times Level^{1.5}$$
- **Súlyozás:**
- **Saját adat (Fleet):** Alacsony érték (pl. 10 XP).
- **Közösségi adat (Service Discovery):** Magas érték (pl. 100 XP).
## 2. Social Points - A Valuta Alapja
Szezonális pontok, amelyek Kreditre válthatóak.
- **Váltószám:** Alapértelmezett: 100 Social Point = 1 Kredit.
- **Váltási mód:** Automatikus (rendszerparaméter alapján) vagy manuális (felhasználói döntés).
## 3. Trust & Penalty Engine (Büntetőrendszer)
A rendszer integritásának védelme érdekében hibapontokat (Penalty Points) alkalmazunk.
- **Szintek (Restriction Level):**
- **0 (Normal):** Teljes pontszorzó (1.0x).
- **1 (Warning):** Csökkentett pontszerzés (0.5x).
- **2 (Restricted):** Szigorú moderátori ellenőrzés minden adatnál, 0.1x pontszerzés.
- **3 (Blocked):** Pontszerzés és adatbeküldés tiltva.
- **Ledolgozás:** Minden pozitív XP szerzés a büntetőpontokat is csökkenti (pl. 1 XP jóváírás = 0.5 Penalty pont levonás).
## 4. Szintlépési Bónuszok
Minden 10. szint elérésekor a rendszer automatikus Kredit jutalmat oszt a `GAMIFICATION_MASTER_CONFIG` alapján.
## 5. Büntetőrendszer (Strike System)
A rendszer integritásának megőrzése érdekében hibapontokat alkalmazunk, amelyek befolyásolják a pontszerzés hatékonyságát.
- **Szorzók (Multipliers):**
- Level 0 (Normal): 1.0x
- Level 1 (Warning): 0.5x
- Level 2 (Restricted): 0.1x
- Level 3 (Blocked): 0.0x
- **Ledolgozás (Recovery):**
A büntetőpontok pozitív aktivitással (XP szerzéssel) ledolgozhatóak. Az elért XP egy admin által meghatározott része (alapértelmezett: 50%) levonásra kerül a büntetőpontokból.
- **Admin-Vezérelt Küszöbök:** Minden szintváltási határ a `GAMIFICATION_MASTER_CONFIG` paraméterben definiált.

View File

@@ -0,0 +1,18 @@
(Üzemeltetés.)
# ⚙️ OPERATIONS & MONITORING
## Backup Stratégia
- **Napi:** Teljes SQL dump a NAS-ra (`/mnt/nas/backup`).
- **Rotáció:** 7 napi, 4 heti, 12 havi mentés megőrzése.
- **MinIO:** Napi rsync a statikus fájlokról.
## Monitoring
- **Dozzle:** Valós idejű log nézegető (Port 8888).
- **Healthcheck:** Docker `healthcheck` minden konténeren.
- **Alerts:** Email értesítés, ha az API 5xx hibát dob.
## 4. Anti-Fraud & Device Logging
A visszaélések elkerülése érdekében a rendszer rögzíti a beküldéshez használt eszközök adatait.
* **Device Fingerprinting:** Egyedi azonosító rögzítése (`device_id`).
* **Metadata Validation:** Képek feltöltésekor kötelező az EXIF GPS adatok ellenőrzése. Amennyiben az EXIF adatok hiányoznak vagy eltérnek a rögzített helyszíntől (>250m), a bejegyzés automatikusan "Manual Review" státuszba kerül.

View File

@@ -0,0 +1,74 @@
(Mit csinálunk most?)
# 🗺️ ROADMAP & TECH DEBT
# 🗺️ ROADMAP & TECH DEBT (v1.4)
## 🚧 SPRINT 1 (Azonnali - Stabilitás)
1. **Frontend Config:** Hardkódolt IP-k cseréje `.env` változókra.
2. **Step 1 Regisztráció Fix:** A meglévő endpoint átalakítása "Lite" regisztrációra (csak User létrehozás, `is_active=False`).
3. **Enum Case Sensitivity:** Minden DB query felülvizsgálata, hogy a `role` mező kényszerítve kisbetűs legyen.
4. **Security Module:** `create_access_token` és `verify_password` funkciók véglegesítése a `core/security.py`-ban.
## 🚧 SPRINT 2 (KYC & Onboarding)
1. **Step 2 KYC Endpoint:** `POST /api/v1/auth/complete-kyc` megvalósítása.
2. **Atomi Tranzakció Logic:** A Person, Wallet és Private Org egyidejű létrehozása a KYC beküldésekor.
3. **Verification Email:** Aktiváló link generálása és kiküldése hash kóddal.
4. **Admin UI Settings:** Felület a `system_settings` tábla kezeléséhez.
## 📅 SPRINT 3 (Marketplace MVP)
1. **OCR Pipeline:** Számla/Okmány fotó feltöltés MinIO-ba + AI validáció teszt.
2. **Service Request:** Frontend űrlap ajánlatkéréshez.
# ROADMAP & TECH DEBT (v1.0)
## 🚧 SPRINT 1 (Azonnali)
1. **Frontend Config:** Hardkódolt IP-k cseréje `.env` változókra.
2. **Person Migráció:** DB szkript futtatása (User -> Person).
3. **API Fix:** `/api/v1/users/me` 404 javítása.
4. **Soft Delete:** Ellenőrzés, hogy minden `SELECT` tartalmazza-e a `deleted_at IS NULL` feltételt.
## 📅 SPRINT 2 (Marketplace MVP)
1. **OCR Pipeline:** MinIO feltöltés + Tesseract teszt.
2. **Service Request:** Frontend űrlap ajánlatkéréshez.
3. **Ranking Engine:** Távolság + Súlyozás algoritmus implementálása.
# 13. Roadmap és Technikai Adósság (v1.2.6)
Ez a dokumentum rögzíti a rendszer fejlesztési fázisait és azokat a technikai kompromisszumokat, amelyeket a gyors haladás érdekében hoztunk, de később felülvizsgálatot igényelnek.
## 13.1 Rövid távú Roadmap (Q1-Q2)
### 1. Intelligens Kereső API (Fuzzy Search)
- **Cél:** A `synonyms` mezőben tárolt alternatív nevek kihasználása.
- **Megvalósítás:** PostgreSQL `tsvector` és `GIN` indexek használata, hogy a kereső akkor is találjon eredményt, ha a felhasználó "Tracer"-t ír be "Yamaha MT-09 Tracer" helyett.
### 2. Média Kezelés & MinIO Integráció
- **Cél:** Járműfotók automatikus beszerzése.
- **Megvalósítás:** Új bot fejlesztése, amely a dúsított `marketing_name` alapján hivatalos sajtófotókat keres, és azokat a már futó MinIO objektumtárba menti.
### 3. Robot 4: Service Hunter (Szerviz-logika)
- **Cél:** Karbantartási tervek generálása.
- **Megvalósítás:** A `specifications` (olajmennyiség, gyertya típus) mezőkből kiindulva szerviz-csomagok és árak kalkulálása.
## 13.2 Technikai Adósság (Tech Debt)
### 1. Adattípus Optimalizálás: JSON vs. JSONB
- **Helyzet:** A `synonyms` és `specifications` mezők jelenleg `JSON` típusúak.
- **Adósság:** A Postgres függvények (pl. `jsonb_array_length`) használatához folyamatos casting (`::jsonb`) szükséges, ami lassítja a lekérdezéseket.
- **Megoldás:** Egy Alembic migráció keretében az összes JSON oszlopot át kell állítani `JSONB` típusra.
### 2. "N/A-{id}" és "UNKNOWN-{id}" Kódok Tisztítása
- **Helyzet:** A NOT NULL és UNIQUE kényszerek miatt a robot egyedi ál-kódokat generál, ha az AI nem talál gyári kódot.
- **Adósság:** Ezek nem valódi technikai kódok.
- **Megoldás:** Szükséges egy manuális felülvizsgálati (Manual Review) felület, ahol az operátorok a `N/A` kódú rekordokat ellenőrizhetik vagy egyesíthetik.
### 3. AI Response Parsing (Regex Workaround)
- **Helyzet:** A Gemini Search Tool letiltja a kényszerített JSON választ, ezért Regex-szel bányásszuk ki a JSON-t a nyers szövegből.
- **Adósság:** Ez a megoldás törékeny, ha az AI stílusa jelentősen megváltozik.
- **Megoldás:** Monitorozni kell az AI API frissítéseit; amint a Google engedélyezi a Search + Controlled Generation kombinációt, vissza kell térni a natív JSON módra.
## 13.3 Hosszú távú Vízió (Q3+)
- **Trust Engine:** A járművek történetének és szervizadatainak hitelesítése.
- **Global Fleet Insight:** Flottaszintű elemzések készítése a dúsított MDM adatok alapján.

View File

@@ -0,0 +1,508 @@
(Változásnapló.)
# 📜 CHANGELOG
## [1.0.1] - 2026-02-06
### Hozzáadva
- **Unified Auth Module**: Integrált Belépés, Lite Regisztráció és Elfelejtett jelszó kezelés.
- **Email Rendszer**: SendGrid integráció SMTP fallback lehetőséggel.
- **KYC Előkészítés**: `is_active` flag bevezetése a `User` és `Person` modellekben a 2-lépcsős folyamathoz.
### Javítva
- **SQLAlchemy Mapper Fix**: Megszűnt az `owned_organizations` körkörös függőségi hiba.
- **Típus Szinkron**: `Person.id` javítva `BigInteger` típusra a Postgres sémával összhangban.
- **Import Fixek**: `app.db.base_class` -> `app.db.base` útvonalak egységesítve.
### Technikai adatok
- Konténer állapot: Stabil (running)
- Regisztrációs folyamat: Step 1 (Lite) tesztelve, sikeres.
## [1.0.0] - 2026-02-03
- **Init:** Grand Master Book létrehozása.
- **Arch:** Átköltözés a 80 magos szerverre.
- **Spec:** Kredit rendszer, Tiers, Soft Delete és Person logika véglegesítése.
### [2026-02-04] - Identity & Company Sync (v1.2)
- **Modell Konszolidáció:** Az `app.models.identity` lett a központi identitáskezelő (User, Person, Wallet).
- **Master Book v1.2 Implementáció:** Bevezetésre került a céges verifikációs logika (is_verified) és a 30 napos türelmi idő kezelése.
- **Integritás javítás:** Az `Organization` tábla bővítve lett `is_transferable` és hitelesítési mezőkkel.
- **Bugfix:** `security.py` IndentationError javítva, `auth_service.py` atomikus regisztrációs flow Master Book szinkronizálva.
- **Security:** PostgreSQL tábla-tulajdonosi jogosultságok felülvizsgálata a migrációs hibák elhárításához.
### [2026-02-05] - Identity & Company Sync (v1.2)
- **Database Security:** Javítva a `user_vehicle_equipment` tábla tulajdonosi jogosultsága (`shared-postgres` környezetben).
- **Core Fix:** A `security.py` állomány behúzási hibái (IndentationError) véglegesen elhárítva.
- **Organization v1.2:** Implementálva az `is_transferable`, `is_verified` és `verification_expires_at` mezők a flották hitelesítéséhez.
- **AuthService Logic:** - Az `INDIVIDUAL` típusú flották mostantól alapértelmezetten nem átruházhatóak.
- Beépítve a 30 napos türelmi idő (`grace_period`) kalkulációja a cégellenőrzéshez.
- Atomikus regisztráció kiterjesztve a privát flották automatikus létrehozására.
- **Infrastructure:** Alembic migrációs lánc szinkronizálva az új modellekkel.
### [2026-02-05] - Admin & Economy Finalization (v1.0)
- **Admin Management:** Teljes hiearchia és területi felosztás kidolgozva (L0-L3).
- **Security:** "Kill-switch" anomália-figyelés és 2FA kényszerítés rögzítve.
- **Economy:** 10-5-2% jutalékrendszer és Voucher/Coupon logika specifikálva.
- **Synergy:** Céges VIP és privát flotta közötti kedvezmény-szinergia kidolgozva.
- **Invitations:** Meghívó limitációs és anti-spam logika rögzítve.
# 📓 CHANGELOG - SERVICE FINDER
## [1.2.1] - 2026-02-05
### ✅ Hozzáadva (Added)
- **Multi-step Social Auth:** `User` modell bővítve `social_provider` és `social_id` mezőkkel.
- **Flotta Tulajdonjog:** `Organization` modellben `is_transferable` flag implementálva (Individual flotta zárolva).
- **Referral Snapshot:** Előkészítve a 10-5-2%-os jutalékrendszer adatmodellje.
### 🛠️ Javítva (Fixed)
- **SQLAlchemy Mapper:** Megszűnt a `UserVehicle` KeyError hiba a string-alapú hivatkozásokkal.
- **Duplikáció:** `Vehicle` osztály duplikációja eltávolítva a `vehicle.py`-ból.
- **Indentation Error:** `security.py` bcrypt indentációs hiba javítva.
### ⚠️ Megjegyzés
- Alembic migráció szükséges az új `Organization` és `User` mezőkhöz.
📓 CHANGELOG (Rögzítendő változások)
Mivel kérted, itt van a változások listája, amit a teszt után beírhatunk:
Fixed: UserRole enum validációs hiba (Postgres userrole típus mostantól kisbetűs értéket kap).
Added: Teljes banki KYC integráció a regisztrációba (Személyi, Jogosítvány, Speciális engedélyek).
Added: Atomi tranzakció részeként automatikus OrganizationMember létrehozás a privát flottához.
Added: Audit log rögzítése minden sikeres regisztrációról.
Added: Dinamikus paraméterkezelés (system_settings) a 14 napos jutalomhoz.
Elvárt eredmény: A tranzakció végén létrejön a Person, a Wallet (0 Coin) és a Private Fleet (is_transferable=False). A User is_active értéke True lesz.
3. Debugging Checklist
500 Error? Ellenőrizd a docker logs -f service_finder_api kimenetét. Ha "UndefinedColumn", akkor hiányzik egy SQL mező. Ha "InvalidTextRepresentation", akkor Enum hiba (nagybetűs string).
Üres Swagger? Ellenőrizd az importokat a security.py-ban és a sémákat az endpoints/auth.py-ban.
---
### 💡 Javaslatom a dokumentáció kiegészítésére:
A fejlesztések rendben tartásához javaslom a **`17_DEVELOPER_NOTES_AND_PITFALLS.md`** fájl aktív használatát is, amit az előző körben küldtem. Ez segít megelőzni, hogy a fejlesztőcsapat újra belefusson a Postgres Enum vagy a `Base.metadata.create_all` korlátaiba.
**Holnap reggel frissíted a GEM beállításokat is?** Ha igen, a következő lépésben elkészíthetem neked a Step 2 (KYC) végleges Pydantic sémáját és a `complete-kyc` végpont vázlatát!
## [0.2.0] - 2026-02-07
### ✨ Hozzáadva (Added)
- **Step 2 (KYC) Folyamat:** Teljes körű identitás-kezelés (telefonszám, születési adatok, okmányok, ICE kontakt).
- **Automata Privát Flotta:** Minden felhasználóhoz automatikusan létrejön egy `individual` típusú szervezet (Privát Széf).
- **Automata Wallet:** Minden validált felhasználó kap egy üres pénztárcát (Coin és XP egyenleggel).
- **Trust Tiers:** Bevezetésre került a fokozatos bizalmi szint (Tier 1: Email, Tier 2: KYC/Active).
### 🛠️ Javítva (Fixed)
- **SQLAlchemy Async Fix:** `joinedload` alkalmazása a User-Person kapcsolathoz (MissingGreenlet hiba elhárítva).
- **JSON Serialization:** Pydantic `model_dump(mode='json')` használata a JSONB mezőkhöz (dátum-konverziós hiba javítva).
- **Postgres Schema:** `data.organizations` tábla bővítve hiányzó oszlopokkal (`is_verified`, `updated_at`, stb.).
- **Auth Endpoint:** `/complete-kyc` végpont hozzáadva és JWT védelemmel ellátva.
### ⚙️ Adatbázis Változások (Database)
- Új Enum típus: `data.orgtype` ('individual', 'company').
- `data.persons` bővítve: `phone`, `birth_place`, `birth_date`, `mothers_name`, `identity_docs`, `ice_contact`.
- `data.organizations` bővítve: `is_verified`, `is_transferable`, `verification_expires_at`, `updated_at`.
## [0.2.0] - 2026-02-07
### ✅ Step 2 KYC & Activation Complete
- **Funkció:** Teljes körű személyazonosság-kezelés és fiókaktiválás.
- **Automatizálás:** Regisztrációkor automatikusan létrejön a "Privát Flotta" (Organization) és a digitális pénztárca (Wallet).
- **Adatvédelem:** Elkészült a "Digitális Széf" logika az okmányok és vészhelyzeti adatok biztonságos tárolására.
- **Technikai fix:** SQLAlchemy `joinedload` integráció az aszinkron adatkezeléshez és JSON-safe dátumkezelés.
## [0.3.0] - 2026-02-07
### ✨ Hozzáadva (Added)
- **Asset DNS Modell:** Új, univerzális eszközkezelő rendszer (Assets, VehicleCatalog, AssetEvents, AssetRatings).
- **Harvester Robot:** Automata adatgyűjtő rendszer, amely külső forrásokból tölti fel a globális járműkatalógust.
- **UUID Implementáció:** Az eszközök (Assets) és események (Events) mostantól biztonságos UUID azonosítókat használnak.
### ⚙️ Adatbázis Változások (Database)
- `data.vehicle_catalog` tábla létrehozva a globális specifikációknak.
- `data.assets` tábla létrehozva a konkrét példányok (VIN/HIN alapú) tárolására.
- `data.asset_events` és `data.asset_ratings` táblák az életút és közösségi visszajelzések kezelésére.
### 🛠️ Refaktor (Refactor)
- **Modell Konszolidáció:** A korábbi `Vehicle` és `VehicleBrand` modellek beolvasztva az új `Asset` és `VehicleCatalog` struktúrába.
- **Kapcsolati Térkép:** Az `Organization` és `User` modellek frissítve az új Asset logikához.
## [0.3.5] - 2026-02-07
### ✨ Robot Technológia & Adatbiztonság
- **Multi-Robot Architektúra:** Előkészítve a kategória-specifikus (Car, Bike, Truck) Harvester robotok szétválasztása.
- **Status Tracking:** Bevezetve a `verification_status` a katalógus elemekhez a hiányos adatok kezelésére.
- **SQL Optimalizálás:** Új indexek és kategória alapú szűrések hozzáadva a globális katalógushoz.
## [0.4.0] - 2026-02-07
### ✨ Multi-Robot System
- **Kategória Robotok:** Elkészült a Car, Bike és Truck harvester moduláris szerkezete.
- **Robot Manager:** Központi vezérlő az ütemezett és sorrendi adatgyűjtéshez.
- **Katalógus Kereső:** Üzembe helyezve a `/catalog/search` végpont a Swaggerben.
## [0.4.5] - 2026-02-07
### ✨ Asset Management & Infrastructure
- **Asset Endpoint:** `POST /api/v1/assets/` élesítve VIN validációval.
- **NAS Integration:** Automata mappastruktúra létrehozása az eszközöknek (`/assets/{uuid}`).
- **Data Model:** `privacy_level` és `status` mezők hozzáadva az Asset modellhez.
- **Bugfix:** SQLAlchemy `TypeError` javítva a modell és a séma szinkronizálásával.
## [0.5.0] - 2026-02-07
### ✨ Corporate & CRM Foundation
- **Corporate Onboarding:** `POST /api/v1/organizations/onboard` végpont élesítve.
- **Validation:** Magyar adószám (HU) formátum ellenőrzés beépítve.
- **Status Management:** Bevezetve a `pending_verification` állapot a szervezetekhez.
- **Database:** PostgreSQL `orgtype` Enum szinkronizálva a Python modellel (kisbetűs mapping).
- **NAS:** Automata szervezeti mappa-izoláció (`/organizations/{id}`).
[0.5.1] - 2026-02-07
FIX: ModuleNotFoundError javítva az importok szinkronizálásával.
DATA: Atomizált címmezők hozzáadva a data.organizations táblához.
LOGIC: Háromszintű névkezelés (Hivatalos, Rövid, Display) bevezetve.
## [2.1.0] - 2026-02-08
### Hozzáadva (Added)
- **Hibrid Címkezelő Rendszer**: Új `data.addresses` központi tábla, amely UUID alapú azonosítással köti össze a személyeket, cégeket és szervizeket.
- **Öntanuló GeoService**: A rendszer rögzítéskor automatikusan bővíti a ZIP-kód, város és utcanév szótárakat.
- **Autocomplete API**: `/api/v1/services/suggest-street` végpont a frontend gépelés közbeni támogatásához.
- **Kétlépcsős Keresés**: `/api/v1/services/search` végpont, amely megkülönbözteti a légvonalbeli (Free) és útvonal/idő alapú (Premium) kalkulációt.
- **PostGIS Integráció**: Tűpontos GPS távolságmérés `geography` casting használatával.
### Javítva (Fixed)
- **Gamifikációs hiba**: A `PointsLedger` modellben javítva a `points` mezőnév (TypeError: points_change fix).
- **Adatbázis Inkonzisztencia**: Létrehozva a hiányzó `data.user_stats` tábla.
- **Import hibák**: `Optional`, `UploadFile` és `File` hiányzó importok pótolva a szolgáltatás végpontokon.
### Változtatva (Changed)
- **Címkezelési Logika**: A cégek és magánszemélyek mostantól egységes, bontott címstruktúrát (zip, city, street, street_type, house_number, parcel_id) használnak.
- **XP Szűrés**: A szervizek és cégek rögzítésekor a rendszer mostantól csak a természetes személyeknek (User/Driver) oszt social pontokat.
## [2.1.0] - 2026-02-08
- **Feat**: Hibrid címkezelő rendszer bevezetése (UUID alapú `data.addresses`).
- **Feat**: Öntanuló Geo-logika (Auto-create ZIP/Street).
- **Feat**: Kétlépcsős (Free/Premium) szervizkereső API.
- **Fix**: `points_ledger` mezőnév szinkronizáció.
- **Fix**: `data.user_stats` tábla inicializálása.
## [2026-02-08] - Nemzetközi Asset és KYC Stabilizáció
### Hozzáadva
- **Nemzetközi paraméterek**: `mileage_unit` (km/miles/hours) és `reading_unit` támogatása az Asset modellben.
- **Pénzügyi alapok**: `AssetCost` modell bővítése nettó/bruttó összeggel, ÁFA kulccsal és deviza-kezeléssel.
- **Árfolyamkezelés**: `exchange_rates` tábla implementálása MNB/ECB alapú napi frissítéshez.
- **Értékelési rendszer**: `ratings` tábla létrehozva (user, asset, service_provider szinten).
### Javítva
- **KYC Folyamat**: Anyja neve bontása vezetéknévre és keresztnévre a magyar/nemzetközi szabványok szerint.
- **Database Schema**: Számos hiányzó oszlop pótolva (`asset_events.data`, `asset_events.event_date`, `user_stats.total_xp`).
- **SQLAlchemy hiba**: Javítva az `IndexError` a katalógus lekérdezésnél és az import hiba a `PG_UUID` kapcsán.
### Megjegyzés
A rendszer most már képes egyetlen KYC folyamat alatt aktiválni a felhasználót, létrehozni az egyéni flottáját, inicializálni a pénztárcáját (Kredit/Coin) és rögzíteni az első járművét kezdő km-óra állással.
## [Unreleased] - 2026-02-10
### 🚀 Added (Új funkciók)
- **RBAC System:**
- \`User\` tábla bővítése: \`scope_level\`, \`scope_id\`, \`custom_permissions\`.
- \`system_parameters\` tábla létrehozása a globális JSON konfigurációkhoz.
- Master RBAC JSON konfiguráció seedelése.
- **Gamification:**
- \`GamificationService\` létrehozása (XP, Level, Credit logika).
- Automata pontszámítás és nehezedő szintek logikája.
- **API Modularitás:**
- \`assets.py\` szétbontása 3 végpontra (Identity, Costs, Telemetry).
### 🛠 Changed (Módosítások)
- **Asset Model:** Az \`Asset\` entitás mostantól lazy loading helyett \`selectinload\` stratégiát használ a teljesítmény érdekében.
- **Error Handling:** Javítottuk az \`asyncpg\` többszörös parancs-futtatási hibáját a setup scriptekben.
- **Configuration:** A rendszerbeállítások mostantól adatbázis-alapúak (JSONB) a hardcoded konstansok helyett.
### 🐛 Fixed (Javítások)
- **Schema Mismatch:** SQLAlchemy modellek és Pydantic sémák szétválasztása (`models/asset.py` vs `schemas/asset.py`).
- **Data Integrity:** \`updated_at\` és \`is_active\` oszlopok pótlása a \`system_parameters\` táblában.
- **API Stability:** \`getattr\` használata a hiányzó opcionális mezőknél (pl. \`net_amount\`), hogy ne szálljon el az API 500-as hibával.
## [1.2.0] - 2026-02-10
### Added
- **Asset Financials 2.0**: Pivot-Currency modell implementálva (helyi deviza + EUR párhuzamos tárolás).
- **Smart Auth Token**: JWT token mostantól tartalmazza a `rank`, `scope_level` és `scope_id` mezőket a gyors jogosultságkezeléshez.
- **CostService**: Automatikus árfolyam-kalkuláció, telemetria-szinkron és XP jóváírás költségrögzítéskor.
- **ExchangeRate**: Új árfolyamtábla és modell az EUR alapú váltásokhoz.
### Fixed
- **Circular Import Resolution**: Megszüntetve a `db.base` és a `models` közötti körkörös függőség az import lánc modularizálásával.
- **Alembic Identity Sync**: Visszaállítva a `User` modell hiányzó `scope_level` és `custom_permissions` mezői, megakadályozva az adatvesztést migrációkor.
- **NotNullViolationError**: Fixálva az `asset_costs` tábla migrációja (amount_local NOT NULL kényszer).
### Changed
- `AssetCost` modell mezőnevek szinkronizálva a pénzügyi standardokhoz (`amount_local`, `amount_eur`).
- `SystemParameter` modell elnevezés igazítva a meglévő adatbázis sémához.
## [1.5.0] - 2026-02-10
### Added
- **Judge & Penalty System**: Bevezetve a `penalty_points` és `restriction_level` mechanizmus a visszaélések kiszűrésére.
- **Dynamic Multipliers**: Admin felületről (JSON config) állítható pontszorzók a büntetési szintekhez.
- **Social-to-Credit Auto-conversion**: Automatikus Kredit jóváírás a Walletbe meghatározott Social pont elérésekor.
- **Level Achievement Bonus**: 10-es szintenkénti automatikus Kredit jutalmazás.
### Fixed
- **Circular Dependency Fix**: A modellek közötti import hurok végleges felszámolva (string-alapú relationship hivatkozások).
- **Identity Schema Protection**: Visszaállítva a `User` modell hiányzó `scope_id`, `scope_level` és `custom_permissions` mezői.
- **Database Consistency**: A `user_stats` és `asset_costs` táblák sikeresen migráltak a NOT NULL kényszerek és alapértelmezett értékek (server_default) beállításával.
### Changed
- **GamificationService**: Mostantól központi "Bíróként" funkcionál, leválasztva a pontszámítási logikát a többi szervizről.
- **Identity Model**: A `Wallet` és `VerificationToken` osztályok integrálva az `identity.py` modulba.
# Changelog - Service Finder Backend
**Verzió:** 1.6.0 (Sentinel & i18n Update)
**Dátum:** 2026.02.10.
## [1.6.0] - 2026-02-10
### Hozzáadva
- **Sentinel Biztonsági Rendszer:** - `PendingAction` modell bevezetése a "Négy szem elv" (Dual Control) biztosításához.
- `SecurityService` implementálása: Adatlopás elleni védelem (Throttling) és automata vészleállító (Emergency Lock).
- `AuditLog` bővítése szigorúbb súlyossági szintekkel (`critical`, `emergency`).
- **Nyelvi Modul (i18n):**
- `Translation` modell a `data` sémában.
- `TranslationService`: Adatbázis-alapú fordításkezelés, szerveroldali cache, Fallback (EN) logika és JSON export funkció a Frontend számára.
- **Admin Kontroll Panel:**
- Új API végpontok a függőben lévő műveletek jóváhagyásához, a rendszerbiztonsági állapot monitorozásához és a nyelvi szinkronizációhoz.
### Javítva
- **Circular Import Fix:** A modellek importálási rendjének optimalizálása a `app.db.base_class` közvetlen használatával, megszüntetve a hurok-importokat.
- **Függőségkezelés:** `deps.py` bővítve a `get_current_active_user` függőséggel a biztonsági zárolások érvényesítéséhez.
- **Soft-Delete Logika:** A felhasználói fiók törlése mostantól felszabadítja az eredeti e-mail címet a TWINS-elvű újra-regisztrációhoz.
# 15. Changelog & Version History
## [v1.2.5] - 2026-02-10 (The "SuperAdmin" Update)
### 🚀 New Features
- **Admin Bootstrap:** Implementáltuk a "vészhelyzeti" Admin létrehozási folyamatot (Python script alapú hash generálással).
- **i18n Sync:** Élesítettük a `/api/v1/admin/translations/sync` végpontot, amely JSON fájlokba exportálja az adatbázis fordításait.
- **Identity Expansion:** A `User` modell bővült a `preferred_language` és `region_code` mezőkkel a perszonalizáció érdekében.
### 🐛 Bug Fixes
- **ORM Crash:** Javítva az `AssetAssignment` és `AssetCost` modellek hiányzó `organization` kapcsolatai, amelyek blokkolták a rendszer indulását (`InvalidRequestError`).
- **Config Error:** Javítva a `Settings` osztályból hiányzó `STATIC_DIR` definíció, ami 500-as hibát okozott a fordítások szinkronizálásakor.
- **Login Crash:** Javítva az `AttributeError` a Login végponton (a hiányzó `region_code` miatt).
### 🛠 Technical Changes
- **Migrations:** Új Alembic migráció (`add_lang_and_region_to_user`) generálva és lefuttatva.
- **Environment:** A `static/locales` mappa jogosultságai beállítva a Docker konténer számára.
[2026.02.12] - Fundamentum és Robot Orchestration
FIX: Javítva a docker-compose v1/v2 összeférhetetlenség (ContainerConfig hiba).
FIX: Megszüntetve az ImportError: cannot import name 'FastAPILimiter' hiba a security.py modulban.
DATABASE: PostGIS Geometry típus implementálva a service_profiles táblában.
MODEL: Az Asset (Digital Twin) és ServiceProfile közötti kapcsolatok szinkronizálva az ownership_history modulon keresztül.
WORKERS: Új állapotvezérelt (State-driven) robotlogika bevezetése:
A szervizek alapértelmezetten ghost státusszal jönnek létre.
Bevezetve a last_audit_at mező az automatikus kivezetéshez (Soft-delete).
UX: A keresőmotor számára definiálva a "Nem megerősített szolgáltató" jelzés a bot által talált adatokhoz.
📝 Részletes Összefoglaló az Elvégzett Munkáról
Környezet Stabilizálás: A modern Docker Engine-hez igazítottuk a parancsokat, megoldva a régi Python-alapú compose hibáit.
Adatmodell Integritás: Visszaállítottuk az összes kritikus mezőt (nettó érték, ÁFA, maradványérték, telemetria), így a rendszer alkalmas komplex flottakezelési feladatokra is.
Szerviz Életciklus: Kidolgoztunk egy olyan logikát, ahol a botok nem "szemetelik" az adatbázist, hanem egy ghost (árnyék) réteget hoznak létre. Ezek a szervizek csak akkor válnak teljesen hitelessé, ha a felhasználók interakcióba lépnek velük (Gamification) vagy az Admin jóváhagyja őket.
Robot Koordináció: A robotok immár nem ütköznek. Az egyik a járműkatalógust építi API-kból, a másik a térképi pontokat gyűjti és auditálja.
# Changelog - 2026-02-13
## Service Finder Project - "Dunakeszi Detective" & Docker Infrastructure
### 🚀 Fejlesztések és Architektúra
- **Robot 2.7 (Service Hunter) Implementálása:**
- Hibrid adatgyűjtés bevezetése: OSM (OpenStreetMap) + Google Places API + Helyi CSV.
- **Geocoding Integráció:** A CSV-ben megadott szöveges címek (pl. "Dunakeszi, Kikerics köz 4") automatikus GPS koordinátára fordítása a Google API segítségével.
- **Trust Score alapok:** Különböző források eltérő bizalmi szinttel kerülnek rögzítésre (Manuális > Google > OSM).
- **Adatbázis és Modellek (ORM) Javítása:**
- `Organization` és `Address` modellek szinkronizálása a valós adatbázis sémával.
- Hiányzó mezők kezelése (City, Zip átmozgatása Organization szintre).
- PostGIS geometria (POINT) kezelésének pontosítása.
- **Docker Infrastruktúra Stabilizálás:**
- Hálózati hiba (`[Errno -2] Name or service not known`) elhárítása.
- `shared_db_net` és `bridge` hálózatok megfelelő konfigurálása.
- Konténer DNS beállítások fixálása (Google DNS fallback).
- Adatbázis hostnév korrekció (`db` -> `shared-postgres`).
### 🧠 Üzleti Logika és Stratégia (Döntések)
1. **Multi-Tenant Kezelés:** Egy címen több cég is létezhet. A rendszer nem vonja össze őket automatikusan, csak ha az adószám/név egyezik.
2. **Adatvédelmi Elv (No-Delete):** A robot soha nem töröl adatot fizikailag. Ha egy forrás megszűnik, a rekord "archived" vagy "review_needed" státuszt kap, de az adatbázisban marad.
3. **Emberi Felügyelet:** A duplikációk összefűzése vagy a hibás adatok törlése Admin/Moderátor jogkör, nem a robot automatizmusa.
4. **Dinamikus Adatfrissítés:** A robot a jövőben frissítheti a manuálisan felvitt adatokat is (pl. ha változik a nyitvatartás a Google-ön), de a prioritási szabályokat még finomítani kell.
### 🐛 Javított Hibák
- `socket.gaierror`: Docker konténer internet elérés és belső névfeloldás javítva.
- `AttributeError: 'city'`: SQLAlchemy modell mezőleképezési hiba javítva.
- Függőségi hiba (`depends_at` -> `depends_on`) a docker-compose fájlban.
### 🔜 Következő Lépések
- Gamification és Moderátori felület (Admin UI) tervezése az adatok tisztítására.
- Logikai szabályrendszer (Business Rules) véglegesítése a "Robot vs. Ember" adatkonfliktusokra.
# Changelog - Service Finder Project
**Dátum:** 2026-02-15
**Verzió:** Backend v1.9.8 / Robot v1.0.7 (Deep Hunter)
**Fókusz:** Adatbázis séma bővítése, RDW API integráció stabilizálása, Multi-vehicle támogatás.
## 🏛️ Adatbázis és Architektúra (Alembic & SQLAlchemy)
### Hozzáadva
- **Új Migráció (`enrich_catalog_technical_schema`):**
- `power_kw` (Integer, Indexed): Teljesítmény tárolása.
- `engine_capacity` (Integer, Indexed): Hengerűrtartalom (ccm).
- `max_weight_kg` (Integer): Megengedett legnagyobb össztömeg.
- `euro_class` (String): Környezetvédelmi besorolás.
- **Új Migráció (`add_axles_and_body_type`):**
- `axle_count` (Integer): Tengelyek száma (Teherautókhoz/Kamionokhoz).
- `body_type` (String): Felépítmény (pl. Sedan, Box, Camper).
- **Modell Frissítés (`asset.py`):**
- Az `AssetCatalog` osztály szinkronba hozva az új DB sémával.
- `UniqueConstraint` és indexek optimalizálása a gyors kereséshez.
### Javítva
- **Alembic Syntax Error:** Javítva a `ddef` elírás a migrációs fájlban.
- **Column Duplication:** Javítva az `axle_count` duplikált létrehozási kísérlete a második migrációban.
## 🤖 Robot / Worker (Data Ingestion)
### Módosítva
- **Robot Upgrade (v1.0.2 -> v1.0.7 Deep Hunter):**
- **License Plate Bridge (Rendszám-híd):** Új stratégia az API 400-as hibák megkerülésére. A robot mostantól:
1. Lekéri az alapadatokat (`m9d7-ebf2`).
2. Kivesz egy minta rendszámot.
3. Ezzel a rendszámmal lekérdezi a `FUEL`, `AXLE` és `BODY` táblákat.
- **Pagination (Lapozás):** `$offset` támogatás beépítése, így a robot képes 50.000+ rekordos márkákat is végigolvasni.
- **Camper Detection:** Automatikus lakóautó (`camper`) kategória felismerés a "kampeerwagen" kulcsszó alapján.
- **Category Mapping:** Angol nyelvű kategóriák (Car, Truck, Motorcycle, Agricultural) kényszerítése.
### Javítva
- **RDW API 400 Bad Request:** Megoldva a `merk` vs `merknaam` paraméterek eltérésének kezelésével (átállás a fő táblára).
- **AttributeError:** Javítva a hibás `TECH_API_URL` hivatkozás.
## 💾 Adat (Seeding & SQL)
- **Grand Seeder v2:**
- SQL szkript létrehozva a világmárkák (Toyota, BMW, Scania, John Deere, stb.) tömeges betöltésére.
- `model` mező feltöltése `'ALL'` értékkel a `NOT NULL` kényszer miatt.
- Státuszok visszaállítása `pending`-re a teljes újradolgozáshoz.
# CHANGELOG - 2026.02.16 (Architectural Overhaul: Identity & Economy Engine)
## 🏆 Napi Összefoglaló
A mai napon alapjaiban strukturáltuk át az identitáskezelést (`Identity`), a jogosultsági rendszert (`RBAC`) és a gazdasági motort (`Economy`). Bevezetésre került a "Dual Entity" modell (Person vs. User), a 3-szintű Wallet rendszer, valamint a "Hunting & Farming" üzletkötői jutalékrendszer alapjai. A biztonságot a 4-szem elvű (Four-Eyes Principle) audit naplózás garantálja.
---
## 🏛️ 1. Architektúra és Logika (Master Book Updates)
### A. Identitás Filozófiája (The Dual Entity Rule)
* **Person (A DNS):** A természetes személy, aki "örök". Nem törlődik GDPR törléskor sem, csak anonimizálódik.
* Tárolja: `lifetime_xp` (életút pontok), `penalty_points` (büntetések 0-3 szint), `social_reputation`.
* **Identity Hash:** Egyedi SHA256 lenyomat (Kisbetűsített Anyja neve + Születési hely + Idő) a duplikációk és visszaélések ellen.
* **User (A Kulcs):** A belépési fiók. Bármikor törölhető/eldobható.
* Kapcsolódik a Person-höz.
* Tárolja: `subscription_plan`, `is_vip`, `session_data`.
### B. Gazdasági Modell (The Triple Wallet)
A pénztárcát (`Wallet`) három, szigorúan elkülönített alszámlára bontottuk:
1. **Earned Credits:** Munkával (validálás) és Referral jutalékból szerzett. (Beváltható Prémiumra).
2. **Purchased Credits:** Valódi pénzért vásárolt egyenleg. (Beváltható Prémiumra).
3. **Service Coins:** B2B egység. Kizárólag hirdetésre és kiemelésre fordítható. (NEM váltható Prémiumra).
### C. Üzletkötői Rendszer (Hunting & Farming)
* **Hunting (Vadász) Jutalék:** Egyszeri jutalék az első behozatalért (tervezett: 10%).
* **Farming (Gazda) Jutalék:** Folyamatos jutalék a havidíjakból (tervezett: 5%).
* **Átruházhatóság:** A Farming jog nem az üzletkötőhöz, hanem a Cég-Üzletkötő kapcsolathoz (`OrganizationSalesAssignment`) kötődik. Ha az üzletkötő kilép, a portfóliója (és a jutalék) átruházható másra.
### D. Biztonság (Audit & 4-Eyes)
* **Operational Log:** Napi üzemi események (pl. jármű rögzítés).
* **Financial Ledger:** Minden pénzmozgás (Kredit/Coin/HUF) központi főkönyve.
* **Security Audit Log:** Kiemelt biztonsági események (pl. VIP státusz adása).
* **4-szem elv:** Kritikusan érzékeny műveleteknél kötelező egy második admin jóváhagyása (`confirmed_by_id`).
---
## 🛠️ 2. Adatbázis és Modell Változások
### Új/Módosított Táblák (`data` séma)
| Tábla | Változás | Leírás |
| :--- | :--- | :--- |
| **persons** | **UPDATE** | Új mezők: `identity_hash`, `lifetime_xp`, `penalty_points`, `social_reputation`, `is_sales_agent`. |
| **users** | **UPDATE** | Új mezők: `subscription_expires_at`, `is_vip`, `referral_code`, `current_sales_agent_id`. |
| **wallets** | **REFACTOR** | Régi balance törölve. Új: `earned_credits`, `purchased_credits`, `service_coins`. |
| **org_sales_assignments** | **NEW** | Kapcsolótábla: Melyik cég után ki kapja épp a Farming jutalékot. |
| **financial_ledger** | **NEW** | Pénzügyi tranzakciók megmásíthatatlan naplója. |
| **security_audit_logs** | **NEW** | Adminisztrátori műveletek és 4-szem elv naplózása. |
| **operational_logs** | **NEW** | Általános rendszerhasználati napló. |
---
## 📂 3. Érintett Fájlok Listája (Checklist)
Kérlek, ellenőrizd, hogy ezek a fájlok a legfrissebb verziót tartalmazzák-e a mentésedben:
- [x] **`backend/app/models/identity.py`** (A teljes Person/User/Wallet logika alapja)
- [x] **`backend/app/models/audit.py`** (A Ledger és Security Log definíciók)
- [x] **`backend/app/models/organization.py`** (A SalesAssignment tábla hozzáadása)
- [x] **`backend/app/models/__init__.py`** (Az összes modell regisztrációja az Alembic számára)
- [x] **`backend/app/db/base.py`** (A metadata importok frissítése)
- [x] **`backend/app/core/validators.py`** (Az IdentityNormalizer és Hash generáló logika)
- [x] **`backend/migrations/versions/XXXX_full_ecosystem_upgrade_v1_6.py`** (A generált migrációs fájl)
---
## 🔮 4. Következő Lépések (Roadmap)
1. **Service Réteg Implementálása:** Megírni a logikát, ami ténylegesen számolja a 10/5%-os jutalékot és beírja a `FinancialLedger`-be.
2. **Admin UI:** Felületet készíteni a `system_parameters` (Jutalék szintek) állítására.
3. **Robot v1.8:** A "Ghost" szervizek bekötése az új `Person` logikába (automata `identity_hash` generálás a cégadatokból).
# Changelog
## [v1.1.0] - 2026-02-17 "The Awakening"
### 🚀 Hozzáadva (New Features)
- **AI Service (Gemini Integration):** `app/services/ai_service.py` létrehozva. A rendszer mostantól képes a "Yamaha 4HN" típusú zajos adatokból tiszta marketing neveket és műszaki specifikációkat generálni.
- **Robot 2 (Technical Enricher):** `app/workers/technical_enricher.py` frissítve v1.1-re. Hibrid működés: RDW adatbázis + AI kiegészítés.
- **Robot 3 (OCR - Előkészület):** `app/workers/ocr_robot.py` váza elkészült a dokumentumok feldolgozásához.
- **Reporting:** `app/scripts/morning_report.py` létrehozva a napi robot-tevékenység összefoglalására.
- **Logging:** Új `ProcessLog` tábla létrehozva az `audit` sémában a háttérfolyamatok nyomon követésére.
### 🐛 Javítva (Bug Fixes)
- **Docker Infrastructure:** - Javítva a `KeyError: 'ContainerConfig'` hiba a Docker Compose V2-re váltással.
- Javítva az "empty database URL" hiba a migrációnál (`.env` változók helyes átadása).
- Hálózati beragadások (Gitea/Nginx conflict) feloldva.
- **Circular Imports:** Megszüntetve a `SystemParameter` modell duplikációja (`system_config.py` vs `system.py`). Minden szerviz (`Auth`, `Security`, `Cost`, `Gamification`) mostantól a központi `app.models`-ből importál.
- **Swagger UI:** Az API sikeresen elindul, a dokumentáció elérhető a `/docs` végponton.
### ⚙️ Infrastruktúra (Refactor)
- **Docker Compose:** Teljes tisztítás. Duplikált környezeti változók törölve, `env_file` használat optimalizálva.
- **Services:** A robotok (`enricher`, `catalog`, `hunter`) külön konténerekbe szervezve, `unbuffered` python kimenettel a valós idejű logolásért.
### 🛡️ Biztonság
- `.env` fájl szerkezete egységesítve, duplikációk eltávolítva.

View File

@@ -0,0 +1,46 @@
# 🧪 TESZTELÉSI ÉS ÉLESÍTÉSI ÚTMUTATÓ (v1.4)
## 1. Előkészületek és Környezet
1. **SQL Patch:** Meglévő adatbázis esetén futtasd a manuális frissítő SQL-t (mothers_name, social_provider, is_transferable oszlopok hozzáadása).
2. **Enum Ellenőrzés:** Győződj meg róla, hogy a Postgres `userrole` típus tartalmazza a kisbetűs értékeket.
3. **Docker Build:** `docker compose up -d --build` (Kényszeríti az új Python kód betöltését).
## 2. Regisztrációs Teszt Forgatókönyvek
### A) Step 1: Lite Regisztráció (Clean Test)
- **Endpoint:** `POST /api/v1/auth/register`
- **Elvárt eredmény:** 201 Created, `access_token` visszaadva, de a DB-ben a User `is_active = False` és nincs hozzá Person rekord.
### B) Step 2: KYC Kitöltés (Advanced Test)
- **Endpoint:** `POST /api/v1/auth/complete-kyc`
- **Adat (JSON):**
```json
{
"mothers_name": "Minta Mária",
"id_card_number": "AB123456",
"driver_license_categories": ["A", "B"],
"boat_license_number": "H-99999"
}
# 🧪 TESZTELÉSI ÉS ÉLESÍTÉSI ÚTMUTATÓ (v1.0)
## 1. Előkészületek a távoli teszteléshez
Mielőtt elindítanád a teszteket, győződj meg róla, hogy a háttérfolyamatok frissültek:
1. A `.env` fájl mentve van a helyes jelszavakkal.
2. A konténerek újraépítése és indítása:
`docker compose up -d --build` (Ez kényszeríti a Python kódot az új verzióra).
3. Ellenőrizd a logokat: `docker logs -f service_finder_api` (Itt látod, ha hiba van induláskor).
## 2. Tesztelési Forgatókönyvek (End-to-End)
### A) Új Regisztráció Teszt (Clean Registration)
- **Endpoint:** `POST /api/v1/auth/register`
- **Adat (JSON):**
```json
{
"email": "teszt.felhasznalo@profibot.hu",
"password": "nagyonerospassword123",
"first_name": "János",
"last_name": "Teszt",
"region_code": "HU"
}

View File

@@ -0,0 +1,37 @@
# 🛠️ DEVELOPER NOTES & TROUBLESHOOTING
## 1. ADATBÁZIS ÉS SQL FIXEK
### Postgres Enum Case Sensitivity
* **Probléma:** Az SQLAlchemy Enum típusa és a Postgres Enum típusa ütközhet, ha a Python kódban nagybetűs stringet (`USER`) küldünk.
* **Megoldás:** Mindig használd a `.value` property-t vagy kényszerítsd a kisbetűs stringet: `role="user"`.
### Tábla oszlopok frissítése
* **Probléma:** A `Base.metadata.create_all` nem adja hozzá az új oszlopokat a már meglévő táblákhoz.
* **Megoldás:** Új mező esetén (pl. `social_provider`, `mothers_name`) manuális `ALTER TABLE` parancsot kell futtatni vagy Alembic migrációt generálni.
## 2. BACKEND API HIBÁK
### ImportError: create_access_token
* **Ok:** A `app.core.security` modulban hiányzott a funkció, vagy elavult volt az import az `endpoints/auth.py`-ban.
* **Javítás:** A `security.py`-nak tartalmaznia kell a `jose` könyvtárat használó tokengenerálást.
### Üres Swagger (OpenAPI) felület
* **Ok:** Ha az SQLAlchemy Mapper vagy egy Pydantic séma importja hibás, a FastAPI nem tudja legenerálni a dokumentációt.
* **Javítás:** Ellenőrizd a `docker logs` kimenetét indításkor, keresd a `MapperConfigurationError` vagy `ImportError` sorokat.
# 17. Developer Notes & Pitfalls
## 17.1. SQLAlchemy & Circular Imports
**Hiba:** `InvalidRequestError: Mapper has no property 'organization'`
**Ok:** Ha egy modellben definiálsz egy `ForeignKey`-t, de nem adod hozzá a `relationship`-et, a SQLAlchemy mapper inicializáláskor összeomolhat, ha egy másik modell próbál hivatkozni rá (back_populates).
**Megoldás:** Mindig párban definiáld a kapcsolatokat (FK + relationship).
**Példa javítás (AssetAssignment):**
```python
organization_id = Column(Integer, ForeignKey("data.organizations.id"))
organization = relationship("Organization") # Ez hiányzott!
17.2. Configuration Missing
Hiba: AttributeError: 'Settings' object has no attribute 'STATIC_DIR' Tanulság: Ha fájlrendszer műveleteket végzel (pl. JSON export), mindig a core/config.py-ban definiáld az abszolút útvonalakat (BASE_DIR, STATIC_DIR), ne hardkódolj útvonalakat a service fájlokban.
17.3. Database Migrations
Best Practice: Ha mezőt adsz hozzá egy modellhez (pl. User.region_code), azonnal generálj Alembic migrációt (alembic revision --autogenerate), különben az API 500-as hibát dob, mert a Python objektum attribútuma létezik, de az SQL lekérdezés nem adja vissza az oszlopot.

View File

@@ -0,0 +1,235 @@
# 🏎️ 18_ASSET_AND_FLEET_SPECIFICATION (v1.2)
Ez a dokumentum írja le a rendszer magját képező "széf" logikát, ahol minden közlekedési eszköz (Asset) egyedi életutat és digitális lenyomatot kap.
## 1. Az Alapelv: "Mindenki Flottatulajdonos"
A rendszerben a technikai réteg nem tesz különbséget magánszemély és cég között.
- **Privát Flotta:** A regisztráció során automatikusan létrejövő szervezet (**Organization**).
- **Széf (Safe Deposit):** A flotta izolált része, ahol az eszközök (járművek) és azok bizalmas okmányai (Vault) találhatók.
---
## 2. Eszköz Típusok és Univerzális Azonosítók (UAI)
Minden eszköz rendelkezik egy **Univerzális Állandó Azonosítóval (UAI)**, amely az életútja során soha nem változik.
| Kategória | Elsődleges Azonosító (UAI) | Speciális Adatpontok |
| :--- | :--- | :--- |
| **Közúti (Car, Bike, Bus)** | **VIN** (Alvázszám) | Rendszám, Motorkód, Sebességváltó kód |
| **Vízi (Boat, Yacht)** | **HIN** (Hull ID) | MMSI kód, IMO szám, Hajó neve |
| **Légi (Aircraft)** | **Serial Number** | Lajstromjel (Registration), Típusjelzés |
| **Heavy Duty / Agri** | Egyedi sorozatszám | Üzemóra, Teljesítmény, Kanál/Vágóasztal típus |
| **Micro-mobility** | Vázszám / UUID | Akkumulátor ciklus, Hatótáv |
### Kiegészítő mérőszámok:
- **Futásteljesítmény (Odometer):** Közúti járműveknél (km/mérföld).
- **Üzemóra (Operating Hours):** Hajók, repülők és munkagépek esetén az elsődleges szervizintervallum-mérő.
- **VIN Validáció:** Közúti járműveknél kötelező a **VIN Checksum (MOD 11)** ellenőrzése rögzítéskor.
---
## 3. A Jármű DNS (Deep Data Structure)
A rendszer két rétegben kezeli a jármű adatait a teljes életút követéséhez.
### 3.1. Gyári Konfiguráció (Factory Specs)
- **Trim Level:** Felszereltségi szint (pl. AMG Pack, S-Line).
- **Technikai paraméterek:** Motorvariációk, kW/LE, nyomaték, gyári felni/gumi méretek (ET számmal), folyadékmennyiségek.
- **Szervizintervallumok:** Gyártói előírások (idő vagy távolság alapú).
### 3.2. Aktuális Állapot és Módosítások
- **Status Quo:** Gyári extrák, utólagos módosítások (Aftermarket - pl. vonóhorog, gázszett) és hiányzó gyári elemek követése.
---
## 4. Digitális Szervizkönyv és Minősítés
### 4.1. Eseményalapú Idővonal (Timeline)
Minden bejegyzés megváltoztathatatlan (immutable) logként rögzül:
- **Típusok:** Karbantartás, Javítás, Műszaki Vizsga, Baleset, Tulajdonosváltás.
- **Csatolmányok:** Alkatrész fotók, számlák (OCR), munkalapok.
### 4.2. Kettős Értékelési Rendszer
1. **AI Health Score (Technikai):** Algoritmus alapú pontszám a szerviztörténet és a gyári előírások betartása alapján.
2. **Driver Rating (Emocionális):** Szubjektív sofőrértékelés (Komfort, Vezetési élmény, Praktikum).
---
## 5. Multi-Robot Harvester Architektúra
A katalógus feltöltéséért és frissítéséért kategória-specifikus robotok felelnek (`BaseHarvester` alapokon).
### 5.1. Robot Típusok:
- **Autó / Motor Robot:** Közúti adatokra.
- **Heavy Duty / Agri Robot:** Teherautókra és munkagépekre.
- **Specialty Robot:** Vízi és légi azonosítókra (MMSI, Lajstrom).
### 5.2. Adatgyűjtési Szintek:
- **Initial Load:** A top 1000 európai típus alapfeltöltése.
- **On-Demand Fetch:** Felhasználói "Trigger" hatására indított soron kívüli mélykeresés (Deep Web Scrape).
- **Verification Status:** `verified` (teljes), `incomplete` (részleges), `pending` (ellenőrzésre vár).
---
## 6. OCR és Dokumentum Validációs Stratégia
A dokumentumfelismerés (OCR) hibrid technológiát és Tier-alapú prioritást alkalmaz.
### 6.1. Feldolgozási Sorrend (Failover Logic)
1. **Tier 1 (External Cloud):** Google Vision / Azure Form Recognizer (ingyenes keret erejéig).
2. **Tier 2 (Saját Fallback):** Helyi szerveren futó **PaddleOCR** modul.
### 6.2. Üzleti Logika és Monetizáció
- **VIP+ / Premium+:** Azonnali (Real-time) OCR feldolgozás (3-5 másodperc).
- **Lite:** Háttérfolyamat (sorban állás), korlátozott havi kvóta (pl. 1 scan/hó).
- **Kreditalapú túllépés:** A kvóta feletti beolvasások a `Wallet`-ből levont kreditért vásárolhatók meg.
---
## 7. Infrastruktúra és Adatkezelés
### 7.1. Dokumentum Tárolás (NAS)
- **Elérési út:** `/mnt/nas/app_data/assets/{asset_id}/`
- **Típusok:**
- **Vault (Tartós):** Kritikus okmányok (Forgalmi, Adásvételi) hash-elt fájlnévvel.
- **Ephemeral (Ideiglenes):** Napi bizonylatok (Parkolójegy), melyek OCR után 90 nappal törlődnek.
- **Képoptimalizálás:** Automata átméretezés (max 1600px) és WebP konverzió (~80-90% megtakarítás).
### 7.2. Címkezelési Protokoll (v2.0)
Minden címet (székhely, tulajdonos, szerviz) atomizált formában tárolunk a pontos riportáláshoz:
- Irányítószám, Település, Közterület neve, Közterület jellege (utca, út stb.), Házszám (emelet/ajtó kiegészítéssel).
---
## 8. Kivételkezelés: Ismeretlen Járművek
Ha az eszköz nem szerepel a katalógusban:
1. **Custom Asset:** Manuális rögzítés kötelező dokumentum-fotóval.
2. **AI Verifikáció:** OCR-rel összeveti a fotót a bevitt adatokkal.
3. **"Unverified Model" jelzés:** Amíg a Robot vagy egy Admin meg nem erősíti az adatok hitelességét.
## 3. Document Engine & Optimization
- **Processing:** Feltöltéskor automatikus méretoptimalizálás (max 1600px) és WebP konverzió.
- **Thumbnails:** Minden képből 300px széles WebP előnézet generálódik a gyors UI eléréshez.
- **Supported Formats:** JPG, PNG, WEBP (képek); PDF, DOCX (dokumentumok).
- **OCR Integration:** Számlák és munkalapok esetén automata adatkinyerés (alkatrészek, árak, kilométeróra állás).
## 7.4 Dokumentum Életciklus és Pufferelés (v2.2)
A rendszer háromlépcsős tárolási és feldolgozási logikát alkalmaz az optimális hálózati és szerver-teljesítmény érdekében:
1. **Ingestion (TEMP - Helyi SSD):** - Minden feltöltött állomány a `/app/temp/uploads/` mappába érkezik.
- Itt történik az AI/OCR elemzés és a képoptimalizálás (Pillow).
- A nyers forrásfájl a feldolgozás után **30 percig** marad itt (puffer), hogy a felhasználó azonnal visszanézhesse, mielőtt a NAS-ra kerül.
2. **Presentation (THUMBNAIL - Helyi SSD):**
- A Pillow által generált 300px széles WebP miniképek a szerver lokális `/app/static/previews/` könyvtárába kerülnek.
- A UI (web/app) kizárólag ezeket tölti be a listázáskor, elkerülve a NAS terhelését.
3. **Vault (NAS - Hosszú távú tároló):**
- A feldolgozott, nagyfelbontású (max 1600px) WebP állomány átkerül a NAS-ra: `/mnt/nas/app_data/organizations/{id}/vault/`.
- A NAS-hoz csak akkor fordul a rendszer, ha a felhasználó kifejezetten a dokumentum nagy változatát kéri.
## 5. Discovery Bot Strategy
### 5.1 Prioritási Sorrend
A Botok az alábbi sorrendben pásztázzák az adatforrásokat:
1. **Land (Földi járművek):**
* Személyautók (Car), Motorok (Bike), Teherautók (Truck).
* Adatforrás: Márkakereskedői listák, Gyártói API-k.
2. **Infrastructure (Infrastruktúra):**
* Benzinkutak, Elektromos töltők (OpenChargeMap API).
* Ezek könnyen elérhető, statikus adatok.
3. **Services (Szervizek):**
* Google Maps API, Cégjegyzék adatok.
* Ezeket jelöli meg a rendszer "Unverified" (Bot-talált) státusszal.
### 5.2 Adatgazdagítás
A Bot nem csak a nevet keresi. Célzottan gyűjti:
* Nyitvatartási idők.
* Kapcsolattartói adatok (Email, Weboldal).
* Közösségi média linkek.
* *Szabály:* A Bot által hozott adat felülírható a "Service Hunt" során a felhasználó által (magasabb megbízhatóság).
## 6. Multi-Source Consensus Logic
A szervizek és szolgáltatók hitelességét nem csak az Admin, hanem a források száma határozza meg.
### 6.1 Bizalmi szintek (Confidence Score)
* **Score 1:** Egyetlen forrás (Bot vagy User). Státusz: `pending`.
* **Score 2:** Két független forrás megerősítése.
* **Score 3+:** Automatikus hitelesítés (`verified`). Nincs szükség emberi beavatkozásra.
### 6.2 Bot Adatforrások (Priority: Car & Bike)
A Botok az alábbi sorrendben dolgoznak:
1. Hivatalos gyártói oldalak (Márkaszervizek).
2. Szakmai adatbázisok (pl. Autóklub, Kamarák).
3. Google/Social media API-k.
## 4. Telephelyek (Locations) és Szervizpontok
Minden szolgáltató (Organization) több telephelyet tarthat fenn.
### 4.1 Kötelező Adatstruktúra
Minden telephely rögzítésekor az alábbi bontott címadatok kötelezőek:
- Irányítószám, Város, Közterület neve, Közterület típusa, Házszám.
- Opcionális: Helyrajzi szám (parcel_id) külterületi vagy HRSZ alapú azonosításhoz.
### 4.2 Validációs Folyamat
A rögzített címek automatikusan bekerülnek a Master Geo adatbázisba, építve a rendszer globális címjegyzékét.
## 5. Járművek és Költségek (MVP)
A járműadatok kezelése hibrid módon történik.
### 5.1 Jármű Katalógus
- A rendszer egy központi katalógust (`asset_catalog`) épít.
- Új rögzítéskor a rendszer először a katalógusból kínál fel opciókat (Dropdown).
- Ha a modell nem létezik, a rendszer automatikusan felveszi (Self-learning catalog).
### 5.2 Költségkövetés (TCO)
- Minden Asset-hez rögzíthető költség (`asset_costs`).
- Kötelező adatok: Kategória, Összeg, Dátum.
- Opcionális: Km óra állása (az amortizáció és szervizintervallum számításához).
## 2026.02.10 FRISSÍTÉS - ATOMIZÁLT ADATMODELL ÉS MODULÁRIS API
### 1. Adatbázis Szerkezet (A 4 Pillér)
A járművek kezelése "Single Responsibility" elv alapján 4 modulra bomlott:
1. **Identity (Asset):** Alapadatok (VIN, Rendszám, Tulajdonos).
2. **Catalog (AssetCatalog):** Gyári statikus adatok (Típus, Motor, Akku). Ezt a Robotok töltik.
3. **Telemetry (AssetTelemetry):** Változó állapot (KM óra, VQI minőség index, DBS vezetési stílus).
4. **Financials (AssetCost):** Pénzügyi tranzakciók 9 kategóriába sorolva (Fuel, Service, Tax, stb.).
### 2. Moduláris API Végpontok
A teljesítmény optimalizálása érdekében a \`Full Profile\` helyett 3 dedikált végpontot használunk:
- \`GET /api/v1/assets/{id}\`: Csak identitás és katalógus (Gyors nézet).
- \`GET /api/v1/assets/{id}/costs\`: Csak pénzügyi történet és grafikonok.
- \`GET /api/v1/assets/{id}/telemetry\`: Csak élő adatok (Dashboard).
*A javított AssetAssignment logika dokumentálása.*
```markdown
# 18. Asset & Fleet Management Specification
## 18.2. Asset Assignment Logic
A járművek és eszközök hozzárendelése a rendszer egyik legkritikusabb része.
### 18.2.1. Assignment Model (`AssetAssignment`)
Kapcsolatot teremt egy Jármű (`Asset`) és egy Szervezet (`Organization`) között.
- **asset_id**: UUID (Melyik jármű?)
- **organization_id**: Integer (Melyik cég használja?)
- **status**: Active / Released
- **Validáció:** Egy jármű egyszerre csak egy szervezetnél lehet `active` státuszban.
*(Megjegyzés: A v1.2.5 frissítés javította az ORM kapcsolatokat, így a lekérdezések most már közvetlenül elérik az `assignment.organization` objektumot.)*
## 4.0 Catalog 2022+ Strategy (Hybrid Mode)
A CarQueryAPI korlátai miatt 2022 utáni modelleknél a Robot 1 az alábbi hibrid logikát alkalmazza:
1. **API Ninjas & Auto-Data Sync:** Elsődleges technikai forrás.
2. **European Scraper Mode:** A mobile.de és autoscout24.hu portálok típusválasztóinak (meta-adatok) aratása a legfrissebb modellek és motorváltozatok rögzítéséhez.
## 6. Szerviz Logika és Intervallumok
A szervizkönyv nem csak eseménynapló, hanem előrejelző rendszer.
### 6.1 Karbantartási Terv (Maintenance Plan)
Az MDM-ben rögzített `specifications` tartalmazza a fődarabok szervizigényét:
- **Folyadékok:** Típus, mennyiség, csereperiódus (km/hónap).
- **Alkatrészek:** Gyári kódok és alternatívák (cross-reference).
- **Biztonság:** Időszakos vizsgák (érintésvédelem, emelőhátfal, hajó szemle).

View File

@@ -0,0 +1,154 @@
# 🛠️ 19_ADMIN_AND_PERMISSIONS_SPEC (v1.0)
## 1. Adminisztrátori Hierarchia és Területi Felosztás
A rendszer többszintű, régió-alapú jogosultságkezelést alkalmaz (**RBAC + Geographic Scope**).
| Szint | Megnevezés | Területi hatókör | Jogkörök jellege |
| :--- | :--- | :--- | :--- |
| **L0** | **SuperAdmin** | Globális (Összes ország) | Teljes hozzáférés, Rendszer-paraméterezés, Admin kinevezés. |
| **L1/A** | **Global Director** | Régiós (Több ország) | Országos vezetők felügyelete, aggregált statisztikák. |
| **L1/B** | **National Manager** | Országos (pl. HU) | Saját ország moderátorainak és adatainak teljes kezelése. |
| **L2** | **Staff (Mod/Supp/Fin)** | Lokális / Szakaszolt | Operatív feladatok (VIES, support jegyek, kifizetések). |
| **L3** | **Task Moderator** | Feladat-specifikus | Sablon alapú, korlátozott hozzáférés (pl. csak szerviz validálás). |
### Verseny Logika (Privacy Protection)
Az L1/B szintű vezetők látják más országok aggregált KPI mutatóit (statisztikai összehasonlítás), de **nincs betekintésük** a konkrét személyes vagy céges adatokba.
---
## 2. Jogosultságkezelés és Sablonok
- **Permissions Table:** Elemi jogosultságok atomi tárolása (pl. `approve_vies`, `modify_credits`).
- **Role Templates:** Előre definiált szerepkör-sablonok (pl. "Senior Financial - DE").
- **Regionális Izoláció:** Az adminisztrátorok alapértelmezetten csak a hozzájuk rendelt `ISO_country_code` alá tartozó rekordokat módosíthatják.
---
## 3. Biztonság és "Kill-Switch" Protokoll
### 3.1. Hitelesítés
- **MFA/2FA:** A második bejelentkezéstől kezdve kötelező a **TOTP** (pl. Google Authenticator) használata.
- **Social Auth:** Engedélyezett, de nem váltja ki a kötelező 2FA-t.
### 3.2. Anomaly Score (Fekete Doboz)
- **Audit Logs:** Minden kattintást és módosítást JSON formátumban rögzítünk.
- **Automatikus Felfüggesztés:** Kritikus viselkedés (pl. tömeges adattörlés) esetén a rendszer automatikusan zárolja az admin fiókot és riasztást küld a felette álló szintnek.
- **SuperAdmin Recovery:** Csak egyedi **Offline Kulccsal** és előre regisztrált fizikai eszközzel lehetséges.
### 3.3. State Snapshot (Visszaállíthatóság)
Minden módosítás előtt a rendszer menti a rekord aktuális állapotát. Az L0/L1 szintű adminisztrátorok egy gombnyomással visszaállíthatják az eredeti adatokat károkozás vagy hiba esetén.
---
## 4. Értesítési Engine és Lejárati Figyelmeztetések
A rendszer proaktív módon értesíti az érintetteket a kritikus dátumok előtt (Push, Email, Mini-CRM).
### 4.1. Előfizetési Értesítések
- **Hatókör:** Lite+, VIP, VIP+, Corporate csomagok.
- **Ütemezés:** Automatikus figyelmeztetés **30, 15, 7 és 1** nappal a lejárati dátum előtt.
### 4.2. Technikai és Jármű Okmányok
A rendszer figyeli és jelzi az alábbiak lejáratát:
- **Forgalmi engedély:** Műszaki vizsga érvényessége.
- **Biztosítás:** KGFB és CASCO fordulónapok.
- **Lízing:** Szerződéses futamidő vége.
- **Specialty:** Hajólevél, lajstrom, emelőgép vizsga stb.
---
## 5. CRM és Szervezeti Kontaktok
Minden szervezet (Organization) esetében kötelező legalább egy **Adminisztratív Kontakt** megadása.
- **Multi-Role:** Egy Person több szervezetben is lehet `owner` vagy `fleet_manager`.
- **CRM Mezők:** Név, beosztás, közvetlen elérhetőség (Pénzügyi felelős / Operatív felelős elkülönítve).
---
## 6. Corporate Onboarding és Validáció
A cégek hitelesítése három szinten történik:
1. **Tier 1 (Automata):** Adószám alapú validáció (VIES / Nemzeti API).
2. **Tier 2 (AI/OCR):** Feltöltött dokumentumok (pl. Alapító okirat) intelligens elemzése.
3. **Tier 3 (Human):** L2/L3 szintű adminisztrátori jóváhagyás, ha az automatika bizonytalan.
---
## 7. B2B Jutalék és MLM Korlátok
- **Direct Referral:** Szervezet által meghívott másik szervezet esetén kizárólag az **1. szintű (L1)** jutalék jár.
- **MLM Kivétel:** A szervezetek nem építhetnek többszintű hálózatot; a kifizetés minden esetben fix üzleti megállapodás vagy egyedi szerződés alapján történik.
- **Adminisztrátori Meghívók:** Csak manuálisan generálhatók, és szigorúan **24 órás** lejárati idővel rendelkeznek.
## 6. Dinamikus Szabálymotor (Rule Engine)
A rendszer minden fontos paramétere a `data.system_settings` táblában tárolt JSON objektumokból származik.
### 6.1 Módosítási protokoll
* Az Admin felületen módosított értékek (pl. Kredit jutalom összege) azonnal érvénybe lépnek.
* A módosítás után a Backend Cache-t (`ConfigService`) üríteni kell.
### 6.2 Paraméterezhető modulok
* **Service Hunt:** Távolságok, XP/Kredit szorzók.
* **Fraud Protection:** Strike limitek, kitiltási idők.
* **Billing:** EUR/HUF/USD váltószámok, csomagárak, jármű-slot árak.
## 2026.02.10 FRISSÍTÉS - HIERARCHIKUS RBAC RENDSZER
### 1. Rang-alapú Jogosultság (Rank System)
A rendszer a \`system_parameters\` táblában tárolt \`RBAC_MASTER_CONFIG\` JSON alapján működik.
- **SUPERADMIN (Rank 100):** Globális hatókör, mindent lát.
- **COUNTRY_ADMIN (Rank 80):** Országos felelős.
- **REGION_ADMIN (Rank 60):** Területi vezető (Manage Moderators).
- **MODERATOR (Rank 40):** Adatvalidátor.
- **SALES (Rank 20):** Üzletkötő (Csak saját partnerek).
- **USER (Rank 10):** Végfelhasználó.
### 2. Scope (Hatókör) Védelem
Minden műveletnél ellenőrizzük a \`scope_id\` egyezését:
- Ha a felhasználó \`scope_level = 'region'\`, akkor csak olyan adatot szerkeszthet, ami ugyanahhoz a régióhoz tartozik.
- Kivétel: Impersonation (Megszemélyesítés) - Audit loggal védve.
## 1. Gamification Adminisztráció
A `data.system_parameters` táblában a `GAMIFICATION_MASTER_CONFIG` kulcs alatt az alábbiak állíthatóak:
- `xp_logic`: `base_xp`, `exponent`.
- `penalty_thresholds`: A szintekhez tartozó büntetőpont határok.
- `level_up_rewards`: 10-es szintenkénti Kredit jutalom mértéke.
- `blocked_roles`: [superadmin, service_bot].
- `auto_convert_social`: True/False.
## 2. Gamification Konfiguráció (JSON Schema)
A `GAMIFICATION_MASTER_CONFIG` struktúrája:
- `xp_logic`: Alap XP és kitevő a nehezedő szintezéshez.
- `penalty_logic`: Küszöbértékek, szorzók és ledolgozási ráta.
- `conversion_logic`: Social-to-Credit váltási arány.
- `level_rewards`: Szintlépési bónuszok mértéke.
## 19.1. SuperAdmin Capabilities
A `rank: 100` szintű felhasználó (SuperAdmin) az egyetlen, aki:
1. **Translation Sync:** Írási joga van a szerver fájlrendszerére a `/api/v1/admin/translations/sync` végponton keresztül.
2. **Sentinel Override:** Felülbírálhatja az automatikus biztonsági zárolásokat.
## 19.2. Admin API Endpoints
- `POST /admin/translations/sync`:
- **Trigger:** Manuális (Gombnyomás a Dashboardon).
- **Action:** `data.translations` -> `static/locales/*.json`.
- **Permission:** SuperAdmin ONLY.
## 5. Security & Audit Logging
A rendszer két szinten naplózza az eseményeket:
### 5.1 Operational Log (Üzemi Napló)
* **Cél:** Hibakeresés, User Activity követés.
* **Tartalom:** Jármű rögzítés, Adatjavítás, Keresés.
* **Hozzáférés:** Moderátor szinttől felfelé.
### 5.2 Security Audit Log (Biztonsági Napló)
* **Cél:** Visszaélések megelőzése, Jogosultságok védelme.
* **Tartalom:** Rang emelés (Role Change), Kredit manuális jóváírása, VIP státusz adása, Admin belépés.
* **Hozzáférés:** Csak Superadmin és Country Admin (Szigorított).
### 5.3 The "Four-Eyes" Principle (4-Szem Elv)
Kritikus műveletek (pl. egy User `is_vip` státuszának kézi átállítása vagy `penalty_points` törlése) esetén a rendszer:
1. Rögzíti a kérést a `security_audit_logs`-ban.
2. A státusz "Pending" marad.
3. A változás **csak akkor lép életbe**, ha egy MÁSIK Adminisztrátor jóváhagyja azt (`confirmed_by_id` kitöltése).
4. Szuperadmin esetén a `is_critical` flag aktiválódik, és azonnali riasztás megy a többi adminnak.

View File

@@ -0,0 +1,85 @@
20. SERVICE FINDER & SPECIALIZED MARKETPLACE (TRUST ENGINE)
20.1 Szerviz Identitás és Szpecializációs Taxonómia
Minden szolgáltatói pont (szerviz, kút, étterem) egy Organization (org_type='service'), de mély szűrési attribútumokkal rendelkezik.
Fő kategóriák: Repair (Javítás), Fuel (Üzemanyag), Food (Vendéglátás), Safety (Mentés/Vizsga).
Mély Szpecializáció (Deep Expertise):
A rendszer ExpertiseTag-eket használ (pl. bmw_gs_adventure_specialist, boat_transport, ev_charging_fast, truck_repair).
A keresőmotor a jármű típusa (AssetCatalog) és a bejelentett hiba/igény alapján párosítja a specialistákat.
20.2 Többszintű Validációs Mátrix (Trust Score)
A szerviz adatlapjának hitelessége egy 0-100% közötti skálán mozog, több forrásból táplálkozva:
Robot Discovery (30%): A Robot 2 (Service Hunter) találta meg (nyilvános adatok, cégjegyzék).
First User Entry (50%): Az első felhasználó rögzítette manuálisan.
Crowd Validation (User 2-5, +10% alkalmanként): További felhasználók megerősítették az adatokat (Gamification XP jár érte).
Admin Approval (100%): A belső moderátorok manuálisan leellenőrizték és "Verified" státuszba tették.
AI OCR Validation: Ha egy felhasználó számlát tölt fel egy adott szerviztől, a Robot 2 (OCR) automatikusan validálja a szerviz létezését és adatait (státusz frissítés).
20.3 Geo-Keresés és Rangsorolási Logika (PostGIS)
A keresés alapja a felhasználó vagy a jármű aktuális GPS koordinátája.
Keresési algoritmus:
Szűrés: PostGIS ST_DWithin (távolság alapú) + Szpecializáció Match.
Rangsorolás (Szkópolt logika):
Premium User: 1. Preferált szervizek, 2. Legmagasabb Trust Score, 3. Hirdetők, 4. Útvonaltervezés szerinti valós távolság.
Free User: 1. Hirdetők, 2. Légvonalbeli távolság, 3. Trust Score.
Útvonaltervezés (Premium): Külső motor (pl. OSRM vagy GraphHopper) integráció a pontos elérési időhöz.
## 3.0 Specialization & Filtering (Bentley Logic)
A keresőmotor prioritási rendszere:
1. **Explicit Specialist:** Specializációs tag-ek alapján (pl. brand: Bentley).
2. **General Service:** Univerzális javítók, ahol nincs kizáró ok.
3. **Exclusion Logic:** Ha a keresett márka Bentley, de a szerviz specializációja csak "BMW", a találat tiltva van.
## 4.0 Trust Score Multipliers
- **Economic Stability:** 3+ év nyereséges működés (+20 pont).
- **Physical Validation:** Google Street View / Robot Photo Verification (+15 pont).
- **Verified Staff:** Ha a szerelőregisztrációk száma > 2 (+10 pont).
# 20. Service Finder & Trust Engine
## Pre-searching (Silent Service Hunter) Logika
A cél a szervizek felderítése API költségek nélkül, kereszt-ellenőrzött forrásokból.
### 1. Felderítési Fázis (Hunter A)
Többmotoros keresés (DuckDuckGo Lite, Bing, Yandex, OSM) segítségével:
- **Kulcsszó-dorking:** `site:facebook.com "Dunakeszi" "szerviz"`.
- **Informális adatok:** Fórumok, blogok és helyi közösségi posztok elemzése.
- **TEAOR Mátrix:** Az e-Cégközlöny napi frissítéseinek szűrése (4520, 4540, 2920 kódok).
### 2. Validációs Pontrendszer (Trust Engine)
Minden talált entitás pontszámot kap:
- **+40 pont:** Aktív adószám és megfelelő TEAOR (4520/4540).
- **+20 pont:** Friss digitális jelenlét (Facebook/Instagram poszt < 30 nap).
- **+20 pont:** Fizikailag validált cím (OSM vagy lakossági megerősítés).
- **+10 pont:** Hívható, formátum-helyes telefonszám.
### 3. Döntési Szintek
- **80+ pont:** Ellenőrzött (Verified) - Automatikus publikálás.
- **40-79 pont:** Moderációra vár - Manuális adminisztrátori jóváhagyás szükséges.
- **<40 pont:** Elutasítva/Inaktív - Marad a Stage táblában.
## 6. Szerviz Logika és Intervallumok
A szervizkönyv nem csak eseménynapló, hanem előrejelző rendszer.
### 6.1 Karbantartási Terv (Maintenance Plan)
Az MDM-ben rögzített `specifications` tartalmazza a fődarabok szervizigényét:
- **Folyadékok:** Típus, mennyiség, csereperiódus (km/hónap).
- **Alkatrészek:** Gyári kódok és alternatívák (cross-reference).
- **Biztonság:** Időszakos vizsgák (érintésvédelem, emelőhátfal, hajó szemle).

View File

@@ -0,0 +1,57 @@
21.1 Adatmélység és Idővonal
A rendszer célja a teljes EU-s járműpark lefedése a 2000-es évjárattól kezdődően.
Hierarchia: Make -> Model -> Generation -> Engine Variant -> Trim Level.
Kezdeti adatok: Az első fázisban a robot a 4 alapszintet tölti (Márka, Típus, Évjárat, Motor), majd iteratívan mélyíti a factory_data JSONB mezőt (olajmennyiség, nyomaték, guminyomás stb.).
# 21. Deep Asset Catalog (MDM)
Ez a dokumentum írja le a járművek technikai mélységét kategóriánként.
## 1. Kategória Specifikus Adatok (JSONB Schemas)
- **Személyautó:** Klíma fajták (digit, többzónás), hajtáslánc, ADAS rendszerek.
- **Teherautó/Kamion:** Tengelyek száma, fülke típusa, retarder típusok, menetíró.
- **Motorkerékpár:** Munkaütem, hűtés módja, táskák/dobozok konfigurációja.
- **Hajó:** Merülés, vízkiszorítás, orrsugárkormány, navigációs elektronika.
## 2. Numerikus Indexelés
A gyors keresés érdekében a következő mezők fix oszlopok:
- `engine_capacity` (ccm)
- `power_kw` (kW)
- `weight_kg` (Súly)
- `year_from / year_to` (Gyártási időszak)
# 21. Deep Asset Catalog & Master Data Management (MDM)
Ez a modul a rendszer "agyát" képezi, ahol a zajos külső forrásokból származó adatok tiszta, dúsított és egyedi járműspecifikációkká alakulnak.
## 21.1 Adatmodell (vehicle_model_definitions)
A katalógus nem egyszerűen rekordokat tárol, hanem egy Master-Slave viszonyrendszert valósít meg a duplikációk elkerülése érdekében.
### Kulcsfontosságú mezők:
- `technical_code`: Egyedi gyári azonosító (pl. PC44, ZX600R). Elsődleges kulcs a deduplikációhoz.
- `parent_id`: Önhivatkozás. Ha egy rekord duplikátum, itt mutat a Master (eredeti) rekordra.
- `synonyms` (JSONB): Alternatív elnevezések gyűjteménye (pl. "Tracer 9", "MT-09 Tracer") a kereshetőség javítására.
- `year_from / year_to`: Gyártási intervallumok a generációk megkülönböztetéséhez.
- `specifications` (JSONB): Műszaki adatok (olajmennyiség, gyertya típus, hűtőfolyadék).
## 21.2 Master-Merge Logika
A rendszer az "Igazság Hierarchiáját" követi az adatok mentésekor:
1. **Hatósági Adat (RDW):** CCM és teljesítmény (kW) forrása.
2. **AI Adatbányászat (Gemini + Google Search):** Technikai kódok, évjáratok és szervizadatok forrása.
3. **Manuális felülbírálat:** Legmagasabb prioritású `status = 'manual_check'`.
### Összefésülési szabály (Deduplikáció):
A Robot 2 csak akkor olvaszt össze két rekordot, ha:
- A `make` (gyártó) egyezik.
- A `technical_code` azonos és nem 'N/A'.
- A `engine_capacity` (CCM) megegyezik.
## 21.3 Állapotgépek (Status Lifecycle)
- `unverified`: Alapállapot, csak nyers adatok.
- `ai_enriched`: Sikeresen dúsított, hitelesített Master rekord.
- `duplicate`: Felismert másolat, amely egy Master rekordhoz van láncolva.

View File

@@ -0,0 +1,164 @@
22.1 Robot 1: Catalog Scout (The Library)
Feladat: Folyamatos, háttérben futó adatgyűjtés (EU-szintű járműspecifikációk).
Működés: Web-crawling és technikai adatbázisok szinkronizációja. Nem áll le, folyamatosan frissíti a vehicle_catalog táblát.
22.2 Robot 2: Service Hunter & OCR (The Auditor)
Service Hunting: EU-szintű térképadatok és szaknévsorok (Google, OSM, Yellow Pages) alapján szervizpontok felderítése.
OCR Validation: Felhasználói dokumentumok (forgalmi, számla) feldolgozása. Ha az OCR szervizadatot talál, keresztellenőrzi a data.organizations táblával.
22.3 Robot 3: RobotScout (The Detective)
Feladat: Egyedi jármű (Asset) validáció. VIN alapú lekérdezés és factory_data összevetés a felhasználói adatokkal.
23. SERVICE ONBOARDING & THREE-STEP FLOW
A szolgáltatói (szerviz) regisztráció integrálódik az alap onboarding folyamatba:
Step 1 (Lite): Alap felhasználói fiók létrehozása.
Step 2 (KYC & Org): Személy azonosítása, Wallet nyitása és az Alapértelmezett Szervezet (Privát flotta) létrehozása.
Step 3 (Service Setup - Opcionális): Ha a felhasználó szolgáltató is, itt rögzíti a Szerviz Profilját.
Létrejön egy második Organization rekord (org_type='service').
Hozzárendelésre kerülnek az ExpertiseTag-ek (Szakmai szempontok).
GPS koordináták rögzítése (PostGIS).
24. ROBOT SCOUT & CATALOG STRATEGY (HU -> EU)
A Robot 1 (Catalog Filler) egy rétegelt feltöltési stratégiát követ:
Layer 1 (Basic Identity): Márka, Típus, Évjárat, Motor (HU piac fókusz).
Layer 2 (Technical Depth): Folyadékmennyiségek, kerékméretek, meghúzási nyomatékok.
Layer 3 (Service Relation): Melyik alkatrész/szerviz igény kapcsolódik az adott típushoz.
API Strategy
24. Robot Scout Adatforrások:
Járművek: A robot a CarQuery API és a NHTSA vPIC API kombinációját használja a 2000 utáni EU-s modellek feltöltéséhez. A ciklusidő: 1 év/5 perc.
Szervizek: Az OSM Overpass API az elsődleges forrás a lokációkhoz. A validációt a Robot 2 végzi a Google Places adatokkal való összevetéssel (Trust Engine).
Motorok: Külön prioritást élveznek a prémium márkák (BMW, KTM, Honda) szakszervizei a "Specialization Tag" rendszerben.
📘 MASTER BOOK KIEGÉSZÍTÉS (v2.4) - 2026.02.13
20.4 Szerviz Életciklus és Automatikus Kivezetés (Soft-Delete)
A Marketplace tisztaságát az automatikus inaktiválási folyamat garantálja:
Státuszok:
ghost: Bot által talált, nem hitelesített rekord.
active: Működő, publikus szerviz.
flagged: Gyanús (pl. bezártnak jelentett), felülvizsgálatra vár.
inactive: Megszűnt vagy inaktivált szerviz (Soft-deleted).
Audit ciklus: A Robot 2 (Auditor) 90 naponta minden active szervizt keresztellenőriz külső forrásokkal (OSM/Google). Ha egy hely "Permanently Closed", a robot átállítja: is_active = False és status = 'inactive'.
22.4 Robot Orchestration (Koordináció)
A robotok az adatbázist használják "jelzőtáblának", így elkerülik az ütközéseket:
Robot 1 (Catalog Scout): Kizárólag a data.vehicle_catalog táblát írja.
Robot 2 (Hunter/Auditor): * A Hunter csak olyan helyeket rögzít, amik még nincsenek az organizations táblában.
Az Auditor csak az is_active=True rekordokat vizsgálja felül.
Robot 3 (OCR/Detective): Dokumentum-alapú validálást végez. Ha az OCR egy inactive szervizt talál egy friss számlán, nem írja felül a robotot, hanem flagged státuszba teszi a szervizt manuális ellenőrzésre ("Lehet, hogy mégis kinyitott?").
20.4 Szerviz Állapotok és Láthatóság
ghost (Alapértelmezett): Bot által talált rekord.
Keresés: Megjelenik, de kötelező "Nem megerősített szolgáltató" jelzéssel ellátni.
Gamification: Teljesen nyitott. A felhasználók értékelhetik, fotózhatják. Minden ilyen interakció növeli a trust_score-t.
active: Megerősített szolgáltató (Admin vagy magas Trust Score alapján).
flagged: Felülvizsgálat alatt (pl. ellentmondásos adatok).
inactive: Igazoltan megszűnt. Csak ez az állapot rejtett a keresés elől.
## 2.0 Robot 2 (The Detective)
A Robot 2 három fázisban dolgozik:
- **Phase 1 (Discovery):** OSM/Overpass alapú koordináta és név rögzítés.
- **Phase 2 (Deep Enrichment):** Google Places, Web Scraping (Email, telefon, tulajdonos neve).
- **Phase 3 (Financial Audit):** Nyilvános cégadatok (Árbevétel, létszám, adózott eredmény) éves szinkronizálása.
# 22. ROBOT ÖKOSZISZTÉMA
## Robot v1.9.2 (Ghost Commander) & n8n
A robotok és az n8n szoros együttműködésben dolgoznak.
### Funkciók
- **Auto-Heal:** A járműkatalógus hiányos (null) adatainak automatikus pótlása Holland (RDW) és US (NHTSA) forrásokból.
- **Ban-Detection:** Automatikus "Circuit Breaker" logika. Ha a CarQuery vagy más forrás tilt, a robot átvált "Silent Mode"-ba.
- **Event Hunter:** n8n workflow figyeli a motoros/autós találkozókat és eseményeket, majd összeköti őket a helyi szervizpartnerekkel.
- **Gamification Link:** A robot regisztrálja a felhasználói validálásokat és kiosztja a pontokat/krediteket.
# 22. Robot Ökoszisztéma
A rendszer automatizált adatgyűjtő és dúsító ágensei.
## 1. Model Enrichment Robot (Dúsító)
- **Működés:** Hajnali 01:00 - 05:00 között.
- **Logika:** 1. Új `unverified` kódok keresése.
2. RDW API lekérdezés (Holland alapok).
3. AI (Gemini) Deep Scraping: Marketing név, felszereltségi lista, szervizintervallumok kinyerése.
4. Validálás a JSON Sémák alapján.
5. Master státusz beállítása.
## 2. Resource Management
A robot figyeli a szerver terhelését. Ha a CPU > 70%, az AI lekérdezéseket lassítja (throttle), hogy ne zavarja a hajnali biztonsági mentéseket.
# 22. Robot Ökoszisztéma Specifikáció
A rendszer autonóm robotok hálózatából áll, amelyek egymásra épülve tisztítják és dúsítják a flottaszintű adatokat.
## 22.1 Robot 1: Catalog Scraper (RDW)
- **Feladata:** Külső API-k (pl. Holland RDW) folyamatos monitorozása és új járművek importálása.
- **Működés:** Nyers adatokat hoz létre `unverified` státusszal.
## 22.2 Robot 2: Technical Enricher & Master Merge (v1.2.6)
Ez a legkomplexebb modul, amely AI-t és webes keresést használ.
### Főbb képességek:
- **Google Search Integration (RAG):** Ha az AI nem ismeri a modellkódot, valós időben keres a gyártói oldalakon.
- **Safe-Merge Technológia:** Megakadályozza a technikai kód nélküli rekordok véletlen összevonását (`N/A-{id}` generálásával).
- **Atomi tranzakciókezelés:** Minden mentés külön tranzakció, így a hiba nem szakítja meg a tömeges feldolgozást.
### Működési folyamat:
1. Rekord kiválasztása (`status = unverified`).
2. RDW kiegészítő adatok lekérése.
3. Gemini 2.0 Flash meghívása keresőeszközzel.
4. JSON parseolás és kód-validáció.
5. Deduplikáció ellenőrzése és mentés.
## 22.3 Robot 3: OCR & Document AI
- **Feladata:** Feltöltött okmányok, számlák és kilométeróra állások felismerése.
- **Technológia:** Multimodális Gemini 2.0 elemzés.
- **Kimenet:** Strukturált JSON, amely azonnal validálható a katalógus (R2) adataival.
## 22.4 Robot 4: Service Hunter (Tervezett)
- **Cél:** A dúsított technikai adatok alapján szervizpartnerek és árak keresése.
- **Input:** Robot 2 által generált szerviz-specifikációk (olaj típus, mennyiség).
## 22.5 Robot Monitoring & Operáció
A robotok állapotát nem csak SQL-ben, hanem az n8n Dashboardon és a logok szintjén is követjük.
- **Hibakezelés:** Automatikus visszalépés és ideiglenes kódgenerálás (`RESET-`, `UNKNOWN-`) az adatbázis kényszerek (Unique, Not Null) betartása érdekében.

View File

@@ -0,0 +1,24 @@
# 🏢 23_BRANCH_AND_LOCATION_SPEC (v1.0)
## 1. Telephely (Branch) Logika
A rendszer alapelve, hogy a jogi entitás (Organization) és a fizikai helyszín (Branch) elválik egymástól.
### 1.1 Struktúra
- **Organization:** Jogi egység (Adószám, név).
- **Branch (Telephely):** Konkrét fizikai pont, ahol a szolgáltatás zajlik vagy ahol a flotta állomásozik.
- **Main Branch:** Minden szervezetnek van legalább egy "Fő" telephelye (`is_main=True`).
### 1.2 Kapcsolatok
- **Szerviz:** Az értékelések és a nyitvatartás a `Branch`-hez kötődik.
- **Flotta:** A jármű hozzárendelés (`AssetAssignment`) opcionálisan tartalmaz egy `branch_id`-t, meghatározva a jármű fizikai helyét.
## 2. Részletes Címkezelés
A címeket atomizált formában tároljuk a `data.branches` és `data.addresses` táblákban:
- `postal_code`, `city`
- `street_name`, `street_type` (utca, út, tér)
- `house_number`, `stairwell`, `floor`, `door`
- `hrsz` (Helyrajzi szám külterületi vagy speciális telkekhez)
## 3. Életút Követés (Dual Twin)
- **Törlés:** A telephelyek "Soft Delete" (`is_deleted`) alá esnek.
- **Áthelyezés:** Ha egy telephely megszűnik, a hozzárendelt járművek automatikusan visszaállnak a Szervezet "Main Branch" helyszínére.

View File

@@ -0,0 +1,274 @@
# ROLE: Senior Backend Architect & Security Engineer
# PROJECT: Service Finder Ecosystem (FastAPI, SQLAlchemy Async, PostgreSQL, Docker)
## CONTEXT & ARCHITECTURE
A rendszer egy magas biztonságú, mikroszolgáltatás-jellegű monolit (Modular Monolith). A biztonsági és üzleti logika szigorúan elkülönül.
## CORE LOGIC RULES (NON-NEGOTIABLE)
1. IDENTITY & ONBOARDING (Twin-Model):
- **Step 1 (Registration/Social):** Csak `User` és `Person` rekord jön létre.
Státusz: `is_active = False`.
Folder Slug: `NULL`.
Organization/Wallet: NEM jön létre.
Service: `SocialAuthService` vagy `AuthService.register_lite`.
**Step 2 (KYC/Activation):** Itt történik az üzleti aktiválás.
- Státusz váltás: `is_active = True`.
- Slug Generálás: `generate_secure_slug(12)` a Usernek és az új Organization-nek.
- Shadow Identity: Mindig ellenőrizni kell, létezik-e már a `Person` (név, szül. adat, anyja neve alapján).
- Service: `AuthService.complete_kyc`.
2. SECURITY & AUTH:
- **Dual Token:** Mindig Access és Refresh tokent adunk vissza (`create_tokens`).
- **Dynamic Config:** SOHA ne használj hardcoded értékeket rankokra vagy limitekre. Mindig a `config.get_setting` (DB-ből: `data.system_parameters`) használandó.
- **RBAC:** A jogosultságot a `deps.check_min_rank` ellenőrzi dinamikusan.
- **Resource Access:** Mindig ellenőrizni kell a `scope_id`-t (Slug) a `deps.check_resource_access`-szel.
3. DATABASE & MODELS:
- Schema: Minden tábla a `data` sémában van (`__table_args__ = {"schema": "data"}`).
- Migráció: Adatbázis módosítás CSAK Alembic-kel történhet.
## FILE STRUCTURE & RESPONSIBILITIES
- `app/api/deps.py`: Auth függőségek, Active User check, Scope check.
- `app/services/auth_service.py`: Step 2 logika, Slug generálás, Soft Delete.
- `app/services/social_auth_service.py`: Csak Step 1 logika (Google login).
- `app/core/config.py`: Dinamikus beállítások olvasása a DB-ből.
- `app/models/system_config.py`: A `SystemParameter` modell definíciója.
## CODING STANDARDS
- Minden aszinkron (`async/await`).
- SOHA ne rövidíts kódot "..."-al, mindig a teljes, működő fájlt add vissza.
- Type hint-ek (typing) kötelezőek.
- Logolás (`logger`) minden kritikus ponton kötelező (Security Service hívással).
## CURRENT STATE (STARTING POINT)
A rendszer Security Hardening v2 fázisa kész. A `system_parameters` tábla létezik, a User/Org táblákban ott a `folder_slug`. A kód ezekre a mezőkre támaszkodik.
🧬 SERVICE FINDER - UNIVERSAL SYSTEM PROMPT (v1.2)
ROLE: Senior Technical Product Manager & Lead System Architect PROJECT: Service Finder - Traffic Ecosystem SuperApp SOURCE OF TRUTH: Grand Master Book (0019) + 2026.02.10 System Updates CONTEXT: Monolit-moduláris refaktorálás (FastAPI, Vue3, Postgres 15).
1. VÍZIÓ ÉS KONTEXTUS (00, 01)
Nem egy egyszerű nyilvántartó rendszert építünk, hanem egy Digital Twin (Digitális Iker) alapú ökoszisztémát.
Core Philosophy: "A jármű örök, a tulajdonos vándor." (Vehicle-Centric Architecture).
Pillére:
Core Fleet: Életút és TCO követés.
Marketplace: Szervizkereső és időpontfoglalás.
Trust Engine: Bizonyíték alapú előélet (OCR, Fotó).
Economy: Kredit és Gamification.
2. TECHNOLÓGIAI STACK ÉS INFRA (02, 03, 04, 08)
Frontend: Vue 3 (Composition API) + Vite + Tailwind CSS + Pinia. Dumb Frontend elv.
Backend: Python 3.12 + FastAPI. Szigorú Pydantic validáció.
Adatbázis: PostgreSQL 15. Két séma: data (üzleti), public (rendszer).
Storage: MinIO (S3 kompatibilis) titkosított dokumentumokhoz.
Hálózat: Internal Net (shared_db_net) zárt. Public Net: csak 80/443 (NPM Proxy).
Config: Minden konfiguráció .env fájlból vagy data.system_parameters táblából jön. Hardkódolás TILOS.
3. IDENTITÁS ÉS ONBOARDING (05, 07)
Szétválasztás:
USER: Technikai fiók (Email/Pass).
PERSON: Valós jogi személy (Okmányok, KYC). Nem törölhető.
Folyamat: Kétlépcsős (2-Step) Onboarding.
Lite: Csak User létrehozása (is_active=False).
KYC: Okmányok feltöltése -> Person létrehozása -> Wallet nyitása -> Aktiválás (Atomi tranzakció).
4. ATOMIZÁLT ASSET MODELL (18) [FRISSÍTVE 2026.02.10]
A járművek kezelése 4 elkülönített modulra bomlott (SRP elv):
Identity (Asset): VIN, Rendszám, Tulajdonos (AssetAssignment).
Catalog (AssetCatalog): Gyári statikus adatok. Robot Scout tölti.
Telemetry (AssetTelemetry): Változó állapot (KM, VQI, DBS).
Financials (AssetCost): Pénzügyi tranzakciók 9 kategóriában.
API Design: 3 külön végpont (/assets/{id}, /assets/{id}/costs, /assets/{id}/telemetry).
5. HIERARCHIKUS JOGOSULTSÁG (RBAC & SCOPE) (09, 19) [FRISSÍTVE 2026.02.10]
A rendszer egy Rang- és Hatókör-alapú mátrixot használ (RBAC_MASTER_CONFIG JSON).
Szintek (Rank):
SUPERADMIN (100): Globális (L0).
COUNTRY_ADMIN (80): Országos (L1).
REGION_ADMIN (60): Területi (L1/B).
MODERATOR (40): Adatvalidátor (L2).
SALES (20): Üzletkötő (L3).
USER (10): Végfelhasználó.
Védelem: Middleware szinten: Token Role >= Required Rank ÉS User Scope == Resource Scope.
Adattábla: User tábla új mezői: scope_level, scope_id, custom_permissions.
6. GAMIFICATION ÉS ECONOMY (10, 11) [FRISSÍTVE 2026.02.10]
XP (Tapasztalat): Végleges szintlépés (BaseXP×Level1.5). Nem csökken.
Social Points: Szezonális, resetelhető pontok.
Kredit: Valuta, Social pontokból váltható.
Service: GamificationService és PointsLedger (auditált naplózás).
Billing: Többvalutás rendszer (HUF/EUR tárolás).
7. ÜZEMELTETÉS ÉS ADATINTEGRITÁS (06, 12, 16, 17)
Soft Delete: Nincs DELETE parancs, csak is_deleted vagy is_active flag.
Audit: Kritikus műveletek (pl. Impersonation) előtt/után állapotmentés az audit_logs táblába.
Enum: Postgres Enum típusok mindig kisbetűsek (pl. role='user').
Migráció: Minden DB módosításhoz SQL script + Alembic migráció kötelező.
🚀 KÖVETKEZŐ LÉPÉSEK (ACTION PLAN - 2026.02.11)
A rendszer magja (Asset, RBAC, Gamification) stabil. A következő fejlesztési ciklus célja a biztonsági réteg és az automatizáció bekapcsolása.
🔴 PRIORITY 1: SMART AUTH TOKEN (Security)
Feladat: A Login (/auth/login) folyamat átírása.
Cél: A generált JWT Token tartalmazza a DB-ből frissen kinyert RBAC adatokat: role, rank, scope_level, scope_id.
Miért: Hogy a Middleware DB-lekérdezés nélkül tudjon dönteni a jogosultságról.
File: backend/app/core/security.py, backend/app/api/v1/endpoints/auth.py.
🟠 PRIORITY 2: IMPERSONATION ENGINE (Ops)
Feladat: POST /api/v1/admin/impersonate végpont.
Logika: SuperAdmin token cseréje egy cél-felhasználó tokenjére (időkorlátos).
Biztonság: Szigorú naplózás az audit_logs táblába (reason kötelező).
🟡 PRIORITY 3: ROBOT SCOUT (Automation)
Feladat: Háttérfolyamat (Worker) indítása create_asset után.
Logika: VIN alapján külső API / Mock adatbázis lekérdezése -> AssetCatalog.factory_data feltöltése.
# 📘 SERVICE FINDER - MASTER ARCHITECT SYSTEM INSTRUCTIONS
ROLE: Senior Technical Product Manager & System Architect PROJECT: Service Finder - Traffic Ecosystem SuperApp 2.0 CONTEXT: Monolit-moduláris refaktorálás (FastAPI backend, Vue3 frontend, PostgreSQL 15). SSoT: Grand Master Book (v1.4).
🎯 ALAPVETŐ MŰKÖDÉSI PROTOKOLL
Zéró Találgatás: Tilos feltételezésekre alapozva kódot írni. Ha egy összefüggés (adatbázis-program-fájlrendszer) nem egyértelmű, pontosító kérdéseket kell feltenni.
Fájlbekérési Kényszer: Minden módosítás vagy hibajavítás előtt kötelező bekérni az érintett fájlok aktuális, teljes tartalmát. Tilos korábbi logikát törölni; a meglévő kódrészeket integrálni kell a tiszta kód elvei szerint.
Teljes Kódközlés: Mindig a teljes, javított állományt kell visszaadni, nem csak kódrészleteket.
Gitea & Changelog: Csak működő, tesztelt verziók után generálj Git commit üzenetet és frissítsd a Changelog.md fájlt (.md formátumban).
🏗️ ARCHITEKTURÁLIS ÉS ÜZLETI LOGIKA
Identity Strategy: Szigorú elválasztás a technikai User (fiók) és a valós Person (identitás) között. A Person nem törölhető (Soft Delete). Újraregisztrációkor a KYC adatok alapján kötelező a korábbi person_id összekötése.
Kétlépcsős Onboarding: * Step 1 (Lite): is_active = False, csak technikai User jön létre.
Step 2 (KYC/Aktiválás): Atomi tranzakcióban: Person rögzítése, Wallet nyitása, Private Org létrehozása, aktiválás.
Economy & Dynamic Config: * A 10-5-2%-os jutalék és minden üzleti változó (pl. auth.reward_days) kizárólag a data.system_settings táblából jöhet. Tilos beégetett (hardcoded) változók használata.
Minden költséget helyi pénznemben és EUR-ban is tárolni kell (CostEUR=CostLocal⋅ExchangeRate).
Admin Hierarchy & Security: L0 (SuperAdmin) -> L3 szintek közötti jogosultságkezelés. Regionális izoláció alkalmazása: az adminok csak a hozzájuk rendelt country_code adatait láthatják.
🗄️ ADATBÁZIS ÉS SQL IRÁNYELVEK
Séma: Üzleti logika a data, rendszeradatok a public sémában.
Enumok: A Postgres Enum típusok miatt minden szerepkört és státuszt kényszerített kisbetűvel kell kezelni (role="user").
Migráció: Minden adatbázis-módosításhoz pgAdmin felületen futtatható SQL-t és Alembic migrációs szkriptet kell készíteni.
Audit Trail: Minden módosítás előtt és után State Snapshot (JSON) mentése az audit_logs táblába.
🛠️ TECHNIKAI STACK SPECIFIKÁCIÓK
Backend: Python 3.12, FastAPI, SQLAlchemy (Alembic), Pydantic validáció.
Frontend: Vue 3 (Composition API), Vite, Tailwind CSS, Pinia. Hardkódolt IP tilos, csak .env (VITE_API_BASE_URL).
Storage: MinIO (S3 kompatibilis) számlákhoz és okmányokhoz.
Útvonalak: A projekt gyökere: /opt/docker/dev/service_finder. Dokumentációk a /docs/V01_gemini/ mappában.
💬 KOMMUNIKÁCIÓ ÉS DOKUMENTÁCIÓ
Ha a Master Book specifikációja és a kérés ütközik, jelezd és tegyél javaslatot a Master Book frissítésére.
Minden megoldás után frissítsd a megfelelő Master Book fejezetet, ha a rendszerlogika változott.
Használj technikai angol kifejezéseket a magyar szövegkörnyezetben (pl. refactoring, dependency injection, endpoint).
könyvtárszerkezetét Bash tree -I "node_modules|vendor|.git|dist|build|storage" -L 3
adatbázis szerkezet Bash docker exec -it shared-postgres pg_dump -U kincses -s service_finder > schema_dump.sq
## 🛠️ SERVICE FINDER - SYSTEM ARCHITECT GEM CONFIGURATION
ROLE: Senior Technical Product Manager & System Architect PROJECT: Service Finder - Flotta Menedzsment Rendszer OBJECTIVE: MVP Refaktorálás (Monolit -> Moduláris) a "Grand Master Book" (v1.0) elvei mentén.
🎯 ALAPVETŐ MŰKÖDÉSI PROTOKOLL
Szigorú Adatgyűjtés: Kódmódosítás vagy javítás előtt kötelező bekérni az érintett fájlok teljes tartalmát. Tilos korábbi logikát törölni vagy módosítani anélkül, hogy tisztáznánk annak összefüggéseit a rendszer többi részével.
Single Source of Truth (SSoT): Minden válasz alapja a Master Book (00-17.md dokumentumok). Ha a Master Book és a kód ellentmondásban van, vagy a leírás hiányos, állj meg, tegyél javaslatot a kiegészítésre, és csak a tisztázás után folytasd a kódolást.
Tiszta és Teljes Kód: Mindig a teljes, javított fájltartalmat add vissza. Kerüld a töredékes kódokat. A kódnak tartalmaznia kell a Master Bookban rögzített logikai folyamatokat (clean code thought process).
Zéró Találgatás: Ha egy összefüggés (adatbázis-program-fájlrendszer) nem egyértelmű, tegyél fel pontosító kérdéseket. Inkább több tisztázó kör, mint hibás kód.
🏗️ ARCHITEKTÚRA ÉS FEJLESZTÉS
Modularitás: A fejlesztés iránya a monolitból a moduláris felépítés felé mutat. Minden új kódnak támogatnia kell a skálázhatóságot.
Adatbázis & SQL: SQL módosításokat pgAdmin felületre optimalizálva készíts. Minden adatbázis-módosításhoz kötelező migrációs szkriptet generálni az egységesség megőrzése érdekében.
Fájlstruktúra: Tartsd be a projekt meglévő könyvtárszerkezetét. Ne javasolj olyan útvonalakat, amelyek eltérnek a meglévő rendszertől.
📝 DOKUMENTÁCIÓ ÉS VERZIÓKEZELÉS
Gitea: Csak a már tesztelt, működő és jóváhagyott javítások után generálj Git commit üzeneteket és instrukciókat.
Changelog.md: Minden sikeres módosítás után kötelező legenerálni a Changelog.md bejegyzést, amely tartalmazza a változtatások pontos listáját.
Master Book Frissítés: Ha a fejlesztés során új logika születik, vagy pontosítunk egy meglévőt, generáld le a Master Book megfelelő fejezetének (pl. 07_API_Guide.md vagy 06_Database_Guide.md) frissített szöveges részét is.
💬 KOMMUNIKÁCIÓS STÍLUS
Szakmai, tömör és határozott.
Használj technikai angol szakkifejezéseket a magyar kontextusban (pl. refactoring, dependency injection, migration).
Minden válasz elején röviden összegezd a megértett problémát, mielőtt a megoldásra térsz.
könyvtárszerkezetét Bash tree -I "node_modules|vendor|.git|dist|build|storage" -L 3
adatbázis szerkezet Bash docker exec -it shared-postgres pg_dump -U kincses -s service_finder > schema_dump.sq

View File

@@ -0,0 +1,95 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
# Cím beállítása
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def build_db():
print(f"🔌 Kapcsolódás a rendszerhez...")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("🏗️ 'DATA' séma előkészítése...")
await conn.execute(text("CREATE SCHEMA IF NOT EXISTS data;"))
# 1. FELHASZNÁLÓK TÁBLA (Céges/Magán logika)
print("👤 Users tábla létrehozása...")
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
role VARCHAR(20) DEFAULT 'PRIVATE', -- 'PRIVATE', 'COMPANY', 'ADMIN'
company_name VARCHAR(255), -- Ha cég
tax_number VARCHAR(50), -- Ha cég
is_active BOOLEAN DEFAULT FALSE, -- Email megerősítésig
created_at TIMESTAMP DEFAULT NOW()
);
"""))
# 2. JÁRMŰ TÖRZS (A Fizikai Vas - Tulajdonos nélkül!)
print("🚗 Vehicles tábla létrehozása (A Vas)...")
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.vehicles (
id SERIAL PRIMARY KEY,
model_id INTEGER REFERENCES ref.vehicle_models(id),
vin VARCHAR(50) UNIQUE NOT NULL, -- ALVÁZSZÁM (Az igazi kulcs)
current_plate VARCHAR(20) NOT NULL, -- A mostani rendszám
production_year INTEGER,
created_at TIMESTAMP DEFAULT NOW()
);
"""))
# 3. ÉLETÚT ÉS JOGOSULTSÁG (A Történelem)
print("📜 History tábla létrehozása (Kié mikor volt?)...")
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.vehicle_history (
id SERIAL PRIMARY KEY,
vehicle_id INTEGER REFERENCES data.vehicles(id),
user_id INTEGER REFERENCES data.users(id),
role VARCHAR(20) NOT NULL, -- 'OWNER' (Tulaj), 'DRIVER' (Sofőr), 'LEASE' (Lízingelő)
start_date DATE NOT NULL, -- Mikor vette át?
end_date DATE, -- Mikor adta le? (Ha NULL, akkor nála van!)
start_mileage INTEGER, -- Óraállás átvételkor
end_mileage INTEGER, -- Óraállás leadáskor
is_active BOOLEAN GENERATED ALWAYS AS (end_date IS NULL) STORED -- Segédmező a gyors kereséshez
);
"""))
# 4. KÖLTSÉGEK (Szeparált pénzügyek)
print("💸 Costs tábla létrehozása...")
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.costs (
id SERIAL PRIMARY KEY,
vehicle_id INTEGER REFERENCES data.vehicles(id),
user_id INTEGER REFERENCES data.users(id), -- Ki fizette? (Csak ő láthatja!)
cost_type VARCHAR(50) NOT NULL, -- FUEL, SERVICE, TAX, INSURANCE, LEASE...
amount DECIMAL(10, 2) NOT NULL,
date DATE NOT NULL,
mileage_at_cost INTEGER,
description TEXT,
document_url VARCHAR(255), -- Fotó linkje
created_at TIMESTAMP DEFAULT NOW()
);
"""))
print("✅ KÉSZ! A Professzionális Adatmodell felépült.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(build_db())

View File

@@ -0,0 +1,51 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
# DB Config
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def check_data():
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("\n🚗 A TE GARÁZSOD (User ID: 1):")
print("-" * 80)
# Ez a lekérdezés összeköti a Történelmet (History), a Vasat (Vehicle) és a Katalógust (Model)
query = text("""
SELECT
vh.role,
vh.start_date,
v.vin,
v.current_plate,
m.name as brand,
mo.model_name
FROM data.vehicle_history vh
JOIN data.vehicles v ON vh.vehicle_id = v.id
JOIN ref.vehicle_models mo ON v.model_id = mo.id
JOIN ref.vehicle_makes m ON mo.make_id = m.id
WHERE vh.user_id = 1;
""")
result = await conn.execute(query)
rows = result.fetchall()
if not rows:
print("📭 A garázs üres.")
else:
for r in rows:
print(f"🔹 {r.brand} {r.model_name} | 🆔 {r.vin} | 🔢 {r.current_plate}")
print(f" Jogviszony: {r.role} | Kezdete: {r.start_date}")
print("-" * 80)
await engine.dispose()
if __name__ == "__main__":
asyncio.run(check_data())

View File

@@ -0,0 +1,35 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
# Adatbázis elérés
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def create_user():
print(f"🔌 Kapcsolódás...")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("👤 1-es számú felhasználó beszúrása...")
# Kényszerítjük az ID=1-et, hogy passzoljon a main.py-hoz
await conn.execute(text("""
INSERT INTO data.users (id, email, password_hash, role, is_active)
VALUES (1, 'demo@user.com', 'dummy_hash', 'PRIVATE', TRUE)
ON CONFLICT (id) DO NOTHING;
"""))
# Frissítjük a számlálót, hogy a következő user ID 2 legyen (ne akadjon össze)
await conn.execute(text("SELECT setval('data.users_id_seq', (SELECT MAX(id) FROM data.users));"))
print("✅ KÉSZ! A Demo User (ID: 1) létezik.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(create_user())

View File

@@ -0,0 +1,42 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def hire_driver():
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("👤 Kovács János (User ID: 2) létrehozása...")
# Létrehozzuk a User-t
await conn.execute(text("""
INSERT INTO data.users (id, email, password_hash, role, country, default_currency, is_active)
VALUES (2, 'sofor@ceg.hu', 'hash123', 'PRIVATE', 'HU', 'HUF', TRUE)
ON CONFLICT (id) DO NOTHING;
"""))
# Frissítjük a sorrendet
await conn.execute(text("SELECT setval('data.users_id_seq', (SELECT MAX(id) FROM data.users));"))
print("🤝 Hozzárendelés a Te cégedhez (ID: 1)...")
# Betesszük a fleet_members táblába
await conn.execute(text("""
INSERT INTO data.fleet_members (user_id, owner_id, role)
VALUES (2, 1, 'DRIVER')
ON CONFLICT (user_id, owner_id) DO NOTHING;
"""))
print("✅ KÉSZ! Kovács János mostantól a csapatod tagja.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(hire_driver())

View File

@@ -0,0 +1,17 @@
services:
service_finder_api:
build: .
container_name: service_finder_api
env_file:
- .env
networks:
- existing_net
ports:
- "8000:8000"
restart: unless-stopped
networks:
existing_net:
external: true
name: docker-server_internal_net

View File

@@ -0,0 +1,81 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
# Cím összeállítása (Ugyanaz a logika, mint a main.py-ban)
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def init_db():
print(f"🔌 Kapcsolódás ide: {DATABASE_URL}")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("🏗️ Séma és Táblák létrehozása...")
# 1. Séma létrehozása
await conn.execute(text("CREATE SCHEMA IF NOT EXISTS ref;"))
# 2. Márka tábla
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS ref.vehicle_makes (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL UNIQUE
);
"""))
# 3. Modell tábla
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS ref.vehicle_models (
id SERIAL PRIMARY KEY,
make_id INTEGER REFERENCES ref.vehicle_makes(id),
model_name VARCHAR(100) NOT NULL,
category VARCHAR(50)
);
"""))
print("🧹 Meglévő adatok törlése (Tiszta lap)...")
await conn.execute(text("TRUNCATE TABLE ref.vehicle_models, ref.vehicle_makes RESTART IDENTITY CASCADE;"))
print("🚗 Adatok beszúrása...")
# Adatok
makes = ["BMW", "Audi", "Mercedes-Benz", "Toyota", "Honda", "Suzuki", "Volkswagen"]
models = [
("BMW", "3 Series", "Autó"), ("BMW", "5 Series", "Autó"), ("BMW", "X5", "Autó"), ("BMW", "R 1250 GS", "Motor"),
("Audi", "A3", "Autó"), ("Audi", "A4", "Autó"), ("Audi", "A6", "Autó"), ("Audi", "Q5", "Autó"),
("Mercedes-Benz", "C-Class", "Autó"), ("Mercedes-Benz", "E-Class", "Autó"), ("Mercedes-Benz", "S-Class", "Autó"), ("Mercedes-Benz", "G-Class", "Autó"),
("Toyota", "Corolla", "Autó"), ("Toyota", "Yaris", "Autó"), ("Toyota", "RAV4", "Autó"), ("Toyota", "Hilux", "Autó"),
("Honda", "Civic", "Autó"), ("Honda", "CR-V", "Autó"), ("Honda", "Africa Twin", "Motor"), ("Honda", "CB500X", "Motor"),
("Suzuki", "Swift", "Autó"), ("Suzuki", "Vitara", "Autó"), ("Suzuki", "S-Cross", "Autó"), ("Suzuki", "DL 650 V-Strom", "Motor"),
("Volkswagen", "Golf", "Autó"), ("Volkswagen", "Passat", "Autó"), ("Volkswagen", "Polo", "Autó"), ("Volkswagen", "Tiguan", "Autó")
]
# Márkák beszúrása
for make in makes:
await conn.execute(text(f"INSERT INTO ref.vehicle_makes (name) VALUES ('{make}') ON CONFLICT DO NOTHING;"))
# Modellek beszúrása (kicsit trükkös, mert kell a make_id)
for brand, model, cat in models:
# Megkeressük az ID-t
result = await conn.execute(text(f"SELECT id FROM ref.vehicle_makes WHERE name = '{brand}'"))
make_id = result.scalar()
# Beszúrjuk a modellt
await conn.execute(text(f"""
INSERT INTO ref.vehicle_models (make_id, model_name, category)
VALUES ({make_id}, '{model}', '{cat}')
"""))
print("✅ KÉSZ! Az adatbázis feltöltve.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(init_db())

View File

@@ -0,0 +1,61 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
# Cím beállítása
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def inspect_schema():
print(f"🔎 Kapcsolódás az adatbázishoz...")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
# SQL lekérdezés a rendszer katalógusból (information_schema)
# Ez megmondja milyen táblák és oszlopok léteznek
query = text("""
SELECT
table_schema,
table_name,
column_name,
data_type,
is_nullable
FROM information_schema.columns
WHERE table_schema IN ('public', 'ref', 'data')
ORDER BY table_schema, table_name, ordinal_position;
""")
result = await conn.execute(query)
rows = result.fetchall()
if not rows:
print("⚠️ Nem találtam táblákat a 'ref' vagy 'data' sémákban!")
current_table = ""
for row in rows:
schema = row.table_schema
table = row.table_name
full_table_name = f"{schema}.{table}"
# Ha új táblához érünk, kiírjuk a nevét
if full_table_name != current_table:
print(f"\n📦 TÁBLA: {full_table_name.upper()}")
print("-" * 50)
print(f"{'OSZLOP NÉV':<20} | {'TÍPUS':<15} | {'KÖTELEZŐ?'}")
print("-" * 50)
current_table = full_table_name
# Oszlop adatok
req = "IGEN" if row.is_nullable == 'NO' else "nem"
print(f"{row.column_name:<20} | {row.data_type:<15} | {req}")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(inspect_schema())

View File

@@ -0,0 +1,69 @@
import asyncio
from sqlalchemy import inspect, text
from sqlalchemy.ext.asyncio import create_async_engine
# CSERÉLD KI a saját adataidra, ha nem ezeket használod!
DATABASE_URL = "postgresql+asyncpg://kincses:MiskociA74@postgres-db:5432/service_finder"
async def run_inspection():
# Aszinkron motor létrehozása
engine = create_async_engine(DATABASE_URL)
async with engine.connect() as conn:
def do_inspect(sync_conn):
inspector = inspect(sync_conn)
# 1. Sémák lekérése (amiket mi hoztunk létre + public)
target_schemas = ['public', 'data', 'ref']
all_schemas = inspector.get_schema_names()
schemas_to_check = [s for s in target_schemas if s in all_schemas]
print(f"{'='*60}")
print(f" JÁRMŰNYILVÁNTARTÓ RENDSZER - ADATBÁZIS AUDIT")
print(f"{'='*60}")
for schema in schemas_to_check:
print(f"\n--- SÉMA: {schema.upper()} ---")
tables = inspector.get_table_names(schema=schema)
if not tables:
print(" (Nincsenek táblák ebben a sémában)")
continue
for table_name in tables:
print(f"\n[Tábla: {schema}.{table_name}]")
# Oszlopok részletei
columns = inspector.get_columns(table_name, schema=schema)
for col in columns:
pk = " [PK]" if col['primary_key'] else ""
nullable = "NULL" if col['nullable'] else "NOT NULL"
print(f" L {col['name']:<15} | {str(col['type']):<12} | {nullable}{pk}")
# Idegen kulcsok (Kapcsolatok)
fks = inspector.get_foreign_keys(table_name, schema=schema)
for fk in fks:
constrained = fk['constrained_columns']
referred_schema = fk['referred_schema']
referred_table = fk['referred_table']
referred_cols = fk['referred_columns']
print(f" --> Kapcsolat: {constrained} -> {referred_schema}.{referred_table}({referred_cols})")
# Mivel az SQLAlchemy inspector alapvetően szinkron, run_sync-et használunk
await conn.run_sync(do_inspect)
# 2. Extra: Kiterjesztések ellenőrzése
print(f"\n{'='*60}")
print(" AKTÍV POSTGRESQL KITERJESZTÉSEK:")
result = await conn.execute(text("SELECT extname FROM pg_extension;"))
for row in result:
print(f" - {row[0]}")
print(f"{'='*60}")
await engine.dispose()
if __name__ == "__main__":
try:
asyncio.run(run_inspection())
except Exception as e:
print(f"HIBA TÖRTÉNT: {e}")

View File

@@ -0,0 +1,81 @@
from fastapi import FastAPI, HTTPException, Form, Depends
from fastapi.responses import FileResponse, JSONResponse
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
from datetime import datetime, timedelta, date
from jose import jwt
import bcrypt, os, traceback
from dotenv import load_dotenv
load_dotenv()
SECRET_KEY = "SZUPER_TITKOS_KULCS_2026"
ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="api/auth/login")
DATABASE_URL = os.getenv("DATABASE_URL", "").replace("postgresql://", "postgresql+asyncpg://")
engine = create_async_engine(DATABASE_URL, pool_pre_ping=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
app = FastAPI()
# --- AUTH ---
def get_password_hash(p): return bcrypt.hashpw(p.encode('utf-8')[:72], bcrypt.gensalt()).decode('utf-8')
def verify_password(p, h): return bcrypt.checkpw(p.encode('utf-8')[:72], h.encode('utf-8'))
async def get_current_user(token: str = Depends(oauth2_scheme)):
try:
p = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
return int(p.get("sub"))
except: raise HTTPException(status_code=401)
@app.post("/api/auth/register")
async def register(email: str = Form(...), password: str = Form(...)):
try:
async with AsyncSessionLocal() as session:
async with session.begin():
await session.execute(text("INSERT INTO data.users (email, password_hash) VALUES (:e, :p)"),
{"e": email, "p": get_password_hash(password)})
return {"status": "success"}
except Exception as e:
return JSONResponse(status_code=400, content={"detail": "Email már létezik vagy adatbázis hiba."})
@app.post("/api/auth/login")
async def login(f: OAuth2PasswordRequestForm = Depends()):
async with AsyncSessionLocal() as session:
res = await session.execute(text("SELECT id, password_hash FROM data.users WHERE email = :e"), {"e": f.username})
u = res.fetchone()
if not u or not verify_password(f.password, u.password_hash): raise HTTPException(status_code=401, detail="Hibás adatok")
t = jwt.encode({"sub": str(u.id), "exp": datetime.utcnow() + timedelta(days=1)}, SECRET_KEY, algorithm=ALGORITHM)
return {"access_token": t, "token_type": "bearer"}
# --- DATA ---
@app.get("/api/meta/vehicle-hierarchy")
async def get_hierarchy():
async with AsyncSessionLocal() as session:
q = text("SELECT vm.category, m.name as brand, vm.id as model_id, vm.model_name FROM ref.vehicle_models vm JOIN ref.vehicle_makes m ON vm.make_id = m.id ORDER BY vm.category, m.name")
res = await session.execute(q)
h = {}
for r in res:
if r.category not in h: h[r.category] = {}
if r.brand not in h[r.category]: h[r.category][r.brand] = []
h[r.category][r.brand].append({"id": r.model_id, "name": r.model_name})
return h
@app.get("/api/meta/cost-types")
async def get_cost_types():
async with AsyncSessionLocal() as session:
res = await session.execute(text("SELECT code, name FROM ref.cost_types ORDER BY name"))
return {r.code: r.name for r in res.fetchall()}
@app.get("/api/my_vehicles")
async def my_vehicles(uid: int = Depends(get_current_user)):
async with AsyncSessionLocal() as session:
q = text("SELECT v.id as vehicle_id, v.current_plate as plate, m.name as brand, mo.model_name as model, v.status FROM data.vehicle_history vh JOIN data.vehicles v ON vh.vehicle_id = v.id JOIN ref.vehicle_models mo ON v.model_id = mo.id JOIN ref.vehicle_makes m ON mo.make_id = m.id WHERE vh.user_id = :uid AND vh.end_date IS NULL")
res = await session.execute(q, {"uid": uid})
return [dict(r._mapping) for r in res.fetchall()]
@app.get("/")
async def index(): return FileResponse("/app/frontend/index.html")

View File

@@ -0,0 +1,120 @@
from fastapi import FastAPI, HTTPException
from fastapi.staticfiles import StaticFiles
from fastapi.responses import FileResponse
from pydantic import BaseModel, validator
from typing import Optional
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
import os
from datetime import date
from dotenv import load_dotenv
load_dotenv()
# --- 1. ADATBÁZIS KAPCSOLAT ---
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
fixed_url = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
engine = create_async_engine(fixed_url)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
app = FastAPI(title="Service Finder API")
# --- 2. ADATMODELLEK (VALIDÁCIÓVAL) ---
class VehicleRegister(BaseModel):
model_id: int
vin: str # Alvázszám (KÖTELEZŐ!)
plate: str # Rendszám
mileage: int # Km óra
purchase_date: date
role: str = "OWNER" # Alapértelmezett: Tulajdonos
# Adatőr: Automatikus nagybetűsítés és tisztítás
@validator('vin')
def clean_vin(cls, v):
if len(v) < 5: raise ValueError('Az alvázszám túl rövid!')
return v.upper().replace("-", "").replace(" ", "")
@validator('plate')
def clean_plate(cls, v):
return v.upper().replace("-", "").replace(" ", "")
@validator('mileage')
def positive_mileage(cls, v):
if v < 0: raise ValueError('A kilométer nem lehet negatív!')
return v
# --- 3. VÉGPONTOK ---
# Lista lekérése (Katalógus)
@app.get("/api/vehicles")
async def get_vehicles():
async with AsyncSessionLocal() as session:
result = await session.execute(text("""
SELECT vm.id, m.name as brand, vm.model_name, vm.category
FROM ref.vehicle_models vm
JOIN ref.vehicle_makes m ON vm.make_id = m.id
ORDER BY m.name, vm.model_name
"""))
return [{"id": r.id, "brand": r.brand, "model": r.model_name, "category": r.category} for r in result.fetchall()]
# ÚJ: JÁRMŰ REGISZTRÁCIÓ (A Nagy Logika)
@app.post("/api/register")
async def register_vehicle(data: VehicleRegister):
async with AsyncSessionLocal() as session:
async with session.begin(): # Tranzakció indítása
try:
# 1. Megnézzük, létezik-e már ez a VAS (Alvázszám alapján)?
check_query = text("SELECT id FROM data.vehicles WHERE vin = :vin")
result = await session.execute(check_query, {"vin": data.vin})
existing_car_id = result.scalar()
vehicle_id = existing_car_id
# 2. HA NEM LÉTEZIK -> Létrehozzuk a VASAT
if not vehicle_id:
print(f"🆕 Új autó az adatbázisban: {data.vin}")
insert_car = text("""
INSERT INTO data.vehicles (model_id, vin, current_plate)
VALUES (:mid, :vin, :plt)
RETURNING id
""")
res = await session.execute(insert_car, {
"mid": data.model_id, "vin": data.vin, "plt": data.plate
})
vehicle_id = res.scalar()
else:
print(f"♻️ Létező autó átvétele: {data.vin} (ID: {vehicle_id})")
# Itt később lezárhatjuk az előző tulajdonos history-ját!
# 3. BEJEGYZÉS A TÖRTÉNELEMBE (HISTORY)
# Ez köti össze a User-t (most fixen ID=1) az Autóval
insert_history = text("""
INSERT INTO data.vehicle_history
(vehicle_id, user_id, role, start_date, start_mileage)
VALUES (:vid, 1, :role, :s_date, :s_mil)
""")
await session.execute(insert_history, {
"vid": vehicle_id,
"role": data.role,
"s_date": data.purchase_date,
"s_mil": data.mileage
})
return {"status": "success", "message": "Jármű sikeresen rögzítve a flottában!"}
except Exception as e:
print(f"❌ Hiba: {e}")
raise HTTPException(status_code=500, detail=str(e))
# Frontend kiszolgálása
@app.get("/")
async def serve_frontend():
if os.path.exists("/app/frontend/index.html"):
return FileResponse("/app/frontend/index.html")
return {"error": "Frontend hiányzik"}

View File

@@ -0,0 +1,49 @@
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
import os
from dotenv import load_dotenv
load_dotenv()
app = FastAPI(title="Service Finder API")
# --- A DUPLA JAVÍTÁS ---
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
# Vészhelyzeti fallback (ha nem lenne .env)
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
# 1. Javítás: Driver csere (asyncpg)
fixed_url = raw_url.replace("postgresql://", "postgresql+asyncpg://")
# 2. Javítás: Adatbázis név csere (Ha véletlenül _db a vége, levágjuk)
fixed_url = fixed_url.replace("/service_finder_db", "/service_finder")
print(f"🔧 VÉGLEGES ADATBÁZIS CÍM: {fixed_url}")
# Kapcsolódás a javított címmel
engine = create_async_engine(fixed_url)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
@app.get("/")
async def root():
return {"message": "Service Finder API működik! 🚀"}
@app.get("/vehicles")
async def get_vehicles():
async with AsyncSessionLocal() as session:
try:
query = text("""
SELECT m.name as brand, vm.model_name, vm.category
FROM ref.vehicle_models vm
JOIN ref.vehicle_makes m ON vm.make_id = m.id
ORDER BY m.name, vm.model_name
""")
result = await session.execute(query)
vehicles = result.fetchall()
return [{"brand": r.brand, "model": r.model_name, "category": r.category} for r in vehicles]
except Exception as e:
return {"error": str(e)}

View File

@@ -0,0 +1,52 @@
from fastapi import FastAPI
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from sqlalchemy import text
import os
from dotenv import load_dotenv
# Betöltjük a környezeti változókat
load_dotenv()
app = FastAPI(title="Service Finder API")
# --- A FIX ---
# Kiolvassuk a címet
raw_url = os.getenv("DATABASE_URL")
# Ha nincs beállítva, adunk egy vészhelyzeti alapértelmezettet
if not raw_url:
print("⚠️ FIGYELEM: Nincs DATABASE_URL, alapértelmezett használata!")
# Itt a konténer belső nevét (postgres-db) használjuk
raw_url = "postgresql://admin:MiskociA74@postgres-db:5432/service_finder"
# A LÉNYEG: Ha hiányzik az '+asyncpg', hozzáadjuk!
if "asyncpg" not in raw_url:
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://")
print(f"🔧 URL javítva erre: {DATABASE_URL}")
else:
DATABASE_URL = raw_url
# Motor indítása a javított URL-lel
engine = create_async_engine(DATABASE_URL)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
@app.get("/")
async def root():
return {"message": "Service Finder API működik! 🚀"}
@app.get("/vehicles")
async def get_vehicles():
async with AsyncSessionLocal() as session:
try:
query = text("""
SELECT m.name as brand, vm.model_name, vm.category
FROM ref.vehicle_models vm
JOIN ref.vehicle_makes m ON vm.make_id = m.id
ORDER BY m.name, vm.model_name
""")
result = await session.execute(query)
vehicles = result.fetchall()
return [{"brand": r.brand, "model": r.model_name, "category": r.category} for r in vehicles]
except Exception as e:
return {"error": str(e)}

View File

@@ -0,0 +1,71 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def seed_cost_types():
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("🔨 Költség típusok tábla létrehozása...")
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS ref.cost_types (
code VARCHAR(50) PRIMARY KEY,
name VARCHAR(100) NOT NULL,
parent_code VARCHAR(50) REFERENCES ref.cost_types(code), -- Hierarchia!
is_active BOOLEAN DEFAULT TRUE,
sort_order INTEGER DEFAULT 0
);
"""))
print("📥 Adatok feltöltése...")
# Először a szülők (Főkategóriák)
parents = [
('FUEL', '⛽ Tankolás', 10),
('PURCHASE', '💰 Beszerzés / Pénzügy', 20),
('INSURANCE', '📄 Biztosítás', 30),
('TAX', '🏛️ Adó / Illeték', 40),
('SERVICE', '🔧 Szerviz', 50),
('OTHER', 'Egyéb', 99)
]
for p in parents:
await conn.execute(text("INSERT INTO ref.cost_types (code, name, sort_order) VALUES (:c, :n, :s) ON CONFLICT (code) DO NOTHING"), {"c": p[0], "n": p[1], "s": p[2]})
# Aztán a gyerekek (Alkategóriák)
children = [
# Beszerzés
('PURCHASE_PRICE', 'Vételár', 'PURCHASE'),
('FINANCE_LEASE', 'Lízing díj', 'PURCHASE'),
('FINANCE_LOAN', 'Hitel törlesztő', 'PURCHASE'),
('IMPORT_FEE', 'Honosítás / Regadó', 'PURCHASE'),
# Biztosítás
('INSURANCE_KGFB', 'Kötelező (KGFB)', 'INSURANCE'),
('INSURANCE_CASCO', 'Casco', 'INSURANCE'),
('INSURANCE_GAP', 'GAP', 'INSURANCE'),
('INSURANCE_ASSIST', 'Assistance', 'INSURANCE'),
# Adó
('TAX_WEIGHT', 'Gépjárműadó (Súlyadó)', 'TAX'),
('TAX_COMPANY', 'Cégautóadó', 'TAX'),
('TAX_TRANSFER', 'Vagyonszerzési illeték', 'TAX'),
('TAX_OTHER', 'Egyéb adó', 'TAX'),
# Szerviz
('SERVICE_MAINTENANCE', 'Kötelező karbantartás', 'SERVICE'),
('SERVICE_REPAIR', 'Javítás', 'SERVICE'),
('SERVICE_TIRE', 'Gumicsere', 'SERVICE'),
('SERVICE_MOT', 'Műszaki vizsga', 'SERVICE')
]
for c in children:
await conn.execute(text("INSERT INTO ref.cost_types (code, name, parent_code) VALUES (:c, :n, :p) ON CONFLICT (code) DO NOTHING"), {"c": c[0], "n": c[1], "p": c[2]})
print("✅ KÉSZ! A tudás most már az adatbázisban van, nem a HTML-ben.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(seed_cost_types())

View File

@@ -0,0 +1,46 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def build_audit_system():
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("📜 Audit Log tábla létrehozása...")
# Ez a tábla sosem töröl, csak ír! (Append-only)
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.audit_logs (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES data.users(id), -- KI csinálta?
event_type VARCHAR(50) NOT NULL, -- MIT? (pl. ISSUE_REPORT, MILEAGE_UPDATE)
target_id INTEGER, -- MELYIK autón? (Vehicle ID)
old_value TEXT, -- MI volt előtte? (A visszaállításhoz)
new_value TEXT, -- MI lett utána?
details TEXT, -- Egyéb megjegyzés (pl. hiba leírása)
ip_address VARCHAR(45), -- Honnan? (Biztonság)
created_at TIMESTAMP DEFAULT NOW()
);
"""))
print("🚦 Jármű Státusz mezők hozzáadása...")
# Bővítjük a járműveket, hogy tárolják a hibát
await conn.execute(text("""
ALTER TABLE data.vehicles
ADD COLUMN IF NOT EXISTS status VARCHAR(20) DEFAULT 'OK', -- OK, WARNING, CRITICAL
ADD COLUMN IF NOT EXISTS current_issue TEXT; -- A hiba leírása
"""))
print("✅ KÉSZ! A mindent látó szem (Audit Log) aktív.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(build_audit_system())

View File

@@ -0,0 +1,56 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def expand_categories():
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("📥 Új Főkategóriák beszúrása...")
parents = [
('EQUIPMENT', '🛠️ Felszerelés / Extrák', 25), # Vételár után
('OPERATIONAL', '🅿️ Üzemeltetés / Út', 15), # Tankolás után
('FINE', '👮 Bírság / Büntetés', 90)
]
for p in parents:
await conn.execute(text("INSERT INTO ref.cost_types (code, name, sort_order) VALUES (:c, :n, :s) ON CONFLICT (code) DO NOTHING"), {"c": p[0], "n": p[1], "s": p[2]})
print("📥 Új Alkategóriák beszúrása...")
children = [
# Felszerelés (EQUIPMENT)
('EQUIP_SHELVING', 'Raktérburkolat / Polcrendszer', 'EQUIPMENT'),
('EQUIP_BRANDING', 'Matricázás / Fóliázás', 'EQUIPMENT'),
('EQUIP_TOWBAR', 'Vonóhorog / Tetőcsomagtartó', 'EQUIPMENT'),
('EQUIP_SAFETY', 'Kötelező tartozékok (Eü. csomag)', 'EQUIPMENT'),
('EQUIP_GPS', 'GPS / Nyomkövető hardver', 'EQUIPMENT'),
('EQUIP_WINTER_TIRE', 'Téli gumi szett (Beszerzés)', 'EQUIPMENT'),
# Üzemeltetés (OPERATIONAL)
('OP_PARKING', 'Parkolás', 'OPERATIONAL'),
('OP_TOLL', 'Útdíj / Matrica / Behajtás', 'OPERATIONAL'),
('OP_WASH', 'Mosás / Kozmetika', 'OPERATIONAL'),
('OP_ADBLUE', 'AdBlue', 'OPERATIONAL'),
('OP_EV_CHARGE', 'Elektromos töltés', 'OPERATIONAL'),
('OP_STORAGE', 'Gumi hotel / Tárolás', 'OPERATIONAL'),
# Bírság (FINE)
('FINE_SPEEDING', 'Gyorshajtás', 'FINE'),
('FINE_PARKING', 'Parkolási bírság', 'FINE'),
('FINE_ADMIN', 'Közigazgatási bírság', 'FINE')
]
for c in children:
await conn.execute(text("INSERT INTO ref.cost_types (code, name, parent_code) VALUES (:c, :n, :p) ON CONFLICT (code) DO NOTHING"), {"c": c[0], "n": c[1], "p": c[2]})
print("✅ KÉSZ! A költséglista most már teljeskörű.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(expand_categories())

View File

@@ -0,0 +1,46 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def upgrade_db():
print(f"🔌 Kapcsolódás...")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("🌍 Felhasználói tábla bővítése (Ország + Alapértelmezett pénznem)...")
# 1. Users tábla bővítése
await conn.execute(text("""
ALTER TABLE data.users
ADD COLUMN IF NOT EXISTS country VARCHAR(2) DEFAULT 'HU',
ADD COLUMN IF NOT EXISTS default_currency VARCHAR(3) DEFAULT 'HUF';
"""))
print("💶 Költség tábla bővítése (Tranzakciós pénznem)...")
# 2. Costs tábla bővítése
await conn.execute(text("""
ALTER TABLE data.costs
ADD COLUMN IF NOT EXISTS currency VARCHAR(3) DEFAULT 'HUF';
"""))
# Frissítjük a meglévő Demo Usert (ID=1)
print("👤 Demo User beállítása: Magyarország / HUF")
await conn.execute(text("""
UPDATE data.users
SET country = 'HU', default_currency = 'HUF'
WHERE id = 1;
"""))
print("✅ KÉSZ! Az adatbázis mostantól támogatja a több pénznemet.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(upgrade_db())

View File

@@ -0,0 +1,26 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def add_doc_column():
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("📄 Dokumentum oszlop hozzáadása a Costs táblához...")
await conn.execute(text("""
ALTER TABLE data.costs
ADD COLUMN IF NOT EXISTS document_url VARCHAR(255);
"""))
print("✅ KÉSZ! Mehetnek a fájlok.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(add_doc_column())

View File

@@ -0,0 +1,58 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def upgrade_invites():
print(f"🔌 Kapcsolódás...")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("📨 Invitations (Meghívók) tábla létrehozása...")
# Ez tárolja a függőben lévő meghívásokat
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.invitations (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
inviter_id INTEGER REFERENCES data.users(id), -- Ki hívta meg? (Cég)
role VARCHAR(20) NOT NULL, -- Milyen szerepre? (MANAGER, DRIVER)
access_level VARCHAR(20) DEFAULT 'FULL', -- A/B Sofőr szint
token VARCHAR(100) UNIQUE NOT NULL, -- A titkos link kódja
status VARCHAR(20) DEFAULT 'PENDING', -- PENDING, ACCEPTED, EXPIRED
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP
);
"""))
print("🤝 Fleet Members (Többcéges tagság) tábla létrehozása...")
# Ez teszi lehetővé, hogy valaki több céghez is tartozzon
await conn.execute(text("""
CREATE TABLE IF NOT EXISTS data.fleet_members (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES data.users(id), -- A Dolgozó
owner_id INTEGER REFERENCES data.users(id), -- A Cég / Tulajdonos
role VARCHAR(20) NOT NULL, -- FLEET_MANAGER, DRIVER
joined_at TIMESTAMP DEFAULT NOW(),
-- Egy ember egy cégnél csak egyszer szerepelhet
UNIQUE(user_id, owner_id)
);
"""))
# Takarítás: A régi 'parent_id' már nem kell, mert a fleet_members kiváltja
# De biztonságból egyelőre csak NULL-ra állítjuk, nem töröljük az oszlopot
# await conn.execute(text("UPDATE data.users SET parent_id = NULL;"))
print("✅ KÉSZ! A rendszer készen áll a biztonságos meghívókra.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(upgrade_invites())

View File

@@ -0,0 +1,61 @@
import asyncio
import os
from sqlalchemy.ext.asyncio import create_async_engine
from sqlalchemy import text
from dotenv import load_dotenv
load_dotenv()
raw_url = os.getenv("DATABASE_URL")
if not raw_url:
raw_url = "postgresql://admin:PASSWORD_111@postgres-db:5432/service_finder"
DATABASE_URL = raw_url.replace("postgresql://", "postgresql+asyncpg://").replace("/service_finder_db", "/service_finder")
async def upgrade_permissions():
print(f"🔌 Kapcsolódás...")
engine = create_async_engine(DATABASE_URL)
async with engine.begin() as conn:
print("👑 USERS tábla bővítése (Rendszer és Szervezeti szintek)...")
# 1. SYS_ROLE: Rendszergazda / Moderátor / User
await conn.execute(text("""
ALTER TABLE data.users
ADD COLUMN IF NOT EXISTS sys_role VARCHAR(20) DEFAULT 'USER';
"""))
# 2. HIERARCHIA: Ki a főnököd? (Parent User ID)
# Ha NULL, akkor ő a Cégtulajdonos (SuperUser). Ha van ID, akkor Alkalmazott.
await conn.execute(text("""
ALTER TABLE data.users
ADD COLUMN IF NOT EXISTS parent_id INTEGER REFERENCES data.users(id);
"""))
# 3. ORG_ROLE: Cégen belüli szerep (Owner, Fleet Manager, Employee)
await conn.execute(text("""
ALTER TABLE data.users
ADD COLUMN IF NOT EXISTS org_role VARCHAR(20) DEFAULT 'OWNER';
"""))
print("🚦 VEHICLE_HISTORY tábla bővítése (Sofőr jogosultságok)...")
# 4. ACCESS_LEVEL: Mit láthat a sofőr? (COST_MANAGER vs LOG_ONLY)
await conn.execute(text("""
ALTER TABLE data.vehicle_history
ADD COLUMN IF NOT EXISTS access_level VARCHAR(20) DEFAULT 'FULL';
-- Lehetséges értékek: 'FULL', 'COST_MANAGER', 'LOG_ONLY'
"""))
# --- DEMO ADATOK FRISSÍTÉSE ---
print("👤 Demo User (ID:1) kinevezése Rendszergazdának és Cégtulajdonosnak...")
await conn.execute(text("""
UPDATE data.users
SET sys_role = 'SYS_ADMIN', org_role = 'OWNER', parent_id = NULL
WHERE id = 1;
"""))
print("✅ KÉSZ! A jogosultsági mátrix beépítve az adatbázisba.")
await engine.dispose()
if __name__ == "__main__":
asyncio.run(upgrade_permissions())

View File

@@ -0,0 +1,38 @@
from fastapi import APIRouter, Depends, HTTPException, Request, status, Body
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import get_db
from app.schemas.auth import UserRegister, Token, UserLogin
from app.services.auth_service import AuthService
from app.core.security import create_access_token
router = APIRouter()
@router.post("/register", response_model=Token, status_code=status.HTTP_201_CREATED)
async def register(
request: Request,
user_in: UserRegister = Body(...),
db: AsyncSession = Depends(get_db)
):
"""Atomi Regisztráció KYC adatokkal és privát flotta létrehozásával."""
# 1. Elérhetőség
is_available = await AuthService.check_email_availability(db, user_in.email)
if not is_available:
raise HTTPException(status_code=400, detail="Az e-mail cím már foglalt.")
# 2. Végrehajtás
user = await AuthService.register_new_user(
db=db,
user_in=user_in,
ip_address=request.client.host
)
# 3. Token generálás
token_data = {"sub": str(user.id), "email": user.email}
access_token = create_access_token(data=token_data)
return {"access_token": access_token, "token_type": "bearer"}
@router.post("/login", response_model=Token)
async def login(user_in: UserLogin = Body(...), db: AsyncSession = Depends(get_db)):
# TODO: Implement login logic
raise HTTPException(status_code=501, detail="Login not yet implemented")

View File

@@ -0,0 +1,90 @@
# /opt/docker/dev/service_finder/backend/app/workers/brand_seeder.py
import asyncio
import httpx
import logging
from sqlalchemy import text
from app.db.session import AsyncSessionLocal
# Logolás beállítása a Sentinel monitorozáshoz
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s')
logger = logging.getLogger("Smart-Seeder-v1.0.2")
async def seed_with_priority():
"""
Feltölti a catalog_discovery táblát az RDW alapján.
Logika: Csak azokat a márkákat keressük, amikből legalább 10 db fut az utakon,
hogy ne szemeteljük tele a katalógust egyedi barkács-járművekkel.
"""
# RDW SoQL lekérdezés: Márka (merk), Típus (voertuigsoort) és Darabszám (total)
# A szerveroldali csoportosítás és szűrés (having total >= 10) miatt villámgyors.
RDW_URL = (
"https://opendata.rdw.nl/resource/m9d7-ebf2.json?"
"$select=merk,voertuigsoort,count(*)%20as%20total"
"&$group=merk,voertuigsoort"
"&$having=total%20>=%2010"
)
logger.info("📥 Adatok lekérése az RDW-től prioritásos besoroláshoz...")
async with httpx.AsyncClient(timeout=120) as client:
try:
resp = await client.get(RDW_URL)
if resp.status_code != 200:
logger.error(f"❌ RDW API hiba: {resp.status_code}")
return
raw_data = resp.json()
logger.info(f"📊 {len(raw_data)} potenciális márka-kategória páros érkezett.")
async with AsyncSessionLocal() as db:
for entry in raw_data:
make = str(entry.get("merk", "")).upper().strip()
v_kind = entry.get("voertuigsoort", "")
if not make:
continue
# --- PRIORITÁS LOGIKA (Master Book 2.0 szerint) ---
# 1. Személyautó (Personenauto) -> 'pending' (Azonnal feldolgozandó)
# 2. Motor (Motorfiets) -> 'queued_motor'
# 3. Minden más (Teher, Busz, Mezőgazdasági) -> 'queued_heavy'
if "Personenauto" in v_kind:
status = 'pending'
v_class = 'car'
elif "Motorfiets" in v_kind:
status = 'queued_motor'
v_class = 'motorcycle'
else:
status = 'queued_heavy'
v_class = 'truck'
# UPSERT Logika: Ha már létezik, de még 'pending', akkor frissítjük a státuszt,
# de nem írjuk felül a már feldolgozott (processed) rekordokat.
query = text("""
INSERT INTO data.catalog_discovery (make, model, vehicle_class, source, status)
VALUES (:make, 'ALL_VARIANTS', :v_class, 'smart_seeder_v1_0_2', :status)
ON CONFLICT (make, model, vehicle_class)
DO UPDATE SET
status = CASE
WHEN data.catalog_discovery.status = 'pending' THEN EXCLUDED.status
ELSE data.catalog_discovery.status
END
WHERE data.catalog_discovery.make = EXCLUDED.make;
""")
await db.execute(query, {
"make": make,
"v_class": v_class,
"status": status
})
await db.commit()
logger.info("✅ Discovery lista sikeresen feltöltve és prioritizálva.")
except Exception as e:
logger.error(f"❌ Kritikus hiba a seeder futása közben: {e}")
if __name__ == "__main__":
asyncio.run(seed_with_priority())

View File

@@ -0,0 +1,35 @@
# app/workers/catalog_filler.py
import asyncio
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import SessionLocal
from app.models.asset import AssetCatalog
from sqlalchemy import select
class CatalogFiller:
@staticmethod
async def seed_initial_data():
"""Alapértelmezett márkák és típusok feltöltése (Példa)."""
initial_data = [
{"make": "Audi", "model": "A4", "generation": "B8 (2008-2015)", "engine_variant": "2.0 TDI (150 LE)", "fuel_type": "Diesel"},
{"make": "BMW", "model": "3 Series", "generation": "F30 (2012-2019)", "engine_variant": "320d (190 LE)", "fuel_type": "Diesel"},
{"make": "Volkswagen", "model": "Passat", "generation": "B8 (2014-)", "engine_variant": "2.0 TDI (150 LE)", "fuel_type": "Diesel"}
]
async with SessionLocal() as db:
for item in initial_data:
# Ellenőrizzük, létezik-e már
stmt = select(AssetCatalog).where(
AssetCatalog.make == item["make"],
AssetCatalog.model == item["model"],
AssetCatalog.engine_variant == item["engine_variant"]
)
exists = (await db.execute(stmt)).scalar_one_or_none()
if not exists:
db.add(AssetCatalog(**item))
await db.commit()
print("Catalog seeding complete.")
if __name__ == "__main__":
asyncio.run(CatalogFiller.seed_initial_data())

View File

@@ -0,0 +1,208 @@
import asyncio
import httpx
import logging
import json
import os
import datetime
from sqlalchemy import text
from app.db.session import SessionLocal
from app.models.asset import AssetCatalog
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("Robot-v1.0.13-Global-Hunter")
class CatalogMaster:
"""
Master Hunter Robot v1.0.13 - Global Hunter Edition
- Holland (RDW), Brit (DVLA) és Amerikai (NHTSA) adatbázis integráció.
- Ratio-Filter: Kiszűri a 0.19-es kW/kg arányszámokat.
- Multi-field Power Discovery: Minden lehetséges mezőből kinyeri a kW-ot.
- Dinamikus évjárat kezelés a duplikációk ellen.
"""
# API Végpontok
RDW_MAIN = "https://opendata.rdw.nl/resource/m9d7-ebf2.json"
RDW_FUEL = "https://opendata.rdw.nl/resource/8ys7-d773.json"
RDW_AXLE = "https://opendata.rdw.nl/resource/3huj-srit.json"
RDW_BODY = "https://opendata.rdw.nl/resource/vezc-m2t6.json"
UK_DVLA = "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles"
US_NHTSA = "https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVinValuesBatch/"
RDW_TOKEN = os.getenv("RDW_APP_TOKEN")
UK_API_KEY = os.getenv("UK_DVLA_API_KEY")
HEADERS_RDW = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {}
HEADERS_UK = {"x-api-key": UK_API_KEY, "Content-Type": "application/json"} if UK_API_KEY else {}
CATEGORY_MAP = {
"Personenauto": "car",
"Motorfiets": "motorcycle",
"Bedrijfsauto": "truck",
"Vrachtwagen": "truck",
"Opleggertrekker": "truck",
"Bus": "bus",
"Aanhangwagen": "trailer",
"Oplegger": "trailer",
"Landbouw- of bosbouwtrekker": "agricultural",
"camper": "camper"
}
@classmethod
def clean_kw(cls, val):
"""Speciális kW tisztító: ignorálja az 1.0 alatti arányszámokat."""
try:
if val is None: return None
f_val = float(str(val).replace(',', '.'))
if 0 < f_val < 1.0: return None # Ez csak arányszám (kW/kg)
v = int(f_val)
return v if v > 0 else None
except (ValueError, TypeError):
return None
@classmethod
def clean_int(cls, val):
"""Általános egész szám tisztító."""
try:
if val is None: return None
return int(float(str(val).replace(',', '.')))
except (ValueError, TypeError):
return None
@classmethod
async def fetch_api(cls, url, params=None, headers=None, method="GET", json_data=None):
"""Univerzális API hívó sebességkorlátozással."""
async with httpx.AsyncClient(headers=headers, follow_redirects=True) as client:
try:
await asyncio.sleep(1.2) # Biztonsági késleltetés
if method == "POST":
resp = await client.post(url, json=json_data, timeout=30)
else:
resp = await client.get(url, params=params, timeout=30)
return resp.json() if resp.status_code in [200, 201] else []
except Exception as e:
logger.error(f"❌ API Hiba ({url}): {e}")
return []
@classmethod
async def get_deep_tech(cls, plate, main_kw=None, vin=None):
"""Nemzetközi dúsítás: Holland -> Brit -> Amerikai sorrendben."""
res = {"kw": cls.clean_kw(main_kw), "fuel": "Unknown", "axles": None, "body": "Standard", "euro": None}
# 1. HOLLAND (RDW) DÚSÍTÁS
fuel_data = await cls.fetch_api(cls.RDW_FUEL, {"kenteken": plate}, headers=cls.HEADERS_RDW)
if fuel_data:
f0 = fuel_data[0]
if not res["kw"]:
res["kw"] = cls.clean_kw(f0.get("nettomaximumvermogen") or f0.get("netto_maximum_vermogen"))
res["fuel"] = f0.get("brandstof_omschrijving", "Unknown")
res["euro"] = f0.get("uitlaatemissieniveau")
# 2. BRIT (DVLA) ELLENŐRZÉS (Ha van UK kulcs és még hiányzik adat)
if cls.UK_API_KEY and (not res["kw"] or not res["euro"]):
uk_data = await cls.fetch_api(cls.UK_DVLA, method="POST", json_data={"registrationNumber": plate}, headers=cls.HEADERS_UK)
if uk_data:
res["kw"] = res["kw"] or cls.clean_kw(uk_data.get("engineCapacity")) # Brit adatok finomítása
res["euro"] = res["euro"] or uk_data.get("euroStatus")
# 3. AMERIKAI (NHTSA) KUTATÁS (Ha van alvázszám)
if vin and len(vin) == 17:
us_data = await cls.fetch_api(cls.US_NHTSA, params={"format": "json", "data": vin})
if us_data and "Results" in us_data:
# Az amerikai adatbázisból kinyerjük a lóerőt (HP), ha a kW még mindig nincs meg
hp = us_data["Results"][0].get("EngineHP")
if hp and not res["kw"]:
res["kw"] = int(float(hp) * 0.7457) # HP -> kW konverzió
# RDW Extra adatok (Tengely, Karosszéria)
axle = await cls.fetch_api(cls.RDW_AXLE, {"kenteken": plate}, headers=cls.HEADERS_RDW)
if axle: res["axles"] = cls.clean_int(axle[0].get("aantal_assen"))
body = await cls.fetch_api(cls.RDW_BODY, {"kenteken": plate}, headers=cls.HEADERS_RDW)
if body: res["body"] = body[0].get("carrosserie_omschrijving", "Standard")
return res
@classmethod
async def process_make(cls, db, task_id, make_name):
logger.info(f"🚀 >>> {make_name} GlobalHunter v1.0.13 INDUL...")
offset, limit, total_saved = 0, 1000, 0
unique_variants = {}
while True:
params = {"merk": make_name.upper(), "$limit": limit, "$offset": offset}
main_data = await cls.fetch_api(cls.RDW_MAIN, params, headers=cls.HEADERS_RDW)
if not main_data: break
for item in main_data:
plate = item.get("kenteken")
if not plate: continue
model = str(item.get("handelsbenaming", "Unknown")).upper()
ccm = cls.clean_int(item.get("cilinderinhoud"))
weight = cls.clean_int(item.get("massa_ledig_voertuig") or item.get("massa_rijklaar"))
kw_candidate = item.get("netto_maximum_vermogen") or item.get("vermogen_massarijklaar")
raw_date = item.get("datum_eerste_toelating")
prod_year = int(str(raw_date)[:4]) if raw_date else 2024
v_class = cls.CATEGORY_MAP.get(item.get("voertuigsoort"), "other")
if "kampeerwagen" in str(item.get("inrichting", "")).lower(): v_class = "camper"
# Variáns kulcs: Modell + CCM + Súly + kW + Év = Egyedi technikai ujjlenyomat
variant_key = f"{model}-{ccm}-{weight}-{v_class}-{kw_candidate}-{prod_year}"
if variant_key not in unique_variants:
unique_variants[variant_key] = {
"model": model, "ccm": ccm, "weight": weight, "v_class": v_class,
"plate": plate, "main_kw": kw_candidate, "prod_year": prod_year,
"vin": item.get("vin") # Ha az RDW-ben benne van a VIN
}
if len(main_data) < limit or offset > 90000: break
offset += limit
logger.info(f"📊 {len(unique_variants)} egyedi variáns kutatása indul...")
for key, v in unique_variants.items():
deep = await cls.get_deep_tech(v["plate"], main_kw=v["main_kw"], vin=v["vin"])
try:
db_item = AssetCatalog(
make=make_name.upper(), model=v["model"], vehicle_class=v["v_class"],
fuel_type=deep["fuel"], power_kw=deep["kw"], engine_capacity=v["ccm"],
max_weight_kg=v["weight"], axle_count=deep["axles"], body_type=deep["body"],
year_from=v["prod_year"], euro_class=deep["euro"],
factory_data={
"source": "GlobalHunter-v1.0.13",
"sample_plate": v["plate"],
"enriched_at": str(datetime.datetime.now())
}
)
db.add(db_item)
await db.commit()
total_saved += 1
if total_saved % 50 == 0: logger.info(f"{total_saved} variáns elmentve.")
except Exception:
await db.rollback()
continue
await db.execute(text("UPDATE data.catalog_discovery SET status = 'processed' WHERE id = :id"), {"id": task_id})
await db.commit()
logger.info(f"🏁 {make_name} KÉSZ. {total_saved} rekord rögzítve.")
@classmethod
async def run(cls):
logger.info("🤖 Robot 1.0.13 (Global Hunter) ONLINE")
while True:
async with SessionLocal() as db:
res = await db.execute(text("SELECT id, make FROM data.catalog_discovery WHERE status = 'pending' LIMIT 1"))
task = res.fetchone()
if task:
await cls.process_make(db, task[0], task[1])
else:
logger.info("😴 Várólista üres. Alvás 60 mp...")
await asyncio.sleep(60)
await asyncio.sleep(1)
if __name__ == "__main__":
asyncio.run(CatalogMaster.run())

View File

@@ -0,0 +1,270 @@
import asyncio
import httpx
import logging
import json
import os
import datetime
import sys
from sqlalchemy import text
from app.db.session import SessionLocal
from app.models.asset import AssetCatalog
# --- KÉNYSZERÍTETT IDŐBÉLYEGES LOGOLÁS ---
# Töröljük az esetleges korábbi konfigurációkat, hogy az időbélyeg garantált legyen
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s.%(msecs)03d [%(levelname)s] %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S',
stream=sys.stdout
)
logger = logging.getLogger("Robot-v1.4.1-Powerhouse")
class CatalogMaster:
"""
Master Hunter Robot v1.4.1 - Powerhouse Edition
- Párhuzamos Holland (RDW) és Amerikai (NHTSA Batch) Discovery.
- Garantált időbélyeges naplózás.
- Multi-Worker Safe (FOR UPDATE SKIP LOCKED).
- Rate Limit (429) védelem.
"""
# API Végpontok
RDW_MAIN = "https://opendata.rdw.nl/resource/m9d7-ebf2.json"
RDW_FUEL = "https://opendata.rdw.nl/resource/8ys7-d773.json"
RDW_AXLE = "https://opendata.rdw.nl/resource/3huj-srit.json"
RDW_BODY = "https://opendata.rdw.nl/resource/vezc-m2t6.json"
US_BATCH = "https://vpic.nhtsa.dot.gov/api/vehicles/GetModelsForMakeYear/make/{make}/modelyear/{year}?format=json"
# BRIT API (Token után aktiválható)
UK_DVLA = "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles"
RDW_TOKEN = os.getenv("RDW_APP_TOKEN")
UK_API_KEY = os.getenv("UK_DVLA_API_KEY")
HEADERS_RDW = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {}
HEADERS_UK = {"x-api-key": UK_API_KEY, "Content-Type": "application/json"} if UK_API_KEY else {}
CATEGORY_MAP = {
"Personenauto": "car",
"Motorfiets": "motorcycle",
"Bedrijfsauto": "truck",
"Vrachtwagen": "truck",
"Opleggertrekker": "truck",
"Bus": "bus",
"Aanhangwagen": "trailer",
"Oplegger": "trailer",
"Landbouw- of bosbouwtrekker": "agricultural",
"camper": "camper"
}
# Szabályozzuk a párhuzamos dúsítást (egyszerre max 5 kérés robotpéldányonként)
semaphore = asyncio.Semaphore(5)
@classmethod
def clean_kw(cls, val):
try:
if val is None: return None
f_val = float(str(val).replace(',', '.'))
if 0 < f_val < 1.0: return None
v = int(f_val)
return v if v > 0 else None
except (ValueError, TypeError):
return None
@classmethod
def clean_int(cls, val):
try:
if val is None: return None
return int(float(str(val).replace(',', '.')))
except (ValueError, TypeError):
return None
@classmethod
async def fetch_api(cls, url, params=None, headers=None, method="GET", json_data=None):
"""Intelligens API hívó 429-es védelemmel és időzített logolással."""
async with httpx.AsyncClient(headers=headers, follow_redirects=True) as client:
for attempt in range(3):
try:
if method == "POST":
resp = await client.post(url, json=json_data, timeout=30)
else:
resp = await client.get(url, params=params, timeout=30)
if resp.status_code == 429:
wait_time = (attempt + 1) * 5
logger.warning(f"⚠️ RATE LIMIT! Várakozás {wait_time}mp: {url}")
await asyncio.sleep(wait_time)
continue
return resp.json() if resp.status_code in [200, 201] else []
except Exception as e:
logger.error(f"❌ API Hiba ({url}): {e}")
await asyncio.sleep(2)
return []
@classmethod
async def get_deep_tech(cls, plate, main_kw=None, vin=None):
"""Mély dúsítás több forrásból párhuzamosan."""
async with cls.semaphore:
res = {"kw": cls.clean_kw(main_kw), "fuel": "Unknown", "axles": None, "body": "Standard", "euro": None}
# --- 1. HOLLAND (RDW) DÚSÍTÁS ---
fuel_task = cls.fetch_api(cls.RDW_FUEL, {"kenteken": plate}, headers=cls.HEADERS_RDW)
axle_task = cls.fetch_api(cls.RDW_AXLE, {"kenteken": plate}, headers=cls.HEADERS_RDW)
fuel_data, axle_data = await asyncio.gather(fuel_task, axle_task)
if fuel_data:
f0 = fuel_data[0]
if not res["kw"]:
res["kw"] = cls.clean_kw(f0.get("nettomaximumvermogen") or f0.get("netto_maximum_vermogen"))
res["fuel"] = f0.get("brandstof_omschrijving", "Unknown")
res["euro"] = f0.get("uitlaatemissieniveau")
if axle_data:
res["axles"] = cls.clean_int(axle_data[0].get("aantal_assen"))
# --- 2. BRIT (DVLA) ELLENŐRZÉS (AKTIVÁLHATÓ KULCCSAL) ---
"""
if cls.UK_API_KEY and (not res["kw"] or not res["euro"]):
uk_data = await cls.fetch_api(cls.UK_DVLA, method="POST",
json_data={"registrationNumber": plate},
headers=cls.HEADERS_UK)
if uk_data and not isinstance(uk_data, list):
res["kw"] = res["kw"] or cls.clean_kw(uk_data.get("engineCapacity"))
res["euro"] = res["euro"] or uk_data.get("euroStatus")
"""
return res
@classmethod
async def discover_holland(cls, make_name, limit=1000):
"""Holland Discovery ág: rendszámok gyűjtése."""
offset, variants = 0, {}
while True:
params = {"merk": make_name.upper(), "$limit": limit, "$offset": offset}
data = await cls.fetch_api(cls.RDW_MAIN, params, headers=cls.HEADERS_RDW)
if not data: break
for item in data:
plate = item.get("kenteken")
if not plate: continue
model = str(item.get("handelsbenaming", "Unknown")).upper()
ccm = cls.clean_int(item.get("cilinderinhoud"))
weight = cls.clean_int(item.get("massa_ledig_voertuig") or item.get("massa_rijklaar"))
kw = item.get("netto_maximum_vermogen") or item.get("vermogen_massarijklaar")
raw_date = item.get("datum_eerste_toelating")
year = int(str(raw_date)[:4]) if raw_date else 2024
v_class = cls.CATEGORY_MAP.get(item.get("voertuigsoort"), "other")
key = f"{model}-{ccm}-{weight}-{v_class}-{kw}-{year}"
if key not in variants:
variants[key] = {
"model": model, "ccm": ccm, "weight": weight, "v_class": v_class,
"plate": plate, "main_kw": kw, "prod_year": year, "vin": item.get("vin")
}
if len(data) < limit: break
offset += limit
return variants
@classmethod
async def discover_usa_batch(cls, make_name):
"""Amerikai NHTSA Batch Discovery: Típusok gyűjtése."""
variants = {}
years = range(datetime.datetime.now().year - 5, datetime.datetime.now().year + 1)
async def fetch_year(year):
url = cls.US_BATCH.format(make=make_name.upper(), year=year)
logger.info(f"🇺🇸 USA Batch Discovery indítása: {make_name} ({year})")
data = await cls.fetch_api(url)
if data and "Results" in data:
for m in data["Results"]:
m_name = m.get("Model_Name", "Unknown").upper()
key = f"US-{m_name}-{year}"
if key not in variants:
variants[key] = {
"model": m_name, "ccm": None, "weight": None, "v_class": "car",
"plate": "US-DISCOVERY", "main_kw": None, "prod_year": year, "vin": None
}
await asyncio.gather(*(fetch_year(y) for y in years))
return variants
@classmethod
async def process_make(cls, db, task_id, make_name):
logger.info(f"🚀 >>> {make_name} Powerhouse v1.4.1 INDUL...")
# Párhuzamos Discovery
holland_task = cls.discover_holland(make_name)
usa_task = cls.discover_usa_batch(make_name)
holland_variants, usa_variants = await asyncio.gather(holland_task, usa_task)
all_variants = {**usa_variants, **holland_variants}
logger.info(f"📊 Összefésült variánsok száma: {len(all_variants)}")
async def enrich_and_save(v):
deep = await cls.get_deep_tech(v["plate"], main_kw=v["main_kw"], vin=v["vin"])
try:
db_item = AssetCatalog(
make=make_name.upper(), model=v["model"], vehicle_class=v["v_class"],
fuel_type=deep["fuel"], power_kw=deep["kw"], engine_capacity=v["ccm"],
max_weight_kg=v["weight"], axle_count=deep["axles"], body_type=deep["body"],
year_from=v["prod_year"], euro_class=deep["euro"],
factory_data={
"source": "Powerhouse-v1.4.1",
"discovery_nl": v["plate"] != "US-DISCOVERY",
"enriched_at": str(datetime.datetime.now())
}
)
return db_item
except Exception:
return None
# Párhuzamos dúsítás (Semaphore korláttal)
results = await asyncio.gather(*(enrich_and_save(v) for v in all_variants.values()))
total_saved = 0
for item in results:
if item:
db.add(item)
total_saved += 1
await db.commit()
await db.execute(text("UPDATE data.catalog_discovery SET status = 'processed' WHERE id = :id"), {"id": task_id})
await db.commit()
logger.info(f"🏁 {make_name} KÉSZ. {total_saved} egyedi rekord rögzítve.")
@classmethod
async def run(cls):
logger.info("🤖 Robot 1.4.1 (Powerhouse) ONLINE - Multi-Worker Safe Mode")
while True:
async with SessionLocal() as db:
# SKIP LOCKED védelem a párhuzamos futtatáshoz
query = text("""
SELECT id, make FROM data.catalog_discovery
WHERE status = 'pending'
LIMIT 1
FOR UPDATE SKIP LOCKED
""")
res = await db.execute(query)
task = res.fetchone()
if task:
task_id, make_name = task
await db.execute(
text("UPDATE data.catalog_discovery SET status = 'running' WHERE id = :id"),
{"id": task_id}
)
await db.commit()
await cls.process_make(db, task_id, make_name)
else:
logger.info("😴 Várólista üres vagy minden feladat foglalt. Alvás 60mp...")
await asyncio.sleep(60)
await asyncio.sleep(1)
if __name__ == "__main__":
asyncio.run(CatalogMaster.run())

View File

@@ -0,0 +1,272 @@
import asyncio
import httpx
import logging
import json
import os
import datetime
from sqlalchemy import text
from app.db.session import SessionLocal
from app.models.asset import AssetCatalog
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("Robot-v1.4-Powerhouse")
class CatalogMaster:
"""
Master Hunter Robot v1.4 - Powerhouse Edition
- Párhuzamos Holland (RDW) és Amerikai (NHTSA Batch) Discovery.
- Előkészített, kikommentelt Brit (DVLA) integráció.
- Async Semaphore: Párhuzamos technikai dúsítás (egyszerre 10 szálon).
- Intelligens összefésülés a globális források között.
"""
# API Végpontok
RDW_MAIN = "https://opendata.rdw.nl/resource/m9d7-ebf2.json"
RDW_FUEL = "https://opendata.rdw.nl/resource/8ys7-d773.json"
RDW_AXLE = "https://opendata.rdw.nl/resource/3huj-srit.json"
RDW_BODY = "https://opendata.rdw.nl/resource/vezc-m2t6.json"
# AMERIKAI BATCH API: Egyetlen hívással az összes modell évjárat szerint
US_BATCH = "https://vpic.nhtsa.dot.gov/api/vehicles/GetModelsForMakeYear/make/{make}/modelyear/{year}?format=json"
# BRIT API (Kikapcsolva a tokenig)
# UK_DVLA = "https://driver-vehicle-licensing.api.gov.uk/vehicle-enquiry/v1/vehicles"
RDW_TOKEN = os.getenv("RDW_APP_TOKEN")
UK_API_KEY = os.getenv("UK_DVLA_API_KEY") # Jövőbeli token helye
HEADERS_RDW = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {}
# HEADERS_UK = {"x-api-key": UK_API_KEY, "Content-Type": "application/json"} if UK_API_KEY else {}
CATEGORY_MAP = {
"Personenauto": "car",
"Motorfiets": "motorcycle",
"Bedrijfsauto": "truck",
"Vrachtwagen": "truck",
"Opleggertrekker": "truck",
"Bus": "bus",
"Aanhangwagen": "trailer",
"Oplegger": "trailer",
"Landbouw- of bosbouwtrekker": "agricultural",
"camper": "camper"
}
# Szabályozzuk a párhuzamos dúsítást, hogy ne tiltsanak le (egyszerre max 10 kérés)
semaphore = asyncio.Semaphore(5)
@classmethod
def clean_kw(cls, val):
try:
if val is None: return None
f_val = float(str(val).replace(',', '.'))
if 0 < f_val < 1.0: return None
v = int(f_val)
return v if v > 0 else None
except (ValueError, TypeError):
return None
@classmethod
def clean_int(cls, val):
try:
if val is None: return None
return int(float(str(val).replace(',', '.')))
except (ValueError, TypeError):
return None
@classmethod
async def fetch_api(cls, url, params=None, headers=None, method="GET", json_data=None):
async with httpx.AsyncClient(headers=headers, follow_redirects=True) as client:
for attempt in range(3): # 3-szor próbáljuk újra, ha kell
try:
if method == "POST":
resp = await client.post(url, json=json_data, timeout=30)
else:
resp = await client.get(url, params=params, timeout=30)
if resp.status_code == 429: # HOPPÁ, túl gyorsak vagyunk!
wait_time = (attempt + 1) * 5 # Egyre többet vár: 5s, 10s...
logger.warning(f"⚠️ RDW limit elérve! Pihenő {wait_time} mp...")
await asyncio.sleep(wait_time)
continue
return resp.json() if resp.status_code in [200, 201] else []
except Exception as e:
logger.error(f"❌ API Hiba ({url}): {e}")
await asyncio.sleep(2)
return []
@classmethod
async def get_deep_tech(cls, plate, main_kw=None, vin=None):
"""Mély dúsítás párhuzamos forrásokból."""
async with cls.semaphore:
res = {"kw": cls.clean_kw(main_kw), "fuel": "Unknown", "axles": None, "body": "Standard", "euro": None}
# --- 1. HOLLAND (RDW) DÚSÍTÁS ---
fuel_task = cls.fetch_api(cls.RDW_FUEL, {"kenteken": plate}, headers=cls.HEADERS_RDW)
axle_task = cls.fetch_api(cls.RDW_AXLE, {"kenteken": plate}, headers=cls.HEADERS_RDW)
# Holland adatok párhuzamos lekérése
fuel_data, axle_data = await asyncio.gather(fuel_task, axle_task)
if fuel_data:
f0 = fuel_data[0]
if not res["kw"]:
res["kw"] = cls.clean_kw(f0.get("nettomaximumvermogen") or f0.get("netto_maximum_vermogen"))
res["fuel"] = f0.get("brandstof_omschrijving", "Unknown")
res["euro"] = f0.get("uitlaatemissieniveau")
if axle_data:
res["axles"] = cls.clean_int(axle_data[0].get("aantal_assen"))
# --- 2. BRIT (DVLA) ELLENŐRZÉS (KIKOMMENTELVE A TOKENIG) ---
"""
if cls.UK_API_KEY and (not res["kw"] or not res["euro"]):
uk_data = await cls.fetch_api(cls.UK_DVLA, method="POST",
json_data={"registrationNumber": plate},
headers=cls.HEADERS_UK)
if uk_data and not isinstance(uk_data, list):
res["kw"] = res["kw"] or cls.clean_kw(uk_data.get("engineCapacity"))
res["euro"] = res["euro"] or uk_data.get("euroStatus")
"""
return res
@classmethod
async def discover_holland(cls, make_name, limit=1000):
"""Holland Discovery ág."""
offset, variants = 0, {}
while True:
params = {"merk": make_name.upper(), "$limit": limit, "$offset": offset}
data = await cls.fetch_api(cls.RDW_MAIN, params, headers=cls.HEADERS_RDW)
if not data: break
for item in data:
plate = item.get("kenteken")
if not plate: continue
model = str(item.get("handelsbenaming", "Unknown")).upper()
ccm = cls.clean_int(item.get("cilinderinhoud"))
weight = cls.clean_int(item.get("massa_ledig_voertuig") or item.get("massa_rijklaar"))
kw = item.get("netto_maximum_vermogen") or item.get("vermogen_massarijklaar")
raw_date = item.get("datum_eerste_toelating")
year = int(str(raw_date)[:4]) if raw_date else 2024
v_class = cls.CATEGORY_MAP.get(item.get("voertuigsoort"), "other")
key = f"{model}-{ccm}-{weight}-{v_class}-{kw}-{year}"
if key not in variants:
variants[key] = {
"model": model, "ccm": ccm, "weight": weight, "v_class": v_class,
"plate": plate, "main_kw": kw, "prod_year": year, "vin": item.get("vin")
}
if len(data) < limit: break
offset += limit
return variants
@classmethod
async def discover_usa_batch(cls, make_name):
"""Amerikai NHTSA Batch Discovery ág (2020-2025 évjáratokra)."""
variants = {}
# Az utolsó 5 évjáratot nézzük a legfrissebb modellekért
years = range(datetime.datetime.now().year - 5, datetime.datetime.now().year + 1)
async def fetch_year(year):
url = cls.US_BATCH.format(make=make_name.upper(), year=year)
data = await cls.fetch_api(url)
if data and "Results" in data:
for m in data["Results"]:
m_name = m.get("Model_Name", "Unknown").upper()
# US adatoknál nincs rendszám, de a Robot 2 dúsítani fogja ha kell
key = f"US-{m_name}-{year}"
variants[key] = {
"model": m_name, "ccm": None, "weight": None, "v_class": "car",
"plate": "US-DISCOVERY", "main_kw": None, "prod_year": year, "vin": None
}
await asyncio.gather(*(fetch_year(y) for y in years))
return variants
@classmethod
async def process_make(cls, db, task_id, make_name):
logger.info(f"🚀 >>> {make_name} Powerhouse v1.4 INDUL...")
# PÁRHUZAMOS DISCOVERY: Holland és USA egyszerre
holland_task = cls.discover_holland(make_name)
usa_task = cls.discover_usa_batch(make_name)
holland_variants, usa_variants = await asyncio.gather(holland_task, usa_task)
# Összefésülés (Holland élvez elsőbbséget a rendszám miatt)
all_variants = {**usa_variants, **holland_variants}
logger.info(f"📊 Összesen {len(all_variants)} egyedi variáns (NL: {len(holland_variants)}, US: {len(usa_variants)})")
# PÁRHUZAMOS DÚSÍTÁS
async def enrich_and_save(v):
deep = await cls.get_deep_tech(v["plate"], main_kw=v["main_kw"], vin=v["vin"])
try:
db_item = AssetCatalog(
make=make_name.upper(), model=v["model"], vehicle_class=v["v_class"],
fuel_type=deep["fuel"], power_kw=deep["kw"], engine_capacity=v["ccm"],
max_weight_kg=v["weight"], axle_count=deep["axles"], body_type=deep["body"],
year_from=v["prod_year"], euro_class=deep["euro"],
factory_data={
"source": "Powerhouse-v1.4",
"discovery_nl": v["plate"] != "US-DISCOVERY",
"enriched_at": str(datetime.datetime.now())
}
)
return db_item
except Exception:
return None
# Egyszerre indítjuk a dúsításokat (A semaphore korlátozza a szálakat)
results = await asyncio.gather(*(enrich_and_save(v) for v in all_variants.values()))
# Mentés
total_saved = 0
for item in results:
if item:
db.add(item)
total_saved += 1
await db.commit()
await db.execute(text("UPDATE data.catalog_discovery SET status = 'processed' WHERE id = :id"), {"id": task_id})
await db.commit()
logger.info(f"🏁 {make_name} KÉSZ. {total_saved} rekord rögzítve.")
@classmethod
async def run(cls):
logger.info("🤖 Robot 1.4 (Powerhouse) ONLINE - Multi-Worker Safe")
while True:
async with SessionLocal() as db:
# 1. 'FOR UPDATE SKIP LOCKED' - Megfogjuk a sort és lelakatoljuk,
# de a többi robot átugorja, amit mi már fogunk.
query = text("""
SELECT id, make FROM data.catalog_discovery
WHERE status = 'pending'
LIMIT 1
FOR UPDATE SKIP LOCKED
""")
res = await db.execute(query)
task = res.fetchone()
if task:
task_id, make_name = task
# 2. Azonnal átállítjuk 'running'-ra a tranzakción belül,
# így senki más nem nyúl hozzá.
await db.execute(
text("UPDATE data.catalog_discovery SET status = 'running' WHERE id = :id"),
{"id": task_id}
)
await db.commit() # Itt véglegesítjük a foglalást
# 3. Indulhat a tényleges munka
await cls.process_make(db, task_id, make_name)
else:
logger.info("😴 Várólista üres (vagy minden sor foglalt). Alvás 60 mp...")
await asyncio.sleep(60)
await asyncio.sleep(1)
if __name__ == "__main__":
asyncio.run(CatalogMaster.run())

View File

@@ -0,0 +1,198 @@
services:
# 1. MIGRÁCIÓ (Adatbázis szerkezet frissítése)
migrate:
build:
context: ./backend
dockerfile: Dockerfile
container_name: service_finder_migrate
env_file: .env
volumes:
- ./backend:/app # Ez tartalmazza az alembic.ini-t és a migrations mappát is!
environment:
PYTHONPATH: /app
DATABASE_URL: ${MIGRATION_DATABASE_URL}
command: ["bash", "-lc", "alembic upgrade head"]
networks:
- default
- shared_db_net
restart: "no"
# 2. BACKEND API
service_finder_api:
build:
context: ./backend
dockerfile: Dockerfile
container_name: service_finder_api
env_file: .env
volumes:
- ./backend:/app
- /mnt/nas/app_data:/mnt/nas/app_data # Központi NAS elérés
- ./static_previews:/app/static/previews # Lokális SSD gyorsítótár
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips="*"
ports:
- "8000:8000"
environment:
PYTHONPATH: /app
DATABASE_URL: ${DATABASE_URL}
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS}
MINIO_ENDPOINT: ${MINIO_ENDPOINT}
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
depends_on:
migrate:
condition: service_completed_successfully
minio:
condition: service_started
redis:
condition: service_started
networks:
- default
- shared_db_net
restart: unless-stopped
# 3. MINIO (NAS-ra ment)
minio:
image: minio/minio
container_name: service_finder_minio
env_file: .env
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- /mnt/nas/app_data/minio_data:/data
ports:
- "9000:9000"
- "9001:9001"
networks:
- default
restart: unless-stopped
# 4. REDIS (Lokális cache)
redis:
image: redis:alpine
container_name: service_finder_redis
volumes:
- /mnt/nas/app_data/redis_data:/data
networks:
- default
restart: unless-stopped
# 5. FRONTEND
service_finder_frontend:
build:
context: ./frontend
container_name: service_finder_frontend
env_file: .env
ports:
- "3001:80"
environment:
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS}
networks:
- default
depends_on:
service_finder_api:
condition: service_started
restart: unless-stopped
# Katalógus felderítő robot
catalog_robot:
build: ./backend
image: service_finder-catalog_robot
container_name: service_finder_robot_catalog
command: python -m app.workers.catalog_robot
volumes:
- ./backend:/app
env_file:
- .env
depends_on:
migrate:
condition: service_completed_successfully
networks:
- default
- shared_db_net
restart: always
# Szerviz vadász robot (Robot 2.7)
service_hunter:
build: ./backend
container_name: service_finder_robot_hunter
command: python -m app.workers.service_hunter
volumes:
- ./backend:/app
- ./backend/app/workers/local_services.csv:/app/app/workers/local_services.csv
environment:
- GOOGLE_API_KEY=${GOOGLE_API_KEY}
# JAVÍTVA: shared-postgres lett a gépnév a 'db' helyett!
- DATABASE_URL=postgresql+asyncpg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@shared-postgres:5432/${POSTGRES_DB}
env_file:
- .env
dns:
- 8.8.8.8
- 1.1.1.1
depends_on:
migrate:
condition: service_completed_successfully
networks:
- default
- shared_db_net
restart: always
# --- ÚJ: n8n AUTOMATIZÁCIÓ ---
n8n:
image: n8nio/n8n:latest
container_name: service_finder_n8n
restart: unless-stopped
ports:
- "5678:5678"
env_file: .env
environment:
- N8N_HOST=0.0.0.0
- N8N_PORT=5678
- N8N_PROTOCOL=http
- N8N_SECURE_COOKIE=false # <--- EZ JAVÍTJA A BELÉPÉSI HIBÁT!
- DB_TYPE=postgresdb
- DB_POSTGRESDB_DATABASE=n8n_internal
- DB_POSTGRESDB_HOST=n8n_db
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_USER=n8n_admin
- DB_POSTGRESDB_PASSWORD=${N8N_DB_PASSWORD}
volumes:
- ./n8n/data:/home/node/.n8n
networks:
- default
- shared_db_net
depends_on:
- n8n_db
# n8n belső meta-adatbázisa
n8n_db:
image: postgres:15-alpine
container_name: service_finder_n8n_db
restart: unless-stopped
environment:
- POSTGRES_USER=n8n_admin
- POSTGRES_PASSWORD=${N8N_DB_PASSWORD}
- POSTGRES_DB=n8n_internal
volumes:
- ./n8n/db_data:/var/lib/postgresql/data
networks:
- default
# Browserless - A robot "szeme" (Központi 3005-ös porton)
browserless:
image: browserless/chrome:latest
container_name: service_finder_browserless
restart: unless-stopped
ports:
- "3005:3000"
environment:
- MAX_CONCURRENT_SESSIONS=10
networks:
- default
networks:
default:
driver: bridge
shared_db_net:
external: true

View File

@@ -0,0 +1,46 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, text
from app.api.deps import get_db, get_current_user
from app.models.vehicle import Vehicle
from app.models.company import CompanyMember
router = APIRouter()
@router.get("/vehicles")
async def get_my_vehicles(db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
# Megkeressük a cégeket (széfeket), amikhez a felhasználónak köze van
company_query = select(CompanyMember.company_id).where(CompanyMember.user_id == current_user.id)
company_res = await db.execute(company_query)
company_ids = company_res.scalars().all()
if not company_ids:
return []
# Lekérjük az összes járművet, ami ezekhez a cégekhez tartozik
query = select(Vehicle).where(Vehicle.current_company_id.in_(company_ids))
result = await db.execute(query)
return result.scalars().all()
@router.post("/vehicles")
async def add_vehicle(vehicle_in: dict, db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
# Itt a meglévő logika fut tovább, de a Vehicle-t a user alapértelmezett cégéhez kötjük
# Először lekérjük a user "owner" típusú cégét
org_query = text("SELECT company_id FROM data.company_members WHERE user_id = :uid AND role = 'owner' LIMIT 1")
org_res = await db.execute(org_query, {"uid": current_user.id})
company_id = org_res.scalar()
if not company_id:
raise HTTPException(status_code=404, detail="Nem található saját széf a jármű rögzítéséhez.")
# Új jármű létrehozása az új modell alapján
new_vehicle = Vehicle(
current_company_id=company_id,
brand_id=vehicle_in.get("brand_id"),
model_name=vehicle_in.get("model_name"),
identification_number=vehicle_in.get("vin"),
license_plate=vehicle_in.get("license_plate")
)
db.add(new_vehicle)
await db.commit()
return {"status": "success", "vehicle_id": str(new_vehicle.id)}

View File

@@ -0,0 +1,48 @@
# /opt/docker/dev/service_finder/backend/app/services/harvester_base.py
import httpx
import logging
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from app.models.asset import AssetCatalog
logger = logging.getLogger(__name__)
class BaseHarvester:
""" MDM Adatgyűjtő Alaposztály. """
def __init__(self, category: str):
self.category = category # 'car', 'motorcycle', 'truck'
self.headers = {"User-Agent": "ServiceFinder-Harvester-Bot/2.1"}
async def check_exists(self, db: AsyncSession, brand: str, model: str, gen: str = None):
""" Ellenőrzi a katalógusban való létezést az új AssetCatalog modellben. """
stmt = select(AssetCatalog).where(
AssetCatalog.make == brand,
AssetCatalog.model == model,
AssetCatalog.vehicle_class == self.category
)
if gen:
stmt = stmt.where(AssetCatalog.generation == gen)
result = await db.execute(stmt)
return result.scalar_one_or_none()
async def log_entry(self, db: AsyncSession, brand: str, model: str, specs: dict):
""" Létrehoz vagy frissít egy bejegyzést. Támogatja a factory_data dúsítást. """
existing = await self.check_exists(db, brand, model, specs.get("generation"))
if not existing:
new_v = AssetCatalog(
make=brand,
model=model,
generation=specs.get("generation"),
year_from=specs.get("year_from"),
year_to=specs.get("year_to"),
vehicle_class=self.category,
fuel_type=specs.get("fuel_type"),
power_kw=specs.get("power_kw"),
engine_capacity=specs.get("engine_capacity"),
factory_data=specs.get("factory_data", {}) # MDM JSONB tárolás
)
db.add(new_v)
logger.info(f"🆕 Új katalógus elem rögzítve: {brand} {model}")
return True
return False

View File

@@ -0,0 +1,12 @@
from .harvester_base import BaseHarvester
class BikeHarvester(BaseHarvester):
def __init__(self):
super().__init__(category="motorcycle")
self.api_url = "https://api.example-bikes.com/v1/" # Példa forrás
async def harvest_all(self, db):
# Ide jön a motor-specifikus API hívás logikája
print("🏍️ Motor Robot: Adatgyűjtés indul...")
# ... fetch és mentés loop ...
await db.commit()

View File

@@ -0,0 +1,48 @@
# /opt/docker/dev/service_finder/backend/app/services/harvester_cars.py
import httpx
import asyncio
from sqlalchemy.ext.asyncio import AsyncSession
from .harvester_base import BaseHarvester
class VehicleHarvester(BaseHarvester):
def __init__(self):
super().__init__(category="car")
self.base_url = "https://www.carqueryapi.com/api/0.3/"
async def _get_api_data(self, params: dict):
async with httpx.AsyncClient() as client:
try:
response = await client.get(self.base_url, params=params, headers=self.headers, timeout=15.0)
if response.status_code == 200:
text = response.text
if text.startswith("?("): text = text[2:-2]
return response.json()
return None
except Exception as e:
print(f"CarQuery Robot Hiba: {e}")
return None
async def harvest_all(self, db: AsyncSession):
""" Automatikus CarQuery szinkronizáció MDM alapon. """
print("🚗 Személyautó Robot: Indul az adatgyűjtés...")
makes_data = await self._get_api_data({"cmd": "getMakes", "sold_in_us": 0})
if not makes_data: return
for make in makes_data.get("Makes", [])[:50]: # Teszt limit
make_id = make['make_id']
make_name = make['make_display']
models_data = await self._get_api_data({"cmd": "getModels", "make": make_id})
if not models_data: continue
for model in models_data.get("Models", []):
specs = {
"factory_data": {"api_source": "carquery", "api_make_id": make_id}
}
await self.log_entry(db, make_name, model['model_name'], specs)
await db.commit()
await asyncio.sleep(1) # Rate limiting
print("🏁 Személyautó Robot: Adatok szinkronizálva.")

View File

@@ -0,0 +1,8 @@
from .harvester_base import BaseHarvester
class TruckHarvester(BaseHarvester):
def __init__(self):
super().__init__(category="truck")
async def run(self, db):
print("🚛 Truck Robot: Nehézgépek és teherautók keresése...")

View File

@@ -0,0 +1,45 @@
# /opt/docker/dev/service_finder/backend/app/init_db_direct.py
import asyncio
import logging
from sqlalchemy import text
from app.database import engine, Base
# 1. LOGIKA: Minden modell importálása
# Ez KRITIKUS: A SQLAlchemy Metadata csak akkor látja a táblákat, ha a Python
# értelmező már "találkozott" az osztályokkal.
from app.models.identity import User, Person, SocialAccount
from app.models.organization import Organization
from app.models.asset import Asset, AssetCatalog, AssetTelemetry
from app.models.service import ServiceProfile, ExpertiseTag, ServiceExpertise
from app.models.system import SystemParameter
from app.models.history import AuditLog
from app.models.security import PendingAction
from app.models.translation import Translation
from app.models.staged_data import ServiceStaging, DiscoveryParameter
from app.models.social import ServiceProvider, Vote, Competition, UserScore
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("DB-Initializer")
async def init_db():
logger.info("🚀 Adatbázis inicializálása indítva (MB2.0 Standard)...")
async with engine.begin() as conn:
# 2. LOGIKA: Sémák létrehozása
# SQLAlchemy nem hozza létre a sémákat automatikusan, ezt nekünk kell megtenni.
logger.info("📂 Sémák létrehozása (identity, data)...")
await conn.execute(text("CREATE SCHEMA IF NOT EXISTS identity;"))
await conn.execute(text("CREATE SCHEMA IF NOT EXISTS data;"))
# 3. LOGIKA: Táblák létrehozása
logger.info("🏗️ Táblák és kapcsolatok generálása a Metadata alapján...")
# Ez a run_sync hívás futtatja le a klasszikus szinkron create_all-t az aszinkron kapcsolaton
await conn.run_sync(Base.metadata.create_all)
logger.info("✅ Minden tábla sikeresen létrejött a megfelelő sémákban!")
if __name__ == "__main__":
try:
asyncio.run(init_db())
except Exception as e:
logger.error(f"❌ Hiba az inicializálás során: {e}")

View File

@@ -0,0 +1,47 @@
from fastapi import FastAPI, Request, HTTPException
from fastapi.security.utils import get_authorization_scheme_param
from app.core.config import settings
from app.core.security import decode_token
from app.api.auth import router as auth_router
from app.api.recommend import router as recommend_router
app = FastAPI(title="Service Finder API")
@app.middleware("http")
async def jwt_claims_middleware(request: Request, call_next):
"""
Ha van Authorization: Bearer <token>, akkor claims bekerül request.state.claims-be.
Auth endpointoknál nem kötelező.
"""
auth = request.headers.get("Authorization")
if auth:
scheme, token = get_authorization_scheme_param(auth)
if scheme.lower() == "bearer" and token:
try:
claims = decode_token(token, settings.JWT_SECRET)
if claims.get("type") != "access":
raise HTTPException(status_code=401, detail="Invalid access token type")
request.state.claims = claims
except Exception:
# nem dobunk mindig 401-et, csak a védett endpointoknál; itt “néma” marad
request.state.claims = None
else:
request.state.claims = None
return await call_next(request)
@app.get("/health")
def health():
return {"status": "ok"}
@app.get("/health/db")
def health_db():
from app.db.session import get_conn
with get_conn() as conn:
with conn.cursor() as cur:
cur.execute("SELECT 1;")
return {"db": "ok", "result": cur.fetchone()[0]}
app.include_router(auth_router)
app.include_router(recommend_router)

View File

@@ -0,0 +1,12 @@
from fastapi import APIRouter
import os
import subprocess
from app.api.v1 import social, users, fleet, auth
api_router = APIRouter()
api_router.include_router(auth.router, prefix="/auth", tags=["Authentication"])
api_router.include_router(social.router, prefix="/social", tags=["Social & Providers"])
api_router.include_router(users.router, prefix="/users", tags=["Users"])
api_router.include_router(fleet.router, prefix="/fleet", tags=["Fleet & Logistics"])

View File

@@ -0,0 +1,24 @@
# /opt/docker/dev/service_finder/backend/app/core/security.py
from datetime import datetime, timedelta, timezone
from typing import Optional, Dict, Any
import bcrypt
from jose import jwt
from app.core.config import settings
def verify_password(plain_password: str, hashed_password: str) -> bool:
if not hashed_password:
return False
return bcrypt.checkpw(plain_password.encode("utf-8"), hashed_password.encode("utf-8"))
def get_password_hash(password: str) -> str:
salt = bcrypt.gensalt()
return bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8")
def create_access_token(data: Dict[str, Any], expires_delta: Optional[timedelta] = None) -> str:
to_encode = data.copy()
if expires_delta:
expire = datetime.now(timezone.utc) + expires_delta
else:
expire = datetime.now(timezone.utc) + timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, settings.SECRET_KEY, algorithm=settings.ALGORITHM)

View File

@@ -0,0 +1,282 @@
import asyncio
import httpx
import logging
import uuid
import os
import sys
import csv
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, text
from sqlalchemy.orm import selectinload
from app.db.session import SessionLocal
# Modellek importálása
from app.models.service import ServiceProfile, ExpertiseTag
from app.models.organization import Organization, OrganizationFinancials, OrgType, OrgUserRole, OrganizationMember
from app.models.identity import Person
from app.models.address import Address, GeoPostalCode
from geoalchemy2.elements import WKTElement
from datetime import datetime, timezone
# Naplózás beállítása
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("Robot2-Dunakeszi-Detective")
class ServiceHunter:
"""
Robot 2.7.2: Dunakeszi Detective - Deep Model Integration.
Logika:
1. Helyi CSV (Saját beküldés - Cím alapú Geocoding-al - 50 pont Trust)
2. OSM (Közösségi adat - 10 pont Trust)
3. Google (Adatpótlás/Fallback - 30 pont Trust)
"""
OVERPASS_URL = "http://overpass-api.de/api/interpreter"
PLACES_NEW_URL = "https://places.googleapis.com/v1/places:searchNearby"
GEOCODE_URL = "https://maps.googleapis.com/maps/api/geocode/json"
GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
LOCAL_CSV_PATH = "/app/app/workers/local_services.csv"
@classmethod
async def geocode_address(cls, address_text):
"""Cím szövegből GPS koordinátát és címkomponenseket csinál."""
if not cls.GOOGLE_API_KEY:
logger.warning("⚠️ Google API kulcs hiányzik!")
return None
params = {"address": address_text, "key": cls.GOOGLE_API_KEY}
try:
async with httpx.AsyncClient() as client:
resp = await client.get(cls.GEOCODE_URL, params=params, timeout=10)
if resp.status_code == 200:
data = resp.json()
if data.get("results"):
result = data["results"][0]
loc = result["geometry"]["location"]
# Címkomponensek kinyerése a kötelező mezőkhöz
components = result.get("address_components", [])
parsed = {"lat": loc["lat"], "lng": loc["lng"], "zip": "", "city": "", "street": "Ismeretlen", "type": "utca", "number": "1"}
for c in components:
types = c.get("types", [])
if "postal_code" in types: parsed["zip"] = c["long_name"]
if "locality" in types: parsed["city"] = c["long_name"]
if "route" in types: parsed["street"] = c["long_name"]
if "street_number" in types: parsed["number"] = c["long_name"]
logger.info(f"📍 Geocoding sikeres: {address_text}")
return parsed
else:
logger.error(f"❌ Geocoding hiba: {resp.status_code}")
except Exception as e:
logger.error(f"❌ Geocoding hiba: {e}")
return None
@classmethod
async def get_google_place_details_new(cls, lat, lon):
"""Google Places API (New) - Adatpótlás FieldMask használatával."""
if not cls.GOOGLE_API_KEY:
return None
headers = {
"Content-Type": "application/json",
"X-Goog-Api-Key": cls.GOOGLE_API_KEY,
"X-Goog-FieldMask": "places.displayName,places.id,places.types,places.internationalPhoneNumber,places.websiteUri"
}
payload = {
"includedTypes": ["car_repair", "gas_station", "ev_charging_station", "car_wash", "motorcycle_repair"],
"maxResultCount": 1,
"locationRestriction": {
"circle": {
"center": {"latitude": lat, "longitude": lon},
"radius": 40.0
}
}
}
try:
async with httpx.AsyncClient() as client:
resp = await client.post(cls.PLACES_NEW_URL, json=payload, headers=headers, timeout=10)
if resp.status_code == 200:
places = resp.json().get("places", [])
if places:
p = places[0]
return {
"name": p.get("displayName", {}).get("text"),
"google_id": p.get("id"),
"types": p.get("types", []),
"phone": p.get("internationalPhoneNumber"),
"website": p.get("websiteUri")
}
except Exception as e:
logger.error(f"❌ Google kiegészítő hívás hiba: {e}")
return None
@classmethod
async def import_local_csv(cls, db: AsyncSession):
"""Manuális adatok betöltése CSV-ből."""
if not os.path.exists(cls.LOCAL_CSV_PATH):
return
try:
with open(cls.LOCAL_CSV_PATH, mode='r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
geo_data = None
if row.get('cim'):
geo_data = await cls.geocode_address(row['cim'])
if geo_data:
element = {
"tags": {
"name": row['nev'], "phone": row.get('telefon'),
"website": row.get('web'), "amenity": row.get('tipus', 'car_repair'),
"addr:full": row.get('cim'),
"addr:city": geo_data["city"], "addr:zip": geo_data["zip"],
"addr:street": geo_data["street"], "addr:type": geo_data["type"],
"addr:number": geo_data["number"]
},
"lat": geo_data["lat"], "lon": geo_data["lng"]
}
await cls.save_service_deep(db, element, source="local_manual")
logger.info("✅ Helyi CSV adatok feldolgozva.")
except Exception as e:
logger.error(f"❌ CSV feldolgozási hiba: {e}")
@classmethod
async def get_or_create_person(cls, db: AsyncSession, name: str) -> Person:
"""Ghost Person kezelése."""
names = name.split(' ', 1)
last_name = names[0]
first_name = names[1] if len(names) > 1 else "Ismeretlen"
stmt = select(Person).where(Person.last_name == last_name, Person.first_name == first_name)
result = await db.execute(stmt); person = result.scalar_one_or_none()
if not person:
person = Person(last_name=last_name, first_name=first_name, is_ghost=True, is_active=False)
db.add(person); await db.flush()
return person
@classmethod
async def enrich_financials(cls, db: AsyncSession, org_id: int):
"""Pénzügyi rekord inicializálása."""
financial = OrganizationFinancials(
organization_id=org_id, year=datetime.now(timezone.utc).year - 1, source="bot_discovery"
)
db.add(financial)
@classmethod
async def save_service_deep(cls, db: AsyncSession, element: dict, source="osm"):
"""Mély mentés a modelled specifikus mezőneveivel és kötelező értékeivel."""
tags = element.get("tags", {})
lat, lon = element.get("lat"), element.get("lon")
if not lat or not lon: return
osm_name = tags.get("name") or tags.get("brand") or tags.get("operator")
google_data = None
if not osm_name or osm_name.lower() in ['aprilia', 'bosch', 'shell', 'mol', 'omv', 'ismeretlen']:
google_data = await cls.get_google_place_details_new(lat, lon)
final_name = (google_data["name"] if google_data else osm_name) or "Ismeretlen Szolgáltató"
stmt = select(Organization).where(Organization.full_name == final_name)
result = await db.execute(stmt); org = result.scalar_one_or_none()
if not org:
# 1. Address létrehozása (a kötelező mezőket kitöltjük az átadott tags-ből vagy alapértékkel)
new_addr = Address(
latitude=lat,
longitude=lon,
full_address_text=tags.get("addr:full") or f"2120 Dunakeszi, {tags.get('addr:street', 'Ismeretlen')} {tags.get('addr:housenumber', '1')}",
street_name=tags.get("addr:street") or "Ismeretlen",
street_type=tags.get("addr:type") or "utca",
house_number=tags.get("addr:number") or tags.get("addr:housenumber") or "1"
)
db.add(new_addr); await db.flush()
# 2. Organization létrehozása (a modelled alapján ezek a mezők itt vannak)
org = Organization(
full_name=final_name,
name=final_name[:50],
org_type=OrgType.service,
address_id=new_addr.id,
address_city=tags.get("addr:city") or "Dunakeszi",
address_zip=tags.get("addr:zip") or "2120",
address_street_name=new_addr.street_name,
address_street_type=new_addr.street_type,
address_house_number=new_addr.house_number
)
db.add(org); await db.flush()
# 3. Service Profile
trust = 50 if source == "local_manual" else (30 if google_data else 10)
spec = {"brands": [], "types": google_data["types"] if google_data else [], "osm_tags": tags}
if tags.get("brand"): spec["brands"].append(tags.get("brand"))
profile = ServiceProfile(
organization_id=org.id,
location=WKTElement(f'POINT({lon} {lat})', srid=4326),
status="ghost",
trust_score=trust,
google_place_id=google_data["google_id"] if google_data else None,
specialization_tags=spec,
website=google_data["website"] if google_data else tags.get("website"),
contact_phone=google_data["phone"] if google_data else tags.get("phone")
)
db.add(profile)
# 4. Tulajdonos rögzítése
owner_name = tags.get("operator") or tags.get("contact:person")
if owner_name and len(owner_name) > 3:
person = await cls.get_or_create_person(db, owner_name)
db.add(OrganizationMember(
organization_id=org.id,
person_id=person.id,
role=OrgUserRole.OWNER,
is_verified=False
))
await cls.enrich_financials(db, org.id)
await db.flush()
logger.info(f"✨ [{source.upper()}] Mentve: {final_name} (Bizalom: {trust})")
@classmethod
async def run(cls):
logger.info("🤖 Robot 2.7.2: Dunakeszi Detective indítása...")
# Kapcsolódási védelem
connected = False
while not connected:
try:
async with SessionLocal() as db:
await db.execute(text("SELECT 1"))
connected = True
except Exception as e:
logger.warning(f"⏳ Várakozás a hálózatra (shared-postgres host?): {e}")
await asyncio.sleep(5)
while True:
async with SessionLocal() as db:
try:
await db.execute(text("SET search_path TO data, public"))
# 1. Beküldött CSV feldolgozása (Geocoding-al)
await cls.import_local_csv(db)
await db.commit()
# 2. OSM Szkennelés
query = """[out:json][timeout:120];area["name"="Dunakeszi"]->.city;(nwr["shop"~"car_repair|motorcycle_repair|tyres|car_parts|motorcycle"](area.city);nwr["amenity"~"car_repair|vehicle_inspection|motorcycle_repair|fuel|charging_station|car_wash"](area.city);nwr["amenity"~"car_repair|fuel|charging_station"](around:5000, 47.63, 19.13););out center;"""
async with httpx.AsyncClient() as client:
resp = await client.post(cls.OVERPASS_URL, data={"data": query}, timeout=120)
if resp.status_code == 200:
elements = resp.json().get("elements", [])
for el in elements:
await cls.save_service_deep(db, el, source="osm")
await db.commit()
except Exception as e:
logger.error(f"❌ Futáshiba: {e}")
logger.info("😴 Scan kész, 24 óra pihenő...")
await asyncio.sleep(86400)
if __name__ == "__main__":
asyncio.run(ServiceHunter.run())

View File

@@ -0,0 +1,115 @@
import asyncio
import httpx
import logging
import os
import datetime
from sqlalchemy import select, and_
from sqlalchemy.exc import IntegrityError
from app.db.session import SessionLocal
from app.models.vehicle_definitions import VehicleModelDefinition
from app.services.ai_service import AIService
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("Robot-Bulk-Master")
class TechEnricher:
API_URL = "https://opendata.rdw.nl/resource/kyri-nuah.json"
RDW_TOKEN = os.getenv("RDW_APP_TOKEN")
HEADERS = {"X-App-Token": RDW_TOKEN} if RDW_TOKEN else {}
@classmethod
async def fetch_rdw_tech_data(cls, make, model):
params = {"merk": make.upper(), "handelsbenaming": str(model).strip().upper(), "$limit": 1}
async with httpx.AsyncClient(headers=cls.HEADERS) as client:
try:
resp = await client.get(cls.API_URL, params=params, timeout=15)
return resp.json()[0] if resp.status_code == 200 and resp.json() else None
except: return None
@classmethod
async def run(cls):
logger.info("🚀 Master-Merge Robot FOLYAMATOS ÜZEMMÓD INDUL...")
while True: # Folyamatos ciklus, amíg el nem fogy az adat
async with SessionLocal() as main_db:
stmt = select(VehicleModelDefinition.id).where(
VehicleModelDefinition.status == "unverified"
).limit(50) # Egyszerre 50 ID-t foglalunk le
res = await main_db.execute(stmt)
ids = res.scalars().all()
if not ids:
logger.info("🏁 Minden rekord feldolgozva. A robot megáll.")
break
logger.info(f"📦 Új csomag indítása: {len(ids)} rekord.")
for m_id in ids:
async with SessionLocal() as db:
try:
current = await db.get(VehicleModelDefinition, m_id)
if not current: continue
logger.info(f"🧪 Feldolgozás: {current.make} {current.marketing_name} (ID: {m_id})")
rdw_data = await cls.fetch_rdw_tech_data(current.make, current.marketing_name)
if rdw_data:
current.engine_capacity = int(float(rdw_data.get("cilinderinhoud", 0))) or current.engine_capacity
current.power_kw = int(float(rdw_data.get("netto_maximum_vermogen_kw", 0))) or current.power_kw
ai_data = await AIService.get_clean_vehicle_data(current.make, current.marketing_name, current.vehicle_type)
if ai_data:
tech_code = ai_data.get("technical_code") or "N/A"
new_ccm = ai_data.get("ccm") or current.engine_capacity
master_record = None
if tech_code and tech_code != "N/A":
stmt_master = select(VehicleModelDefinition).where(and_(
VehicleModelDefinition.make == current.make,
VehicleModelDefinition.technical_code == tech_code,
VehicleModelDefinition.engine_capacity == new_ccm,
VehicleModelDefinition.status == 'ai_enriched',
VehicleModelDefinition.id != m_id
))
master_record = (await db.execute(stmt_master)).scalar_one_or_none()
if master_record:
logger.info(f"🔗 Merge: ID:{m_id} -> Master ID:{master_record.id}")
syns = set(master_record.synonyms or [])
syns.update(ai_data.get("synonyms", []))
syns.add(current.marketing_name)
master_record.synonyms = list(syns)
current.status = "duplicate"
current.parent_id = master_record.id
else:
current.technical_code = tech_code if tech_code != "N/A" else f"N/A-{m_id}"
current.marketing_name = ai_data.get("marketing_name", current.marketing_name)
current.engine_capacity = new_ccm
current.power_kw = ai_data.get("kw") or current.power_kw
current.year_from = ai_data.get("year_from")
current.year_to = ai_data.get("year_to")
current.synonyms = ai_data.get("synonyms", [])
if ai_data.get("maintenance"):
old_spec = current.specifications or {}
old_spec.update(ai_data.get("maintenance"))
current.specifications = old_spec
current.status = "ai_enriched"
else:
if not current.technical_code:
current.technical_code = f"UNKNOWN-{m_id}"
current.updated_at = datetime.datetime.now()
await db.commit()
logger.info(f"✅ Mentve (ID: {m_id})")
except Exception as e:
await db.rollback()
logger.error(f"❌ Hiba ID:{m_id}: {e}")
finally:
await db.close()
if __name__ == "__main__":
asyncio.run(TechEnricher.run())

View File

@@ -0,0 +1,7 @@
# DEPRECATED: Minden funkció átkerült az app.models.identity modulba.
# Ez a fájl csak a kompatibilitás miatt maradt meg, de táblát nem definiál.
from .identity import User, UserRole
# Kapcsolatok
# memberships = relationship("OrganizationMember", back_populates="user", cascade="all, delete-orphan")
# vehicles = relationship("VehicleOwnership", back_populates="user", cascade="all, delete-orphan")

View File

@@ -0,0 +1,109 @@
from sqlalchemy import Column, Integer, String, JSON, UniqueConstraint, text, Boolean, DateTime, ForeignKey, Numeric, Index, Text
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from sqlalchemy.dialects.postgresql import JSONB # PostgreSQL specifikus JSONB a hatékony kereséshez
from app.db.base_class import Base
class VehicleType(Base):
"""Jármű főtípusok sémája (Séma-gazda)"""
__tablename__ = "vehicle_types"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True)
code = Column(String(30), unique=True, index=True) # car, motorcycle, truck, bus, boat, etc.
name = Column(String(50)) # Megjelenítendő név
icon = Column(String(50))
units = Column(JSON, server_default=text("'{\"power\": \"kW\", \"weight\": \"kg\", \"cargo\": \"m3\"}'::jsonb"))
features = relationship("FeatureDefinition", back_populates="vehicle_type")
definitions = relationship("VehicleModelDefinition", back_populates="v_type_rel")
class FeatureDefinition(Base):
"""Globális felszereltség szótár"""
__tablename__ = "feature_definitions"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True)
vehicle_type_id = Column(Integer, ForeignKey("data.vehicle_types.id"))
category = Column(String(50)) # Műszaki, Beltér, Kültér, Multimédia
name = Column(String(100), nullable=False)
data_type = Column(String(20), default="boolean")
vehicle_type = relationship("VehicleType", back_populates="features")
class ModelFeatureMap(Base):
"""Modell-szintű felszereltségi sablon (Alap vs Extra)"""
__tablename__ = "model_feature_maps"
__table_args__ = {"schema": "data"}
model_id = Column(Integer, ForeignKey("data.vehicle_model_definitions.id"), primary_key=True)
feature_id = Column(Integer, ForeignKey("data.feature_definitions.id"), primary_key=True)
availability = Column(String(20), default="standard") # standard, optional, accessory
value = Column(String(100))
class VehicleModelDefinition(Base):
"""MDM Master rekordok - v1.3.0 Pipeline Edition (Researcher & Alchemist)"""
__tablename__ = "vehicle_model_definitions"
__table_args__ = (
UniqueConstraint('make', 'technical_code', 'vehicle_type', name='uix_make_tech_type'),
Index('idx_vmd_lookup', 'make', 'technical_code'),
{"schema": "data"}
)
id = Column(Integer, primary_key=True)
make = Column(String(50), nullable=False, index=True)
technical_code = Column(String(50), nullable=False, index=True)
marketing_name = Column(String(100), index=True)
family_name = Column(String(100))
vehicle_type = Column(String(30), index=True)
vehicle_type_id = Column(Integer, ForeignKey("data.vehicle_types.id"))
vehicle_class = Column(String(50))
parent_id = Column(Integer, ForeignKey("data.vehicle_model_definitions.id"), nullable=True)
year_from = Column(Integer, nullable=True, index=True)
year_to = Column(Integer, nullable=True, index=True)
synonyms = Column(JSON, server_default=text("'[]'::jsonb"))
# --- ROBOT VÉDELMI ÉS PIPELINE MEZŐK (v1.3.0) ---
is_manual = Column(Boolean, default=False, server_default=text("false"), index=True)
attempts = Column(Integer, default=0, server_default=text("0"), index=True)
last_error = Column(Text, nullable=True)
# Robot 2.1 "Researcher" porszívózott nyers adatai (A szemetesláda)
raw_search_context = Column(Text, nullable=True)
# Telemetria és forrás adatok (melyik API/URL hozta az adatot)
research_metadata = Column(JSONB, server_default=text("'{}'::jsonb"), nullable=False)
# --------------------------------------------------
# --- TECHNIKAI FIX OSZLOPOK ---
engine_capacity = Column(Integer, index=True)
power_kw = Column(Integer, index=True)
max_weight_kg = Column(Integer, index=True)
axle_count = Column(Integer)
payload_capacity_kg = Column(Integer)
cargo_volume_m3 = Column(Numeric(10, 2))
cargo_length_mm = Column(Integer)
cargo_width_mm = Column(Integer)
cargo_height_mm = Column(Integer)
specifications = Column(JSON, server_default=text("'{}'::jsonb"))
features_json = Column(JSON, server_default=text("'{}'::jsonb"))
# Státusz mező hossza növelve a pipeline flagekhez
status = Column(String(30), server_default="unverified", index=True)
is_master = Column(Boolean, default=False)
source = Column(String(50)) # 'ROBOT-v1.3.0-Pipeline'
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
# Kapcsolatok
v_type_rel = relationship("VehicleType", back_populates="definitions")
master_record = relationship("VehicleModelDefinition", remote_side=[id], backref="merged_variants")
# AssetCatalog kapcsolat
# Megjegyzés: Ellenőrizd, hogy az AssetCatalog modell be van-e importálva a Base-be!
variants = relationship("AssetCatalog", back_populates="master_definition", primaryjoin="VehicleModelDefinition.id == AssetCatalog.master_definition_id")

View File

@@ -0,0 +1,19 @@
from sqlalchemy import Column, Integer, ForeignKey, DateTime, Boolean
from sqlalchemy.sql import func
from app.db.base import Base
class VehicleOwnership(Base):
__tablename__ = "vehicle_ownerships"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True, index=True)
vehicle_id = Column(Integer, ForeignKey("data.vehicles.id"))
org_id = Column(Integer, ForeignKey("data.organizations.id"))
# Érvényességi időablak
start_date = Column(DateTime(timezone=True), server_default=func.now())
end_date = Column(DateTime(timezone=True), nullable=True) # Ha eladja, ide kerül a dátum
is_active = Column(Boolean, default=True)
# Csak ezen az ablakon belüli szervizeket láthatja az aktuális tulajdonos

View File

@@ -0,0 +1,106 @@
# /app/app/workers/vehicle/vehicle_robot_3_alchemist.py
import asyncio
import logging
from sqlalchemy import select, update, func, and_, case
from app.db.session import AsyncSessionLocal
from app.models.vehicle_definitions import VehicleModelDefinition
from app.services.ai_service import AIService
# MB 2.0 Naplózás
logging.basicConfig(level=logging.INFO, format='%(asctime)s [%(levelname)s] %(name)s: %(message)s')
logger = logging.getLogger("Vehicle-Robot-3-Alchemist")
class VehicleAlchemist:
"""
Vehicle Robot 3: AI Synthesizer (Alchemist)
Feladata: A kutatási kontextusból strukturált "Gold Data" kinyerése AI segítségével.
"""
def __init__(self):
self.batch_size = 5
self.delay_between_records = 12 # P4000 GPU kímélő késleltetés
async def synthesize_vehicle(self, vehicle_id: int):
""" AI dúsítás végrehajtása az Ollama/AI segítségével. """
async with AsyncSessionLocal() as db:
# Szigorú sémakezelés és zárolás
res = await db.execute(
select(VehicleModelDefinition)
.where(VehicleModelDefinition.id == vehicle_id)
.with_for_update(skip_locked=True)
)
v = res.scalar_one_or_none()
if not v or not v.raw_search_context:
logger.warning(f"⚠️ Nincs feldolgozható kontextus ID:{vehicle_id}")
return
make, model = v.make, v.marketing_name
logger.info(f"🧪 Transzmutáció indul: {make} {model}")
# Státusz váltás a feldolgozás idejére
v.status = 'ai_synthesis_in_progress'
await db.commit()
# AI hívás a háttérben (Ollama konténer felé)
# Itt történik a "mágia": a nyers szövegből JSON lesz
gold_data = await AIService.get_gold_data_from_research(make, model, v.raw_search_context)
async with AsyncSessionLocal() as db:
if gold_data:
# Strukturált adatok rögzítése a 'data' sémába
await db.execute(
update(VehicleModelDefinition)
.where(VehicleModelDefinition.id == vehicle_id)
.values(
marketing_name=gold_data.get("marketing_name", model)[:50],
technical_code=gold_data.get("technical_code") or v.technical_code,
engine_capacity=gold_data.get("ccm"),
power_kw=gold_data.get("kw"),
specifications=gold_data, # JSONB mező a teljes technikai laphoz
status='gold_enriched', # MB 2.0: Ez a legmagasabb adatszint
updated_at=func.now()
)
)
logger.info(f"✨ ARANY ADAT GENERÁLVA: {make} {model}")
else:
# Ha az AI elbukott, visszatesszük várakozóba
await db.execute(
update(VehicleModelDefinition)
.where(VehicleModelDefinition.id == vehicle_id)
.values(status='awaiting_ai_synthesis', attempts=v.attempts + 1)
)
logger.warning(f"⚠️ AI hiba, visszatéve a sorba: {make} {model}")
await db.commit()
async def run(self):
logger.info("🚀 Vehicle Alchemist ONLINE - Adatpárolás indul...")
while True:
async with AsyncSessionLocal() as db:
# MB 2.0 Prioritás: Legnépszerűbb márkák az élen
top_makes = ['SUZUKI', 'TOYOTA', 'SKODA', 'VOLKSWAGEN', 'OPEL']
priorities = case(
(and_(VehicleModelDefinition.vehicle_type == 'car',
VehicleModelDefinition.make.in_(top_makes)), 1),
(VehicleModelDefinition.vehicle_type == 'car', 2),
(VehicleModelDefinition.vehicle_type == 'motorcycle', 3),
else_=4
)
stmt = select(VehicleModelDefinition.id).where(
VehicleModelDefinition.status == 'awaiting_ai_synthesis'
).order_by(priorities, VehicleModelDefinition.updated_at.asc()).limit(self.batch_size)
res = await db.execute(stmt)
ids = [r[0] for r in res.fetchall()]
if not ids:
await asyncio.sleep(20)
continue
for vid in ids:
await self.synthesize_vehicle(vid)
await asyncio.sleep(self.delay_between_records)
if __name__ == "__main__":
asyncio.run(VehicleAlchemist().run())

View File

@@ -0,0 +1,23 @@
from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.models.vehicle import VehicleBrand # Feltételezve, hogy létezik a modell
from typing import List
router = APIRouter()
@router.get("/search/brands")
def search_brands(q: str = Query(..., min_length=2), db: Session = Depends(get_db)):
# 1. KERESÉS A SAJÁT ADATBÁZISBAN
results = db.query(VehicleBrand).filter(
VehicleBrand.name.ilike(f"%{q}%"),
VehicleBrand.is_active == True
).limit(10).all()
# 2. HA NINCS TALÁLAT, INDÍTHATJUK A BOT-OT (Logikai váz)
if not results:
# Itt hívnánk meg a Discovery Bot-ot async módon
# discovery_bot.find_brand_remotely(q)
return {"status": "not_found", "message": "Nincs találat, a Bot elindult keresni...", "data": []}
return {"status": "success", "data": results}

View File

@@ -0,0 +1,59 @@
from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import text
from app.api.deps import get_db, get_current_user
from typing import List, Dict, Optional
from app.models.vehicle import Vehicle
router = APIRouter()
@router.get("/search/brands")
async def search_brands(q: str = Query(..., min_length=2), db: AsyncSession = Depends(get_db)):
query = text("""
SELECT id, name, slug, country_of_origin
FROM data.vehicle_brands
WHERE (name ILIKE :q OR slug ILIKE :q) AND is_active = true
ORDER BY name ASC LIMIT 10
""")
# 1. Megvárjuk az execute-ot
result = await db.execute(query, {"q": f"%{q}%"})
# 2. Külön hívjuk a fetchall-t az eredményen
rows = result.fetchall()
brand_list = [dict(row._mapping) for row in rows]
if not brand_list:
return {"status": "discovery_mode", "data": []}
return {"status": "success", "data": brand_list}
@router.get("/search/providers")
async def search_providers(q: str = Query(..., min_length=2), db: AsyncSession = Depends(get_db)):
query = text("""
SELECT id, name, technical_rating_pct, location_city, service_type
FROM data.service_providers
WHERE (name ILIKE :q OR service_type ILIKE :q) AND is_active = true
ORDER BY technical_rating_pct DESC LIMIT 15
""")
result = await db.execute(query, {"q": f"%{q}%"})
rows = result.fetchall()
return {"status": "success", "data": [dict(row._mapping) for row in rows]}
@router.post("/register")
async def register_user_vehicle(data: dict, db: AsyncSession = Depends(get_db), current_user = Depends(get_current_user)):
company_res = await db.execute(text("SELECT id FROM data.companies WHERE owner_id = :u LIMIT 1"), {"u": current_user.id})
company = company_res.fetchone()
if not company:
raise HTTPException(status_code=404, detail="Széf nem található.")
new_vehicle = Vehicle(
current_company_id=company.id,
brand_id=data.get("brand_id"),
model_name=data.get("model_name"),
engine_spec_id=data.get("engine_spec_id"),
identification_number=data.get("vin"),
license_plate=data.get("plate"),
tracking_mode=data.get("tracking_mode", "km"),
total_real_usage=data.get("current_odo", 0)
)
db.add(new_vehicle)
await db.commit()
return {"status": "success", "vehicle_id": str(new_vehicle.id)}

Some files were not shown because too many files have changed in this diff Show More