szolgáltatók beálltásai, szerkesztése , létrehozása

This commit is contained in:
Roo
2026-06-17 11:52:25 +00:00
parent 213ba3b0f1
commit bf3a971ff1
56 changed files with 14421 additions and 1512 deletions

View File

@@ -0,0 +1,194 @@
# 🔍 Deep Dive Audit Jelentés — Címek, API sémák & Autónyíri Kft. (ID 58)
**Dátum:** 2026-06-17
**Auditor:** Architect Mode
**Cél:** A cím szétdarabolás, kapcsolatfelvételi mezők és API sémák állapotának felmérése
---
## 1. ADATBÁZIS SÉMA AUDIT — Organization modell
**Fájl:** [`backend/app/models/marketplace/organization.py`](backend/app/models/marketplace/organization.py)
### 1.1 Cím mezők az `Organization` táblában (`fleet.organizations`)
A modell **rendelkezik atomizált címmezőkkel**:
| Mező | Típus | Hossz | Leírás |
|------|-------|-------|--------|
| `address_id` | PG_UUID, FK→`system.addresses.id` | - | Opcionális hivatkozás a központi cím táblára |
| `address_zip` | String | 10 | Irányítószám |
| `address_city` | String | 100 | Város |
| `address_street_name` | String | 150 | **Utca név** (pl. "Egressy u.") |
| `address_street_type` | String | 50 | **Közterület típus** (pl. "utca", "út", "tér") — jelenleg null |
| `address_house_number` | String | 20 | **Házszám** (pl. "4.") — jelenleg null |
| `address_hrsz` | String | 50 | Helyrajzi szám |
**Megjegyzés:** A `Branch` modell még tovább bontja: `stairwell`, `floor`, `door` — ezek az `Organization`-ben **nincsenek** implementálva, de a `CorpOnboardIn` séma tartalmazza őket.
### 1.2 Kapcsolatfelvételi mezők
**Az `Organization` modell NEM tartalmazza a következőket:**
-`contact_phone`
-`contact_email`
-`website`
**Ezek a `ServiceProfile` modellben vannak** ([`backend/app/models/marketplace/service.py`](backend/app/models/marketplace/service.py:66)):
| Mező | Típus | Tábla |
|------|-------|-------|
| `contact_phone` | String | `marketplace.service_profiles` |
| `contact_email` | String | `marketplace.service_profiles` |
| `website` | String | `marketplace.service_profiles` |
**Következtetés:** A kapcsolatfelvételi adatok **szét vannak szórva** két tábla között. Az Organization-ben tárolódnak a címadatok, míg a ServiceProfile-ban a telefon/email/weboldal. Ez egy **1:1 kapcsolat** `organization_id`-n keresztül.
---
## 2. API SÉMA AUDIT — Provider Pydantic sémák
**Fájl:** [`backend/app/schemas/provider.py`](backend/app/schemas/provider.py)
### 2.1 CRITICAL BUG: A `ProviderQuickAddIn` és `ProviderUpdateIn` sérülékeny
Mindkét séma **összevont `street` mezőt** használ:
```python
# provider.py sor 59
street: Optional[str] = Field(None, max_length=255, description="Utca, házszám")
```
Eközben a modell (`Organization`) **atomizált** mezőket vár:
```python
# organization.py sor 83-86
address_street_name: Mapped[Optional[str]] # Utca név
address_street_type: Mapped[Optional[str]] # Közterület típus
address_house_number: Mapped[Optional[str]] # Házszám
```
**A `quick_add_provider()` függvény** ([`provider_service.py:403`](backend/app/services/provider_service.py:403)) a teljes `street` sztringet az `address_street_name`-be tömöríti:
```python
org.address_street_name = data.street, # "Egressy u. 4." → address_street_name
```
**Következmény:** `address_street_type` és `address_house_number` **mindig `null`** maradnak a crowdsource-olt szolgáltatóknál!
### 2.2 A `ProviderSearchResult` séma hiányosságai
A `ProviderSearchResult` ([`provider.py:21`](backend/app/schemas/provider.py:21)) **nem tartalmazza az atomizált címmezőket**:
-`address_street_name` — hiányzik
-`address_street_type` — hiányzik
-`address_house_number` — hiányzik
-`address_hrsz` — hiányzik
-`address_zip` — van
- ⚠️ `address` — generic string (összefűzött)
- ⚠️ `city` — generic string
### 2.3 A `CorpOnboardIn` séma (organization.py) helyes
A [`CorpOnboardIn`](backend/app/schemas/organization.py:10) **helyesen tartalmazza** az összes atomizált mezőt:
`address_zip`, `address_city`, `address_street_name`, `address_street_type`, `address_house_number`, `address_stairwell`, `address_floor`, `address_door`, `address_hrsz`
Az [`OrganizationUpdate`](backend/app/schemas/organization.py:41) is helyes.
---
## 3. NYERS ADAT — Autónyíri Kft. (ID 58)
### 3.1 Organization rekord
```json
{
"id": 58,
"name": "Autónyíri Kft.",
"full_name": "Autónyíri Kft.",
"org_type": "service_provider",
"status": "pending_verification",
"is_verified": false,
"is_active": true,
"is_deleted": false,
"tax_number": null,
"reg_number": null,
"country_code": "HU",
"language": "hu",
"default_currency": "HUF",
"address_id": null,
"address_zip": null,
"address_city": "Dunakeszi",
"address_street_name": "Egressy u. 4.",
"address_street_type": null,
"address_house_number": null,
"address_hrsz": null,
"first_registered_at": "2026-06-16 23:16:23",
"lifecycle_index": 1,
"subscription_plan": "FREE",
"owner_id": 2,
"legal_owner_id": null,
"folder_slug": "84632013004e",
"aliases": [],
"tags": [],
"external_integration_config": {},
"visual_settings": {"theme": "default", "primary_color": null, "wall_logo_url": null}
}
```
### 3.2 ServiceProfile rekord
```json
{
"id": 3,
"organization_id": 58,
"status": "ghost",
"contact_phone": null,
"contact_email": null,
"website": null,
"bio": null,
"is_verified": false,
"trust_score": 30,
"rating": null,
"specialization_tags": {"primary_category": "auto_szerelo"}
}
```
### 3.3 Branch rekord
```json
{
"id": "3b80ee85-7712-4b17-b992-d62dcefdf5e2",
"name": "Autónyíri Kft.",
"is_main": true,
"status": "active",
"city": "Dunakeszi",
"street_name": "Egressy u. 4.",
"street_type": null,
"house_number": null,
"postal_code": null
}
```
### 3.4 Megállapítások az ID=58-ról
1. **Cím szétdarabolás hiánya:** `address_street_name` = "Egressy u. 4." — a teljes utca+házszám egyben. A `street_type` és `house_number` feldolgozatlan.
2. **Nincs kapcsolatfelvételi adat:** `contact_phone`, `contact_email`, `website` — mind `null` a ServiceProfile-ban.
3. **Nincs adószám:** `tax_number` = null — bár ez egy Kft.
4. **Crowdsource-olt rekord:** `external_integration_config` = `{}` (üres) — a source nincs beállítva, bár a kód logikája szerint "crowdsourced" kéne legyen.
---
## 4. ÖSSZEFOGLALÓ — Feltárt problémák
| # | Probléma | Hatás | Súlyosság |
|---|----------|-------|-----------|
| P1 | `ProviderQuickAddIn` és `ProviderUpdateIn` összevont `street` mezőt használ atomizált `address_street_name`/`_type`/`_house_number` helyett | A cím soha nem kerül szétdarabolásra. A `street_type` és `house_number` mindig `null` marad. | 🔴 MAGAS |
| P2 | `ProviderSearchResult` séma nem tartalmazza az atomizált címmezőket | A frontend nem tudja megjeleníteni a szétdarabolt címet. | 🟠 KÖZEPES |
| P3 | Kapcsolatfelvételi adatok (telefon, email, weboldal) a ServiceProfile-ban vannak, de a gyors felvételkor üresen maradnak | Az Autónyíri Kft.-nek nincs elérhetősége az adatbázisban. | 🟠 KÖZEPES |
| P4 | `OrganizationResponse` séma nem adja vissza a címmezőket | A frontend `OrganizationUpdate`-on keresztül írhat címet, de `OrganizationResponse`-on keresztül nem olvassa vissza. | 🟡 ALACSONY |
| P5 | A `Branch` modellben is hiányzik a `street_type`/`house_number` az autónyíris rekordnál | A Branch címe is strukturálatlan | 🟡 ALACSONY |
### Javasolt javítási sorrend:
1. **P1:** A `ProviderQuickAddIn` és `ProviderUpdateIn` sémák kiterjesztése atomizált mezőkkel (`address_street_name`, `address_street_type`, `address_house_number`)
2. **P2:** A `ProviderSearchResult` kibővítése az atomizált címmezőkkel
3. **P3:** A frontend űrlapok kiegészítése telefonszám, email és weboldal mezőkkel a gyors felvételnél
4. **P5:** A Branch létrehozásánál a `street_type` és `house_number` mezők feltöltése

View File

@@ -0,0 +1,540 @@
# 🏗️ Teljes Adatbázis Séma Audit & Partner Modell Felfedezés
**Dátum:** 2026-06-16
**Auditor:** Rendszer-Architect (DeepSeek Reasoner)
**Cél:** Partner/Szolgáltató modellek azonosítása és a teljes adatbázis térkép elkészítése
---
## 1. 🔍 CÉLTUDATOS KERESÉS: Cégek / Partnerek / Szolgáltatók
### 1.1. Találatok összefoglalása
| Keresőszó | Találat | Modell | Séma |
|-----------|---------|--------|------|
| **Company** | ✅ VAN | `Organization` | `fleet.organizations` |
| **Partner** | ✅ RÉSZBEN | `Organization.is_affiliate_partner` | `fleet.organizations` |
| **Vendor** | ❌ NINCS | - | - |
| **ServiceProvider** | ✅ VAN | `ServiceProvider` (régi) | `marketplace.service_providers` |
| **ServiceProfile** | ✅ VAN | `ServiceProfile` (új) | `marketplace.service_profiles` |
| **Contact/Person** | ✅ VAN | `Person` | `identity.persons` |
| **Tenant** | ❌ NINCS | - | - |
| **Business** | ✅ VAN | `Organization` (org_type=business) | `fleet.organizations` |
| **Branch/Location** | ✅ VAN | `Branch` | `fleet.branches` |
### 1.2. Fő következtetés
**NINCS dedikált "Partner" vagy "Szolgáltató" modell.**
A rendszer **két különböző, egymástól független** entitáskészlettel dolgozik:
1. **`fleet.organizations`** - Szervezetek (Cégek, Flották, Egyéni vállalkozók)
2. **`marketplace.service_providers`** + **`marketplace.service_profiles`** - Szerviz szolgáltatók
Ez a két világ **gyengén kapcsolódik** egymáshoz: a `ServiceProfile` hivatkozhat egy `Organization`-ra, de ez opcionális.
---
## 2. 📋 MEGLÉVŐ MODELLEK RÉSZLETES ELEMZÉSE
### 2.1. `fleet.organizations` (Organization modell)
**Fájl:** `backend/app/models/marketplace/organization.py`
**Tábla:** `fleet.organizations`
**Oszlopok csoportosítva:**
#### 🏢 Alapadatok
| Oszlop | Típus | Kötelező? | Megjegyzés |
|--------|-------|-----------|------------|
| `id` | `INTEGER` | ✅ | PK |
| `name` | `VARCHAR(255)` | ✅ | Cégnév |
| `full_name` | `VARCHAR` | ✅ | Teljes cégnév |
| `display_name` | `VARCHAR(50)` | ❌ | Rövid megjelenítési név |
| `folder_slug` | `VARCHAR(12)` | ✅ | **UNIQUE** Rendszer azonosító |
| `org_type` | `ENUM(OrgType)` | ✅ | `individual`, `service`, `service_provider`, `fleet_owner`, `club`, `business` |
#### 📍 Cím adatok (Denormalizált)
| Oszlop | Típus |
|--------|-------|
| `address_id` | `UUID (FK → system.addresses.id)` |
| `address_zip`, `address_city`, `address_street_name`, `address_street_type`, `address_house_number`, `address_hrsz` | `VARCHAR` |
| `country_code` | `VARCHAR(2)` → default "HU" |
| `language` | `VARCHAR(5)` → default "hu" |
#### 🆔 Adóazonosítók
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `tax_number` | `VARCHAR(20)` | **UNIQUE** Adószám |
| `reg_number` | `VARCHAR(50)` | Cégjegyzékszám |
#### 🛡️ Életút / Biztonság
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `legal_owner_id` | `BIGINT (FK → identity.persons.id)` | Jogi képviselő (Person) |
| `owner_id` | `INTEGER (FK → identity.users.id)` | Technikai tulajdonos (User) |
| `first_registered_at` | `TIMESTAMPTZ` | Első regisztráció (örök) |
| `current_lifecycle_started_at` | `TIMESTAMPTZ` | Aktuális életciklus kezdete |
| `lifecycle_index` | `INTEGER` | Hányadik életciklus |
| `is_deleted` | `BOOLEAN` | Soft delete flag |
| `is_active` | `BOOLEAN` | Aktív flag |
| `is_anonymized` | `BOOLEAN` | Anonimizált flag |
| `is_verified` | `BOOLEAN` | KYC verifikáció |
#### 💰 Partner / Értékesítés
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `is_affiliate_partner` | `BOOLEAN` | **PARTNER FLAG**`false` default |
| `subscription_plan` | `VARCHAR(30)` | "FREE", "PREMIUM", stb. |
| `base_asset_limit` | `INTEGER` | Eszköz limit |
| `is_ownership_transferable` | `BOOLEAN` | Átruházható-e |
#### ⚙️ Konfiguráció
| Oszlop | Típus |
|--------|-------|
| `notification_settings` | `JSON` |
| `external_integration_config` | `JSON` |
| `visual_settings` | `JSONB` |
#### 🔗 Kapcsolatok (Relationships)
```python
Organization
assets: List[AssetAssignment] # Jármű hozzárendelések
members: List[OrganizationMember] # Tagok (User/Person)
owner: User # Technikai tulajdonos
financials: List[OrganizationFinancials] # Pénzügyi adatok
service_profile: ServiceProfile # Opcionális szerviz profil (1:1)
branches: List[Branch] # Telephelyek
legal_owner: Person # Jogi képviselő
vehicle_costs: List[VehicleCost] # Jármű költségek
```
---
### 2.2. `marketplace.service_providers` (ServiceProvider modell - RÉGI)
**Fájl:** `backend/app/models/marketplace/service.py`
**Tábla:** `marketplace.service_providers`
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `id` | `INTEGER` | PK |
| `name` | `VARCHAR` | ✅ Név |
| `address` | `VARCHAR` | ✅ Cím (egyszerű szöveg) |
| `category` | `VARCHAR` | ❌ Kategória |
| `status` | `USER-DEFINED` | ✅ Státusz (ENUM) |
| `source` | `USER-DEFINED` | ✅ Forrás (ENUM) |
| `validation_score` | `INTEGER` | ✅ Validációs pontszám |
| `evidence_image_path` | `VARCHAR` | ❌ Kép bizonyíték |
| `added_by_user_id` | `INTEGER` | ❌ Ki adta hozzá |
| `created_at` | `TIMESTAMPTZ` | Létrehozás |
> ⚠️ **Ez a tábla egy régebbi verzió. Nem használja a `ServiceProfile` modell, hanem külön kezelendő.**
---
### 2.3. `marketplace.service_profiles` (ServiceProfile modell - ÚJ)
**Fájl:** `backend/app/models/marketplace/service.py`
**Tábla:** `marketplace.service_profiles`
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `id` | `INTEGER` | PK |
| `organization_id` | `INTEGER (FK → fleet.organizations.id)` | **UNIQUE** - Kapcsolat a szervezethez |
| `parent_id` | `INTEGER (FK → self)` | Hierarchia (pl. franchise) |
| `fingerprint` | `VARCHAR(255)` | **UNIQUE INDEX** - Robot által generált |
| `location` | `GEOMETRY(POINT)` | PostGIS hely |
| `status` | `ENUM(ServiceStatus)` | `ghost`, `active`, `flagged`, `suspended` |
| `google_place_id` | `VARCHAR(100)` | **UNIQUE** Google Places azonosító |
| `trust_score` | `INTEGER` | Trust engine pontszám |
| `is_verified` | `BOOLEAN` | Verifikált szolgáltató |
| `vibe_analysis` | `JSONB` | AI hangulatelemzés |
| `social_links` | `JSONB` | Közösségi média linkek |
| `specialization_tags` | `JSONB` | Specializációs címkék |
| `opening_hours` | `JSONB` | Nyitvatartás |
| `contact_phone` | `VARCHAR` | Telefon |
| `contact_email` | `VARCHAR` | Email |
| `website` | `VARCHAR` | Weboldal |
| `bio` | `TEXT` | Leírás |
| `rating_overall` | `FLOAT` | Átfogó értékelés |
| `rating_verified_count` | `INTEGER` | Verified review-ok száma |
#### 🔗 Kapcsolatok
```python
ServiceProfile
organization: Organization # 1:1 kapcsolat
expertises: List[ServiceExpertise] # Szakmai címkék
reviews: List[ServiceReview] # Vélemények
```
---
### 2.4. `marketplace.service_reviews` (Verified Service Reviews)
**Tábla:** `marketplace.service_reviews`
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `id` | `INTEGER` | PK |
| `service_id` | `INTEGER (FK → marketplace.service_profiles.id)` | Melyik szerviz |
| `user_id` | `INTEGER (FK → identity.users.id)` | Ki írta |
| `transaction_id` | `UUID` | **UNIQUE** - Tranzakció azonosító |
| `price_rating` | `INTEGER (1-5)` | Ár értékelés |
| `quality_rating` | `INTEGER (1-5)` | Minőség értékelés |
| `time_rating` | `INTEGER (1-5)` | Idő értékelés |
| `communication_rating` | `INTEGER (1-5)` | Kommunikáció értékelés |
| `comment` | `TEXT` | Szöveges vélemény |
| `is_verified` | `BOOLEAN` | Tranzakcióhoz kötött |
| `created_at`/`updated_at` | `TIMESTAMPTZ` | Audit |
---
### 2.5. `marketplace.ratings` (Általános értékelések)
**Tábla:** `marketplace.ratings`
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `id` | `INTEGER` | PK |
| `author_id` | `INTEGER` | Ki írta |
| `target_organization_id` | `INTEGER` | Cél szervezet (opcionális) |
| `target_user_id` | `INTEGER` | Cél felhasználó (opcionális) |
| `target_branch_id` | `UUID` | Cél telephely (opcionális) |
| `score` | `NUMERIC` | Pontszám |
| `comment` | `TEXT` | Szöveges |
| `images` | `JSONB` | Képek |
| `is_verified` | `BOOLEAN` | Verifikált |
---
### 2.6. `fleet.branches` (Telephelyek)
**Tábla:** `fleet.branches`
| Oszlop | Típus | Megjegyzés |
|--------|-------|------------|
| `id` | `UUID` | PK |
| `organization_id` | `INTEGER (FK → fleet.organizations.id)` | ✅ Melyik szervezethez |
| `address_id` | `UUID (FK → system.addresses.id)` | ❌ Cím (strukturált) |
| `name` | `VARCHAR(100)` | ✅ Telephely név |
| `is_main` | `BOOLEAN` | Központi telephely |
| `postal_code`, `city`, `street_name`, stb. | `VARCHAR` | Denormalizált cím |
| `location` | `GEOMETRY(POINT)` | PostGIS |
| `opening_hours` | `JSONB` | Nyitvatartás |
| `branch_rating` | `FLOAT` | Telephely értékelés |
| `status` | `VARCHAR(30)` | `active`, `inactive` |
| `is_deleted` | `BOOLEAN` | Soft delete |
---
## 3. 🗺️ TELJES ADATBÁZIS TÉRKÉP (Minden séma és tábla)
### 3.1. Identity séma (Személyek, Felhasználók, Hitelesítés)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `identity.persons` | Természetes személyek (DNS szint) | ✅ **Aktív** |
| `identity.users` | Technikai fiókok (bejelentkezés) | ✅ **Aktív** |
| `identity.wallets` | Pénztárcák (Triple Wallet) | ✅ **Aktív** |
| `identity.active_vouchers` | Aktív voucher-ek | ✅ **Aktív** |
| `identity.user_trust_profiles` | Trust score profilok | ✅ **Aktív** |
| `identity.verification_tokens` | Email/telefon verifikáció | ✅ **Aktív** |
| `identity.one_time_passwords` | OTP kódok | ✅ **Aktív** |
| `identity.social_accounts` | Közösségi média kapcsolatok | ✅ **Aktív** |
| `identity.devices` | Eszköz fingerprint | ✅ **Aktív** |
| `identity.user_device_links` | User-Eszköz kapcsolatok | ✅ **Aktív** |
### 3.2. Fleet séma (Szervezetek, Flották)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `fleet.organizations` | Szervezetek (cégek, flották, szolgáltatók) | ✅ **Aktív** |
| `fleet.organization_members` | Tagságok (User/Person → Organization) | ✅ **Aktív** |
| `fleet.organization_financials` | Pénzügyi adatok (éves) | ✅ **Aktív** |
| `fleet.branches` | Telephelyek | ✅ **Aktív** |
| `fleet.asset_assignments` | Jármű hozzárendelések | ✅ **Aktív** |
| `fleet.org_sales_assignments` | Értékesítési hozzárendelések | ✅ **Aktív** |
### 3.3. Vehicle séma (Járművek, Katalógus)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `vehicle.vehicle_model_definitions` | Jármű modellek (MDM) | ✅ **Aktív** |
| `vehicle.vehicle_catalog` | Katalógus sablonok | ✅ **Aktív** |
| `vehicle.assets` | Fizikai eszközök (Digital Twin) | ✅ **Aktív** |
| `vehicle.vehicle_types` | Jármű típusok | ✅ **Aktív** |
| `vehicle.feature_definitions` | Felszereltség elemek | ✅ **Aktív** |
| `vehicle.model_feature_maps` | Modell-Felszereltség kapcsolatok | ✅ **Aktív** |
| `vehicle.dict_body_types` | Karosszéria típus szótár | ✅ **Aktív** |
| `vehicle.cost_categories` | Költségkategóriák | ✅ **Aktív** |
| `vehicle.costs` | Jármű költségek (TCO) | ✅ **Aktív** |
| `vehicle.vehicle_expenses` | Jármű kiadások (jelentésekhez) | ✅ **Aktív** |
| `vehicle.odometer_readings` | Kilométeróra állások | ✅ **Aktív** |
| `vehicle.vehicle_ownership_history` | Tulajdonos történet | ✅ **Aktív** |
| `vehicle.vehicle_transfer_requests` | Átruházási kérelmek | ✅ **Aktív** |
| `vehicle.catalog_discovery` | Katalógus felfedező várólista | ✅ **Aktív** |
| `vehicle.gb_catalog_discovery` | UK piaci felfedező | ✅ **Aktív** |
| `vehicle.auto_data_crawler_queue` | Crawler várólista | ✅ **Aktív** |
| `vehicle.vehicle_logbook` | Jármű naplókönyv | ✅ **Aktív** |
| `vehicle.motorcycle_specs` | Motorkerékpár specifikációk | ✅ **Aktív** |
| `vehicle.external_reference_library` | Külső referencia könyvtár | ✅ **Aktív** |
| `vehicle.reference_lookup` | Referencia kereső | ✅ **Aktív** |
| `vehicle.vehicle_user_ratings` | Felhasználói jármű értékelések | ✅ **Aktív** |
| `vehicle.asset_costs` | Eszköz költségek | ✅ **Aktív** |
| `vehicle.asset_events` | Eseménynapló | ✅ **Aktív** |
| `vehicle.asset_financials` | Pénzügyi adatok | ✅ **Aktív** |
| `vehicle.asset_inspections` | Ellenőrzések | ✅ **Aktív** |
| `vehicle.asset_reviews` | Eszköz vélemények | ✅ **Aktív** |
| `vehicle.asset_telemetry` | Telemetria adatok | ✅ **Aktív** |
### 3.4. Marketplace séma (Piactér, Szervizek)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `marketplace.service_providers` | Szolgáltatók (RÉGI, egyszerű) | ⚠️ **Használaton kívül?** |
| `marketplace.service_profiles` | Szerviz profilok (ÚJ) | ✅ **Aktív** |
| `marketplace.service_reviews` | Verifikált vélemények | ✅ **Aktív** |
| `marketplace.expertise_tags` | Szakmai címkék | ✅ **Aktív** |
| `marketplace.service_expertises` | Szerviz-Szakma kapcsolatok | ✅ **Aktív** |
| `marketplace.service_specialties` | Specializációk (hierarchikus) | ✅ **Aktív** |
| `marketplace.service_staging` | Robot által gyűjtött adatok | ✅ **Aktív** |
| `marketplace.discovery_parameters` | Robot keresési paraméterek | ✅ **Aktív** |
| `marketplace.service_requests` | Szervizigények | ✅ **Aktív** |
| `marketplace.ratings` | Általános értékelések | ✅ **Aktív** |
| `marketplace.votes` | Szavazatok | ✅ **Aktív** |
| `marketplace.costs` | Költségnapló (Trust Engine) | ✅ **Aktív** |
### 3.5. Finance séma (Pénzügyek)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `finance.credit_logs` | Hitel napló | ✅ **Aktív** |
| `finance.exchange_rates` | Árfolyamok | ✅ **Aktív** |
| `finance.issuers` | Kibocsátók | ✅ **Aktív** |
| `finance.org_subscriptions` | Szervezeti előfizetések | ✅ **Aktív** |
| `finance.user_subscriptions` | Felhasználói előfizetések | ✅ **Aktív** |
| `finance.payment_intents` | Fizetési szándékok | ✅ **Aktív** |
| `finance.withdrawal_requests` | Kifizetési kérelmek | ✅ **Aktív** |
### 3.6. System séma (Rendszeradatok)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `system.addresses` | Strukturált címek | ✅ **Aktív** |
| `system.documents` | Dokumentumok | ✅ **Aktív** |
| `system.translations` | Többnyelvű fordítások | ✅ **Aktív** |
| `system.system_parameters` | Rendszer paraméterek | ✅ **Aktív** |
| `system.internal_notifications` | Belső értesítések | ✅ **Aktív** |
| `system.pending_actions` | Függőben lévő műveletek | ✅ **Aktív** |
| `system.service_catalog` | Szolgáltatás katalógus | ✅ **Aktív** |
| `system.subscription_tiers` | Előfizetési szintek | ✅ **Aktív** |
| `system.service_staging` | Szolgáltatás staging | ⚠️ **Duplikáció?** |
| `system.staged_vehicle_data` | Jármű adat staging | ✅ **Aktív** |
| `system.geo_postal_codes` | Irányítószám adatok | ✅ **Aktív** |
| `system.geo_streets` | Utcák | ✅ **Aktív** |
| `system.geo_street_types` | Utca típusok | ✅ **Aktív** |
| `system.competitions_deprecated` | Versenyek (DEPR) | ❌ **Deprecated** |
| `system.user_scores_deprecated` | Pontszámok (DEPR) | ❌ **Deprecated** |
| `system.service_staging_deprecated` | Staging (DEPR) | ❌ **Deprecated** |
| `system.system_data_completion_weights` | Adatteljességi súlyok | ✅ **Aktív** |
### 3.7. Audit séma (Naplózás)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `audit.audit_logs` | Általános audit napló | ✅ **Aktív** |
| `audit.financial_ledger` | Pénzügyi főkönyv | ✅ **Aktív** |
| `audit.operational_logs` | Működési napló | ✅ **Aktív** |
| `audit.process_logs` | Folyamat napló | ✅ **Aktív** |
| `audit.security_audit_logs` | Biztonsági audit napló | ✅ **Aktív** |
### 3.8. Gamification séma (Játékosítás)
| Tábla | Leírás | Státusz |
|-------|--------|---------|
| `gamification.badges` | Jelvények | ✅ **Aktív** |
| `gamification.competitions` | Versenyek | ✅ **Aktív** |
| `gamification.level_configs` | Szint konfigurációk | ✅ **Aktív** |
| `gamification.point_rules` | Pont szabályok | ✅ **Aktív** |
| `gamification.points_ledger` | Pont főkönyv | ✅ **Aktív** |
| `gamification.seasonal_competitions` | Szezonális versenyek | ✅ **Aktív** |
| `gamification.seasons` | Szezonok | ✅ **Aktív** |
| `gamification.user_badges` | Felhasználói jelvények | ✅ **Aktív** |
| `gamification.user_contributions` | Felhasználói hozzájárulások | ✅ **Aktív** |
| `gamification.user_scores` | Felhasználói pontszámok | ✅ **Aktív** |
| `gamification.user_stats` | Felhasználói statisztikák | ✅ **Aktív** |
---
## 4. 🔗 KAPCSOLATOK TÉRKÉP (Entity Relationship)
```mermaid
erDiagram
PERSON ||--o{ USER : "has"
PERSON ||--o{ ORGANIZATION_MEMBER : "member of"
PERSON ||--o{ ORGANIZATION : "legal owner of"
USER ||--o{ ORGANIZATION : "technical owner of"
USER ||--o{ SERVICE_REVIEW : "writes"
USER ||--o{ SERVICE_REQUEST : "creates"
USER ||--o{ VEHICLE_USER_RATING : "rates"
ORGANIZATION ||--o{ ORGANIZATION_MEMBER : "has members"
ORGANIZATION ||--o{ BRANCH : "has locations"
ORGANIZATION ||--o| SERVICE_PROFILE : "optional service"
ORGANIZATION ||--o{ ASSET_ASSIGNMENT : "owns vehicles"
ORGANIZATION ||--o{ VEHICLE_COST : "pays costs"
SERVICE_PROFILE ||--o{ SERVICE_REVIEW : "receives"
SERVICE_PROFILE ||--o{ SERVICE_EXPERTISE : "specializes"
SERVICE_PROFILE ||--o{ BRANCH : "operates"
BRANCH ||--o{ RATING : "rated by"
BRANCH ||--o{ SERVICE_REQUEST : "receives requests"
VEHICLE_MODEL_DEFINITION ||--o{ ASSET_CATALOG : "has variants"
VEHICLE_MODEL_DEFINITION ||--o{ VEHICLE_COST : "has costs"
VEHICLE_MODEL_DEFINITION ||--o{ VEHICLE_USER_RATING : "rated by users"
ASSET_CATALOG ||--o{ ASSET : "defines"
ASSET ||--o{ ASSET_EVENT : "has events"
ASSET ||--o{ SERVICE_REQUEST : "referenced in"
ADDRESS ||--o{ PERSON : "lives at"
ADDRESS ||--o{ ORGANIZATION : "located at"
ADDRESS ||--o{ BRANCH : "address"
```
---
## 5. 💡 JAVASLATOK a "Közösségi Kereső" funkciókhoz
### 5.1. Jelenlegi hiányosságok
1. **Nincs dedikált "Partner" entitás** - A `fleet.organizations`-ban az `is_affiliate_partner` egy egyszerű boolean, nincs hozzá partner-specifikus adat (pl. jutalék ráta, partner kategória, szerződés állapota).
2. **`ServiceProvider` (régi) és `ServiceProfile` (új) kettősség** - A régi `marketplace.service_providers` tábla használaton kívülinek tűnik, de még létezik.
3. **Nincs "aliases" (álnév) támogatás** - Egyik táblában sincs JSONB aliases mező.
4. **Kategória rendszer hiányos** - A `marketplace.expertise_tags` és `marketplace.service_specialties` párhuzamos címke rendszert alkot.
### 5.2. Javasolt bővítés: `Organization` kiegészítése (AJÁNLOTT)
Ahelyett, hogy új `Partner` táblát hoznánk létre, bővítsük a meglévő `fleet.organizations` táblát az alábbi JSONB oszlopokkal:
```python
# Javasolt új mezők az Organization modellben
class Organization(Base):
# ... meglévő mezők ...
# ÚJ: Partnerek / Közösségi kereső
aliases: Mapped[dict] = mapped_column(
JSONB, server_default=text("'[]'::jsonb"),
comment="Álnevek / alternatív nevek (pl. 'AutoShop Kft.', 'Autóshop')"
)
is_verified: Mapped[bool] = mapped_column(
Boolean, server_default=text("false"),
comment="Hivatalosan verifikált szervezet"
)
verification_level: Mapped[str] = mapped_column(
String(20), server_default=text("'basic'"),
comment="Verifikációs szint: basic, email, phone, kyc, premium"
)
partner_category: Mapped[str] = mapped_column(
String(50), server_default=text("'none'"),
comment="Partner kategória: none, basic, silver, gold, platinum"
)
commission_rate: Mapped[Optional[float]] = mapped_column(
Numeric(5, 2), nullable=True,
comment="Jutalék ráta (%-ban)"
)
service_radius_km: Mapped[Optional[int]] = mapped_column(
Integer, nullable=True,
comment="Szolgáltatási körzet (km)"
)
tags: Mapped[dict] = mapped_column(
JSONB, server_default=text("'[]'::jsonb"),
comment="Címkék a közösségi kereséshez"
)
search_keywords: Mapped[dict] = mapped_column(
JSONB, server_default=text("'{}'::jsonb"),
comment="Kereső kulcsszavak több nyelven"
)
social_profiles: Mapped[dict] = mapped_column(
JSONB, server_default=text("'{}'::jsonb"),
comment="Közösségi média profilok (Facebook, Instagram, Google Business)"
)
contact_persons: Mapped[dict] = mapped_column(
JSONB, server_default=text("'[]'::jsonb"),
comment="Kapcsolattartó személyek adatai"
)
```
### 5.3. Alternatíva: Új `partner_profiles` tábla
Ha a `fleet.organizations` túl nagyra nőne, hozzunk létre egy új táblát:
```python
class PartnerProfile(Base):
"""Bővített partner profil a Közösségi Keresőhöz."""
__tablename__ = "partner_profiles"
__table_args__ = {"schema": "marketplace"}
id: Mapped[int] = mapped_column(Integer, primary_key=True)
organization_id: Mapped[int] = mapped_column(
Integer, ForeignKey("fleet.organizations.id"), unique=True, nullable=False
)
# --- ALAPADATOK ---
aliases: Mapped[dict] = mapped_column(JSONB, server_default=text("'[]'::jsonb"))
partner_category: Mapped[str] = mapped_column(String(50), default="none")
# --- VERIFIKÁCIÓ ---
verification_level: Mapped[str] = mapped_column(String(20), default="basic")
verified_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
verified_by_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
# --- KERESÉS ---
search_keywords: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
tags: Mapped[dict] = mapped_column(JSONB, server_default=text("'[]'::jsonb"))
service_radius_km: Mapped[Optional[int]] = mapped_column(Integer)
# --- GAZDASÁGI ADATOK ---
commission_rate: Mapped[Optional[float]] = mapped_column(Numeric(5, 2))
contract_start: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
contract_end: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
# --- KAPCSOLATOK ---
social_profiles: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
contact_persons: Mapped[dict] = mapped_column(JSONB, server_default=text("'[]'::jsonb"))
# --- AUDIT ---
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), onupdate=func.now())
```
### 5.4. Ajánlott stratégia
1. **Rövid táv**: Az `Organization` modell bővítése JSONB mezőkkel (`aliases`, `tags`, `search_keywords`, `social_profiles`). Ez azonnal használható, nincs szükség új táblára.
2. **Közép táv**: Ha a partnerek száma eléri a 10.000+ rekordot, hozzuk létre a dedikált `partner_profiles` táblát az `marketplace` sémában.
3. **Hosszú táv**: A régi `marketplace.service_providers` tábla archiválása/eltávolítása, mivel a `ServiceProfile` és a bővített `Organization` lefedi a funkcióit.
### 5.5. Megjegyzések a "Céges nyilvántartás" funkcióról
A rendelkezésre álló kód és adatbázis alapján:
-**Van "Céges nyilvántartás"**`fleet.organizations` tábla
-**Van tagságkezelés**`fleet.organization_members` tábla (User/Person + role)
-**Van telephelykezelés**`fleet.branches` tábla (PostGIS támogatással)
-**Van szolgáltatói profil**`marketplace.service_profiles` tábla
-**Van értékelési rendszer**`marketplace.service_reviews` (verifikált) + `marketplace.ratings` (általános)
-**NINCS dedikált partner modell** - Az `is_affiliate_partner` boolean nem elegendő
-**NINCS keresőoptimalizált adat** (aliases, tags, keywords)
---
## 6. ⚠️ FIGYELMEZTETÉSEK
### 6.1. Duplikált táblák
- `marketplace.service_staging` és `system.service_staging` - Valószínűleg csak egy kellene.
- `marketplace.costs` és `vehicle.costs` - Két külön költség tábla, különböző sémákban.
- `system.competitions_deprecated``gamification.competitions`
- `system.user_scores_deprecated``gamification.user_scores`
### 6.2. Kettős modell architektúra
- `marketplace.service_providers` (régi, egyszerű) vs `marketplace.service_profiles` (új, komplex)
- A régi tábla használata nem javasolt új fejlesztésekhez.
### 6.3. Soft delete következetlenség
- `fleet.organizations`: `is_deleted` + `is_active` boolean mezők
- `marketplace.service_profiles`: státusz alapú (`ghost`, `active`, `flagged`, `suspended`)
- `identity.persons`: `deleted_at` datetime mező
- `identity.users`: `is_active` boolean
- **Hiányzik egy egységes soft-delete stratégia az egész rendszerben.**
---
**Jelentés vége.** A javasolt bővítések implementálása előtt egyeztetés szükséges a Vezető Tervezővel.

View File

@@ -0,0 +1,133 @@
# 📊 ExpertiseTag Mesterlista — Többszintű Kategória Elemzés
**Dátum:** 2026-06-17
**Szerző:** Rendszer-Architect
**Cél:** Annak vizsgálata, hogy az `ExpertiseTag` (`marketplace.expertise_tags`) tábla `category` mezője alkalmas-e többszintű kategória tárolására, és ha igen, milyen módszerekkel tölthetők fel rá adatok.
---
## 🔍 Vizsgált Modell
Az `ExpertiseTag` modell az alábbi mezőkkel rendelkezik:
| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | `Integer` (PK) | Elsődleges kulcs |
| `key` | `String(50)` (unique, index) | Egyedi azonosító kulcs |
| `name_hu` | `String(100)` (nullable) | Magyar név |
| `name_en` | `String(100)` (nullable) | Angol név |
| `category` | **`String(30)`** (index) | Kategória csoportosító címke |
| `is_official` | `Boolean` | Hivatalos-e |
| `suggested_by_id` | `BigInteger` (FK) | Ki javasolta |
| `discovery_points` | `Integer` | Felfedezési pontok |
| `search_keywords` | `JSONB` | Keresőkulcsszavak |
| `usage_count` | `Integer` | Használati számláló |
| `icon` | `String(50)` (nullable) | Ikon neve |
| `description` | `Text` (nullable) | Leírás |
---
## ❌ 1. Válasz: Alkalmas-e a `category` mező többszintű tárolásra?
### **NEM, a jelenlegi implementáció NEM alkalmas többszintű hierarchia tárolására.**
| Követelmény | Jelenlegi állapot | Probléma |
|-------------|-------------------|----------|
| Hierarchikus kapcsolat | ❌ Nincs `parent_id` mező | Nem lehet szülő-gyermek viszonyt ábrázolni |
| Szintek száma | ❌ Nincs `level` mező | Nem tudjuk, hány szint mélyen van egy kategória |
| Útvonal (path) | ❌ Nincs `path` / `ltree` mező | Nem lehet gyorsan lekérdezni a teljes útvonalat |
| Rekurzív lekérdezés | ❌ Nincs `lft`/`rgt` (nested set) | CTE-vel lehetne, de lassú nagy adathalmazon |
| Mező hossza | ⚠️ Csak `String(30)` | "vehicle_service" már 15 karakter; kevés a bővítésre |
A jelenlegi `category` mező **csak egy lapos csoportosító címke** — hasonló egy `tag`-hez, nem pedig egy hierarchikus kategória struktúrához.
---
## 🗄️ 2. Jelenlegi Adatbázis Állapot
Lekérdezés alapján a tábla **11 rekordot** tartalmaz, **8 distinct category** értékkel:
| ID | Key | Category |
|----|-----|----------|
| 1 | `auto_szerelo` | `vehicle_service` |
| 2 | `motor_szerelo` | `vehicle_service` |
| 3 | `gumiszerviz` | `vehicle_service` |
| 4 | `karosszerialakatos` | `body_paint` |
| 5 | `fényező` | `body_paint` |
| 6 | `autómentő` | `roadside` |
| 7 | `benzinkút` | `fuel` |
| 8 | `alkatrész_kereskedés` | `parts` |
| 9 | `vizsgaállomás` | `inspection` |
| 10 | `autókozmetika` | `detailing` |
| 11 | `egyéb` | `other` |
---
## 🔄 3. Adatfeltöltési Lehetőségek — Összehasonlítás
| Módszer | Leírás | Korlátok |
|---------|--------|----------|
| **1⃣ Seed Script** | Egyszeri batch betöltés. Idempotens. 11 alap kategória hardcode-olva. | Csak egyszer futtatható; nem lehet módosítani futás után. |
| **2⃣ Direkt SQL INSERT** | `INSERT INTO marketplace.expertise_tags ...` | Nincs validáció, séma integritás ellenőrzés. |
| **3⃣ API (létező): `GET /categories`** | **Csak OLVASÁS** — listázza a meglévő címkéket. | Nincs POST/PUT/DELETE végpont. |
| **4⃣ Admin UI** (`admin_ui.py`) | Csak jármű HITL modelljavításra fókuszál. | Nincs ExpertiseTag menedzsment. |
### Hiányzó API végpontok:
-`POST /api/v1/admin/categories` — Új szakmai címke létrehozása
-`PUT /api/v1/admin/categories/{id}` — Meglévő címke szerkesztése
-`DELETE /api/v1/admin/categories/{id}` — Címke törlése
---
## 🏗️ 4. Ajánlott Tervezés Többszintű Kategóriához
### 4.1. Új mezők az ExpertiseTag modellben
```python
parent_id: Mapped[Optional[int]] = mapped_column(
Integer, ForeignKey("marketplace.expertise_tags.id")
)
level: Mapped[int] = mapped_column(Integer, default=0)
path: Mapped[Optional[str]] = mapped_column(String(200))
```
### 4.2. Tipikus hierarchia példa
```
Level 0 vehicle_service
Level 1 (parent->child) ├── auto_szerelo
├── motor_szerelo
└── gumiszerviz
Level 2 (sub-child) └── auto_szerelo/diagnosztika
```
### 4.3. Javasolt admin API bővítés
```
POST /api/v1/admin/categories # Új címke
PUT /api/v1/admin/categories/{id} # Szerkesztés
DELETE /api/v1/admin/categories/{id} # Törlés (soft-delete)
GET /api/v1/admin/categories/tree # Hierarchikus fa
```
---
## 📋 5. Összefoglalás
1. A `category` mező (`String(30)`) **lapos, nem hierarchikus** — nem alkalmas többszintű tárolásra
2. Jelenleg **nincs CRUD API** a címkék kezelésére (csak `GET /categories`)
3. **Nincs admin UI** a szakmai címkék menedzselésére
4. A seed script az egyetlen adatbetöltési mód
### Ajánlott roadmap:
| Lépés | Feladat |
|-------|---------|
| 1⃣ | `logic_spec` készítése a hierarchikus kategória rendszerhez |
| 2⃣ | Alembic migráció — `parent_id`, `level`, `path` mezők |
| 3⃣ | CRUD API végpontok létrehozása |
| 4⃣ | Admin UI integráció |
| 5⃣ | Seed script frissítése hierarchikus adatokkal |
### Kritikus hibajavítás:
A `search_providers()` SQL lekérdezés **NEM JOIN-ol** az `ExpertiseTag` táblára, így a `category` mindig `None` a keresési eredményekben. Ez azonnali javítást igényel.

View File

@@ -0,0 +1,232 @@
# 🚨 Full Stack Disconnect Analysis — "Extrák" Hiányzó Checkbox Grid
**Dátum:** 2026-06-16
**Elemző:** Rendszer-Architect
**Scope:** VehicleFormModal (Frontend) ↔ Asset Schema (Backend) ↔ Asset DB Model (PostgreSQL)
---
## 🔍 1. FRONTEND VIZSGÁLAT — VehicleFormModal.vue
### Jelenlegi lépések (line 870-875):
| Index | Lépés neve | Tartalom |
|-------|------------|----------|
| 0 | **Azonosítás** | Kategória, VIN, Rendszám |
| 1 | **Alapadatok** | Márka, Modell, Évjárat, Üzemanyag, **Kivitel/Felszereltség (összemosva)**, Becenév, Km óra |
| 2 | **Műszaki** | Hengerűrtartalom, Teljesítmény kW, Hajtás, Váltó, Karosszéria (body_type), Klíma, Ajtók, Ülések, EV blokk, Okmányadatok |
| 3 | **Extrák** | Saját besorolás, Saját megjegyzés + Features checkbox grid (csak `personal` esetén!) |
### Step 3 ("Extrák") valós tartalma (line 684-764):
```html
<div v-if="step === 3" class="space-y-4">
<p>Itt adhatsz hozzá extra információkat a járművedhez.</p>
<!-- Saját besorolás (condition) select -->
<!-- Saját megjegyzés (notes) input -->
<!-- Features / Extrák - CSAK personal járműveknél -->
<div v-if="form.vehicle_class === 'personal'" class="pt-2">
<!-- Technical, Interior, Exterior, Multimedia, Other checkbox groups -->
</div>
</div>
```
### ⚠️ Kritikus probléma:
A **75+ checkbox** csak akkor jelenik meg, ha a felhasználó `personal` (személyautó) kategóriát választott. Minden más járműosztálynál (motorcycle, light_commercial, commercial, work_machine, trailer, bus, camper, boat, aircraft, other) a Step 3 tényleg **üres** — csak "Saját besorolás" és "Saját megjegyzés" látszik. Ez magyarázza a képernyőképen látott üres felületet!
### A features tömörítve individual_equipment.car_specs.features-ként megy a backendbe
### Mely fájlba lettek a checkboxok?
A checkbox grid a VehicleFormModal.vue fájlban van (line 710-763), de **nem kapta meg a saját dedikált komponensét**, és **nincs külön "Extrák" almappája a kategóriáknak** (Beltér/Kültér/Multimédia/Egyéb). Minden egy `form.features` string tömbben van tárolva, nem pedig strukturált JSONB-ként.
---
## 🗄️ 2. ADATBÁZIS & SÉMA VIZSGÁLAT
### Tervező által kért mezők vs Valós állapot
#### ✅ Azonosítás
| Kért mező | Backend (DB Model) | Pydantic Schema | Frontend Form | Státusz |
|-----------|-------------------|-----------------|---------------|---------|
| Márka | Asset.brand ✅ | AssetCreate.brand ✅ | form.brand ✅ | ✅ OK |
| Modell | Asset.model ✅ | AssetCreate.model ✅ | form.model ✅ | ✅ OK |
| Típusjel | ❌ **NINCS** | ❌ **NINCS** | ❌ **NINCS** | ❌ **HIÁNYZIK** |
> **"Típusjel"** — ez a mező sehol nem létezik önálló entitásként. A `trim_level` ("Kivitel / Felszereltség") próbálja helyettesíteni, de a Tervező szerint a Típusjel (pl. "320i", "X5 xDrive30d") külön fogalom.
#### ✅ Általános
| Kért mező | Backend | Schema | Frontend | Státusz |
|-----------|---------|--------|----------|---------|
| Km óra állás | current_mileage ✅ | ✅ | ✅ | ✅ OK |
| Évjárat | year_of_manufacture ✅ | ✅ | ✅ | ✅ OK |
| Kivitel (Karosszéria) | ❌ body_type a JSONB-ben | ❌ nincs külön mező | form.body_type (Step 2-ben!) | ❌ **ROSSZ helyen** |
| Állapot | condition_score ✅ | ❌ **NINCS a sémában** | form.condition (string!) | ⚠️ **Inkonzisztens** |
> **"Kivitel (Karosszéria)"** — a `body_type` mező létezik a JSONB-ben (individual_equipment.car_specs.body_type), de a **"Műszaki" (Step 2)** fül alatt van, nem az alapadatok között. A Tervező szerint az Általános adatoknál kellene lennie, külön a "Felszereltségtől".
#### ✅ Műszaki
| Kért mező | Backend | Schema | Frontend | Státusz |
|-----------|---------|--------|----------|---------|
| Üzemanyag | fuel_type ✅ | ✅ | ✅ | ✅ OK |
| Hengerűrtartalom (cm³) | engine_capacity ✅ | ✅ | ✅ | ✅ OK |
| Teljesítmény (kW/LE) | power_kw ✅ | ✅ | ✅ (HP display) | ✅ OK |
| **Nyomaték (Nm)** | torque_nm ✅ **DB-ben** | ✅ AssetCreate.torque_nm | ❌ **NINCS input mező!** | ❌ **HIÁNYZIK** |
> **Nyomaték (torque_nm)** — a legkritikusabb hiányzó mező! A backend modellben (Asset.py sor 97) benne van, a Pydantic sémában (AssetCreate.torque_nm sor 151) benne van, de a frontend űrlapban **SEHOL** nincs input mező a Nyomaték megadására. Amikor a felhasználó elmenti az űrlapot, a torque_nm egyszerűen null marad.
#### ✅ Hajtáslánc
| Kért mező | Backend | Schema | Frontend | Státusz |
|-----------|---------|--------|----------|---------|
| Sebességváltó | transmission_type ✅ | ✅ | ✅ | ✅ OK |
| Hajtás | drive_type ✅ | ✅ | ✅ | ✅ OK |
#### ✅ Kényelem
| Kért mező | Backend | Schema | Frontend | Státusz |
|-----------|---------|--------|----------|---------|
| Klíma fajtája | JSONB-ben (ac_type) | ❌ nincs külön mező | form.ac_type ✅ | ⚠️ JSONB-be van rejtve |
#### ✅ Okmányok
| Kért mező | Backend | Schema | Frontend | Státusz |
|-----------|---------|--------|----------|---------|
| Forgalmi szám | JSONB-ben | ❌ nincs külön mező | ✅ | ⚠️ JSONB-ben |
| Törzskönyv szám | JSONB-ben | ❌ nincs külön mező | ✅ | ⚠️ JSONB-ben |
| Műszaki lejárat | JSONB-ben | ❌ nincs külön mező | ✅ | ⚠️ JSONB-ben |
| Okmány lejárat | JSONB-ben | ❌ nincs külön mező | ✅ | ⚠️ JSONB-ben |
#### ✅ Extrák (JSONB)
| Kért mező | Backend | Schema | Frontend | Státusz |
|-----------|---------|--------|----------|---------|
| Beltér | JSONB car_specs.features | individual_equipment | ✅ (checkbox) | ✅ OK |
| Kültér | JSONB car_specs.features | individual_equipment | ✅ (checkbox) | ✅ OK |
| Multimédia | JSONB car_specs.features | individual_equipment | ✅ (checkbox) | ✅ OK |
| Egyéb | JSONB car_specs.features | individual_equipment | ✅ (checkbox) | ✅ OK |
### További hiányzó mezők a frontendről (de backendben léteznek):
| Mező | DB Oszlop | Pydantic Schema | Frontend Input | Státusz |
|------|-----------|----------------|---------------|---------|
| curb_weight (saját tömeg) | ✅ | ✅ | ❌ | **HIÁNYZIK** |
| max_weight (össztömeg) | ✅ | ✅ | ❌ | **HIÁNYZIK** |
| cargo_volume_x (raktér hossz) | ✅ | ✅ | ❌ | **HIÁNYZIK** |
| cargo_volume_y (raktér szél.) | ✅ | ✅ | ❌ | **HIÁNYZIK** |
| roof_type (tető típus) | ✅ | ✅ | ❌ | **HIÁNYZIK** |
| audio_system_type (hangi) | ✅ | ✅ | ❌ | **HIÁNYZIK** |
---
## 🌐 3. API VÁLASZ VIZSGÁLAT
### GET /assets/vehicles/{id} (assets.py line 290-337)
A végpont az AssetResponse Pydantic modellt használja (response_model=AssetResponse). A from_attributes=True miatt az ORM Asset objektum automatikusan Pydantic-ként szerializálódik.
**A JSON válasz tartalmazza:**
- Az összes "sima" oszlopot (brand, model, engine_capacity, power_kw, torque_nm, transmission_type, drive_type, stb.)
- Az individual_equipment JSONB mezőt teljes egészében (benne car_specs, ev_specs, dates, documents)
- A catalog kapcsolódó objektumot (ha van)
**A frontend populateForm() (line 1162-1215) helyesen olvassa vissza a JSONB-t**, de a torque_nm sosem kerül beolvasásra, mert nincs hozzá input mező.
---
## 🎯 4. ÖSSZEGZÉS: A KAPCSOLAT MEGSZAKADÁSI PONTOK
### 1. 🔴 **Nyomaték (torque_nm) — Backend adat, frontend nélkül**
- **Hol:** DB Asset.torque_nm sor 97, Schema AssetCreate.torque_nm sor 151
- **Probléma:** A backend tárolja és a Pydantic séma támogatja, de a VehicleFormModal.vue egyetlen lépésében sincs input mező.
- **Következmény:** A flottavezetők soha nem adják meg a nyomatékot, a "Thick Digital Twin" koncepció adathiányos.
### 2. 🟠 **"Típusjel" mező teljes hiánya**
- **Hol:** Sehol az egész stack-ben
- **Probléma:** A Tervező által kért Típusjel (pl. "320i", "X5 xDrive30d") fogalma nem létezik. Csak a trim_level van.
### 3. 🟠 **"Kivitel" és "Felszereltség" összemosása**
- **Hol:** VehicleFormModal.vue Step 1 (line 376-409)
- **Probléma:** A trim_level egyszerre próbálja lefedni a karosszéria kivitelt ÉS a felszereltségi szintet.
### 4. 🟡 **Features checkbox grid csak personal osztálynál**
- **Hol:** VehicleFormModal.vue line 711
- **Probléma:** v-if="form.vehicle_class === 'personal'" — más osztályoknál tényleg üres az Extrák fül.
### 5. 🟡 **Hiányzó fizikai méret és tömeg mezők**
- curb_weight, max_weight, cargo_volume_x, cargo_volume_y — backendben vannak, de nincsenek a formban.
### 6. 🟡 **Okmányadatok JSONB-be rejtve**
- mot_expiry, document_expiry, reg_cert_number, title_cert_number a JSONB-ben, nem dedikált oszlopokban.
---
## 🏗️ 5. JAVASLAT: 7 LÉPÉSES ÚJ ŰRLAPSTRUKTÚRA
```
Step 0: 🚗 AZONOSÍTÁS
- Kategória (vehicle_class)
- Márka (brand)
- Modell (model)
- Típusjel (type_designation) ⬅️ ÚJ!
- Rendszám (license_plate)
- Alvázszám (vin)
Step 1: 📋 ÁLTALÁNOS ADATOK
- Évjárat (year_of_manufacture)
- Km óra állás (current_mileage)
- Kivitel / Karosszéria (body_type) ⬅️ Külön!
- Állapot / Saját besorolás (condition)
Step 2: ⚙️ MŰSZAKI ADATOK
- Üzemanyag (fuel_type)
- Hengerűrtartalom (engine_capacity)
- Teljesítmény (power_kw) + LE kijelzés
- Nyomaték (torque_nm) ⬅️ ÚJ!
- Hengerelrendezés (cylinder_layout)
Step 3: 🔧 HAJTÁSLÁNC
- Sebességváltó (transmission_type)
- Hajtás (drive_type)
Step 4: 🌡️ KÉNYELEM & KLÍMA
- Klíma fajtája (ac_type)
- Tető típus (roof_type) ⬅️ ÚJ!
- Hangrendszer (audio_system_type) ⬅️ ÚJ!
- Ajtók száma (door_count)
- Ülések száma (seat_count)
Step 5: 📄 OKMÁNYOK
- Műszaki érvényesség (mot_expiry)
- Okmány érvényesség (document_expiry)
- Forgalmi szám (registration_cert_number)
- Törzskönyv szám (title_cert_number)
Step 6: ✨ EXTRÁK (Felszereltség) - Dedikált komponens!
- Beltér (interior features)
- Kültér (exterior features)
- Multimédia (multimedia features)
- Technikai (technical features)
- Egyéb (other features)
- Súly & Méretek (curb_weight, max_weight, cargo)
```
---
## 📊 HIÁNYZÓ MEZŐK MASTER LIST
| # | Mező | DB/Séma | Frontend | Javasolt lépés |
|---|------|---------|----------|----------------|
| 1 | torque_nm | ✅ Van | ❌ NINCS | Step 2 |
| 2 | type_designation | ❌ NINCS | ❌ NINCS | Step 0 |
| 3 | curb_weight | ✅ Van | ❌ NINCS | Step 6 |
| 4 | max_weight | ✅ Van | ❌ NINCS | Step 6 |
| 5 | cargo_volume_x | ✅ Van | ❌ NINCS | Step 6 |
| 6 | cargo_volume_y | ✅ Van | ❌ NINCS | Step 6 |
| 7 | roof_type | ✅ Van | ❌ NINCS | Step 4 |
| 8 | audio_system_type | ✅ Van | ❌ NINCS | Step 4 |
---
## ⚡ AZONNALI TEENDŐK (Prioritási sorrendben)
1. **🟢 FRONTEND:** Add hozzá a `torque_nm` input mezőt a "Műszaki" (Step 2) lépéshez. Ez 5 perc fejlesztés és a legnagyobb adatveszteséget szünteti meg.
2. **🟡 FRONTEND:** Bontsd ki a features checkbox grid-et egy külön Vue komponensbe (`VehicleFeaturesGrid.vue`), és engedélyezd MINDEN járműosztálynál, ne csak personal-nál.
3. **🟡 FRONTEND+SCHEMA:** Válaszd szét a "Kivitel" (body_type) és "Felszereltség" (trim_level) fogalmakat.
4. **🔴 ARCHITECT TERV:** Készíts `logic_spec` dokumentációt az űrlap teljes átépítéséhez a fenti 7 lépéses struktúra alapján.

View File

@@ -0,0 +1,131 @@
# Gamification Penalty System — Adatbázis Felderítési Jelentés
**Dátum:** 2026-06-17
**Cél:** A 3-szintű Büntetési Mátrix (Penalty System) és Árnyéktiltás (Shadowban) bevezetésének adatbázis-struktúra előfeltérképezése
---
## 1. FELADAT: Büntetési Szint (Penalty Level) — Meglévő Struktúra
### ✅ Megállapítás: A büntetési infrastruktúra NAGYRÉSZT KÉSZ
A Vezető Tervező örömére: a rendszer **már tartalmazza** a büntetési pontrendszer alapjait. Az alábbi táblák és mezők **már léteznek** az adatbázisban és a modellekben:
#### backend/app/models/gamification/gamification.py
| Tábla (séma) | Mező | Típus | Státusz |
|---|---|---|---|
| gamification.user_stats | penalty_points | Integer (server_default=0) | ✅ Létezik |
| gamification.user_stats | restriction_level | Integer (server_default=0) | ✅ Létezik |
| gamification.user_stats | penalty_quota_remaining | Integer (default=3) | ✅ Létezik |
| gamification.user_stats | banned_until | DateTime(timezone=True) | ✅ Létezik |
| gamification.user_stats | current_level | Integer (default=1) | ✅ Létezik |
| gamification.level_configs | level_number | Integer (unique) | ✅ Létezik (támogat negatív értékeket!) |
| gamification.level_configs | is_penalty | Boolean (default=False) | ✅ Létezik |
| gamification.level_configs | min_points | Integer | ✅ Létezik |
| gamification.level_configs | rank_name | String | ✅ Létezik |
| gamification.points_ledger | penalty_change | Integer (server_default=0) | ✅ Létezik |
| identity.persons | penalty_points | Integer (default=-1) | ✅ Létezik |
| identity.persons | social_reputation | Numeric(3,2) | ✅ Létezik |
| identity.persons | lifetime_xp | BigInteger (default=-1) | ✅ Létezik |
| identity.user_trust_profiles | trust_score | Integer (default=0) | ✅ Létezik |
| identity.user_trust_profiles | identity_risk_flag | Boolean (default=False) | ✅ Létezik |
### ⚠️ HIÁNYZIK: penalty_level (a 3-szintű büntetési mátrix maga)
A restriction_level mező hasonló koncepció, de jelenleg nincs dedikált penalty_level (Integer, -1 / -2 / -3) mező.
### Javaslat az új mezők helyére
A gamification.user_stats táblába érdemes beilleszteni:
```
PenaltyLevel: Integer, server_default=0 (-1=Figyelmeztetés, -2=Korlátozás, -3=Árnyéktiltás)
GoodDeedsCount: Integer, server_default=0 (Jóvátételi cselekedetek számlálója)
ShadowBannedUntil: DateTime(timezone=True), nullable=True (Látszólagos tiltás vége)
```
**Indoklás:** A user_stats tábla már most is tartalmazza a penalty_points, restriction_level, penalty_quota_remaining és banned_until mezőket — ez a természetes helye minden büntetési információnak. A Person tábla (identity.persons) szintén rendelkezik penalty_points mezővel, de ott ez a személy szintű, nem a gamification profil része.
---
## 2. FELADAT: Hibajelentés (Report) Tábla
### ❌ Megállapítás: NINCS dedikált report/abuse tábla
Az adatbázisban és a modellek között **NEM található** olyan tábla, amelynek neve report, abuse, flag, ticket, moderation_content vagy data_correction lenne. A PostgreSQL information_schema lekérdezés nulla találatot adott.
### Ami KÖZELÍT
| Tábla | Kapcsolat | Korlát |
|---|---|---|
| marketplace.service_providers | status mező ModerationStatus enumnak | Ez a beküldött szolgáltatók moderálására való, **nem** a visszaélés-jelentésre |
| marketplace.service_profiles | flagged státusz a ServiceStatus enumban | Szolgáltatók flag-elésére |
| gamification.user_contributions | contribution_type = 'report_abuse' | Naplózza, hogy ki jelentett, de **nincs dedikált jelentés adattábla** |
### Javaslat: Új user_reports tábla létrehozása
Javasolt séma a gamification sémában (ahol a user_contributions is van):
```
user_reports tábla (gamification séma):
- id Integer (PK)
- reporter_id Integer FK->identity.users.id
- target_type String(50) ('service_profile', 'review', 'vehicle', 'user')
- target_id Integer
- reason_category String(50) ('fake_service', 'wrong_data', 'spam', 'abuse', 'other')
- description Text (nullable)
- evidence_data JSONB (nullable)
- status String(20) default='pending' ('pending','verified','dismissed','action_taken')
- reviewed_by Integer FK->identity.users.id (nullable)
- resolution Text (nullable)
- created_at DateTime
- resolved_at DateTime (nullable)
```
---
## 3. FELADAT: Adminisztrációs Szabályok (System Parameters)
### ✅ Megállapítás: A rendszer RENDELKEZIK dinamikus paraméter táblával
A system.system_parameters tábla **már létezik** és kifejezetten alkalmas a büntetési szabályok adminisztrációjára.
| Oszlop | Típus | Leírás |
|---|---|---|
| key | VARCHAR | Paraméter kulcs (pl. penalty_level_1_quota) |
| category | VARCHAR | Kategorizálás (pl. penalty_system) |
| value | JSONB | A paraméter értéke (JSON, bármi lehet) |
| scope_level | VARCHAR | Hatáskör: global, country, region, organization, user |
| scope_id | VARCHAR | A hatáskör azonosítója |
| is_active | BOOLEAN | Aktív-e |
| description | VARCHAR | Emberi leírás |
### Javasolt paraméterkulcsok a büntetési rendszerhez
| key | category | value (JSON) |
|---|---|---|
| penalty_level_1_threshold | penalty_system | {"min_bad_actions": 2, "quota_reduction": 1} |
| penalty_level_2_threshold | penalty_system | {"min_bad_actions": 5, "xp_multiplier": 0.5} |
| penalty_level_3_threshold | penalty_system | {"min_bad_actions": 10, "shadowban": true, "max_actions_per_day": 1} |
| penalty_action_points | penalty_system | {"fake_service_submission": 10, "fake_review": 15, "spam_comment": 5} |
| penalty_good_deed_recovery | penalty_system | {"points_per_good_deed": -3, "max_recovery_per_day": 1} |
> **Előny:** A scope_level oszlop lehetővé teszi, hogy **ország-specifikus** vagy akár **felhasználó-specifikus** büntetési szabályokat állítsunk be, anélkül hogy a kódot módosítani kellene.
---
## Összefoglaló táblázat
| Feladat | Státusz | Megjegyzés |
|---|---|---|
| **1. Büntetési szint helye** | ✅ **Alap infrastruktúra kész** | user_stats.penalty_points, restriction_level, penalty_quota_remaining, banned_until, level_configs.is_penalty — mind létezik. HIÁNYZIK: dedikált penalty_level és good_deeds_count mező |
| **2. Hibajelentés tábla** | ❌ **NINCS** | Egyetlen dedikált report/abuse tábla sem létezik. A user_contributions.contribution_type = 'report_abuse' csak naplóz, nem tárol jelentéseket. **Teljesen új tábla kell** |
| **3. Adminisztrációs szabályok** | ✅ **Alkalmas** | system.system_parameters JSONB-alapú, scoped paraméter tábla kiválóan megfelel a dinamikus szabályok tárolására. Új paramétereket kell csak beszúrni |
## Következő lépések (ajánlott sorrend)
1. **Új mezők hozzáadása** gamification.user_stats-hoz: penalty_level, good_deeds_count, shadow_banned_until
2. **Új tábla létrehozása:** gamification.user_reports (vagy gamification.content_reports)
3. **Rendszerparaméterek feltöltése:** system.system_parameters büntetési szabályokkal
4. **Penalty Engine service** megírása, ami a level_configs táblából és a system_parameters-ből olvassa a szabályokat, és automatikusan lépteti a penalty_level-et

View File

@@ -0,0 +1,223 @@
# Szolgáltatók Szolgáltatásainak (Category/Specialization) Adatfolyam Elemzése
**Dátum:** 2026-06-17
**Készítette:** Rendszer-Architect
**Cél:** A szolgáltatók kategóriáinak és szolgáltatásainak teljes verem (adatbázis → backend → frontend) adatfolyamának feltérképezése.
---
## Összefoglalás
A vizsgálat során kiderült, hogy a szolgáltatók kategóriáinak (category) adatfolyama **megszakadt** a backend és a frontend között. A `search_providers()` SQL lekérdezése nem csatlakoztatja a `ServiceExpertise``ExpertiseTag` láncot, ezért a `category` mező minden keresési találatnál `None`. Emiatt a frontenden minden kártyán a "Nincs kategória" placeholder látszik, és a detail modalban a kategória blokk teljesen láthatatlan.
---
## 1. Adatbázis Réteg
### 1.1. Érintett Táblák
| Tábla | Séma | Szerep | Category-t tartalmaz? |
|-------|------|--------|----------------------|
| ExpertiseTag | marketplace.expertise_tags | Mesterlista - szakmai címkék | Igen - key, name_hu, name_en, category |
| ServiceExpertise | marketplace.service_expertises | Kapcsolótábla - service / expertise | Csak FK (service_id, expertise_id) |
| ServiceProfile | marketplace.service_profiles | Szerviz szolgáltató profilja | JSONB-ben: specialization_tags.primary_category |
| Organization | fleet.organizations | Szervezet (nincs közvetlen category) | Nincs category mező |
### 1.2. Kapcsolatok
```
ExpertiseTag (marketplace.expertise_tags)
^ expertise_id
ServiceExpertise (marketplace.service_expertises)
^ service_id
ServiceProfile (marketplace.service_profiles)
^ organization_id (unique)
Organization (fleet.organizations)
```
### 1.3. ExpertiseTag Tábla Szerkezete
| Mezo | Típus | Leírás |
|------|-------|--------|
| id | Integer (PK) | |
| key | String(50), unique | Pl. "auto_szerelo", "gumiszerviz" |
| name_hu | String(100) | Magyar név, pl. "Autószerelő" |
| name_en | String(100) | Angol név, pl. "Car mechanic" |
| category | String(30) | Csoportosító, pl. "auto" |
| is_official | Boolean | Hivatalos-e |
| search_keywords | JSONB | Keresőkulcsszavak |
| icon | String(50) | Ikon neve |
### 1.4. ServiceProfile.specialization_tags JSONB Szerkezet
```json
{
"primary_category": "auto_szerelo",
"user_tags": ["olajcsere", "fék", "klíma"]
}
```
---
## 2. Backend API Réteg
### 2.1. GET /categories (Muködik)
**Végpont:** backend/app/api/v1/endpoints/providers.py:30
**Séma:** backend/app/schemas/provider.py:14 - ExpertiseCategoryOut
Visszaadja az összes ExpertiseTag rekordot. Használja a ProviderQuickAddModal a category_id kiválasztáshoz.
### 2.2. GET /search (KRITIKUS HIBA)
**Végpont:** backend/app/api/v1/endpoints/providers.py:60
**Szolgáltatás:** backend/app/services/provider_service.py:130 - search_providers()
**Séma:** backend/app/schemas/provider.py:25 - ProviderSearchResult
```python
class ProviderSearchResult(BaseModel):
id: int
name: str
category: Optional[str] = None # DEFAULT: None!
specialization: List[str] = Field(default_factory=list)
```
#### A HIBA: Az org_stmt SELECT nem tartalmazza a category-t
A provider_service.py:194-225 sorokban az org_stmt SELECT listája:
```python
org_stmt = select(
Organization.id.label("id"),
Organization.name.label("name"),
# ... címmezok ...
ServiceProfile.specialization_tags.label("specialization_tags"),
case(...).label("source"),
# HIÁNYZIK: LEFT JOIN a ServiceExpertise / ExpertiseTag láncon
# HIÁNYZIK: category lekeres
).outerjoin(ServiceProfile, ...)
```
#### Eredmény: A ProviderSearchResult építésekor (318-342. sor) a category soha nincs beállítva
```python
for row in rows:
results.append(
ProviderSearchResult(
id=row.id,
name=row.name,
# category itt NINCS paraméterként! -> default: None
tags=tags_list,
source=row.source,
is_verified=row.is_verified,
)
)
```
### 2.3. POST /quick-add (Muködik)
**Végpont:** backend/app/api/v1/endpoints/providers.py:98
Helyesen hozza létre a ServiceExpertise kapcsolatot:
```python
expertise = ServiceExpertise(
service_id=profile.id,
expertise_id=data.category_id,
confidence_level=50,
)
db.add(expertise)
```
### 2.4. PUT /{provider_id} - NEM kezeli a category-t
A ProviderUpdateIn séma **NEM tartalmaz category_id-t**, csak name, címmezok, contact_phone, email, website, tags.
---
## 3. Frontend Réteg
### 3.1. Kártya (ServiceFinderView.vue)
**Category badge (263-277. sor):**
```vue
<span v-if="provider.category">...SOHA nem fut le, mert category = None...</span>
<span v-else>...MINDEN kártyán "Nincs kategória"...</span>
```
**Specialization chips (244-261. sor):** A provider.specialization lista megjelenik, ha van benne adat.
### 3.2. Detail Modal (ProviderDetailModal.vue)
**Category blokk (42-52. sor):** v-if="provider.category" mindig false -> a blokk láthatatlan.
### 3.3. Edit Modal (ProviderEditModal.vue)
**HIÁNYZIK:** Nincs kategória kiválasztó mező! Csak name, címmezok, phone, email, website, tagsInput.
### 3.4. Quick-Add Modal (ProviderQuickAddModal.vue)
Tartalmaz category_id kiválasztó dropdown-ot, ami a GET /categories-ból tölti az adatokat.
---
## 4. Fejlesztési Javaslatok
### #1 (KRITIKUS) - Category lekerese a search API-ban
**Probléma:** A search_providers() nem tolti be a category-t.
**Megoldás:** Correlated subquery hozzaadasa:
```python
category_subquery = (
select(ExpertiseTag.name_hu)
.select_from(ServiceExpertise)
.join(ExpertiseTag, ServiceExpertise.expertise_id == ExpertiseTag.id)
.where(ServiceExpertise.service_id == ServiceProfile.id)
.limit(1)
.correlate(ServiceProfile)
.label("category")
)
```
**Erintett fajlok:**
- backend/app/services/provider_service.py:194 - org_stmt SELECT kiegeszitese
- backend/app/services/provider_service.py:326 - ProviderSearchResult epitesekor category atadasa
### #2 (HIÁNYZÓ FUNKCIÓ) - Kategoria kivalaszto az Edit Modalban
**Probléma:** Az EditModal nem tartalmaz kategoria kivalasztot.
**Megoldás:** Kategoria dropdown hozzaadasa, ami betolti a GET /categories adatait.
**Erintett fajlok:**
- frontend/src/components/provider/ProviderEditModal.vue - uj kategoria kivalaszto
- backend/app/schemas/provider.py:89 - ProviderUpdateIn kiegeszitese category_id mezovel
- backend/app/services/provider_service.py:497 - update_provider() kiegeszitese ServiceExpertise kezelessel
### #3 (HIÁNYZÓ FUNKCIÓ) - Category szuro implementalasa
**Probléma:** A search_providers() fuggveny elfogadja a category parametert, de nem hasznalja a szureshez.
### #4 (ADAT INTEGRITÁS) - Category fogalmanak tisztazasa
Javaslat: A category mezo a ProviderSearchResult-ban az ExpertiseTag.name_hu erteket tartalmazza (a felhasznalo szamara ertelmes nevet), nem pedig a technikai category csoportosítót.
---
## 5. Érintett Fájlok Listája
| Fájl | Szerep | Status |
|------|--------|--------|
| backend/app/models/marketplace/service.py | Adatbázis modellek | OK |
| backend/app/schemas/provider.py | Pydantic sémák | OK (de hianyzik category_id a ProviderUpdateIn-bol) |
| backend/app/services/provider_service.py | Üzleti logika | HIBA: hianyzik a category JOIN |
| backend/app/api/v1/endpoints/providers.py | API végpontok | OK |
| frontend/src/views/ServiceFinderView.vue | Kereso nézet | OK (de category = None) |
| frontend/src/components/provider/ProviderDetailModal.vue | Detail modal | OK (de category blokk rejtve) |
| frontend/src/components/provider/ProviderEditModal.vue | Edit modal | HIANYZIK a kategoria kivalaszto |
| frontend/src/components/provider/ProviderQuickAddModal.vue | Gyors felvetel | OK |

View File

@@ -0,0 +1,160 @@
# 🔍 Digitális Szerviznapló (Service Book) Architektúra Audit
**Dátum:** 2026-06-15
**Auditor:** Fast Coder (Core Developer)
**Cél:** A Vezető Tervező részére készült mélyreható elemzés a Szerviz események, Javítások és Okmány lejáratok adatbázis-szintű előkészítettségéről.
---
## 1. Összefoglaló
A rendszer **rendelkezik dedikált táblákkal** a Digitális Szerviznaplóhoz, de azok **részben előkészítettek**, részben pedig a `JSONB` mezőkbe vannak integrálva. Nincs külön `ServiceEvent` vagy `Document` tábla — a szerviz eseményeket az [`AssetEvent`](../backend/app/models/vehicle/asset.py:395) modell kezeli, a dokumentumokat (biztosítás, műszaki) pedig az [`Asset.individual_equipment`](../backend/app/models/vehicle/asset.py:114) JSONB mező.
---
## 2. Táblaszerkezet Áttekintés
### 2.1. `vehicle.asset_events` — Digitális Szervizkönyv (Fő tábla)
**Modell:** [`AssetEvent`](../backend/app/models/vehicle/asset.py:395)
**Tábla:** `vehicle.asset_events`
| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | UUID (PK) | Elsődleges kulcs |
| `asset_id` | UUID (FK → `vehicle.assets.id`) | Jármű hivatkozás |
| `user_id` | Integer (FK → `identity.users.id`) | Ki végezte a műveletet |
| `organization_id` | Integer (FK → `fleet.organizations.id`) | Szervezet |
| `event_type` | String(50) | Esemény típusa (lásd `AssetEventTypeEnum`) |
| `odometer_reading` | Integer (nullable) | Km óra állás az eseménykor |
| `description` | Text (nullable) | Leírás |
| `cost_id` | UUID (FK → `vehicle.asset_costs.id`, nullable) | Kapcsolódó költség |
| `event_date` | DateTime | Esemény dátuma |
| `created_at` / `updated_at` | DateTime | Időbélyegek |
**Támogatott eseménytípusok** ([`AssetEventTypeEnum`](../backend/app/models/vehicle/asset.py:383)):
- `SERVICE` — Szerviz
- `REPAIR` — Javítás
- `ACCIDENT` — Baleset
- `INSPECTION` — Műszaki vizsga
- `TIRE_CHANGE` — Gumi csere
- `MAINTENANCE` — Karbantartás
- `UPGRADE` — Fejlesztés
- `RECALL` — Visszahívás
**Kapcsolatok:**
- `asset` → [`Asset`](../backend/app/models/vehicle/asset.py:69) (Many-to-One)
- `user` → [`User`](../backend/app/models/identity/user.py) (Many-to-One)
- `organization` → [`Organization`](../backend/app/models/marketplace/organization.py) (Many-to-One)
- `cost` → [`AssetCost`](../backend/app/models/vehicle/asset.py:246) (Many-to-One)
### 2.2. `vehicle.odometer_readings` — Km óra állás történet
**Modell:** [`OdometerReading`](../backend/app/models/vehicle/asset.py:353)
**Tábla:** `vehicle.odometer_readings`
| Mező | Típus | Leírás |
|------|-------|--------|
| `id` | UUID (PK) | Elsődleges kulcs |
| `asset_id` | UUID (FK → `vehicle.assets.id`) | Jármű |
| `reading` | Integer | Km óra állás |
| `recorded_at` | DateTime | Rögzítés ideje |
| `source` | String(30) | Forrás: `manual`, `api`, `telemetry` |
| `cost_id` | UUID (FK → `vehicle.asset_costs.id`, nullable) | Kapcsolódó költség |
### 2.3. `vehicle.asset_costs` — Költségnapló
**Modell:** [`AssetCost`](../backend/app/models/vehicle/asset.py:246)
**Tábla:** `vehicle.asset_costs`
A költségek `data` JSONB mezőjében tárolódnak a szerviz specifikus adatok:
- `odometer` — km óra állás a költségkor
- `description` — leírás
- `type` — típus (pl. `maintenance`)
- `invoice_number` — számlaszám
### 2.4. `vehicle.assets.individual_equipment` — JSONB (Okmányok, Biztosítás)
**Mező:** [`Asset.individual_equipment`](../backend/app/models/vehicle/asset.py:114) — JSONB
Itt tárolódnak a **dokumentum lejáratok** és egyéb jármű specifikus adatok:
- `insurance_due_date` — Biztosítás fordulónap
- `insurance_premium` — Biztosítás díja
- `mot_due_date` — Műszaki vizsga lejárata
- `tire_change_date` — Gumicsere időpont
- `tire_change_description` — Gumicsere leírás
- `avg_consumption` — Átlagos fogyasztás
- `avg_cost_per_km` — Átlagos km költség
- `is_primary` — Elsődleges jármű flag
- `color` — Szín
- `next_service_days` — Következő szerviz napokban
---
## 3. Hiányosságok és Javaslatok
### 3.1. Dedikált `service_book` tábla hiánya
**Jelenlegi állapot:** Az [`AssetEvent`](../backend/app/models/vehicle/asset.py:395) modell egy generalista eseménytábla, amely minden típusú eseményt (szerviz, javítás, baleset, műszaki) egy táblában kezel. Nincs külön `ServiceEvent` tábla.
**Javaslat:** Az `AssetEvent` megfelelő a Digitális Szerviznaplóhoz, de érdemes lehet:
- `service_provider` (Integer, FK → `marketplace.service_providers.id`) mező hozzáadása a szervizpartner azonosításához
- `parts_cost` / `labor_cost` bontás a költségekhez
- `warranty_claim` (Boolean) mező a garanciális javításokhoz
### 3.2. Dokumentumok tárolása
**Jelenlegi állapot:** A biztosítás, műszaki vizsga és gumicsere adatok az [`individual_equipment`](../backend/app/models/vehicle/asset.py:114) JSONB mezőben vannak. Nincs dedikált `Document` tábla a jármű dokumentumokhoz.
**Javaslat:** Hozz létre egy `vehicle.vehicle_documents` táblát az alábbi mezőkkel:
- `id` (UUID, PK)
- `asset_id` (UUID, FK → `vehicle.assets.id`)
- `document_type` (String) — pl. `insurance`, `mot`, `registration`, `service_invoice`
- `document_number` (String) — pl. biztosítási kötvényszám
- `issue_date` (Date)
- `expiry_date` (Date)
- `document_url` (String) — feltöltött fájl elérési útja
- `notes` (Text)
### 3.3. Szerviz intervallumok
**Jelenlegi állapot:** A következő szerviz számítása a frontenden történik (`nextServiceKm = current_mileage + 15000`), nincs adatbázis szintű szervizütemezés.
**Javaslat:** Vezess be egy `vehicle.service_schedules` táblát:
- `id` (UUID, PK)
- `asset_id` (UUID, FK → `vehicle.assets.id`)
- `schedule_type` (String) — `time_based` vagy `mileage_based`
- `interval_km` (Integer) — km intervallum
- `interval_days` (Integer) — nap intervallum
- `last_service_km` (Integer) — utolsó szerviz km állása
- `last_service_date` (Date) — utolsó szerviz dátuma
- `next_service_km` (Integer) — következő esedékes km
- `next_service_date` (Date) — következő esedékes dátum
### 3.4. API végpontok hiánya
**Jelenlegi állapot:** Az [`AssetEvent`](../backend/app/models/vehicle/asset.py:395) modellhez tartozik egy `POST /{asset_id}/maintenance` végpont ([`create_maintenance_record`](../backend/app/api/v1/endpoints/assets.py:580)), de nincs:
- `GET /assets/{id}/events` — események listázása
- `GET /assets/{id}/events/{event_id}` — egy esemény részletei
- `PUT /assets/{id}/events/{event_id}` — esemény módosítása
- `DELETE /assets/{id}/events/{event_id}` — esemény törlése
---
## 4. Következtetés
| Komponens | Státusz | Megjegyzés |
|-----------|---------|------------|
| Szerviz események (`AssetEvent`) | ✅ **Kész** | Dedikált tábla, 8 eseménytípussal |
| Km óra állás (`OdometerReading`) | ✅ **Kész** | Időbeli nyomonkövetés |
| Költségnapló (`AssetCost`) | ✅ **Kész** | JSONB adatokkal |
| Okmány lejáratok | ⚠️ **JSONB-ben** | `individual_equipment` mezőben |
| Szerviz intervallumok | ❌ **Hiányzik** | Frontenden számolva |
| API végpontok | ⚠️ **Részleges** | Csak `POST /maintenance` létezik |
| Dedikált dokumentum tábla | ❌ **Hiányzik** | Javasolt létrehozni |
A Digitális Szerviznapló alap infrastruktúrája készen áll, de a következő fejlesztési fázisban érdemes:
1. Létrehozni a `vehicle_documents` táblát
2. Létrehozni a `service_schedules` táblát
3. Kibővíteni az API végpontokat CRUD műveletekkel
4. Átmigrálni a JSONB adatokat a dedikált táblákba