From cd171d328906178be065cc5dfca5278ead22158b Mon Sep 17 00:00:00 2001 From: Kincses Date: Sat, 7 Feb 2026 01:16:07 +0000 Subject: [PATCH] STABLE: KYC and Auth working, before Asset refactor --- backend/app/models/__init__.py | 39 +++-- .../__pycache__/__init__.cpython-312.pyc | Bin 624 -> 711 bytes .../__pycache__/vehicle.cpython-312.pyc | Bin 5521 -> 5835 bytes backend/app/models/vehicle.py | 161 +++++++++++------- .../harvester_robot.cpython-312.pyc | Bin 0 -> 4204 bytes backend/app/services/harvester_robot.py | 84 +++++++++ backend/test_robot.py | 20 +++ docs/V01_gemini/15_Changelog.md | 25 +++ .../18_ASSET_AND_FLEET_SPECIFICATION.md | 69 ++++++++ 9 files changed, 320 insertions(+), 78 deletions(-) create mode 100644 backend/app/services/__pycache__/harvester_robot.cpython-312.pyc create mode 100644 backend/app/services/harvester_robot.py create mode 100644 backend/test_robot.py create mode 100644 docs/V01_gemini/18_ASSET_AND_FLEET_SPECIFICATION.md diff --git a/backend/app/models/__init__.py b/backend/app/models/__init__.py index 976b873..86cf85f 100755 --- a/backend/app/models/__init__.py +++ b/backend/app/models/__init__.py @@ -1,21 +1,36 @@ from app.db.base import Base -from .identity import User, Person, Wallet, UserRole +from .identity import User, Person, Wallet, UserRole, VerificationToken from .organization import Organization, OrgType from .vehicle import ( - Vehicle, - VehicleBrand, - EngineSpec, - ServiceProvider, - ServiceRecord, - OrganizationMember + VehicleCatalog, + Asset, + AssetEvent, + AssetRating, + ServiceProvider, + Vehicle, # Alias az Asset-re a kompatibilitás miatt + ServiceRecord # Alias az AssetEvent-re a kompatibilitás miatt ) -# Aliasok a kód többi részének +# Aliasok a kód többi részének szinkronizálásához UserVehicle = Vehicle +VehicleOwnership = Asset __all__ = [ - "Base", "User", "Person", "Wallet", "UserRole", - "Vehicle", "UserVehicle", "VehicleBrand", "EngineSpec", - "ServiceProvider", "ServiceRecord", "Organization", - "OrgType", "OrganizationMember" + "Base", + "User", + "Person", + "Wallet", + "UserRole", + "VerificationToken", + "Organization", + "OrgType", + "VehicleCatalog", + "Asset", + "AssetEvent", + "AssetRating", + "ServiceProvider", + "Vehicle", + "UserVehicle", + "ServiceRecord", + "VehicleOwnership" ] \ No newline at end of file diff --git a/backend/app/models/__pycache__/__init__.cpython-312.pyc b/backend/app/models/__pycache__/__init__.cpython-312.pyc index 8118be38e9c386794a7b1c113bdb81b086ad1a49..c06132a386c336dd89b735ea39577934585b57a0 100644 GIT binary patch delta 484 zcmYk2KT88K7{-%p&$PYX^{&+-sNf*V4WfgSPAclA;=du_aNfPvU~^Y;rJ{?v2yT{s z1MzD(JGi(A5)fy%>LNIq939N?%lo|Hd6K;S{FCWC+ja@5^>}x~7IR%^6t}uFGe?|I zf>C5d`DTF^X_1#`Dbr@t;$>RqHnq7!9bTao?oyX~)ZBu?p z3!nN1AItnokisX{!t6dwUP|u(1UqJ7&}K=zmz+ZE8?wA58bQo1vZf?T?VY#4C(=29 z6BagMHE0LTq#@1aG=;V-W!qW@;g7 z{(UCP5tg=*PVW$pjkr49)6ij}rZL?6#Y^iGs??K87ZmzAjPW}f|3DkBXyXIT{TKyo d{2+xdjeZ?f>Q~lVZS)1X-}$O#ToW;-jDLH9gd_j} delta 406 zcmYk2Jxc>I7{`pzNgj%o@hjufcfQY<3}tjo9oX zZWEgqNa0so{UUdW!(HNXk9gcCJ`YI1OQZw=bx64f;`|FFl`+EhTzAD#n(c5%=THlC z`dWX)hIG$GFHG2dc*oL2BBidz1B&w!b?GgO`c%3rr!B%Hmc^r_#}e8Z&`1UyDn=}# z7a|?8m@$&K_VRJ2nmuw^fz?@(?R5auC8VurmX#Ptclyy`_Pm Wu>=Z>O%QB7Ip3z`7!xFFD*Ff8H*CEC diff --git a/backend/app/models/__pycache__/vehicle.cpython-312.pyc b/backend/app/models/__pycache__/vehicle.cpython-312.pyc index 1d289e14bfd4cdbce2a39ff86896a344ddcfadd1..d88f26d16eed5b4d4e9070f6e8c4710627bd925b 100644 GIT binary patch literal 5835 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 literal 5521 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 R^&#D`$XMZd$aqbo{{vxq1pxp6 literal 0 HcmV?d00001 diff --git a/backend/app/services/harvester_robot.py b/backend/app/services/harvester_robot.py new file mode 100644 index 0000000..3caf7d9 --- /dev/null +++ b/backend/app/services/harvester_robot.py @@ -0,0 +1,84 @@ +import httpx +import asyncio +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import select +from app.models.vehicle import VehicleCatalog # Az imént létrehozott modell + +class VehicleHarvester: + def __init__(self): + # Az ingyenes CarQueryAPI URL-je (0.3-as verzió) + self.base_url = "https://www.carqueryapi.com/api/0.3/" + self.headers = {"User-Agent": "ServiceFinder-Harvester-Bot/1.0"} + + async def get_data(self, params: dict): + """Segédfüggvény az API hívásokhoz.""" + async with httpx.AsyncClient() as client: + try: + response = await client.get(self.base_url, params=params, headers=self.headers, timeout=10.0) + if response.status_code == 200: + # Az API néha JSONP-t ad vissza, ezt itt lekezeljük (levágjuk a felesleget) + text = response.text + if text.startswith("?("): text = text[2:-2] + return response.json() + return None + except Exception as e: + print(f"Robot hiba: {str(e)}") + return None + + async def harvest_all(self, db: AsyncSession): + """A fő folyamat: Minden márka -> Minden modell szinkronizálása.""" + print("🤖 Robot: Indul a nagy adatgyűjtés...") + + # 1. Márkák lekérése + makes_data = await self.get_data({"cmd": "getMakes", "sold_in_us": 0}) + if not makes_data: return + + makes = makes_data.get("Makes", []) + + for make in makes: + make_id = make['make_id'] + make_display = make['make_display'] + print(f"--- 🚗 Feldolgozás: {make_display} ---") + + # 2. Modellek lekérése ehhez a márkához + models_data = await self.get_data({"cmd": "getModels", "make": make_id}) + if not models_data: continue + + models = models_data.get("Models", []) + + for model in models: + model_name = model['model_name'] + + # 3. Megnézzük, benne van-e már a katalógusban + stmt = select(VehicleCatalog).where( + VehicleCatalog.brand == make_display, + VehicleCatalog.model == model_name + ) + res = await db.execute(stmt) + if res.scalar_one_or_none(): + continue # Ha már megvan, ugrunk a következőre + + # 4. Új bejegyzés létrehozása alapadatokkal + # Itt a Robot később "mélyebbre" áshat a specifikációkért + new_v = VehicleCatalog( + brand=make_display, + model=model_name, + category="car", # Alapértelmezett, később finomítható + factory_specs={ + "api_make_id": make_id, + "harvester_source": "carquery" + } + ) + db.add(new_v) + print(f"✅ Robot rögzítve: {make_display} {model_name}") + + # Márkánként mentünk, hogy ne vesszen el a munka, ha megszakad + await db.commit() + await asyncio.sleep(1) # Ne terheljük túl az ingyenes API-t (Rate Limit védelem) + + print("🏁 Robot: A munka oroszlánrésze kész!") + +# Ez a rész csak a teszteléshez kell, ha manuálisan indítod a scriptet +if __name__ == "__main__": + # Itt lehetne egy külön indító logika + pass \ No newline at end of file diff --git a/backend/test_robot.py b/backend/test_robot.py new file mode 100644 index 0000000..9ac6768 --- /dev/null +++ b/backend/test_robot.py @@ -0,0 +1,20 @@ +import asyncio +from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession +from sqlalchemy.orm import sessionmaker +from app.services.harvester_robot import VehicleHarvester +from app.core.config import settings + +# Adatbázis kapcsolat felépítése a pontos névvel +engine = create_async_engine(str(settings.DATABASE_URL)) +AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) + +async def run_test(): + async with AsyncSessionLocal() as db: + harvester = VehicleHarvester() + print("🚀 Robot indítása...") + # Megpróbáljuk betölteni a katalógust + await harvester.harvest_all(db) + print("✅ Teszt lefutott.") + +if __name__ == "__main__": + asyncio.run(run_test()) \ No newline at end of file diff --git a/docs/V01_gemini/15_Changelog.md b/docs/V01_gemini/15_Changelog.md index 577891b..2206888 100644 --- a/docs/V01_gemini/15_Changelog.md +++ b/docs/V01_gemini/15_Changelog.md @@ -93,3 +93,28 @@ A fejlesztések rendben tartásához javaslom a **`17_DEVELOPER_NOTES_AND_PITFAL **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. \ No newline at end of file diff --git a/docs/V01_gemini/18_ASSET_AND_FLEET_SPECIFICATION.md b/docs/V01_gemini/18_ASSET_AND_FLEET_SPECIFICATION.md new file mode 100644 index 0000000..ef9d519 --- /dev/null +++ b/docs/V01_gemini/18_ASSET_AND_FLEET_SPECIFICATION.md @@ -0,0 +1,69 @@ +# 🏎️ Asset és Flotta Specifikáció: A Járművek DNS-e + +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 nincs különbség egy magánszemély és egy cég között a technikai rétegben. +- **Privát Flotta:** A regisztráció (Step 2) során automatikusan létrejövő szervezet (Organization). +- **Széf (Safe Deposit):** A flotta része, ahol az eszközök (járművek) és azok bizalmas okmányai laknak. + +## 2. Eszköz Típusok és Speciális Azonosítók +Minden eszköz rendelkezik egy **Univerzális Állandó Azonosítóval (UAI)**, ami az életútja során soha nem változik. + +| Típus | Elsődleges Azonosító (UAI) | Speciális Adatpontok | +| :--- | :--- | :--- | +| **Közúti** | VIN (Alvázszám) | Rendszám, Motorkód, Sebességváltó kód | +| **Vízi** | HIN (Hull ID / Testszám) | MMSI kód, IMO szám, Név | +| **Légi** | Serial Number (Gyári szám) | Lajstromjel (Registration), Típusjelzés | +| **Egyéb** | Egyedi sorozatszám | Gyártó, Teljesítmény | + +### 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, munkagépek és versenytechnika esetén kritikus. + +## 3. A Jármű DNS (Deep Data Structure) +Az adatbázisnak ismernie kell a járművet "gyári" állapotában és annak minden módosítását. + +### A) Gyári Konfiguráció (Factory Specs) +- **Trim Level:** Felszereltségi csomag (pl. S-Line, AMG Pack, Comfortline). +- **Technikai paraméterek:** Motorválaszték, kW/LE, nyomaték, gyári felni- és gumiméret (ET számmal), folyadékmennyiségek. +- **Szervizintervallumok:** Gyártó által előírt periodikus karbantartások (idő vagy távolság alapú). + +### B) Aktuális Állapot és Módosítások (Modifications) +- **Gyári extrák:** Mi az, ami benne maradt? (pl. bőrbelső, napfénytető). +- **Utólagos (Aftermarket):** Mi került bele? (pl. vonóhorog, gázszett). +- **Hiányzó:** Mi került ki belőle? (pl. kiszerelt gyári hifi). + +## 4. Digitális Szervizkönyv (Digital Service Book) +Nem csak egy lista, hanem egy **Eseményalapú Idővonal (Timeline)**. Minden bejegyzés megváltoztathatatlan (immutable-szerű) logként rögzül. +- **Típusok:** Karbantartás, Javítás, Műszaki Vizsga, Baleset, Tulajdonosváltás. +- **Csatolmányok:** Fotók az alkatrészekről, számlák PDF-ben, munkalapok. + +## 5. Jármű Minősítés és Értékelés +A jármű két különálló, de egymást kiegészítő minősítést kap: + +### A) Technikai Minősítés (AI Health Score) +- **Algoritmus alapú:** A szerviztörténet, az üzemóra/futás aránya és a gyári specifikációk betartása alapján kalkulált pontszám. + +### B) Emocionális és Közösségi Értékelés (Driver Rating) +A járművet használó sofőrök értékelhetik az eszközt szubjektív szempontok alapján: +- **Komfort:** Mennyire kényelmes hosszú távon? +- **Vezetési élmény:** "Lelke van", vagy csak egy gép? +- **Praktikum:** Mennyire használható a mindennapokban? +- **Megbízhatóság érzet:** Mennyire érzi magát benne biztonságban a sofőr? + +Ez a kettős mérőszám adja meg a jármű valós "piaci és használati értékét". + +## 6. Az Adat-Gondnok (Harvester Robot) +A rendszer integritásáért és az adatok pontosságáért egy automata Robot felel. + +### Funkciók: +1. **Initial Load:** A legnépszerűbb 1000 európai járműtípus alapértelmezett feltöltése. +2. **On-Demand Fetch:** Ha egy felhasználó ismeretlen típust keres, a Robot prioritással kutatja fel és rögzíti azt. +3. **Deep Data Scrape:** A Robot nemcsak a típust, hanem a gyári specifikációkat (olajmennyiség, guminyomás, szervizintervallum) is gyűjti. +4. **Maintenance:** Negyedévente frissíti a meglévő adatokat (új modellévek, módosított gyári előírások). + +### Adatforrások hierarchiája: +1. Hivatalos gyártói API-k (ahol elérhető). +2. Nyilvános műszaki adatbázisok (Auto-Data, UltimateSpecs). +3. VIN/HIN dekóder algoritmusok. \ No newline at end of file