From 4e14d57bf6243a5d700d485a7535e524e0a5ca46 Mon Sep 17 00:00:00 2001 From: Kincses Date: Sat, 7 Feb 2026 22:16:03 +0000 Subject: [PATCH] FEAT: Integrated Document Engine with WebP optimization, Thumbnail generation and Hybrid (NAS/SSD) storage logic --- backend/Dockerfile | 7 +- .../api/v1/__pycache__/api.cpython-312.pyc | Bin 818 -> 954 bytes backend/app/api/v1/api.py | 15 +- .../__pycache__/documents.cpython-312.pyc | Bin 0 -> 1534 bytes backend/app/api/v1/endpoints/documents.py | 30 +++ backend/app/main.py | 23 +- .../__pycache__/document.cpython-312.pyc | Bin 0 -> 1693 bytes backend/app/models/document.py | 26 ++ .../document_service.cpython-312.pyc | Bin 0 -> 3963 bytes backend/app/services/document_service.py | 82 ++++++ backend/requirements.txt | 1 + docker-compose.yml | 18 +- docs/V01_gemini/05_AUTH_AND_IDENTITY_SPEC.md | 165 ++++++------ docs/V01_gemini/06_Database_Guide.md | 183 ++++++------- docs/V01_gemini/07_API_Guide.md | 71 ++--- .../07_REGISTRATION_INVITATION_AND_API.md | 206 +++++--------- .../10_Billing_Credits_Subscriptions.md | 86 +++--- .../18_ASSET_AND_FLEET_SPECIFICATION.md | 254 ++++++------------ .../19_ADMIN_AND_PERMISSIONS_SPEC.md | 97 ++++--- ...c7b-0f4d-4a04-875e-9e85a5621c46_thumb.webp | Bin 0 -> 14686 bytes 20 files changed, 657 insertions(+), 607 deletions(-) create mode 100644 backend/app/api/v1/endpoints/__pycache__/documents.cpython-312.pyc create mode 100644 backend/app/api/v1/endpoints/documents.py create mode 100644 backend/app/models/__pycache__/document.cpython-312.pyc create mode 100644 backend/app/models/document.py create mode 100644 backend/app/services/__pycache__/document_service.cpython-312.pyc create mode 100644 backend/app/services/document_service.py create mode 100644 static_previews/organizations/6/067b6c7b-0f4d-4a04-875e-9e85a5621c46_thumb.webp diff --git a/backend/Dockerfile b/backend/Dockerfile index 25809c6..00bee41 100755 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -2,17 +2,20 @@ FROM python:3.12-slim WORKDIR /app -# 1. Rendszerfüggőségek telepítése +# 1. Rendszerfüggőségek telepítése (gcc és képkezelő könyvtárak) RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ python3-dev \ libpq-dev \ + libjpeg-dev \ + zlib1g-dev \ && rm -rf /var/lib/apt/lists/* -# 2. PIP frissítése (Ez némítja el a panaszkodást) +# 2. PIP frissítése RUN pip install --upgrade pip # 3. Függőségek telepítése +# Fontos: A requirements.txt fájlba írd be: Pillow==10.2.0 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt diff --git a/backend/app/api/v1/__pycache__/api.cpython-312.pyc b/backend/app/api/v1/__pycache__/api.cpython-312.pyc index e3466a7a21b1b5f47052ab88011f6ed3bb91be90..b86352d0bb16adeb4dc38de8e25c5067e4d714ba 100644 GIT binary patch delta 363 zcmdnQwu_zjG%qg~0}#Y*ZO^4BO~Ko2HE=zu9q2HCkrz- Na9m|bC=v!r0RRh2D1`t3 diff --git a/backend/app/api/v1/api.py b/backend/app/api/v1/api.py index 9637aa4..5463e63 100755 --- a/backend/app/api/v1/api.py +++ b/backend/app/api/v1/api.py @@ -1,16 +1,19 @@ from fastapi import APIRouter -from app.api.v1.endpoints import auth, catalog, assets, organizations +from app.api.v1.endpoints import auth, catalog, assets, organizations, documents # <--- Ide bekerült a documents! api_router = APIRouter() -# Felhasználó és Identitás +# Hitelesítés api_router.include_router(auth.router, prefix="/auth", tags=["Authentication"]) -# Katalógus és Jármű Robotok +# Katalógus api_router.include_router(catalog.router, prefix="/catalog", tags=["Vehicle Catalog"]) -# Egyedi Eszközök (Assets) +# Eszközök (Járművek) api_router.include_router(assets.router, prefix="/assets", tags=["Assets"]) -# Szervezetek és Onboarding -api_router.include_router(organizations.router, prefix="/organizations", tags=["Organizations"]) \ No newline at end of file +# Szervezetek +api_router.include_router(organizations.router, prefix="/organizations", tags=["Organizations"]) + +# DOKUMENTUMOK (Ez az új rész, ami hiányzik neked) +api_router.include_router(documents.router, prefix="/documents", tags=["Documents"]) \ No newline at end of file diff --git a/backend/app/api/v1/endpoints/__pycache__/documents.cpython-312.pyc b/backend/app/api/v1/endpoints/__pycache__/documents.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e69bc64524d7539bc54d41c99093a7ec9669349b GIT binary patch literal 1534 zcmZuxO=w(I6u$3w{(l-Bo4?wZO~V8`W5pth2(eKVAv8^dGAaLeJG|l~++-!$;Z-N)rYmU)$%sgsy|9%G$t<1dKlbp%+NRW%z*@!n5lJS=zBDi6 z7|G!{>;%zpk|;Pu;`2$I{!lx7A>YUpvww?VMLkMPo`3U#A96yY*c1tfhgp<-J8*mp zzivAuQad#Fs#RNFpnmA#Ig2f`DD%eL-1*lo)kwf?-z!Q{dXhD~+ALwLE9(n{o45)$ zxhcOEy2RtNgx2jESs5#bo%rR;fki=Y@b4<#F~mZH>=t0>VEY#imQhl!ZHlZiSn z(v)$vraeRp#elyG``|kuZy^aP)r3mbC7R(q91&CoD_^Oba@X&Q#FZ|G&=OSr@zqqC zs3|qoro7pE=_SKK+(9gL z{EuMzk}>Yn11(rSH7>#Ys1 z!HGjWqt@DRPV?67AY^0UoMPPKAv0?}CXtQ_w`^xRDg@N8L7Nb4S{^p*R_Jhoi)xg@ zy*@Fa&I!I4x>XN6L=N_X?OBfLSuOmRNVXsc75igix~XNV8J^>&>2~TNfSv7~;>O20r7F z!Z_`qvw;pE0-`5HocPPGk3)yNLMK2Jv&ljrZAFr#-_XS!ba4-r_t4lLdhz$fz$YVX z`h6*OZRCTIt<1Ccq%-?TG&p+W-1WvU$Dh7YzyAJysvzmR$DV8}aNf@iv^6*Z%j2io eF~P-As?bgdE{PI_e}wgcg5>A+W#DKLUj7eOSf$GV literal 0 HcmV?d00001 diff --git a/backend/app/api/v1/endpoints/documents.py b/backend/app/api/v1/endpoints/documents.py new file mode 100644 index 0000000..ba14c90 --- /dev/null +++ b/backend/app/api/v1/endpoints/documents.py @@ -0,0 +1,30 @@ +from fastapi import APIRouter, Depends, UploadFile, File, BackgroundTasks, HTTPException +from sqlalchemy.ext.asyncio import AsyncSession +from app.db.session import get_db +from app.services.document_service import DocumentService + +router = APIRouter() + +@router.post("/upload/{parent_type}/{parent_id}") +async def upload_document( + parent_type: str, + parent_id: str, + background_tasks: BackgroundTasks, + file: UploadFile = File(...), + db: AsyncSession = Depends(get_db) +): + """ + Dokumentum feltöltés, optimalizálás és NAS-ra mentés. + parent_type: 'organizations' vagy 'assets' + """ + if parent_type not in ["organizations", "assets"]: + raise HTTPException(status_code=400, detail="Érvénytelen cél-típus!") + + doc = await DocumentService.process_upload(file, parent_type, parent_id, db, background_tasks) + + return { + "document_id": doc.id, + "thumbnail": doc.thumbnail_path, + "original_name": doc.original_name, + "status": "processed_and_vaulted" + } \ No newline at end of file diff --git a/backend/app/main.py b/backend/app/main.py index f925858..d193f4e 100755 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -1,30 +1,45 @@ +import os from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware +from fastapi.staticfiles import StaticFiles from app.api.v1.api import api_router from app.core.config import settings +# 1. Könyvtárstruktúra biztosítása (SSD puffer a miniképeknek) +# Ez garantálja, hogy az app elindulásakor létezik a célmappa +os.makedirs("static/previews", exist_ok=True) + app = FastAPI( title="Service Finder API", - version="2.0.0", # A rendszer verziója, de a végpont marad v1 + version="2.0.0", openapi_url="/api/v1/openapi.json", docs_url="/docs" ) -# PONTOS CORS BEÁLLÍTÁS +# 2. PONTOS CORS BEÁLLÍTÁS app.add_middleware( CORSMiddleware, allow_origins=[ "http://192.168.100.10:3001", # Frontend portja "http://localhost:3001", - "https://dev.profibot.hu" # Ha van NPM proxy + "https://dev.profibot.hu" # NPM proxy esetén ], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) +# 3. STATIKUS FÁJLOK KISZOLGÁLÁSA +# Ez teszi lehetővé, hogy a /static eléréssel lekérhetőek legyenek a miniképek +app.mount("/static", StaticFiles(directory="static"), name="static") + +# 4. ROUTER BEKÖTÉSE app.include_router(api_router, prefix="/api/v1") @app.get("/") async def root(): - return {"status": "online", "message": "Service Finder Master System v1.0"} \ No newline at end of file + return { + "status": "online", + "message": "Service Finder Master System v2.0", + "features": ["Document Engine", "Asset Vault", "Org Onboarding"] + } \ No newline at end of file diff --git a/backend/app/models/__pycache__/document.cpython-312.pyc b/backend/app/models/__pycache__/document.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ca8f2c8a92a7c4143cc85722161275599b6bd9d1 GIT binary patch literal 1693 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 PdwPH%+MXi(Hbwm#5qq4t literal 0 HcmV?d00001 diff --git a/backend/app/services/document_service.py b/backend/app/services/document_service.py new file mode 100644 index 0000000..ab2eadb --- /dev/null +++ b/backend/app/services/document_service.py @@ -0,0 +1,82 @@ +import os +import shutil +import time +from PIL import Image +from uuid import uuid4 +from fastapi import UploadFile, BackgroundTasks +from sqlalchemy.ext.asyncio import AsyncSession +from app.models.document import Document + +class DocumentService: + @staticmethod + def _clean_temp(path: str): + """30 perc után törli az ideiglenes fájlt (opcionális, ha maradunk a puffer mellett)""" + time.sleep(1800) + if os.path.exists(path): + os.remove(path) + + @staticmethod + async def process_upload( + file: UploadFile, + parent_type: str, + parent_id: str, + db: AsyncSession, + background_tasks: BackgroundTasks + ): + file_uuid = str(uuid4()) + + # 1. Könyvtárstruktúra meghatározása + temp_dir = "/app/temp/uploads" + nas_vault_dir = f"/mnt/nas/app_data/organizations/{parent_id}/vault" + ssd_thumb_dir = f"/app/static/previews/organizations/{parent_id}" + + for d in [temp_dir, nas_vault_dir, ssd_thumb_dir]: + os.makedirs(d, exist_ok=True) + + # 2. Mentés a TEMP-be + temp_path = os.path.join(temp_dir, f"{file_uuid}_{file.filename}") + content = await file.read() + with open(temp_path, "wb") as f: + f.write(content) + + # 3. Képfeldolgozás (Pillow) + img = Image.open(temp_path) + + # A) Thumbnail generálás (300px WebP az SSD-re) + thumb_filename = f"{file_uuid}_thumb.webp" + thumb_path = os.path.join(ssd_thumb_dir, thumb_filename) + thumb_img = img.copy() + thumb_img.thumbnail((300, 300)) + thumb_img.save(thumb_path, "WEBP", quality=80) + + # B) Nagy kép optimalizálás (Max 1600px WebP a NAS-ra) + vault_filename = f"{file_uuid}.webp" + vault_path = os.path.join(nas_vault_dir, vault_filename) + + if img.width > 1600: + ratio = 1600 / float(img.width) + new_height = int(float(img.height) * float(ratio)) + img = img.resize((1600, new_height), Image.Resampling.LANCZOS) + + img.save(vault_path, "WEBP", quality=85) + + # 4. Adatbázis rögzítés + new_doc = Document( + id=uuid4(), + parent_type=parent_type, + parent_id=parent_id, + original_name=file.filename, + file_hash=file_uuid, + file_size=os.path.getsize(vault_path), + has_thumbnail=True, + thumbnail_path=f"/static/previews/organizations/{parent_id}/{thumb_filename}" + ) + db.add(new_doc) + await db.commit() + + # 5. Puffer törlés ütemezése (30 perc) + # background_tasks.add_task(DocumentService._clean_temp, temp_path) + # MVP-ben töröljük azonnal, ha már a NAS-on van a biztonságos másolat + os.remove(temp_path) + + return new_doc \ No newline at end of file diff --git a/backend/requirements.txt b/backend/requirements.txt index 100c560..64bf8e4 100755 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -17,3 +17,4 @@ psycopg[binary] httpx pydantic[email] sendgrid==6.* +Pillow \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 5c2fa5e..79dcbf9 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,14 +10,13 @@ services: - ./backend:/app - ./alembic.ini:/app/alembic.ini - ./migrations:/app/migrations - - /mnt/nas/app_data:/mnt/nas/app_data environment: PYTHONPATH: /app DATABASE_URL: ${MIGRATION_DATABASE_URL} command: ["bash", "-lc", "alembic upgrade head"] networks: - - default # Hogy lássa a saját hálózatát - - shared_db_net # Hogy lássa a KÖZPONTI adatbázist! + - default + - shared_db_net restart: "no" # 2. BACKEND API @@ -31,7 +30,8 @@ services: - ./backend:/app - ./alembic.ini:/app/alembic.ini - ./migrations:/app/migrations - # Fontos: A 0.0.0.0 host kell, hogy a Proxy elérje! + - /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 a miniképeknek command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --proxy-headers --forwarded-allow-ips="*" ports: - "8000:8000" @@ -51,10 +51,10 @@ services: condition: service_started networks: - default - - shared_db_net # <--- ITT KAPCSOLÓDIK A KÖZPONTHOZ + - shared_db_net restart: unless-stopped - # 3. MINIO (Lokális marad a projekthez, de NAS-ra ment) + # 3. MINIO (NAS-ra ment) minio: image: minio/minio container_name: service_finder_minio @@ -72,7 +72,7 @@ services: - default restart: unless-stopped - # 4. REDIS (Gyorsítótár - Lokális marad) + # 4. REDIS (Lokális cache, NAS perzisztencia) redis: image: redis:alpine container_name: service_finder_redis @@ -82,7 +82,7 @@ services: - default restart: unless-stopped - # 5. FRONTEND (Weboldal) + # 5. FRONTEND service_finder_frontend: build: context: ./frontend @@ -99,10 +99,8 @@ services: condition: service_started restart: unless-stopped -# HÁLÓZATOK DEFINIÁLÁSA networks: default: driver: bridge - # Ez a kulcs! Megmondjuk neki, hogy használja a már létező központi hálót: shared_db_net: external: true \ No newline at end of file diff --git a/docs/V01_gemini/05_AUTH_AND_IDENTITY_SPEC.md b/docs/V01_gemini/05_AUTH_AND_IDENTITY_SPEC.md index bd0bb7a..e8eea01 100644 --- a/docs/V01_gemini/05_AUTH_AND_IDENTITY_SPEC.md +++ b/docs/V01_gemini/05_AUTH_AND_IDENTITY_SPEC.md @@ -1,103 +1,94 @@ -# 🔐 AUTHENTICATION & IDENTITY SPECIFICATION (v1.2) +# 🔐 05_AUTH_AND_IDENTITY_SPEC (v1.3) -## I. AZONOSÍTÁSI STRATÉGIA -A rendszer szétválasztja a **technikai hozzáférést** (User) és a **valós identitást** (Person). +## 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. Identitás szintek -- **User (Login):** Email + Jelszó. Csak a belépéshez és a munkamenethez kell. -- **Person (Identity):** Vezetéknév, Keresztnév, Anyja neve, Születési adatok, Okmányok. -- **Azonosító:** Minden Person kap egy globális egyedi azonosítót (UUID). +### 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**). -### 2. Soft Delete & Re-regisztráció -- **Nincs fizikai törlés:** A felhasználó csak egy `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. - - Ez az új fiók a korábbi Person ID-hoz kapcsolódik. - - **Adat-izoláció:** A felhasználó csak az új regisztráció dátuma utáni eseményeket látja. A régi adatok a háttérben maradnak (statisztika, sofőr elemzés), de számára rejtettek. - -## II. BŐVÍTETT ADATTÁR (KYC & SAFETY) -A `persons` tábla az alábbi adatcsoportokat tartalmazza (Progresszív feltöltéssel): -- **Alapadatok:** `last_name`, `first_name`, `birth_place`, `birth_date`, `mothers_name`. -- **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ó. -- **Vészhelyzeti adatok (Safety):** Vércsoport, Allergia, Értesítendő személy (ICE) neve és telefonszáma. -- **Jutalom:** A teljes körű adategyeztetésért 2 hét PRÉMIUM tagság jár. - -## III. JUTALÉK ÉS GAZDASÁG -### 1. Piramis rendszer (3 szint) -Meghívó lánc alapján számolt jóváírás: -- **1. szint (Közvetlen):** 10% -- **2. szint:** 5% -- **3. szint:** 2% -*A százalékok a befizetés pillanatában érvényes admin beállítások alapján rögzülnek a tranzakcióban (Snapshot).* - -### 2. Wallets -Minden regisztrációnál létrejön: -- **Coin Wallet:** Belső fizetőeszköz (Kredit). -- **XP Ledger:** Tapasztalati pontok (Verseny és rangsor). - -## IV. MODERÁCIÓ ÉS VALIDÁLÁS -- **Validált vélemény:** Csak igazolt ott-tartózkodás (GPS) vagy számlafotó után adható. -- **Fellebbezés:** A szerviz kérheti a vélemény felülvizsgálatát, amit a Moderátorok/Validátorok bírálnak el. - -## IV. CÉGES AZONOSÍTÁS ÉS VERIFIKÁCIÓ -1. **Verifikációs szintek:** - - **Unverified (Nem ellenőrzött):** Kézi rögzítés utáni alapállapot. 30 napos türelmi idő. - - **Verified (Hitelesített):** Sikeres VIES vagy nemzeti cégnyilvántartó lekérdezés után. - - **Suspended (Felfüggesztett):** Ha az automatikus időszakos ellenőrzés során a cég "megszűnt" vagy "inaktív" státuszt kap. - -2. **Ellenőrzési logika:** - - Elsődleges: **VIES API** (EU-s adószám ellenőrző). - - Másodlagos: Nemzeti cégkeresők (robotizált lekérdezés). - - Kivételkezelés: Ha a robot nem tud dönteni, a feladat az **Admin/Moderátor** várólistájára kerül. - - ## IV. CÉGES AZONOSÍTÁS ÉS VERIFIKÁCIÓ (v1.2) - -1. **Verifikációs Státuszok:** - - **Unverified (Nem ellenőrzött):** Alapértelmezett állapot kézi rögzítés után. 30 napos türelmi időt biztosít a teljes körű használathoz. - - **Verified (Hitelesített):** Automatikus VIES lekérdezés vagy adminisztrátori jóváhagyás utáni állapot. - - **Suspended (Felfüggesztett):** Megszűnt cégek vagy le nem igazolt adatok esetén az időszakos (havi) ellenőrzés során. - -2. **Ellenőrzési Logika (Robot & Admin):** - - **Robot:** A rendszer a `VAT_NUMBER` rögzítésekor azonnal meghívja az EU-s VIES API-t. Egyezőség esetén a státusz azonnal `Verified`. - - **Adminisztrátor:** Ha az API nem ad eredményt (pl. friss bejegyzés vagy technikai hiba), az Adminisztrátor kézzel állíthatja át a státuszt a feltöltött dokumentumok alapján. - - **Időszakos ellenőrzés:** Egy ütemezett feladat 30 naponta újraellenőrzi a `Verified` cégeket. Ha egy cég megszűntnek tűnik, a rendszer `Suspended` státuszba teszi és értesíti a tulajdonost. - -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. - - ## I. AZONOSÍTÁSI STRATÉGIA (v1.3) -... -### 3. Social Auth (Google / Facebook) +### 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 (anyja neve, születési adatok) pótlása. +- **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. -## IV. CÉGES AZONOSÍTÁS ÉS VERIFIKÁCIÓ -... -- **Hibrid Validálás:** Ha a VIES API nem ad eredményt, a rendszer céges dokumentum feltöltését kéri. -- **Ellenőrzés:** Adminisztrátori jóváhagyás vagy AI-alapú dokumentum-validálás után válik `Verified` státuszúvá. +### 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. -# 🆔 Identitás Validációs és Bizalmi Protokoll +--- -A rendszer a fokozatos adatszolgáltatás és a "Tier-based Access Control" (szintezett hozzáférés) elvét alkalmazza. - -## 1. Bizalmi Szintek (Trust Tiers) +## 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 sikeres | Belépés, saját profil 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. | -## 2. 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ő: -- **Kapcsolat:** Valós telefonszám (nemzetközi formátum). -- **Személyi:** Születési hely, idő, anyja neve. -- **Okmány:** Típus, sorszám és **lejárati dátum**. -- **Biztonság:** ICE (In Case of Emergency) név és telefonszám. +--- -## 3. Adattárolási Stratégia -- A rugalmas okmányadatokat és vészhelyzeti kapcsolatokat a `persons.identity_docs` és `persons.ice_contact` JSONB mezőkben tároljuk a kereshetőség és bővíthetőség érdekében. \ No newline at end of file +## 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. \ No newline at end of file diff --git a/docs/V01_gemini/06_Database_Guide.md b/docs/V01_gemini/06_Database_Guide.md index e30cca2..90ca0a5 100644 --- a/docs/V01_gemini/06_Database_Guide.md +++ b/docs/V01_gemini/06_Database_Guide.md @@ -1,109 +1,112 @@ -(Az Adatbázis Bibliája.) -# 🗄️ DATABASE GUIDE -# 🗄️ DATABASE GUIDE & DATA INTEGRITY (v1.4) +# 🗄️ 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 az alábbi módon kezeli a 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 a felhasználó törli magát (`is_deleted = TRUE`), az email felszabadul. - - Új regisztrációkor, ha a KYC adatok egyeznek, az új technikai User a régi `person_id`-hoz kapcsolódik. +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. -## 2. Person (Identitás) - Banki KYC & Safety -A `data.persons` tábla a valós identitást tárolja. A Step 2 regisztráció során az alábbi JSONB struktúra kerül kitöltésre: -- **`identity_docs` (JSONB):** +- **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óvezetői és repülőgép-vezetői engedélyek. -- **`medical_emergency` (JSONB):** Vércsoport, allergiák, krónikus betegségek. -- **Jutalom Trigger:** A profil 100%-os kitöltése után aktiválódik a `system_settings`-ben megadott PRÉMIUM időszak. + - `special_permits`: hajó- vagy repülőgép-vezetői engedélyek. +- **`medical_emergency`**: Vércsoport, allergiák, krónikus betegségek. -## 3. Technikai Integritás (Enum & Séma) +### 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:** Mivel a `metadata.create_all` nem frissíti a meglévő táblákat, új oszlopok esetén (pl. `social_provider`, `mothers_name`) manuális `ALTER TABLE` vagy Alembic migráció szükséges. +- **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. Dinamikus Paraméterezés (`data.system_settings`) -Minden üzleti változó Admin UI-ról állítható: -- `auth.reward_days`: Regisztrációs prémium hossza (alapértelmezett: 14). -- `referral.l1`: Első szintű jutalék % (alapértelmezett: 10). +--- -## 5. Flotta Tulajdonjog Szabályok (v1.1) -- **`INDIVIDUAL` flotta:** Nem átruházható (`is_transferable = False`), a felhasználóhoz kötött. -- **`FLEET_OWNER / SERVICE` flotta:** Átruházható, új tulajdonoshoz rendelhető. +## 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$$ -# 🗄️ DATABASE GUIDE & DATA INTEGRITY (v1.0) +### 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. -## 1. Soft Delete & Újraregisztráció Logika -A rendszerben nincs fizikai törlés. A `data.users` tábla az alábbi módon kezeli a 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 nem használható újra. - - Ha a felhasználó törli magát (`is_deleted = TRUE`), az email felszabadul. - - Új regisztrációkor a rendszer új `user_id`-t generál, de ha a KYC adatok egyeznek, ugyanahhoz a `person_id`-hoz kapcsolja az új fiókot. +## 5. Flotta és Tulajdonjog Szabályok +A flották (Organization) és járművek tulajdonjogi logikája: -## 2. Person (Személyazonosság) - KYC & Safety -A `data.persons` tábla tárolja a banki szintű azonosításhoz szükséges adatokat: -- **Szétválasztott nevek:** `last_name` és `first_name` a pontos azonosításhoz. -- **JSONB mezők:** Rugalmas adatszerkezet az okmányokhoz (`identity_docs`) és vészhelyzeti adatokhoz (`medical_emergency`). -- **Jutalom Trigger:** A profil 100%-os kitöltése (név, szül. adatok, okmányok) automatikusan aktiválja a 14 napos PRÉMIUM csomagot. - -## 3. Economy (Pénztárca & Referral) -- **Wallet:** Minden regisztrációkor létrejön egy rekord a `data.wallets` táblában (0 Coin, 0 XP). -- **Referral Snapshot:** A jutalékok kifizetésekor a rendszer rögzíti a tranzakció pillanatában érvényes százalékot (`commission_percentage`), így a későbbi admin módosítások nem érintik a múltbeli elszámolásokat. - -## Sémák -- `public`: Csak technikai táblák (pl. Alembic version). -- `data`: Az üzleti logika 55 táblája. - -## 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`. - -## Migrációs Állapot -- **Eszköz:** Alembic. -- **Current Head:** `10b73fee8967`. -- **Hiányzó láncszem:** A `persons` tábla létrehozása és a meglévő `users` tábla migrációja (Ba - -## 4. Regionalizáció és Multi-Currency (EU Scope) -A rendszer fel van készítve az EU-s piacra: -- **`data.regional_settings`**: Tárolja az országkódokat (ISO 3166-1), az alapértelmezett nyelvet és a helyi pénznemet. -- **`data.exchange_rates`**: Napi frissítésű váltószámok (Base: EUR). -- **Valuta Logika:** - Minden költséget a rögzítéskori **helyi pénznemben** (`currency_code`) és az akkori váltószámmal átszámított **EUR-ban** is elmentünk. - - Képlet: $$Cost_{EUR} = Cost_{Local} \cdot ExchangeRate$$ - - Ez biztosítja, hogy a nemzetközi flották egységes kimutatást kapjanak. - -## 5. Dinamikus Paraméterezés (System Settings) -- **`auth.reward_days`**: Adminból állítható egész szám (alapértelmezett: 14). -- **`auth.reward_tier`**: Melyik csomagot kapja (alapértelmezett: PREMIUM). - -## 6. Flotta és Tulajdonjog Szabályok (v1.1) -- **Opcionális Járművek:** Egy flotta (Organization) létezhet járművek nélkül is. A rendszer nem kényszeríti a jármű rögzítését (pl. Flotta menedzser szerepkör esetén). - **Átruházhatóság (Transferability):** - - `INDIVIDUAL` flotta: Nem átruházható, a felhasználóhoz kötött. - - `FLEET_OWNER / SERVICE` flotta: Átruházható (eladható), új tulajdonos (owner_id) rendelhető hozzá. -- **Cég Megszűnése:** Soft delete alkalmazása. A cég `is_active` státusza `False` lesz, a tulajdonosi viszony megszűnik, de a járművek életútjában (history) az adatok megmaradnak a visszakövethetőség miatt. + - `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). -## 7. Gazdasági Izoláció -- **Gamification Korlát:** Csak `INDIVIDUAL` típusú flottákhoz tartozó `Person`-ok vehetnek részt a gamifikációban (XP gyűjtés). -- **Validációs Korlát:** Cég mint identitás nem validálhat szervizpontot, ezt mindig egy hozzárendelt, azonosított `Person` (alkalmazott/technikus) végzi. +--- -## 8. Szervezeti és Gazdasági Szabályok -- **Identitás Elkülönítés:** A `Company` (Szervezet) entitás nem kap `XP_Ledger` és `Coin_Wallet` rekordot a gamifikációhoz. Ezek kizárólag a `Person` (valós személy) szintjén léteznek. -- **Automatizált Felügyelet:** Egy ütemezett feladat (Cron/Celery) havonta ellenőrzi a cégek státuszát a külső adatbázisokban. -- **Értékelési rendszer (Rating):** - - **Person:** Egyéni teljesítmény, megbízhatóság. - - **Service (Szerviz):** Szolgáltatási minőség. - - **Vehicle (Jármű):** Műszaki állapot és előélet. - - *Megjegyzés:* A Cég (mint flotta) nem kap önálló értékelést, a hírneve a tagjai és járművei minősítéséből adódik össze. +## 6. Szervezeti Egységek és CRM +A flottákhoz tartozó humán és üzleti kapcsolatok kezelése. - ## 4. CRM és Szervezeti Kapcsolattartók -A `data.organization_contacts` tábla felelős a flottákhoz tartozó humán kapcsolattartók kezeléséért. -- **Dinamikus beállítások:** A `data.organizations` tábla `notification_settings` (JSONB) mezője szabályozza, ki és mikor kapjon értesítést. -- **Külső szinkron:** Az `external_crm_id` biztosítja a kapcsolatot külső vállalatirányítási rendszerekkel (API-n keresztül). +- **`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. -## 4.1 Szervezeti és CRM Adatmodell -- **data.organizations**: Bővítve `tax_number`, `reg_number`, `headquarters_address` és `is_deleted` mezőkkel. -- **data.organization_contacts**: Új tábla a Mini-CRM funkciókhoz (kapcsolattartók típus szerint: billing, primary, operational). -- **Audit**: Minden státuszmódosítás és adatváltozás snapshot-olva az `audit_logs` táblába. \ No newline at end of file +--- + +## 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. \ No newline at end of file diff --git a/docs/V01_gemini/07_API_Guide.md b/docs/V01_gemini/07_API_Guide.md index 804b5ce..0b1988b 100644 --- a/docs/V01_gemini/07_API_Guide.md +++ b/docs/V01_gemini/07_API_Guide.md @@ -1,56 +1,67 @@ -(API specifikáció.) -# 🔌 API GUIDE +# 🔌 07_API_GUIDE -## Verziózás -- **v1:** Core Fleet funkciók (`/api/v1/vehicles`, `/api/v1/expenses`). -- **v2:** Auth és új modulok (`/api/v2/auth/login`). +## 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`). -## Route Inventory (Kiemelt) -- `POST /api/v2/auth/register` (Regisztráció Person létrehozással) -- `GET /api/v1/fleet/vehicles` (Saját járművek listája) -- `POST /api/v1/search/match` (Szervizkereső algoritmus) -- `POST /api/v1/evidence/upload` (MinIO feltöltés) +--- -## Hiba Kezelés -- **401:** Token lejárt -> Frontend dobjon Loginra. -- **403:** Jogosultság hiba -> "Nincs jogod ehhez a funkcióhoz" (Tier limit). -- **404:** Resource not found OR Soft Deleted. +## 2. Route Inventory (Kiemelt Végpontok) +Az alábbi táblázat tartalmazza a legfontosabb útvonalakat: -## 🌐 8. Nemzetköziesítés (i18n) és Lokalizáció +| 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) | -A rendszer a "Global-Local" elv alapján működik. Tilos a programkódban (hard-coded) szöveges üzeneteket elhelyezni. +--- -### 8.1. Nyelvi fájlok struktúrája +## 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: `hu.json`, `en.json`, `de.json`. +- **Példa fájlok:** `hu.json`, `en.json`, `de.json`. -### 8.2. Kezelési szabályok +### 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. -### 8.3. Nyelvválasztás logikája +### 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`. -# 🛡️ 9. Unified Registration & Security Protocol +--- -A rendszer a "Minimal Friction, Maximum Security" elvét követi. +## 5. Unified Registration & Security Protocol +A rendszer a **"Minimal Friction, Maximum Security"** elvét követi. -### 9.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 gombot/linket. -3. **Step 2 (KYC):** Sikeres verifikáció után a felhasználó megadja az okmányait (rugalmas választó: 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.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`. -### 9.2. Token Biztonsági Előírások +### 5.2. Token Biztonsági Előírások - **Regisztrációs Token:** 48 óra élettartam. - **Jelszó-visszaállítási Token:** 1 óra élettartam. -### 9.3. Rate Limiting (Robotvédelem és Költségkontroll) +### 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 (pl. "Nem kaptam meg a kódot") legkorábban 60 másodperc után lehetséges. +- **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. \ No newline at end of file diff --git a/docs/V01_gemini/07_REGISTRATION_INVITATION_AND_API.md b/docs/V01_gemini/07_REGISTRATION_INVITATION_AND_API.md index 77d8336..f02aad8 100644 --- a/docs/V01_gemini/07_REGISTRATION_INVITATION_AND_API.md +++ b/docs/V01_gemini/07_REGISTRATION_INVITATION_AND_API.md @@ -1,167 +1,101 @@ -# 🏁 REGISZTRÁCIÓS ÉS AUTH PROTOKOLL (v1.4) +# 🏁 07_REGISTRATION_INVITATION_AND_API (v1.4) -## I. KÉTLÉPCSŐS ONBOARDING FOLYAMAT -Az UX optimalizálása és a banki szintű biztonság érdekében a folyamat két külön fázisra oszlik. +## 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. Fázis: "Lite" Regisztráció (Step 1) +### 1.1. Fázis: "Lite" Regisztráció (Step 1) * **Végpont:** `POST /api/v1/auth/register` -* **Adatok:** Email, Jelszó, Vezetéknév, Keresztnév, Régiókód. -* **Rendszeresemény:** - * Létrejön a technikai `User` rekord. - * **Állapot:** `is_active = False`. - * **Szerepkör:** Kényszerített kisbetűs `user` (Postgres Enum fix). - * **Megerősítés:** A rendszer kiküld egy aktiváló emailt egy hash kóddal. - * **Válasz:** JWT token `status: pending_kyc` flaggel. - -### 2. Fázis: Banki KYC & Aktiválás (Step 2) -* **Végpont:** `POST /api/v1/auth/complete-kyc` (Fejlesztés alatt) -* **Kötelező KYC adatok:** - * Anyja születési neve, születési hely/idő. - * Okmányadatok: Személyi igazolvány és Jogosítvány száma + lejárati idők. - * Járműkategóriák (pl. A, B, C) és speciális engedélyek (hajó, repülő). -* **Finalizálás (Atomi tranzakció):** - 1. **Person:** Identitás rögzítése a JSONB dokumentumtárral. - 2. **Wallet:** Pénztárca nyitása 0 egyenleggel. - 3. **Privát Flotta:** Automatikus szervezet létrehozása (`is_transferable = False`). - 4. **Tagság:** Felhasználó rögzítése a flotta tulajdonosaként. - 5. **Aktiválás:** `is_active = True` és hozzáférés a rendszerhez. - -## II. TECHNIKAI SZABÁLYOK ÉS FIXEK -* **Postgres Enum:** Minden szerepkört (role) kisbetűvel kell küldeni az adatbázis felé (`user`, nem `USER`). -* **Dinamikus Paraméterek:** Az `auth.reward_days` (jutalom napok) és jutalék százalékok a `data.system_settings` táblából jönnek. -* **Audit Trail:** Minden regisztrációs fázisról Audit Log készül. - -# 🏁 REGISZTRÁCIÓS ÉS AUTH PROTOKOLL (v1.4) - -## I. KÉTLÉPCSŐS ONBOARDING FOLYAMAT -A rendszer a felhasználói élmény optimalizálása (UX) és a banki szintű biztonság érdekében két fázisra bontja a regisztrációt. - -### 1. Fázis: "Lite" Regisztráció (Step 1) * **Cél:** Gyors belépés és a technikai User fiók létrehozása. -* **Kötelező mezők:** Email, Jelszó, Vezetéknév, Keresztnév, Régiókód. -* **Rendszeresemény:** - * Létrejön a `data.users` rekord. - * **Állapot:** `is_active = False`. - * **Szerepkör:** Kötelezően kisbetűs `user` (Postgres Enum kényszerítés miatt). - * **Email:** A rendszer azonnal kiküld egy ellenőrző emailt egy egyedi hash kóddal/linkkel. - * **Token:** Az API egy korlátozott JWT tokent ad vissza, amely csak a Step 2 végpont elérésére jogosít (`status: pending_kyc`). +* **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). -### 2. Fázis: KYC & Aktiválás (Step 2) -* **Cél:** A valós identitás (Person) rögzítése és a gazdasági egységek inicializálása. -* **Kötelező adatok (Identity Verification):** - * **Személyes:** Anyja születési neve, születési hely, születési idő. +### 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ély adatai (ha releváns). -* **Működés:** A felhasználó csak ezen adatok kitöltése és sikeres ellenőrzése után válik teljes jogú taggá. + * **Speciális:** Hajóvezetői és repülőgép-vezetői engedélyek (ha releváns). -### 3. Fázis: Atomi Tranzakció (Finalization) -A KYC adatok beküldésekor a rendszer egyetlen adatbázis-tranzakcióban (`Atomic`) hajtja végre az alábbiakat: -1. **Person létrehozása:** A KYC adatok és okmánymásolatok (JSONB) rögzítése. -2. **Wallet inicializálás:** 0 Coin és 0 XP egyenleggel. -3. **Privát Flotta (Private Org):** Létrejön a felhasználó saját cége (`OrgType.INDIVIDUAL`), amely **nem átruházható** (`is_transferable = False`). -4. **Aktiválás:** A User fiók `is_active = True` állapotba kerül. -5. **Audit:** Bejegyzés az `audit_logs` táblába a teljes körű regisztrációról. +### 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. -## II. MEGHÍVÓ ÉS JUTALÉK LOGIKA -* **Invite Tokenek:** - * `REG_ONLY`: Általános meghívó, beköti a felhasználót a 10-5-2% jutalék láncba. - * `COMPANY_JOIN`: Meghatározott szervezetbe hív (CEO, Flotta Manager vagy Sofőr szerepkörbe). -* **Kredit Jóváírás:** - * Csak az **első** Prémium csomag befizetésekor történik jutalékfizetés a meghívási láncban. - * A százalékos mérték (10%, 5% vagy 2%) a tranzakció pillanatában érvényes admin beállítások alapján rögzül (Snapshot). +--- -## III. TECHNIKAI ÉS BIZTONSÁGI SZABÁLYOK -* **Enum Case Sensitivity:** A PostgreSQL `userrole` típusa miatt minden Enum értéket (user, admin, driver, service, fleet_manager) szigorúan **kisbetűvel** kell kezelni. -* **Dinamikus Paraméterezés:** Tilos fix értékeket (hardcoded) használni. Az alábbiakat a `data.system_settings` táblából kell lekérni: - * `auth.reward_days`: Regisztrációkor járó prémium napok (alapértelmezett: 14). - * `referral.level1-3`: Jutalék szintek mértéke. -* **Email Manager:** A `send_email` hívásakor tilos a `subject` paraméter átadása; a szerviz a `template_key` alapján automatikusan generálja azt. -* **Szigorú Helyreállítás:** A banki szintű KYC után a jelszó-visszaállítás kérhető a Person adatok (Anyja neve, Okmány szám) megadásával is. +## 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. -## IV. SOCIAL AUTH (GOOGLE / FACEBOOK) -* Social Auth esetén 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, és nem fér hozzá a flottakezeléshez. +### 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). -# 🏁 REGISZTRÁCIÓS ÉS AUTH PROTOKOLL (v1.1) +### 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$): -## 1. Hibakezelési Jegyzet (TypeError fix) -A rendszer korábbi verzióiban az `EmailManager` hívása paraméter-eltérést okozott. -- **Megoldás:** A `send_email` hívásakor tilos a `subject` paraméter átadása, mivel azt a szerviz a `template_key` alapján generálja a belső szótárából. +$$C = P_{amount} \cdot \frac{R_{level}}{100}$$ -## 2. Adatbázis Integritás -Az `Organization` tábla bővült az `owner_id` mezővel, amely a magánszemély (Individual) flottájának tulajdonosát jelöli. -- Minden regisztrációkor létrejön egy automatikus flotta. -- A flotta típusa: `OrgType.INDIVIDUAL`. +*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. Dinamikus Paraméterek -A regisztrációt követő jutalmak (pl. 14 napos prémium) a `data.system_settings` táblából kerülnek kiolvasásra. -Keresett kulcs: `auth.reward_days`. +--- -# 🏁 REGISZTRÁCIÓ, MEGHÍVÓK ÉS API PROTOKOLL (v1.0) +## 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. -## 1. Regisztrációs Flow (Atomcsapás-biztos tranzakció) -Minden új regisztráció egyetlen adatbázis-tranzakcióban (`Atomic`) hajtja végre az alábbiakat: -1. **User & Person létrehozása:** Alapidentitás rögzítése. -2. **Wallet inicializálás:** 0 Coin és 0 XP egyenleggel. -3. **Privát Flotta (Private Org):** Létrejön a felhasználó saját cége, ahol ő a tulajdonos. -4. **Meghívó feldolgozása:** - Ha `Personal Invite`: Bekötés a 10-5-2% jutalék láncba. - - Ha `Company Invite`: Másodlagos kapcsolat létrehozása a meghívó céghez (Role: Driver/Admin). +### 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. -## 2. Meghívó Küldés Logikája (Invitation Engine) -- **Generálás:** Admin vagy jogosult User generál egy egyedi `invite_token`-t. -- **Típusok:** - - `REG_ONLY`: Csak a rendszerbe hív. - - `COMPANY_JOIN`: Meghatározott cégbe és pozícióba hív. -- **Jutalék számítás:** - 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.* +### 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. -## 3. API Végpontok (Baseline v1) -- `POST /api/v1/auth/register`: Komplett onboarding folyamat. -- `POST /api/v1/auth/invite/send`: Meghívó generálása és küldése. -- `GET /api/v1/auth/invite/verify/{token}`: Token ellenőrzése regisztráció előtt. +--- ## 4. Jelszó Helyreállítási Protokoll (Recovery) -A rendszer két szintű helyreállítást biztosít: +A rendszer két biztonsági szintet különít el: -### A) Standard (Email alapú) -- `POST /api/v1/auth/forgot-password` -> Email kiküldése ideiglenes tokennel. +| 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. | -### B) Szigorú (Banki szintű / KYC alapú) -- **Végpont:** `POST /api/v1/auth/recover-identity` -- **Kötelező adatok:** Vezetéknév, Keresztnév, Anyja neve, Személyi igazolvány száma. -- **Logika:** 1. A rendszer azonosítja a `Person` rekordot. - 2. Ha sikeres, a rendszer kiküld egy visszaállító linket a Person-höz tartozó **elsődleges telefonszámra (SMS)** vagy a **legutolsó aktív Email címre**. - 3. Sikeres helyreállítás után a felhasználónak kötelezően jelszót kell cserélnie. +--- - ## 🛡️ 10. Kormányozhatóság és Biztonsági Beállítások +## 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. -A rendszer biztonsági paraméterei központilag, a környezeti változókon keresztül szabályozhatók. Ez lehetővé teszi a biztonsági szint gyors módosítását (pl. támadás esetén szigorítás) a kód módosítása nélkül. +--- -### 10.1. Token Élettartam Szabályok -A `.env` fájlban (vagy a rendszer beállításaiban) az alábbi paraméterekkel szabályozható a hozzáférés: +## 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` | Regisztráció megerősítésére álló idő | 48 óra | -| `PASSWORD_RESET_TOKEN_EXPIRE_HOURS` | Jelszó visszaállítására álló idő | 1 óra | +| `REGISTRATION_TOKEN_EXPIRE_HOURS` | Aktiválásra álló idő | 48 óra | +| `PASSWORD_RESET_TOKEN_EXPIRE_HOURS` | Visszaállítási időablak | 1 óra | -### 10.2. Ideiglenes .env Konfiguráció (Példa) -```env -# SECURITY SETTINGS -REGISTRATION_TOKEN_EXPIRE_HOURS=48 -PASSWORD_RESET_TOKEN_EXPIRE_HOURS=1 +--- -# EMAIL SYSTEM -EMAIL_PROVIDER=sendgrid -EMAILS_FROM_EMAIL=info@profibot.hu -EMAILS_FROM_NAME='Profibot Service Finder' -SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxx - -## 4. Corporate Onboarding (Céges regisztráció) -A folyamat célja, hogy egy már létező Person (vagy új User) saját szervezetet (Organization) alapítson. -- **Többszintű validáció:** Kötelező adószám (VAT/Tax ID) ellenőrzés (HU esetén formátum + VIES API). -- **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 izolált kezelése érdekében. \ No newline at end of file +## 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. \ No newline at end of file diff --git a/docs/V01_gemini/10_Billing_Credits_Subscriptions.md b/docs/V01_gemini/10_Billing_Credits_Subscriptions.md index 972e851..53ee4cb 100644 --- a/docs/V01_gemini/10_Billing_Credits_Subscriptions.md +++ b/docs/V01_gemini/10_Billing_Credits_Subscriptions.md @@ -1,58 +1,76 @@ -# 💰 BILLING, CREDITS & SUBSCRIPTIONS (v1.2) +# 💰 10_BILLING_CREDITS_SUBSCRIPTIONS (v1.2) ## 1. Regionális és Valuta Logika (EU Scope) -A rendszer támogatja a többnyelvű és többvalutás elszámolást az EU teljes területén. Minden pénzügyi tranzakció két értéket tárol: -1. **Local Cost:** A felhasználó helyi pénznemében rögzített összeg (pl. 45.000 Ft). -2. **Standard Cost (EUR):** A rögzítés pillanatában érvényes középárfolyamon átszámított euró érték. +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 Szinergia -A csomagok limiteit a `data.system_settings` tábla szabályozza. A cégtulajdonosok ösztönzése érdekében **Business Synergy** kedvezményt alkalmazunk. +--- + +## 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églog, GEO keresés. | -| **PREMIUM** | 3 db | Teljes dokumentumtár, export, útvonal alapú kereső. | -| **PREMIUM+** | 5 db | Flotta statisztika, TCO elemzés, 5 felhasználó. | +| **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. | -**VIP Synergy Szabályok:** -- **Synergy Discount:** Ha egy felhasználó `FLEET_OWNER` szervezetének aktív **VIP** vagy **VIP+** előfizetése van, **15% kedvezményt** kap minden vásárlásra a saját privát flottájában. -- **Ajándék Kredit:** VIP csomag vásárlásakor a tulajdonos extra krediteket kap, amit skinekre, medálokra vagy a privát Prémium csomagjára költhet el. -- **Időbeli korlát:** A privát Prémium/Prémium+ kedvezmények időtartama **2-6 hónapra korlátozott**, elkerülve a tartós ingyenhasználatot. +### 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 nem automatikusak, a kód manuális beírása kötelező. -- **Gift Card (Fix Kredit):** Fix összegű ajándék kredit (pl. 5000 Ft értékben). -- **Subscription Coupon (%):** Százalékos kedvezmény előfizetési díjakból, meghatározott időszakra. -- **Szabályok:** - - Minden kupon rendelkezik **lejárati idővel**. - - Minden felhasználást auditálni kell: `redeemed_at`, `user_id`, `original_price`, `discount_price`. +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). -## 4. MLM Jutalomrendszer (10-5-2%) -A rendszer jutalmazza a sikeres meghívásokat az első befizetés után: - **1. szint (Közvetlen):** 10% jóváírás. - **2. szint:** 5% jóváírás. - **3. szint:** 2% jóváírás. -A százalékos érték a befizetés pillanatában rögzül a tranzakcióban (Snapshot). + +--- ## 5. Invitation Engine (Meghívó Rendszer) -A spam elkerülése érdekében korlátozott keretrendszert alkalmazunk: -- **Lejárati idők:** - - **Felhasználói meghívó:** 72 óra. +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 (pl. 10 vagy 20 db). -- **Anti-Spam Logika:** Új meghívási lehetőséget csak sikeres regisztrációk után kap vissza a felhasználó. A keret mértéke adminisztrációs felületről állítható. +- **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 szerviz események és értékelések csak bizonyítékok megléte esetén válnak **Verified** (hiteles) státuszúvá: -- **Fotó/Dokumentum:** Munkalap és kilométeróra fotó kötelező. -- **GPS Check-in:** Igazolás a helyszíni tartózkodásról. -- **Identitás:** Cég mint entitás nem validálhat, csak azonosított `Person`. +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 -- **Grace Period (30 nap):** Csak rögzítés lehetséges, statisztika zárolva. -- **Zárolás (60 nap):** A fiók írásvédetté válik. -- **Helyreállítás:** 6 hónapon belüli visszamenőleges befizetéssel minden funkció és korábbi adat újra aktiválódik. \ No newline at end of file +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. \ 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 index 3eaeedb..9687b50 100644 --- a/docs/V01_gemini/18_ASSET_AND_FLEET_SPECIFICATION.md +++ b/docs/V01_gemini/18_ASSET_AND_FLEET_SPECIFICATION.md @@ -1,206 +1,130 @@ -# 🏎️ Asset és Flotta Specifikáció: A Járművek DNS-e +# 🏎️ 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 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. +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 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 | +## 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** | 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 | +| **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, munkagépek és versenytechnika esetén kritikus. +- **Ü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) -Az adatbázisnak ismernie kell a járművet "gyári" állapotában és annak minden módosítását. +A rendszer két rétegben kezeli a jármű adatait a teljes életút követéséhez. -### 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ú). +### 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ú). -### 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). +### 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 (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. + + +--- + +## 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:** Fotók az alkatrészekről, számlák PDF-ben, munkalapok. +- **Csatolmányok:** Alkatrész fotók, számlák (OCR), 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: +### 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). -### 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? +## 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). -Ez a kettős mérőszám adja meg a jármű valós "piaci és használati értékét". +### 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). -## 6. Az Adat-Gondnok (Harvester Robot) -A rendszer integritásáért és az adatok pontosságáért egy automata Robot felel. +### 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). -### 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. -## 7. Kivételkezelés: Ismeretlen és Egyedi Járművek +--- -Ha egy jármű nem található a globális katalógusban, a rendszer kétlépcsős mentőövet nyújt: +## 6. OCR és Dokumentum Validációs Stratégia +A dokumentumfelismerés (OCR) hibrid technológiát és Tier-alapú prioritást alkalmaz. -### A) On-Demand Harvester (Robot hívása) -1. A felhasználó jelzi, hogy hiányzik a típus. -2. A Robot utasítást kap egy mélyebb keresésre (Deep Web Search). -3. Ha találat van, a Robot rögzíti a katalógusba, és a felhasználó folytathatja a rögzítést. +### 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. -### B) Custom Asset (Egyedi/Sport jármű rögzítése) -Ha a jármű sehol nem szerepel (pl. épített versenyautó, egyedi yacht): -1. **Manuális nyilatkozat:** A felhasználó rögzíti az adatokat. -2. **Dokumentum alapú validáció:** A forgalmi engedély vagy sportigazolvány fotóját kötelező feltölteni. -3. **AI Verifikáció:** A rendszer OCR-rel (szövegfelismerés) kiolvassa az adatokat a fotóról, és összeveti a manuális bevitelével. -4. **"Unverified Model" jelzés:** A katalógusban egyedi azonosítót kap, amíg egy admin vagy a Robot más forrásból meg nem erősíti. +### 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. -## 8. Multi-Robot Harvester Architektúra -A rendszer kategóriánként különálló kutató robotokat használ az erőforrások optimalizálása és az adatok pontossága érdekében. -### A) Működési elv -- **Ütemezett futás:** Minden kategória (Autó, Motor, Teher, Hajó) saját időablakban frissít, elkerülve a szerver túlterhelését. -- **Hiányos adatok kezelése:** A Robot köteles rögzíteni a járművet akkor is, ha csak részleges információt talál (pl. csak márka és típus). -- **Státusz jelölések (`verification_status`):** - - `verified`: Teljes DNS adatsor (Robot által hitelesítve). - - `incomplete`: Alapadatok megvannak, de hiányoznak technikai részletek (pl. guminyomás, olaj). - - `pending`: Felhasználó által felvett, Robot általi ellenőrzésre váró egyedi típus. +--- -### B) On-Demand prioritás -Amikor a felhasználó olyan típust keres, ami nem szerepel a katalógusban, a rendszer egy "Priority Trigger"-t küld az adott kategória Robotjának, amely soron kívül megkezdi a célzott adatgyűjtést. - -## 9. OCR és Dokumentum Validációs Stratégia - -A rendszer a járműokmányok (forgalmi engedély, hajólevél, lajstrom) feldolgozására hibrid OCR (Optical Character Recognition) technológiát alkalmaz. - -### A) Hibrid Feldolgozási Sorrend (Failover Logic) -A költséghatékonyság és a pontosság érdekében a rendszer az alábbi sorrendben próbálkozik: -1. **Tier 1 (External Free/Limited APIs):** Ingyenes keretű felhő szolgáltatások (pl. Google Vision API, Azure Form Recognizer). A rendszer figyeli a havi limiteket, és azok elérésekor automatikusan vált a következő szolgáltatóra. -2. **Tier 2 (Saját Erőforrás - Fallback):** Ha minden ingyenes külső keret elfogyott, a rendszer a saját szerveren futó PaddleOCR (AI alapú) modult használja. - -### B) Monetizáció és Jogosultságok -A dokumentum alapú automata rögzítés és validáció prémium funkció: -- **Free/Lite:** Manuális rögzítés (limitált mezők). -- **VIP:** Automata rögzítés (OCR) 1-2 eszközre. -- **VIP + / Premium +:** Korlátlan okmányfelismerés, automata lejárati figyelmeztetések és hivatalos adat-összevetés. - -## 10. Multi-Robot Harvester (Moduláris Felépítés) - -A járműkatalógus feltöltését egy bázis-osztályra (`BaseHarvester`) épülő, kategória-specifikus robotcsalád végzi. - -- **Autó Robot:** Közúti gépjárművekre optimalizálva. -- **Motor Robot:** Kétkerekű és hobbi járművekre. -- **Heavy Duty Robot:** Teherautók, kamionok és munkagépek specifikációira. -- **Specialty Robot:** Vízi és légi járművek egyedi azonosítóihoz (MMSI, Lajstrom). - -# 🏎️ Asset és Flotta Specifikáció: A Járművek DNS-e (v1.2) - -## 7. Kivételkezelés: Ismeretlen és Egyedi Járművek -- **On-Demand Harvester:** Ha a katalógus hiányos, a Robot kérésre (Trigger) indítja a mélykeresést. -- **Custom Asset:** Egyedi/Sport eszközök rögzítése dokumentum alapú validációval. - -## 8. Multi-Robot Harvester Architektúra -A rendszer kategória-specifikus (Car, Bike, Truck, Specialty) robotokat használ. -- **Ütemezés:** Éjszakai batch-futás a szerver terhelésének minimalizálására. -- **Státuszok:** `verified` (teljes), `incomplete` (részleges), `pending` (ellenőrzésre vár). - -## 9. VIN (Alvázszám) és Validáció -- **Algoritmus:** Minden közúti járműnél kötelező a VIN Checksum (MOD 11) ellenőrzése a beíráskor. -- **Auto-Fill:** Érvényes alvázszám esetén a rendszer felajánlja a gyártói adatok (gyártási év, üzem, motorverzió) automatikus kitöltését. - -## 10. Dokumentum Kezelés és Tárolás (NAS) -Minden eszközhöz csatolt dokumentum (forgalmi, fotók, számlák) központi NAS tárolón kerül rögzítésre. +## 7. Infrastruktúra és Adatkezelés +### 7.1. Dokumentum Tárolás (NAS) - **Elérési út:** `/mnt/nas/app_data/assets/{asset_id}/` -- **Archiválás:** `/mnt/nas/git_vault/` (Adatbázis mentések és konfigurációk). +- **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). -## 11. OCR és Üzleti Logika (Tier-based) -A dokumentumfelismerés (OCR) prioritása a felhasználói csomagtól függ: -- **VIP+ / Premium+:** Azonnali (Real-time) OCR feldolgozás. A felhasználó a feltöltés után 3-5 másodperccel már látja az előtöltött adatokat. -- **Alap csomag:** Háttérfolyamat (Background task). A feldolgozás sorban állítás után történik, a felhasználó értesítést kap a befejezésről. -- **Failover:** Külső API-k (Google/Azure) és saját erőforrás (PaddleOCR) hibrid használata a költségkontroll érdekében. +### 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). -## 12. OCR Monetizáció és Kreditszabályok (Admin Kontroll) +--- -A rendszer az OCR alapú adatbeolvasást kvótákhoz és kreditekhez köti. +## 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. -### A) Csomag alapú kvóták (Admin beállítás) -Az Admin felületen csomagonként (Lite, VIP, VIP+) meghatározható egy ingyenes havi dokumentum-beolvasási keret: -- **Lite:** 0-1 scan/hó. -- **VIP:** 10 scan/hó. -- **VIP+:** Korlátlan vagy magas limit (pl. 100). +## 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). -### B) Kreditalapú túllépés -Ha a felhasználó kimerítette a keretét, minden további beolvasás kreditért vásárolható meg. -- **Egységár:** Admin felületről állítható (pl. 1 beolvasás = 10 kredit). -- **Tranzakció:** A rendszer levonja a kreditet a felhasználó `Wallet`-jéből a sikeres OCR feldolgozás után. +## 7.4 Dokumentum Életciklus és Pufferelés (v2.2) -### C) Egyedi engedélyek (Permissions) -Lehetőség van egyedi felhasználóknak vagy flottáknak "OCR_Override" jogot adni, amivel a csomagtól függetlenül ingyenes vagy kedvezményes beolvasást kapnak (pl. tesztelők vagy stratégiai partnerek). +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. -## 13. Kiterjesztett Jármű Kategóriák -A rendszer az alábbi kategóriákat különbözteti meg az életút- és költségkövetéshez: -- **Bus:** Tömegközlekedési és távolsági buszok. -- **Motorhome:** Lakóautók és speciális lakókocsik. -- **Trailer:** Utánfutók, pótkocsik, trélerek. -- **Construction:** Munkagépek (markolók, daruk). -- **Agriculture:** Mezőgazdasági vontatók, kombájnok. -- **Micro-mobility:** E-roller, e-bike flották. +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. -# 18. ASSET ÉS FLOTTA SPECIFIKÁCIÓ (v1.1) - -## 1. Dokumentum Tárolási és Feldolgozási Stratégia -A rendszer a tárhelyköltségek optimalizálása és a gyors elérés érdekében hibrid tárolást alkalmaz: - -### A) Tárolási típusok -- **Vault (Tartós):** Jogilag kritikus okmányok (Alapító okirat, Forgalmi, Adásvételi). - - Tárolás: NAS, hash-elt fájlnévvel. - - Elérhetőség: Korlátlan ideig, amíg az Asset/Szervezet aktív. -- **Ephemeral (Ideiglenes):** Napi bizonylatok (Parkolási jegy, Tankolási nyugta). - - Folyamat: Feltöltés -> OCR adatkinyerés -> Adatbázis rögzítés -> Kép törlése (90 nap után). - -### B) Képoptimalizálási Motor -Minden feltöltött dokumentum (JPG/PNG) automata feldolgozáson esik át: -- Átmretezés: Max 1600px szélesség. -- Formátum konverzió: WebP (veszteségmentes tömörítés). -- Eredmény: ~80-90%-os tárhely megtakarítás olvashatóság vesztése nélkül. - -## 2. Címkezelési Protokoll (Atomizált Adatok) -A pontos szűrés és a hivatalos iratok generálása érdekében a címeket az alábbi bontásban tároljuk: -- Irányítószám (IRSZ) -- Település (Város) -- Közterület neve -- Közterület jellege (utca, út, tér, stb. - választható listából) -- Házszám (emelet, ajtó, lépcsőház kiegészítéssel) - - Címkezelés (v2.0): Minden magánszemély és szervezet címét atomizált formában tároljuk (IRSZ, Város, Utca, Házszám, HRSZ). Ez alapfeltétele a későbbi flotta-riportoknak és a pontos térképi megjelenítésnek. \ No newline at end of file +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. \ No newline at end of file diff --git a/docs/V01_gemini/19_ADMIN_AND_PERMISSIONS_SPEC.md b/docs/V01_gemini/19_ADMIN_AND_PERMISSIONS_SPEC.md index 9e44683..2afe8bb 100644 --- a/docs/V01_gemini/19_ADMIN_AND_PERMISSIONS_SPEC.md +++ b/docs/V01_gemini/19_ADMIN_AND_PERMISSIONS_SPEC.md @@ -1,7 +1,7 @@ -# 🛠️ ADMIN MANAGEMENT & PERMISSIONS (v1.0) +# 🛠️ 19_ADMIN_AND_PERMISSIONS_SPEC (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). +## 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 | | :--- | :--- | :--- | :--- | @@ -11,56 +11,67 @@ A rendszer többszintű, régió-alapú jogosultságkezelést alkalmaz (RBAC + G | **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. + + +### 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 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. +- **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 -- **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. +### 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. -## 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. +### 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. -## 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. +### 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. -## 6. Értesítési Engine és Lejárati Figyelmeztetések +--- -A rendszer proaktív figyelmeztető rendszert alkalmaz minden előfizetői szinten (Individual és Corporate egyaránt). +## 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). -### A) Előfizetés és Pénzügyi Értesítések -- **Hatókör:** Minden fizetős csomag (Lite+, VIP, VIP+, Corporate). -- **Logika:** Automatikus értesítés küldése 30, 15, 7 és 1 nappal a csomag lejárta előtt. -- **Csatornák:** Push notification, Email és a Mini-CRM kontakt személyek értesítése. +### 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. -### B) Jármű Okmányok és Technikai Lejáratok -A rendszer figyeli az eszközökhöz rögzített metaadatokat: -- **Forgalmi engedély:** Műszaki vizsga lejárata. -- **Biztosítás:** Kötelező (KGFB) és CASCO fordulónapok. -- **Lízing/Szerződés:** Szerződéses futamidő vége. -- **Okmányok:** Hajólevél, lajstrom, emelőgép vizsga stb. +### 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. -### C) CRM Kontaktok és Kapcsolattartás -Minden szervezet (Organization) esetében kötelező megadni legalább egy **Adminisztratív Kontaktot**. -- **Több cég kezelése:** Egy Person több szervezetben is betölthet `owner` vagy `fleet_manager` szerepkört. -- **CRM Mezők:** Név, beosztás, közvetlen elérhetőség (fizetésért felelős, operatív felelős). +--- -## 7. Corporate Onboarding és Validációs Szintek -A cégek rögzítése háromlépcsős ellenőrzésen esik át: -1. **Tier 1 (Automata):** Adószám alapú validáció (HU/VIES API). -2. **Tier 2 (AI/OCR):** Feltöltött dokumentumok (Alapító okirat) intelligens elemzése. -3. **Tier 3 (Human):** Adminisztrátori jóváhagyás (L2/L3 szint), ha az automata folyamat bizonytalan. +## 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). -## 8. B2B Jutalék és MLM Kivételek -- **Direct Referral:** Cég által meghívott másik cég esetén csak 1. szintű (L1) jutalék jár. -- **MLM Korlát:** Szervezetek nem építhetnek többszintű hálózatot, a kifizetés fix üzleti megállapodás alapú. \ No newline at end of file +--- + +## 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. \ No newline at end of file diff --git a/static_previews/organizations/6/067b6c7b-0f4d-4a04-875e-9e85a5621c46_thumb.webp b/static_previews/organizations/6/067b6c7b-0f4d-4a04-875e-9e85a5621c46_thumb.webp new file mode 100644 index 0000000000000000000000000000000000000000..eb8f0fa6a95cdb4bd1b4d4811b825e5d3fba247e GIT binary patch literal 14686 zcmV-kIibcy5@w|WWv zsr`uek@SoG*VF_0kEM^Q&+d1yckIunU$V#dkNZEk9@4-6@T|Q@2};4p&yd}LjQ^V)5<4q#{vGs&@bAruz%J6AMA1XfA&2V z`#1jQ?wjlf`N#C{_x`{C-tfHqXZx?&Z-6i7AKQQHf0q2k`k4P)|F8Q`%%5?ew*R>Q z<^GT0Bl-XLZ%&W@|NMRq{_X$&|Jm^4``0Dfud*#vBYavDKcv`L;r(z1;`q z*`dUhRT**Y!S;x_z6DLL+W#}1Nld*7wAsl?q9>%5--f~hH1`3MUlmx`(;>?rK{Z(S zBAt&TJ?P#~(^yFKT$dIJv(cm+Cw9$0P&g}5Xj+;=`U-vdb;5aML^n<%6=)oY@DLI^ zTfzxH!L2?H5wP4mJmA7G!DS+@Ydk6Uuzw1nyLi;cDPnN9`Z;WRx#jQ!diZql*kFpS zt|fHRBvKW~9@9$qYnKTInFh$pOL7uE8PM8Zec;u#Zb2&72*bxQ$y8!Z*wULXwNM;f z`*FuJ>f<9CJw2lCmvR2m9Vg$3#Zw5!iC+qOSY!g?)$HdPKJHw%W;OGB0R~CqnZE)6 zBl~Ef#F=?1@9?W~?Q}xxWY-PTb%}rpBpc6PM&O}oPd%D8M_vH4V(5crcGJ}#c4m;I zdmwt_26x{6WL+jqQjcht8$bKf*3n~r7m^-xDdHP^eeScu2vMry7*7)*bDq~? zFg{WDR+H-+bPoLoN@!*rLd9zEM&p0X!f!U%|Kx5i*I)lX5M1GYQIK&x-`?guUK0Be zxz{kFM<;20w({$i+1FQ~?wO&zi$_F6(P?&pB|3oW zSY0xwSTJNMRj~OPvy@cfzDdJs%n3FZ^7-ka+A0dpuJW4m_Sh+s70TW*kHIFY;}zT( zzfN$$?LBW5m`_^Ap=r6l8EE7)Jj52P9vFbu87HN;O8ra}*%|YIXPrPtbznI(8OOX_vpg5T~S0MWo`X z)8MP#E)(rUs(C^oz!hKfwJcqhi-1ez(>A5&@8B5e zCsJ^q_5%CH^NeEK)xPeDwO;CZeT|i=c^Ps9BJ75oUeqU=)&#dky7{?Lxs^Cb33--T zJ`8=Db;eyxxF+#AWWID@p-%VD}nwt@M14xd6%|p9y`y9T_*!1TR zs-aoxzLbwIN^+aG=IS9m&!*eh~^J6liQ~c`ep@y>%}dK=~1zQbRx13sGkPqFb~3yt=(~1Tsp8g zNuBZS+7XcQBMSf7m-_2SQ}%iK_Qa6Ad&Y{qZ-e7{!#p*tYPj*iDA=I!!F(@kCTiuM zw`ci-Vet{@a_Sspo^*|fvAtt6ShTu4Z5P@ytWo#;O_#qy-(Ud#|1v|jxF;cg`R*pv zz5vn&%Lgxy>p$dR!fY)obQnK^T1ITaa{%AOL7x=>9QFbHT%1g=O{u3={c!%}dD*n? zUs-{M!T4bTmR;%GP-`J(MS}6Yazg~KH5w_FVVlwqJhfn~u|ZW(GfbBE=gCN8+doE_ zGQlI^=5}ecsg2GO1%TN$>WF@}2y6Reeb5I`g%WF}`KV2qv%B<1Z2HOh0+ zz=YZKz{$%EClVn!@CU!Ybt~`oOeo*x&nEut4^Y+?o_$5HcTag$sweZ4KQQDw@`?tq zy{5l5DiM9LyD^Tj$TVY98}{rV0oG<}wi8GHMFSWmQu|^SJQQPr@;bs5(vMyElf$I?bbyfJ4tmE(rDrlMqU^vIWW}0#n*y{tzsac8( zZL6D$YdRjzH>J!nKaUQErL(#tSAUg+6S7%TtlkC%Oi<{qGEk=6b?D_NKkyg5tVl@H zK8s`coJ&Pc{DWD?MxNZxY6`D018SenB?@J$pewY}fGh-UUSX&4G- zwD;6IYv34QuF8-82#@@E8qUL!E+g28kkkC*m+&wMNm4dcX`>p*P;*80cOx+#tI4Qq z+a-D_#J|w4)Y{;JWSnv33N1Y5z>c_1FP&&-Ms-8Eg`M|cMQe}Pjsv^BMbv#!ji?%w zND&5%ZX=Jr&M{CDaudyvxClQo1=P6>27vaY!}SYyY>+{EW|M{_0eC(?<6HYJHpg&+ z>$R)6`ks_bKOlCbKt2D;j+#oP>j1WZzN>jLomp zl6lH3>s%#Lu*7rFaXi8^ib4M6hPP=vARf#3V$g-wE-%6j9nf`;n`QF(Rmle#rOEh7 zOlYVuDS2Ffq9wI4Cq-8h6yZ$A(|Yc(gB2Wvi3F5sebnL z##p37e8!ZCRnh3$jI6MH=rSLZ%xZ>Z47N&UOCIJjALS0E%+Sa-cGU71#FU0O9JcC* zI+tKW<35CHM%ZR5pb+7iiq2)ke5N;jG$FL{H6-4eb9ckf02CdK=W5#d>5q^-hArti zH#1D^4Uzy504WVoXMiM_Q(!CO`YBEP89kThb{T^ zv>AxR)@fJwERa_ww)6LCD*<&wrU?N51zha-21A)VS#-i+aw_r|(#}J~=pnh_PI7pH zYb91X*&B0K(JG@7s5*u6jJxX@DrE-vLX5($Y{-cy5>ofWPdz4nuGjD>JdtH_ASkD( z;TAiDOU_&ig+|HZf-<>PvLtPx!&i}$qjCI|U-+FG&luroV(F5xO&KM>aE)TL5sn;LkIKL7dI zqyZQVJ7@WzSjTh;Poa2(pi`4IE{$?vfEdj1RE>oe_BmlefmPV59}=RVEhPB&GiAYi z_J1Zg*zx$u__1#xFM)pt@?jFkkwk_s(T`gphEq$2oK)rJ^0>2ypKA)gR%=$l@fZ-l z1sScpY97Y{eUVoG9d^qUNmU{U6f?m6I9M)&_>`~TfOX*=T{SZaU*m6n7CK$wd@Fnz zl{L6}aAhl{!9fi`_lX>awW()XnHUMks%9BsCbY&vU zS{hY2Wl#mGJ;E^QRnEX8ZaGij(CaC!qX*^a-`+E@xw3l#clgvL4u5Mhw-)ZIUs{e3 zfj`)$ia+HHc>HC*-2Z(c(Q9rGI0O;+T^&6x;skWvB<-yfa-kK{CnY&>7Ur;JbeYq? z2}S)MoB)7(o;>QVo7bkx8mS%?{3f5@5Lax%HS#@PtE=Cs4#olfO-AQkx z1{rfATocM`cLEfP*W*;>K49T&#usWx7Ut|cy%T9`)NSN_5?suu=Hz>NO7J~K!m&r? z`69H4yiGRHnE23cmW$d~kwqSgf*t+29vb4-VjG(=X3-Zo6b*E6%X|kVcEm z{b8WyblVgO7BzA7@;6FYM_5sK|5k5)I3U>;Y-TH~*9`r`^aQs3n%iqOYTI0Ze3wi; zpxBDSJN|OJcBvBOh7Xi#$+pEqM6W+K*pvNK(DY6hWFq{{^O_+8MQLnR!L`S~f`wG4 z+QSRBmodnCWJQ}fG+TcgUdQu_%N%SA7Eomd`2tTK(|NFx6tiNkr861(F5{~90G^g! zmizUf=O5SC7=mmiMv;24f@L+|-+kk}c#jy38JLAy)Ff0tVPWjYw2mw&s}BWmtKvnn zvK?l~G7*a6gC{V!JWCoDI9#OJ?IR+de#O3GUWvJ=Y(WwmX$k~QiRg+%tb2OGZ4!_6 z&)eZ{IN)BvD^G8H`VPiouI0ADK~uK5j~(s!chXva5(Zvc-9JS+4C17Q?6H5x*m#T# z671Ft%MeNcASBINHg}n5@gC1HYmVOUXjy=?j7y09NZ347P<2qj%TG4OinHltNcNA= zGO7u?+C*{@TR2!S13X@r2i=3n7g|8S&wX?cuH#EMev)@wwk^QnHl2YNoKyo=BawTy z>{=f;k;%pq4=W4;(ZJv=`xe>re^f#`YXw9NGx~Qif1LBSfr++&E4DcN-#F5zO^uR7 z#J+RttVdpjj|RPi87fL`j~`9vOJY*&<8WY@m^Zr5gtUC5Z#%#340O(6`5oz*3cFW| zpLT3a{EQ$9s7!q9X{kWL{1xA%KrmsVfETcq(zz)muX7X+xuqwy@I@KC_EQzNg<)Ka zOhYYa)gg_iy9!0~j96KU6Lnr?fo?y!KFVc`7%(R-HkKbX+H$yf%YK}*?t1TV7QHoF zM%mjJOips)dxP$c>8tD@)SjYt_r?~$Ld0A{NKIhalwB!Lsi`=c#YJ; z)&dVL-$m&iW)oxux}!?Qf(aMyq;dVrw02p1dk#P)3MB8GJQwl_D)7iF!mqp>wD^+C z{{bh_S)RDI_KaN*tsSLOe=beH@^Vj(A22%Y4>c%~a z*|0ty{Wm6FR0CR%^+l(_ZbaBj8eq*(>+Z!5=te-qrZx5ffPsO-7DGc#+#auyFm74X zV5xm-#bw_)KZ?$aqnOCO=iFqLA}_fB@YAXAYEJ5?`{c;Ru> zxndL@G`x^m4Ax;APTy;@1cfb3)K7o$p_i8Nlrf2R#kg;(R#29pw%T(;a3Oh&t-_A` z5@1BHwE$%eDy4}Kt1o|hoZlE0-scbfRI|8rila4|t}Az(eX?%t`iV@G z%61Yn1Zd}*M04OJ2dz1Qv{w1`@Ehdo9nF`BU&3#IpkA`IC039gc%@Vdc^UoZ-xw>s znk=VzUVs{Z%3bqq6GWSBPPLEW`C4wLtgjR!B6}fG4=Cw5zBad=KvqV6Q<+B{z9A zv&fLq6HLerg|1CXI)0xdMO+l&p%(s>)P*8G(qjy>xQ?&v{_GLTIA}{we!UhB<10ih z#u?gD9C^OOVm=mU=iLPWNE#AJ^t;Jnc6_Q91C$*DKOn zpyUpnj__kc$jVof#d3-HBnm6ftHPl|?vIp(sd-%e6>BYCE4#sBl@3fV@fOYv-hbon z&9)Q~b)U)8xR^p3?|w=bQ&FNm37E35m^tugh9$fLX~s$TBk1ond~OM-s9!rXoRrD| zVCcE>l&I)LX-t$Alk8ir_bS$WhU=IPSrS}l|JLm} zVs&RwVxqHo77X&rC@whncQ?W{+-kF3$+Gb%tC*2I3v~ZkoVr=DmnlcUF7?QePW1#< z>VO*;+%)~?5Sp=pEyJbvEKr6=4#4f0h$efDUnvcm=sQWuuKq1UfV6duht@nRp)zM9 zD#<0*tCLoCtS?u;_Vwzb+}Xtqf`n$@$px^BrVq zWH6zrzNrsB3;YOcS8_!YtO%5(Up6;nJ}LMr(3dPO%i$Dom$ZkLGna?>{ZYqNL$>l0 zNtx?*hv2d1OHOk&M}QiZ@cztP-1#Q;;OiMv5&zBo4qr9Y5Vr>-MKk0D zXM4B65?Qq{bDQO_DD6=Ax=eP8UGSrT4Xjy!KONbH6;K5sZ-?RRbYYG8HbNJpHj6Ch zH7Up6&k<=(M{P;E$DuJP^!RTS zKfYVDA;DXKe%haalBDj4Mh-)T=j}VRL*~nUz3nm8seHAOOng?xy8chZ##?D*hW%v3 z(6=hIwDk{lFEl>rtz?KeiUZJf1Tc}2lL5KT#tubxr@oKL)7-bvt#mJmTPa3IJ}S}I zU4qhF6MiUnV>?m|S*(ex|eB}tv7 zT{Qoi0`ifF0Ew-FC81|cs~`OTz->E0px`8{{83)tWO3N_*q7wu8w@%i%J7 z_Zab;{dVdAB_Jr9`uCjK7i zy%WaiSjrDI6L&ou5HUkkG!NrTbRnnPl}oa;h{s7gsOJ=r-@$`%+m&PHLkO<;91fFg zz8`9lrRE9iUCZR!unhditx4KVfQ06$xayKUq?g`ts@*Y!ulynC60rqi zH9MJTelul8t!VT3=qiJ*uqA0E1f42 z1637aB@Nn+E7f{H9G#B09O>4g214V+)*jm524NK3OMuy+c5VZB-&DS~u?FIx4CgdT zpyN>2dt%#Ru*wY=-OSEAb4ny>=*xbf*X7|@&n$<&pcEhLzbkfQe<+Lxx-rWehhncK z9Q3GF$D@bp%6?oke@<;6__(m26zd1pAtV`}r({8i3Zt6*giZKHtXBk-=ure-lK&Oj z4iwmk%;h8icnCMee=o_#rVd*O*9-MOwT#|Ctj^>yS)@9+8GV5ksi^SGk0KT+?kFcJ zTBXW>6L=?fpyT-L`2?9-O+%L9)Ah#{W3E=)ofdZBU?6XIoTibM#0u5|A~LHvb^&Y) zTX&CBT@bH9_6t5dJRGs@;0O#dtI}dDs$gXD5Nn$%Zz(hntd4dG;XXA|QQtK>!Nr(G zzgJ-vx{i-$@{)e?-^5$U^Xxr9aXm}torUoAONz>XzLy%@Edoz@E?p8U-D?C?A)}dp z10PRRmlXJT9$FLy;mb83S;&alS8JHzmBZv|4?6tq`JQ(7eJz`04?&LR!=InWUt%Bh zc)uAf;VO3qwo=jsU}q#Q;RCj2-4r=Kb7@DEM&(lUw}7%CNT ziGz*hg2)H;4urBwyN$HPOTq#@KDpGWp|W~EK%snTLJ5wAyb`bURZ1Nt0f4(B`tk0B z@Bw)1ZUopoSXI@4SNMKu+Q4yf2m9@7exqYgu|Z!bD^u7Ifi$^Zr(DSZJSRv!I3}DM9^E%Q%s?`QW)`at?pg0W)7tC%ymQhrw>Vmr z0b;x?D2anK7%s}cq@ae~r+lbc9$saYIeL_6Ht>UT;Em^rb@6Iv>HIYpg^z>z@lc?R z-~Os`wV)_Z6j&v1zf7N=@q-nS7{zT9v!9Yx2NjsN|8VwC#5NzopJ>$vXuI_}Ry6x%rlh4O8>cMU{XOSrd`VFPEq`eDbgk*>~5%C$Pwc4R4hrU_ar&@BxA zyc(Pt9zzVb5(MDq4H717A9Vn>xY4Mym@d=F2lqU^dn?GC?SP*TJGCz#+3%RONyoq{ z5gG)Jn;|PBM@adr7KZk>ysq*N9SD^otx|K0A&b`60$4)rbm8B+B{k?`ld0m&iGy9d zFup?Wk6wuiT(b;IKRsqu13C>wWSrszqde!)i$<#tEJTdIp$s7$$4x8@Tmj z&8sZepMt=JtaQ8Y#nWsOgBy3Rrq*<1;UJk1=Y2DsGhz&$A5L+xa@P;MV5MzYK;0d? zJZ$%LO)0|c5u7q^g0gw4V$=PNRT zK4ps`H1s|;_;nrKKKnSJA5MsGuG8W^4W(SDBQ=_a^H~bN<+fiKFS&aj_w9g6CRGbQMmp6K|64Sr0>tIf3LGi}h%a=AmpSa_Jal^;ZaKyuWL>A)1;)(DMe@;mLR zJa8qM)fUR6N5GmvGHK*u|)w~_^jGPio0?_LuVpIAVY;c3p;O|HlCF!xAJ4Du|tq3~zGn6|UVrAX){6*6HD`g|69SS;| zCFUGnNLQfm**Gs~1ooW_PCeFntW6-qwmLHeUjk+S$^w_#szXVliF_@(mc6yes%en>&c&fBm^Qhi=d%u);OUuGviPv=K7o;2Zfy~BfC9YyEJM2rkca@pKhl1>MPU^M4ru$~@&+j(~+ z;)yEYvw=5>^oONc2oq(Ai}XNM8IrmnrKwl0;H+~SVkK~v8ih@-=f21ya(;f0Y});i zgc@YA`wCG!@F2mV3N@S z`%_(aN3}f91i2)t){Yko+#kb%BUtXNq}BLkmS&p;eIe(Ga{LM+qnEl8Xkpbh-70rx z+hNWTYVOE%J9Y^P{pVc2N=^qE_rCCr7a^g5zmVp`cr|QT#7UKSm_7-`(WO;YM5vnG zHSp42ESHF+%nu_+UZ?7V4Ws#?doJ;gF_X}!JlpAyIT=nURY=k+=JsUDGYNgxnaFGq z%wbYu*dX{9cqu@ukyUWGZkNHTm@%EPxINt0l9E5K-}bRMOudR-h`73E; zowB#YB#FO0)~eJY=>-9djA4?0F(Z-1=qhTM@J=HUH`r^)!SDH323f0OXPVUczZ0)H?(PYA`1!&uo0<8|e90qH>Zm1e zs&F;J=$$2M6n1!B7UmCsfi0%dAN>rM^58oLm~)?=2jpKGtV%UCHG{w)V4-{3lcER) z;MO|!zdG(;IW|n5nK^_U)WJuQe-3gFo&kNnFSj+qq!6GYM&D`2U&=bergAYXdmppQ zTEMBk_N(}yi5a5~47JQj$!^j+9@k`sM zTCHO{8h|6Awdd36FV!Ekpu3-ca3l|{&Y<$(n>j)_!mTT-D?+Vf898%9^15uB9j$w{ zRCts>v{_c|9iSHdEoXE4x^=K>d0Qd+Cf~{rMfy)Wpz1o56p=J=K7y$Wqe;^bykN?B zZfWxNAEZx8;kh?jsUTUf^uAgt98+z#>v!rD)~xmNX&gGT=(v{r zL}W;^<#pl=-jyguRpM%;2gDfHO9tU>>@WvwLu5|%p%X@^L{bvo&nNr}Bz|*`0tFUVF_0oTKsp#<3Bh&huCEW%S z>!T0H>F9&3)$JSp$<1LPE1`RZouJN6Iq${r#|umOVyH$D=`4fx7OzJQDDyyc+HOEP z&NMs)+u!1i@1f{Ss`1E6z*f*D*-n`0d z^T&Pru|`RWrNxvxO<$-}vrDq=BJgC2+zLbLRhz5y^MRH!;=n3l&Z`aT^L~_=@J&6m zr7kM)rY~u}p9~lkw;f77Cb7BnSF6mD0q%2DvU|jFH=paZjYXS@h^w|OnO-_>D~dl) z?OmwLQgZb^jxucJ&uU6BrLZzZ&W~bHLI}Xq8&M%HgVT;%INpa#&9DJ1cTQ-jqr!9N zW_X8IzA9cex2UM3wZ{Y@ajuL%TER0a9jtRCsHSBEH3UWLe)OA08>K%itV5PtT3Ilu zrV!zk5WV?`xqV1#(g5fv9buN10a4C0E1pl1z=>pxU%H$0VjMb`A^MmO{*tIpIu^5X zSioqR!RzCxcB3rf4*a8p!RuyIJ=+3Aqc82q&g6x&uR7<kv~_yq0@(WSxKq z`Q<)G31;S}f9P!X%!#Dhv4Gzk-AV!b6~ePKPSSIx9DO!fRF4hx>fX%Pci`ZDZ)S2` z2L+IYd#q!Lr;B2oM^ccZ(#TKVJz;D0#0>3$y*_AjDK52|F^LrDOK~S#632}h2FOcG zvWEZ~rX2UroqC^xUojfKW(&Ntd-?DWi$;SI)EJYBnpi)~Pct`}i&R;F0|FzEbI?Gt z6|`(fT|o`&QY?QqO+L2D|0iyG1Y7oHqa?2Q2aGfg(B&UtnBoZZmoJ#K_YhS1_$vZb z$03h!WnPqseI|-&4^n{LJTe)sujr`ogHGcIv}kWyeVBbpmNsdSQmxMQU;EJY?fowU zctJ$_>}9sE{E}clo1&JZ^%WOuZog%u(R@y8(n^OzC9xjVC=(N>PI~NboJ_Z-DOv=s zG+OC0!Q3Qe?cc=w_I%%&F|)U&uBDQ+w0pw+e}i@^MF!rvrq8WGX+9ROKQ8{=H!v+- z&{0fIBIpSU8*)DvSeFIRsQ>gTTvC+_LzmLCzNI(46QMispXzu^;0yY+yUcaaW%R^U zT^@CVMu4!t%Z?MzC)#+y6|pZDNWO42p^W#!X5}k;i@sZ1O_kIr@`irB)WibI$pAklKCijSRri$L0#qK^>91#x}pCp?`_wY8J7 zM4os=^{~Zh-&|np>)kHz&y;HEx^3lN%{1i)IX<*NdJKH1%s`Y(>j)quYcimp{{8Rp z;SRSE3vStrl!B~tvxLXD!!0Usa+TT2$BR`M>Lo1bDHnX&xEQmgx;l=V<5 z)=;PGfna(47N6DQgF*VRYA(S5#_#%#eFS%g?g8GSXE&0`oj~Hm0YM9Y+am>-Q9K!( z5-j0=prG1tk0|unP~Oj_veQI?Q?%Yc>}dDUCs+`8L6sLOF1xT+a~&?+wxwd7O}67Ml)#iwO08Q+X{r`Z@nQ~_c#)bdk* zl=(XRxtWWcm!uJ!QM-R0_-?#w^bbdLDQ-C2r6!IP8#qo6rmI>9RcF?BVkOo5ZL@)a zdwM%Ym2FCp&y=a9G%O8eBJn>%yRNgoLC+vUKbSm?0NwWKg6#SXM4o$ilcQL4p z%g{e1X6-OSe!(Q42Dk3pBL(q{-ajQ7K?nF0vG8$3Q)3=~!`@uQT}yL-(HHU8udVCb za>0xI9JOTx4cq63z?whh>wKRfsQzrfZaLQR@UC(0b!ka9l4^*zX)Q!lAbW9cctx8?6grOUD^8RJ@@yEMTznb1fT^)>)0woydk@XkvlK z&kovR+;qmu8K8?ADV*l4FqTVWA(D`vWJ>sK2i#+|5=TCkc2|T|$1L42IhcLPc@0?C z={e49Th{j<4!?jBBXLYCEf2qczaA@Lii8xGCW?lUy-|zg&r;>4+9%m)2$e^xG?kMgjFH)4-&k#c*61W$-iX1I&q`5F!FR`@mR7@DcrU zTpXP5J)=DW(ZoII(wM@#R|PzK;a3(X(I8T?{qrKD5`>z@2w-;=yJmQsnAa#LhJJ@c zXzgF>gPQ#wlr~v(s^;W?*3j7Q{=ZI}{?K>JK7uTW(>DZ)w7=o+9&8#9|0l3$^w#ew z6Y9{t>8-3h$^%E9+)U%e)a!#5WQJO=_8CI*M#Nxv8GzV(1|t%PIF1ebi@8aQFSVB- zFb}{(6NMHpzCSzGhdd5u6b*9HOzxso>f@;{+M(agochLC+l~s*tEy~Cwam7jow<4Z zL)O(Gfo9@qV;5L?k*wvjy3M^uA`tFjBO8dejOI1h7e)0ddHOAZGAh=c7AS2K_9?&?u*MupKeHaC-QU0BN8q zgjl#$;2Ib2(pPnh=i>u^cqf-L;6sqFP%fc!w@qbGb6Fw8>dLt`LhASd1$9@wa;-T; zfQe<0+_5pG-u1JZNgL2qjCf~Jo?>vjI<|wM+~QhOyfc0a)X+dp5r##CaFT^?Q@a=l z{yeN8r|e5=+Hu(r*#4pviWU^b7KM76Tm}=@qTx`^!5{!~bU(bE9AVYRn6k$sV<;;r4LL`?eWDgv2vcYo;$0BV?!`ajnLIl0y zNI!^HLBZjg+Km!;zFC()eV!knBeex4v}%AWy>Tpw7wqUaFszST8PPDVt@_=^W?hG~ z06dEvpkYo4I~z~~t!(b39AwwAJPwTUn|LnJE7?E}m1_7MwGS~&#oZQ7v%=MmSUTh4 zI_N+Fp)=A~ur<&S{=v!kf~b;mZEWb38xuT;GOd8)NG9i9Fy3vCpeC+REAPPPT3@bY zX!Sww1Ndq8A|L0sFuBkoe>OS8@R`>Y6#n8K7~O5HO|!-+stw3uPczmF6*|cIk$2qN@z7-3 zu9-XrRNC7Y$>YMa%lUJWph)rzZb#ga=*T>w3tyBG&(e!3)GHiz6b)nW@@|*!Qu`t)e5*|(KbtGi& zk|{y#(C)6SV>v7D1?qa*8bq86kj_@*d@38O2A>)3HoB}`Rjb5dHGx#kLuqr7xU?6@ zXw#7F)lH}h>i{m&ru~|=$5nQB92{XOO7(h-tc6&RVl#eWGA4=L2SmXQ2vS@9Lscwy z*&qqfp4O!T)81H9e?~Z_Ai4r8jFaIh9-3Mf*)pJD0_A5*6dljG*q{ufGk@<1H9UF0 zud&?|oEN}Xx-T)A>ID;?0DF5sT{)o9zVdFbiUHyKiEgn2C&6G^ZuhNC*`<%iFjVNL zgqX-@vr`fw0Ob}-NTX^ZtH!qJQ@#VleP z7GRW^eCJRt_t2?~zU*h(Xrq!d#k_DDG3FI$&$Ojy9EfC!+DccH0IM`szP><*H}$*f zSVIrL1i&J)wNCn|FG1<@doDsyMM<-?LCy1M6T&BMK-Ks{<&p^PaXXGs{kz>IEd0Zs zikvy-z=Glbbd)SW(M-avv{O7^=C%b5ZEHG8kxB!i+EKG9=-m+lZ@MYcN+7nML2c?d z){8=OgiA|HjQ7o=$AySg91zm-V4mSuM@!*?&AGdxMP1a%i>}UIi>g%6OlPQA6;^}XKVuLVz1T5z!GkF1)y$kDje70V z*SgR~Qd6lS*n?27y^ofP>v)toFAynm_RzMKY`EZS?}#s_)=GDdY>%fvU9(vQ_&Ip;Ot9 zZx&qF25%gd?~MicSHImYB3y(}0LL0#b7ddQf?y*dAz~7{ z1R?hXkh;Co$&$~x7N2yg%nKYwA>koHOF+uVh$Lq%2fUweQZmbX z6BzU&;R?L!5WTdVY>_2Kx7pC8DLhO)d-iABL*|j9`&L^$j6t=7zi`NPR7wY z18xDRlS6cS(4;;5`Kq|qFsBeWhC2E0RY79TDU?