Files
service-finder/.roo/history.md

826 lines
55 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
1 | # Service Finder Fejlesztési Történet
2 |
3 | ## 2026-06-21 - P0 Deep Audit: Database Consistency & Zombie API Hunt
4 |
5 | ### 🎯 Cél
6 | Teljes körű adatbázis konzisztencia ellenőrzés és zombie API végpontok felderítése a `vehicle`, `finance`, `fleet_finance` sémákban, mielőtt a frontend fejlesztés elkezdődik.
7 |
8 | ### 🔧 Eredmények
9 |
10 | **1. ADATBÁZIS TISZTASÁG:** ✅ PASS
11 | - API modul import: ✅ Sikeres (2 route: GET, POST)
12 | - Sync Engine: ✅ 1210 OK, 0 Fixed, 0 Extra
13 | - E2E test: ⚠️ Pre-existing conftest hiba (verification token timeout - nem kapcsolódó)
14 |
15 | ## 2026-06-23 - Cost Entry Wizard (CostEntryWizard.vue) - 4-lépéses Számla Űrlap
16 |
17 | ### 🎯 Cél
18 | 4-lépéses stepper wizard építése részletes számla/invoice költségek rögzítésére a CostsActionsCard-ból indíthatóan.
19 |
20 | ### 🔧 Módosított fájlok
21 |
22 | ## 2026-06-24 - P0 Fix & Enhance: Permissions Page Data Flow, Editing & i18n
23 |
24 | ### 🎯 Cél
25 | Permissions oldal adatáramlás javítása, szerkesztés/mentés funkció bevezetése, és @nuxtjs/i18n telepítése/konfigurálása.
26 |
27 | ### 🔧 Módosított fájlok
28 | - `frontend_admin/pages/permissions/index.vue` - Teljes átírás: client-side data fetch onMounted-ben, szerkeszthető toggle-ok (modifiedPermissions Map), PATCH mentés, toast notification, $t() hívások
29 | - `frontend_admin/nuxt.config.ts` - @nuxtjs/i18n modul hozzáadása, locales konfiguráció (hu/en)
30 | - `frontend_admin/i18n/locales/hu.json` - Magyar fordítási fájl (permissions oldal összes szövege)
31 | - `frontend_admin/i18n/locales/en.json` - Angol fordítási fájl
32 |
33 | ### ✅ Eredmények
34 | - Build: ✅ Sikeres (hu-DbjfOUfH.mjs, en-DnJ23n0t.mjs locale chunk-ok)
35 | - i18n modul: @nuxtjs/i18n v10.4.0 telepítve, no_prefix stratégiával
36 | - Szerkesztés: modified/original Map-ek, handleToggle, savePermissions (PATCH /admin/permissions/override/{org_id})
37 | - Adatmentés: success/error toast notification auto-clear-el
38 |
39 | ## 2026-06-24 - P0 Execution: Wire Packages UI to Real Database
40 |
41 | ### 🎯 Cél
42 | A frontend_admin Packages oldal (packages/index.vue) mock adatok helyett valós API adatbázisból töltse a SubscriptionTier csomagokat. "Új Csomag Létrehozása" gomb és modal hozzáadása.
43 |
44 | ### 🔧 Módosított fájlok
45 | - `backend/app/schemas/subscription.py` - `tier_level` és `feature_capabilities` mezők hozzáadva a SubscriptionTierResponse, SubscriptionTierCreate, SubscriptionTierUpdate modellekhez
46 | - `backend/app/api/v1/endpoints/admin_packages.py` - create/update végpontok frissítve az új mezők kezelésére
47 | - `frontend_admin/pages/packages/index.vue` - Teljes átírás: mock adatok eltávolítva, fetchPackages() API hívás, create/edit/delete modal-ok, loading/error/empty állapotok, i18n támogatás
48 | - `frontend_admin/locales/hu.json` - packages i18n kulcsok (magyar)
49 | - `frontend_admin/locales/en.json` - packages i18n kulcsok (angol)
50 |
51 | ### ✅ Eredmények
52 | - Backend API: GET /api/v1/admin/packages → 200 OK, 10 tier (tier_level, feature_capabilities mezőkkel)
53 | - Frontend: mock adatok eltávolítva, valós API hívás onMounted-ben, loading/error/empty állapotok
54 | - CRUD: Létrehozás (POST), Szerkesztés (PATCH), Törlés (DELETE soft-delete) teljes körűen implementálva
55 | - i18n: Minden UI szöveg magyar és angol nyelven elérhető
56 |
57 | ## 2026-06-24 - P0 CRITICAL FIX: Deep Merge JSONB (Multi-zone Pricing Data Loss)
58 |
59 | ### 🎯 Cél
60 | Javítani a `PATCH /api/v1/admin/packages/{tier_id}` végpontot, hogy a `rules` JSONB oszlop frissítésekor a meglévő nested kulcsok (pl. `pricing_zones.HU`, `pricing_zones.US`, `lifecycle.available_until`) ne vesszenek el, ha a frontend csak egy részhalmazt küld (pl. csak `pricing_zones.DEFAULT`).
61 |
62 | ### 🔧 Módosított fájlok
63 | - `backend/app/api/v1/endpoints/admin_packages.py``deep_merge_dict()` függvény hozzáadva, `update_package` endpoint átírva deep merge szemantikára
64 | - `tests/active/test_deep_merge_fix.py` — Verifikációs teszt (unit + API PATCH)
65 |
66 | ### ✅ Eredmények
67 | - **Unit test:** ✅ PASS — `deep_merge_dict()` helyesen működik: nested dict-ek rekurzív merge, None értékek megőrzése, üres override megőrzése
68 | - **API test:** ✅ PASS — `private_pro_v1` (id=14) csomagon: HU, US, DEFAULT zónák mind megmaradtak a PATCH után, DEFAULT ára frissült, lifecycle.available_until megőrződött
69 | - **Sync Engine:** ✅ 1220 OK, 0 Fixed — adatbázis séma konzisztens
70 | - **Root cause:** A frontend `packages/index.vue` `rulesPayload` függvénye csak `pricing_zones.DEFAULT`-ot állítja elő, a backend pedig wholesale replace-t végzett → multi-zone adatvesztés
## 2026-06-24 - P0 System Architecture: Global Region Config & Smart Pricing
### 🎯 Cél
Globális régió konfigurációs rendszer (RegionConfig modell + API) megvalósítása, frontend region store és formatter composable létrehozása, Smart Pricing Calculator beépítése a package edit modalba, valamint nyelvi preferencia perzisztálása a layoutban.
### 🔧 Módosított fájlok
- `backend/app/models/core_logic.py``RegionConfig` osztály hozzáadva (`system.region_config` séma, mezők: country_code, name, currency, default_vat_rate, locale_code, timezone, is_active)
- `backend/app/models/__init__.py``RegionConfig` import hozzáadva
- `backend/app/api/v1/endpoints/regions.py`**LÉTREHOZVA**: `GET /system/regions` publikus végpont
- `backend/app/api/v1/api.py` — regions router regisztrálva `/system` prefix-szel
- `backend/scripts/seed_regions.py`**LÉTREHOZVA**: 3 régió seedelése (HU, GB, DEFAULT)
- `backend/app/api/v1/endpoints/auth.py``PATCH /auth/me/language` végpont hozzáadva nyelvi preferencia perzisztáláshoz
- `frontend_admin/stores/region.ts`**LÉTREHOZVA**: Pinia store régiók lekérésére, aktív régió getterekkel (currency, locale, VAT, timezone)
- `frontend_admin/composables/useFormatter.ts`**LÉTREHOZVA**: Lokalizált formatter (number, currency, date, datetime, percent, VAT számítás)
- `frontend_admin/pages/packages/index.vue` — Tabbed modal refaktor (Basic Info, Pricing, Features), per-régió árazási grid, Smart Pricing Calculator net/VAT/gross kijelzéssel
- `frontend_admin/layouts/default.vue` — Nyelvváltó perzisztálás PATCH hívással, region store inicializálás onMounted-ban
### ✅ Eredmények
- **Sync Engine:** ✅ 1220 OK, 1 Fixed, 0 Shadow — `system.region_config` tábla létrejött
- **GET /api/v1/system/regions:** ✅ 200 — 3 régió (DEFAULT/EUR/0%, GB/GBP/20%, HU/HUF/27%)
- **PATCH /auth/me/language:** ✅ 200 — `preferred_language` perzisztálódik és visszaolvasható
- **Frontend build (admin):** ✅ Sikeres — `region-*.mjs` chunk generálódott
- **Adatbázis:** `country_code` VARCHAR(5)→VARCHAR(10) manuális ALTER a seed előtt
## 2026-06-25 - P0 CRITICAL SECURITY & UI FIX - RBAC Middleware & Mock Data Removal
### 🎯 Cél
Szigorú frontend Route-Based Access Control (RBAC) bevezetése az admin middleware-ben, és a hardcoded mock email (`admin@servicefinder.hu`) eltávolítása a Topbar-ból.
### 🔧 Módosított fájlok
- `frontend_admin/middleware/auth.ts` — Teljes átírás: token cookie ellenőrzés után `authStore.fetchUser()` hívás, majd `authStore.user.role` ellenőrzés az allowed staff role-ok listája (`SUPERADMIN`, `ADMIN`, `MODERATOR`, `SALES_REP`, `SERVICE_MGR`) alapján. Ha a role nem staff szintű → `authStore.logout()` + `navigateTo('/login')`.
- `frontend_admin/layouts/default.vue``userEmail` computed fallback `'admin@servicefinder.hu'``'Ismeretlen Felhasználó'`, `userInitials` fallback `'AD'``'??'`, dropdown role label `'Administrator'` → dinamikus `authStore.userRole` alapú.
### ✅ Eredmények
- **RBAC Middleware:** ✅ Standard USER role esetén a middleware kilépteti a felhasználót és a `/login` oldalra irányítja
- **Mock adatok eltávolítva:** ✅ `admin@servicefinder.hu` sehol sem szerepel hardcoded értékként
- **Auth Store:** ✅ Tiszta, nincs benne mock/default user adat
- **Minden admin oldal** (`index.vue`, `garages/index.vue`, `packages/index.vue`, `permissions/index.vue`) használja a `definePageMeta({ middleware: 'auth' })` direktívát
## 2026-06-25 - P0 Data Architecture: Populate Full EU Region Registry
### 🎯 Cél
A `system.region_config` tábla feltöltése mind a 27 EU tagállammal, plusz UK, Svájc és DEFAULT/Eurozone fallback rekorddal. Korábban csak 3 dummy/seed régió (HU, GB, DEFAULT) volt az adatbázisban.
### 🔧 Módosított fájlok
- `backend/scripts/seed_regions.py` — Teljes átírás: 30 régiós adatbázis (27 EU + GB + CH + DEFAULT), UPSERT logika (meglévő rekordok frissítése, új rekordok beszúrása), pontos VAT kulcsok, devizanemek, locale kódok és időzónák minden országra.
### ✅ Eredmények
- **Seed futtatás:** ✅ 27 új régió létrehozva, 3 meglévő frissítve (HU, GB, DEFAULT)
- **API verifikáció:** ✅ `GET /api/v1/system/regions` → 30 régió visszaadva, minden adat helyes
- **UPSERT idempotencia:** ✅ A script többször is futtatható, frissíti a meglévő rekordokat ahelyett, hogy duplikációt okozna
## 2026-06-25 - Garages CRM Wiring & Custom B2B Deals UI
### 🎯 Cél
Garázsok (Organizations) CRM felületének teljes körű implementálása: backend API végpontok, frontend adattábla mock adatok nélkül, előfizetéskezelő modál egyedi lejárati dátumokkal (B2B deal-ekhez).
### 🔧 Módosított/Létrehozott fájlok
**1. `backend/app/api/v1/endpoints/admin_organizations.py`** (LÉTREHOZVA)
- `GET /admin/organizations` — Garázsok listázása előfizetési adatokkal, taglétszámmal, kereséssel, szűréssel, lapozással
- `PATCH /admin/organizations/{org_id}/subscription` — Előfizetés módosítása tier_id és opcionális expires_at megadásával
- Tömeges subscription és member_count lekérdezés (N+1 elkerülése)
**2. `backend/app/api/v1/api.py`** (MÓDOSÍTVA)
- `admin_organizations` router regisztrációja
**3. `frontend_admin/pages/garages/index.vue`** (ÁTÍRVA)
- Mock adatok eltávolítva, valós API hívások (`$fetch`)
- Statisztikai kártyák (összes, aktív, premium, enterprise)
- Keresés és szűrés (tier alapján)
- Adattábla: ID, cégnév, státusz, csomag, lejárat, műveletek
- Előfizetéskezelő modál: tier dropdown + egyéni datetime-local input
- Mentés utáni automatikus refresh
**4. `frontend_admin/i18n/locales/hu.json`** (MÓDOSÍTVA)
- Garázs CRM-hez kapcsolódó összes magyar fordítás hozzáadva
**5. `frontend_admin/i18n/locales/en.json`** (MÓDOSÍTVA)
- Garázs CRM-hez kapcsolódó összes angol fordítás hozzáadva
### ✅ Teszt Eredmények
- Sync Engine: ✅ 1230 OK, 0 Fixed, 0 Extra (tökéletes szinkron)
- `GET /admin/organizations?limit=5`: ✅ 200 — 31 garázs, 5 visszaadva
- `GET /admin/packages?limit=5`: ✅ 200 — 5 tier elérhető
- `PATCH /admin/organizations/2406/subscription`: ✅ 200 — Celebro Kft. → corp_premium_v1, lejárat: 2027-06-25
- Verifikáció: ✅ Tier és lejárati dátum helyesen perzisztálva
## 2026-06-25 - P0 FIX & ENHANCE: Auth Token Missing & Duplicate Package Button
### 🎯 Cél
1. Garázsok oldal "Not authenticated" hiba javítása — hiányzó Authorization header pótlása
2. "Másolás" (Duplicate) gomb implementálása a csomagok oldalon
### 🔧 Módosított fájlok
**1. `frontend_admin/pages/garages/index.vue`** (MÓDOSÍTVA)
- `getAuthHeaders()` helper hozzáadva — `access_token` cookie-ból olvassa a tokent
- `fetchGarages()` és `fetchTiers()` hívásokhoz `headers: getAuthHeaders()` hozzáadva
- `saveSubscription()` PATCH híváshoz `Authorization` header hozzáadva
**2. `frontend_admin/pages/packages/index.vue`** (MÓDOSÍTVA)
- "Másolás" (Duplicate) gomb hozzáadva a kártya akcióihoz (Szerkesztés mellett, zöld színnel)
- `duplicatePackage(pkg)` függvény implementálva:
- Megnyitja a Create Modalt a kiválasztott csomag adataival előtöltve
- `id` mező törölve (új rekordként mentődik)
- Névhez `_copy` utótag fűzve, display_name-hez ` (másolat)` fűzve
- `is_default_fallback` false-ra állítva (nem duplikálható a visszaesési státusz)
- Árazási zónák, allowance-ok, feature_capabilities teljes körű másolása
**3. `frontend_admin/i18n/locales/en.json`** (MÓDOSÍTVA)
- `packages.duplicate: "Duplicate"` kulcs hozzáadva
**4. `frontend_admin/i18n/locales/hu.json`** (MÓDOSÍTVA)
- `packages.duplicate: "Másolás"` kulcs hozzáadva
### ✅ Domain Audit
- `backend/app/api/v1/endpoints/admin_organizations.py` végpont kizárólag core táblákat érint:
- `Organization`, `OrganizationMember`, `OrganizationSubscription`, `SubscriptionTier`, `User`
- Nincs scraped provider tábla lekérdezés — domain határok helyesek
## 2026-06-25: P0 Audit - Domain Conflation in Expense/Cost Service Provider Flow
**Gitea Card:** #291
**Scope:** Backend
**Type:** Bug / Domain Conflation
### Findings
Identified **6 code locations** causing domain conflation when `quick_add_provider()` creates `Organization()` (→ `fleet.organizations`) instead of `ServiceProvider()` (→ `marketplace.service_providers`):
1. **PRIMARY (provider_service.py:507-550):** `quick_add_provider()` creates `Organization()` instead of `ServiceProvider()`
2. **SECONDARY (provider_service.py:561-570):** `ServiceProfile.organization_id` FK to incorrectly created fleet.organizations
3. **TERTIARY (provider_service.py:618-630):** Branch creation in fleet.branches for lightweight vendor
4. **QUATERNARY (provider_service.py:639-646):** OrganizationMember addition for creating user
5. **SYSTEMIC (fleet_finance/models.py:104-110):** `AssetCost.vendor_organization_id` FK references ONLY `fleet.organizations.id`
6. **STRUCTURAL (provider_service.py):** `search_providers()` UNION masks domain conflation
### Outcome
- Report: `/opt/docker/docs/p0_domain_conflation_cost_provider_audit.md` (in roo-helper container)
- **No code changes made.** Awaiting Architect decision on refactoring approach.
- Refactoring Options proposed: A (flag in fleet), B (split to marketplace), C (hybrid - recommended)
## 2026-06-25 - P0 Hybrid Vendor Refactor & Categorization (Option C)
### 🎯 Cél
Implementálni az Option C (Hybrid) architektúrát: `quick_add_provider()` mostantól `ServiceProvider`-t (`marketplace.service_providers`) hoz létre `Organization` helyett (`fleet.organizations`). A valódi garázsok (safe list: 13 ID) továbbra is Organization-ként maradnak.
### 🔧 Módosított fájlok
**PHASE 1 - Schema Updates:**
- `backend/app/models/fleet_finance/models.py``service_provider_id` hozzáadva `AssetCost`-hoz + FK javítás (relációk indentálása)
- `backend/app/models/marketplace/service.py``service_provider_id` hozzáadva `ServiceProfile`-hoz
- `backend/app/models/identity/social.py``ServiceProvider` kiterjesztve 10 új mezővel (cím, kontakt)
- `unified_db_sync.py` futtatva → 10 új oszlop létrehozva az adatbázisban
**PHASE 2 - Refactor quick_add_provider():**
- `backend/app/services/provider_service.py``quick_add_provider()` átírva: `ServiceProvider` + `ServiceProfile` létrehozása (NO Organization, NO Branch, NO OrganizationMember)
- `backend/app/schemas/asset_cost.py``service_provider_id` hozzáadva a Pydantic modellekhez
- `backend/app/schemas/provider.py``ProviderQuickAddIn` kiegészítve új mezőkkel
- `backend/app/api/v1/endpoints/expenses.py``service_provider_id` átadva `AssetCost` creation-nél
**PHASE 3 - Data Migration:**
- `backend/scripts/migrate_providers.py` — Létrehozva: 7 Organization → ServiceProvider migrálva
**PHASE 4 - Verification:**
- 7 ServiceProvider rekord létrejött (`marketplace.service_providers`)
- 6/7 rendelkezik ServiceProfile kapcsolattal (MOL-nak 0 profilja volt)
- 1 AssetCost linkelve (Aszalós Motorszervíz)
- Safe list garázsok (13) érintetlenek a `fleet.organizations` táblában
## 2026-06-25 - P0 DATABASE PURGE & E2E VERIFICATION
### 🎯 Cél
Teljes adatbázis tisztítás: fake organization-ök eltávolítása a `fleet.organizations` táblából, az összes hivatkozó FK rekord előzetes felszabadításával. E2E verifikáció: quick_add_provider flow tesztelése.
### 🔧 Eredmények
**deep_purge_fake_orgs.py** — Sikeres purge:
- **Step A (Financial Relink):** 6 ServiceProfile organization_id → NULL (már volt sp_id), 1 residual vendor_org cleaned
- **Step B (Garbage Destroyed):** 12 org_subscriptions, 26 asset_assignments, 24+19 vehicle.assets org refs NULLed, 5 asset_costs reassigned to org_id=15, 15 branches, 9 org_members
- **Step C (Final Purge):** 18 fake organizations DELETED (IDs: 1,26,27,32,33,34,37,38,44,46,51,57,58,62,63,2406,4859,7676)
- **Verification:** ✅ PASS — No fake organizations remain
**test_quick_add_flow.py** — E2E teszt:
- Assert 1 ✅: ServiceProvider 'OMV Teszt Kút' létezik `marketplace.service_providers`-ben
- Assert 2 ✅: Nincs Organization `fleet.organizations`-ben
- Assert 3 ✅: AssetCost helyesen linkelve (service_provider_id=8, vendor_organization_id=NULL)
- **Eredmény: 3/3 PASS**
### 📁 Létrehozott fájlok
- `backend/scripts/deep_purge_fake_orgs.py` — Deep purge & relink script
- `backend/scripts/test_quick_add_flow.py` — E2E verification script
## 2026-06-25 - P0 UI POLISH: Garages CRM & Display Name Normalization
### 🎯 Cél
Private garázsok display_name normalizálása és a Garages CRM admin UI frissítése a clean display name-ek megjelenítésére.
### 🔧 Módosított fájlok
- `backend/scripts/safe_rename_garages.py` — LÉTREHOZVA: Safe rename script (17 private garage updated)
- `frontend_admin/pages/garages/index.vue` — MÓDOSÍTVA: display_name prioritás a cégnév oszlopban + "Részletek" gomb
- `frontend_admin/i18n/locales/hu.json` — MÓDOSÍTVA: "details" i18n kulcs hozzáadva
- `frontend_admin/i18n/locales/en.json` — MÓDOSÍTVA: "details" i18n kulcs hozzáadva
### ✅ Eredmények
1. **Safe Rename Script:** 17 private garage `name` és `display_name` mezője frissítve. `name` tartalmazza az ID-t az egyediségért (`#{user_id}`), `display_name` tiszta, emberi olvasásra szánt formátumban (`{last_name} {first_name} - Privát Garázs`).
2. **Frontend UI:** A "Cégnév" oszlop most `display_name`-t használ elsődlegesen, `name`-et csak fallback-ként. Új "Részletek" gomb hozzáadva az akciókhoz.
3. **Corporate orgs érintetlenek:** Csak `individual` típusú szervezetek lettek módosítva.
---
## 2026-06-25 - P0 UI MICRO-FIX: Page Title & Expiration Date Logic
### 🎯 Cél
Két UX hiba javítása az admin felületen: (1) böngésző fül címének beállítása, (2) lejárati dátum megjelenítése "Határozatlan" szöveggel NULL esetén.
### 🔧 Módosított fájlok
- [`frontend_admin/app.vue`](frontend_admin/app.vue) — `useHead` hozzáadva `titleTemplate`-mel: "Service Finder Admin" alapértelmezett, oldalnév esetén "Oldalnév | Service Finder Admin" formátum.
- [`frontend_admin/pages/garages/index.vue`](frontend_admin/pages/garages/index.vue:183) — Lejárati dátum cella: NULL esetén a "—" helyett `$t('garages.indefinite')` i18n kulcs jelenik meg.
- [`frontend_admin/i18n/locales/hu.json`](frontend_admin/i18n/locales/hu.json:141) — `garages.indefinite`: "Határozatlan" kulcs hozzáadva.
- [`frontend_admin/i18n/locales/en.json`](frontend_admin/i18n/locales/en.json:141) — `garages.indefinite`: "Indefinite" kulcs hozzáadva.
### ✅ Verifikáció
- Nuxt build sikeres (`sf_admin_frontend` konténerben).
- Böngésző fül: alapértelmezetten "Service Finder Admin", oldalnézetben "Page Name | Service Finder Admin".
- Garázs tábla: subscription_expires_at = NULL esetén "Határozatlan" (HU) / "Indefinite" (EN) szöveg jelenik meg.
## 2026-06-25 - Garage Details (General Tab) - P0 Implementation
### 🎯 Cél
Garázs részletes adatlap implementálása General Tab-bal: backend API végpont + frontend oldal + i18n fordítások.
### 🔧 Backend API
- [`backend/app/api/v1/endpoints/admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:301) — `GET /{org_id}/details` végpont:
- Pydantic modellek: `ContactPersonInfo`, `SubscriptionSummary`, `GarageDetailsResponse`
- Lekérdezi: Organization (selectinload subscription_tier), OrganizationSubscription (active, limit 1, selectinload tier), ContactPerson (is_primary == True, selectinload person), member_count via func.count
- Fallback: ha nincs OrganizationSubscription, az org.subscription_tier adatait használja
### 🖼️ Frontend Oldal
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue) — Teljes Nuxt 3 oldal:
- **Header:** Vissza gomb, Avatar (kezdőbetűk), Garázs név + státusz badge
- **Tab navigáció:** Általános, Dolgozók, Flotta, Analitika (a 3 utolsó "Coming soon")
- **General Tab (3 Info Card):**
1. **Cég adatok:** cégnév, megjelenítési név, szervezet típusa, adószám, cégjegyzékszám, létrehozva, cím
2. **Előfizetés státusza:** csomag, szint, lejárat (Határozatlan ha null), járműkorlát, járművek száma
3. **Elérhetőség:** kapcsolattartó neve, szerepkör, osztály, telefonszám
- Helper függvények: `garageDisplayName()`, `getInitials()`, `getInitialsColor()`, `statusBadgeClass()`, `statusDotClass()`, `statusLabel()`, `tierBadgeClass()`, `orgTypeLabel()`, `formatDate()`, `formattedAddress` computed
### 🌐 i18n Fordítások
- [`frontend_admin/i18n/locales/hu.json`](frontend_admin/i18n/locales/hu.json:142) — `garages.details` objektum 20+ kulccsal
- [`frontend_admin/i18n/locales/en.json`](frontend_admin/i18n/locales/en.json:142) — Angol megfelelők
- [`frontend_admin/i18n/locales/hu.json`](frontend_admin/i18n/locales/hu.json:140) — `garages.view_details` kulcs (a régi `details` string átnevezve)
### 🔗 Navigáció
- [`frontend_admin/pages/garages/index.vue`](frontend_admin/pages/garages/index.vue:570) — `openDetails()`: "Coming soon" helyett `navigateTo()` a részletes oldalra
### ✅ Verifikáció
- Backend API `GET /api/v1/admin/organizations/51/details` → HTTP 200, teljes válasz (org adatok + subscription + member_count)
- `sf_api` konténer újraindítva a kód élesítéséhez
- `sf_admin_frontend` volume mount miatt automatikusan érzékeli a változásokat
## 2026-06-25 - P0 RECOVERY: Surgical Vehicle Relinking Verification
### 🎯 Cél
Adatbázis restore után ellenőrizni, hogy a `vehicle.assets` táblában lévő járművek `current_organization_id` mezője nem NULL (nem árva rekordok). Ha szükséges, relinkelni a járműveket a `fleet.organization_members` tábla user-to-organization kapcsolatai alapján.
### 🔧 Diagnosztikai Eredmények
**1. DIAGNOSE — Orphaned Vehicles Query:**
- SQL: `SELECT COUNT(*) FROM vehicle.assets WHERE current_organization_id IS NULL AND status NOT IN ('deleted', 'archived') AND owner_person_id IS NOT NULL`
- **Eredmény: 0 orphaned vehicle** — mind a 42 jármű rendelkezik érvényes `current_organization_id` értékkel
**2. Teljes adatbázis konzisztencia ellenőrzés:**
- Összes jármű: **42 db**
- `current_organization_id IS NULL`: **0 db**
- `current_organization_id` + `owner_person_id` együtt NULL: **0 db** (csak archived rekordoknál, ahol nincs owner)
- Minden `current_organization_id` hivatkozás érvényes `fleet.organizations` rekordra mutat
**3. Járművek eloszlása szervezetenként:**
| Org ID | Szervezet Neve | Járművek |
|--------|----------------|----------|
| 1 | Profibot Tester - Privát Garázs (#28) | 18 (10 active + 8 draft) |
| 21 | Admin Super - Privát Garázs (#29) | 6 active |
| 43 | Accipe Tímea - Privát Garázs (#79) | 2 (1 active + 1 draft) |
| 44 | Profibot Kft. | 4 archived |
| 45 | Gyöngyössy Zsolt - Privát Garázs (#86) | 1 active |
| 46 | Gyöngyössy Krisztina - Privát Garázs (#100) | 1 active |
| 48 | User Test - Privát Garázs (#104) | 2 active |
| 49 | Test Final - Privát Garázs (#105) | 1 active |
| 50 | Profibot Tester - Privát Garázs (#106) | 1 active |
| 66 | Admin Super - Privát Garázs (#1) | 1 active |
| 67 | User Admin - Privát Garázs (#2) | 3 archived |
**4. Organization Members verifikáció:**
- Minden olyan org, amelyhez aktív jármű tartozik, rendelkezik OWNER vagy ADMIN taggal a `fleet.organization_members` táblában
- A user-to-person kapcsolatok (`identity.users.person_id`) konzisztensek az org tagságokkal
### ✅ Végkövetkeztetés
- **Recovery script nem szükséges** — az adatbázis restore után a `current_organization_id` kapcsolatok sértetlenek maradtak
- **0 jármű maradt árva** — minden aktív jármű egy valid organizationhöz van linkelve
- **Adatbázis konzisztencia:** ✅ PASS — nincs szükség beavatkozásra
## 2026-06-25 - P0 Phase 1: DB-Driven RBAC Foundation (Backend Schema & Seed)
### 🎯 Cél
RBAC Phase 1 (Foundation) implementálása: DB-driven role/permission rendszer kiépítése a `system` sémában, a hardcoded `SYSTEM_CAPABILITIES_MATRIX` és `UserRole` enum leváltásának első lépése.
### 🔧 Létrehozott fájlok
- `backend/app/models/system/rbac.py` - 3 új SQLAlchemy modell: SystemRole, SystemPermission, SystemRolePermission
- `backend/app/scripts/seed_rbac.py` - Seed script: 6 role, 28 permission, 168 role-permission mapping, 33 user migráció
### 🔧 Módosított fájlok
- `backend/app/models/system/__init__.py` - RBAC modellek exportja
- `backend/app/models/__init__.py` - RBAC modellek globális exportja
- `backend/app/models/identity/identity.py` - `role_id` FK + `system_role` relationship hozzáadva a User modellhez
### ✅ Eredmények
- **Sync Engine:** 4 fix (3 új tábla + 1 új oszlop) ✅
- **Seed:** 6 role, 28 permission, 168 role-permission mapping, 33 user migrálva ✅
- **Adatbázis séma:** system.roles, system.permissions, system.role_permissions létrehozva
- **User modell:** role_id (FK→system.roles.id, nullable=True, ondelete=SET NULL) hozzáadva
## 2026-06-25 - RBAC Phase 2: DB-Driven Permission Check (Backend Service Layer)
### 🎯 Cél
Implementálni a DB-driven RBAC permission check-et: `RBACService.get_role_permissions()` metódus, `RequirePermission(permission_code)` dependency factory, és egy verifikációs végpont.
### 🔧 Módosított fájlok
- `backend/app/services/rbac_service.py` - `get_role_permissions()` metódus hozzáadva (lekérdezi a `system.role_permissions` + `system.permissions` táblákból a granted permission code-okat role_id alapján); `invalidate_role_cache()` placeholder hozzáadva
- `backend/app/api/deps.py` - `RequirePermission(permission_code: str)` dependency factory hozzáadva (SUPERADMIN bypass rank=100, DB lekérdezés, 403 ha hiányzik a permission)
- `backend/app/api/v1/endpoints/admin_permissions.py` - `GET /admin/rbac-test` verifikációs végpont hozzáadva `RequirePermission("fleet:view")` védelemmel; dead code cleanup
### ✅ Eredmények
- **Import check:** ✅ Minden modul importálható hiba nélkül
- **Sync Engine:** ✅ 1265 OK, 0 Fixed - rendszer tökéletes szinkronban
- **HTTP teszt:** ✅ `GET /api/v1/admin/rbac-test` → 200 OK, permission check passed (user_id=2, role=ADMIN, role_id=2, permission=fleet:view)
- **Adatbázis:** 28 permission, 168 role-permission mapping (6 role × 28 permission) létezik és konzisztens
## 2026-06-25 - RBAC Phase 5: Backend Cleanup (Zombie Code Removal)
### 🎯 Cél
Az RBAC Phase 1-3 legacy kód teljes eltávolítása, miután az új DB-driven RBAC rendszer élesben fut a frontenden.
### 🔧 Végrehajtott módosítások
1. **`backend/app/api/deps.py`** - Törölve: `get_current_admin()`, `RequireRole()`, `RequireSystemCapability()` függvények és az import `SYSTEM_CAPABILITIES_MATRIX, role_has_capability` a capabilities modulból. (~114 sor)
2. **`backend/app/core/capabilities.py`** - Törölve: `SYSTEM_CAPABILITIES_MATRIX` dictionary (196 sor), `get_capabilities_for_role()`, `role_has_capability()` helper függvények. Megtartva: `Capability` osztály (string konstansok). (~220 sor)
3. **`backend/app/services/rbac_service.py`** - Törölve: `ADMIN_SCOPE_ACTIONS`, `MODERATOR_SCOPE_ACTIONS`, `SALES_REP_SCOPE_ACTIONS`, `SERVICE_MGR_SCOPE_ACTIONS` hardcoded set-ek, `ROLE_ACTIONS` mapping, és az import `SYSTEM_CAPABILITIES_MATRIX, role_has_capability`. A `check_admin_access()` metódus továbbra is működik, de a `get_permitted_actions()` már csak SUPERADMIN-ra ad vissza action-öket. (~47 sor)
4. **Import javítások:** `organizations.py` (RequireSystemCapability import eltávolítva), `users.py` (get_capabilities_for_role import és hívás eltávolítva), `admin_permissions.py` (scope action set importok eltávolítva). (~9 sor)
### ✅ Eredmények
- **Import check:** ✅ Minden modul importálható hiba nélkül (`deps.py`, `capabilities.py`, `rbac_service.py`)
- **Sync Engine:** ✅ 1265 OK, 0 Fixed - rendszer tökéletes szinkronban
- **Zombie code removed:** ~390 sor legacy kód eltávolítva a projektből
- **Dead-code verification:** 0 maradék import a törölt függvényekre
## 2026-06-25 - RBAC Phase 4: Dynamic Permission Matrix UI & API
### 🎯 Cél
Dinamikus permission management UI építése a DB-driven RBAC rendszerhez. Backend API végpontok (GET/PUT) a SystemRole és SystemPermission entitásokhoz, frontend permission mátrix UI toggle kapcsolókkal, SUPERADMIN védelemmel.
### 🔧 Módosított fájlok
- `backend/app/api/v1/endpoints/admin_permissions.py` — 3 új végpont: GET /admin/permissions/roles, GET /admin/permissions, PUT /admin/permissions/roles/{role_id}/permissions
- `frontend_admin/pages/permissions/index.vue` — Teljes átírás: statikus tömbök eltávolítva, dinamikus API-alapú permission mátrix UI
- `frontend_admin/i18n/locales/en.json` — Elavult statikus permission kulcsok eltávolítva
- `frontend_admin/i18n/locales/hu.json` — Elavult statikus permission kulcsok eltávolítva
### ✅ Eredmények
- **API smoke test:** ✅ Minden végpont működik (GET roles, GET permissions, PUT permissions, SUPERADMIN 403 protection)
- **Sync Engine:** ✅ 1265 OK, 0 Fixed - rendszer tökéletes szinkronban
- **Permissions hozzáadva:** `permissions:view` (id=29), `permissions:edit` (id=30) — SUPERADMIN és ADMIN szerepkörökhöz rendelve
- **SUPERADMIN védelem:** rank>=100, is_system=True szerepkörök módosítása 403-mal tiltva
## 2026-06-25 — RBAC Permission Audit (Gitea #298)
**Auditor:** Rendszer-Architect
**Scope:** Adatbázis ↔ Backend Service ↔ API ↔ Frontend Admin UI szinkron vizsgálata
### Vizsgált fájlok:
- `backend/app/services/rbac_service.py` — Dual RBAC rendszer feltárva (Scope-based AdminAction vs DB-driven SystemPermission)
- `backend/app/models/system/rbac.py` — SystemRole, SystemPermission, SystemRolePermission modellek validálva
- `backend/app/api/v1/endpoints/admin_permissions.py` — Matrix endpoint hibás (Scope-based), roles/permissions endpointok helyesek (DB-driven)
- `backend/app/api/v1/endpoints/users.py``system_capabilities` mindig üres, legacy mátrix eltávolítva, DB lekérdezés nem implementálva
- `backend/app/api/deps.py``RequirePermission()` helyesen működik DB-driven rendszerrel
- `backend/app/core/capabilities.py` — Deprecated Capability class, eltérő formátum
- `frontend_admin/pages/permissions/index.vue` — Valós API hívások, NINCS mock adat
- `frontend_admin/stores/auth.ts` — UserProfile interface helyes
- `frontend_admin/middleware/auth.ts` — Role-alapú auth check OK
### Feltárt hibák:
1. 🔴 KRITIKUS: Dual RBAC rendszer — `get_permitted_actions()` csak SUPERADMIN-nak ad vissza adatot
2. 🔴 KRITIKUS: `system_capabilities`/`org_capabilities` mindig üres a `/auth/me` response-ban
3. 🟡 KÖZEPES: Deprecated Capability class eltérő formátumú konstansokkal
### Pozitívum:
- Frontend admin UI-ban NINCS mock adat — minden végpont valós API-t hív
- Adatbázis séma helyes: 6 role, 30 permission, teljes role-permission mapping
- `RequirePermission()` függőség jól működik
- Permission mátrix UI (2D táblázat) megfelelően épül fel
## 2026-06-25 - P0 Phase 6: DB-Driven RBAC & Phantom Permission Fix
### 🎯 Cél
8 darab "szellem" (orphaned) permission kód beillesztése a `system.permissions` táblába, az RBAC service refaktorálása az `AdminAction` enum eltávolításával, és a `_build_user_response` függvény átalakítása, hogy a `system_capabilities` mezőt DB-driven lekérdezésből töltse.
### 🔧 Módosított fájlok
- `backend/scripts/fix_phantom_permissions.py` (ÚJ) - 8 hiányzó permission beszúrása + role mapping
- `backend/app/services/rbac_service.py` - `AdminAction` enum eltávolítva, `get_permitted_actions` async + DB-driven
- `backend/app/api/v1/endpoints/admin_permissions.py` - `AdminAction` import eltávolítva, DB-driven action validáció
- `backend/app/api/v1/endpoints/users.py` - `_build_user_response` async-re váltva, DB-driven permission lookup
- `backend/app/api/v1/endpoints/auth.py` - `_build_user_response` hívás `await`-el + `db` paraméter átadva
- `backend/app/core/capabilities.py` - `Capability` osztály eltávolítva (deprecated)
- `backend/app/api/v1/endpoints/organizations.py` - `Capability` import eltávolítva
### ✅ Eredmények
- 8 új permission beszúrva (id: 31-38): `dual-control:request/approve/view`, `services:manage`, `subscription:manage`, `user:manage`, `moderation:manage`, `gamification:manage`
- 16 role-permission mapping létrehozva (8 permission × 2 role: SUPERADMIN + ADMIN)
- `get_permitted_actions` most már minden role-ra DB-driven lekérdezést használ
- `_build_user_response` async függvény, ami `rbac_service.get_role_permissions(db, role_id)`-t hív
- `/auth/me` és `/users/me` endpoint-ok 38 db system_capabilities-t adnak vissza (mind True)
- `Capability` osztály eltávolítva a kódbázisból
## 2026-06-25 - P0 EXECUTION: Garage CRM Completion (Status & Edit)
### 🎯 Cél
Garázs CRM funkciók teljes körű implementálása: backend státuszváltó és adatszerkesztő végpontok, frontend UI integráció a listázó és részletes oldalakon.
### 🔧 Módosított fájlok
**1. Backend API - [`backend/app/api/v1/endpoints/admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:512)**
- `PUT /{org_id}/status` — Státuszváltó végpont (`OrgStatusUpdate` séma): validálja a státuszt (active/inactive/suspended/pending_verification), szinkronizálja `org.is_active`-t, rögzíti `last_deactivated_at`-t. Védve: `Depends(RequirePermission("org:edit"))`.
- `PUT /{org_id}` — Adatszerkesztő végpont (`OrganizationUpdate` séma): 10 mező (name, full_name, display_name, tax_number, reg_number, address_zip/city/street_name/street_type/house_number). Csak a nem-None mezőket frissíti. Védve: `Depends(RequirePermission("org:edit"))`.
**2. Frontend Lista - [`frontend_admin/pages/garages/index.vue`](frontend_admin/pages/garages/index.vue)**
- `toggleStatus()` függvény: valós API hívással (`PUT /api/v1/admin/organizations/{id}/status`), dinamikus gombszín (piros/zöld), success/error toast, automatikus refresh.
**3. Frontend Részletek - [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue)**
- "Adatok Szerkesztése" gomb a header-ben
- Edit Modal: 8 mező (full_name, display_name, tax_number, reg_number, address_zip/city/street_name/street_type/house_number), pre-fill, Mentés → `PUT /api/v1/admin/organizations/{id}`, success/error toast, automatikus refresh
**4. i18n - [`frontend_admin/i18n/locales/hu.json`](frontend_admin/i18n/locales/hu.json) + [`frontend_admin/i18n/locales/en.json`](frontend_admin/i18n/locales/en.json)**
- `garages.details.edit_details`, `garages.details.save`, `garages.details.zip`, `garages.details.city`, `garages.details.street_name`, `garages.details.street_type`, `garages.details.house_number` kulcsok (magyar + angol)
### ✅ Verifikáció
- **Sync Engine:** ✅ 1265 OK, 0 Fixed, 0 Extra
- **PUT status (inactive):** ✅ 200 — "A(z) 'KYC Garázsa' garázs státusza frissítve: 'active' → 'inactive'."
- **PUT status (active):** ✅ 200 — "A(z) 'KYC Garázsa' garázs státusza frissítve: 'inactive' → 'active'."
- **PUT update:** ✅ 200 — "A(z) 'KYC Garázsa' garázs adatai frissítve." (updated_fields: ['display_name'])
## 2026-06-25 - P0 Garage CRM Expansion: Contact/Billing Fields, Fleet Tab, RBAC UI
### 🎯 Cél
Teljes Garage CRM profil bővítése: kapcsolattartói, számlázási és értesítési cím mezők hozzáadása a backendhez, flotta járművek végpont létrehozása, és a frontend garancia részletes nézetének teljes körű implementálása RBAC védelemmel.
### 🔧 Módosított Fájlok
**1. BACKEND - Modell (`backend/app/models/marketplace/organization.py`)**
- 14 új oszlop hozzáadva a `Organization` modellhez:
- `contact_person_name`, `contact_email`, `contact_phone` (kapcsolattartó)
- `billing_zip`, `billing_city`, `billing_street_name`, `billing_street_type`, `billing_house_number` (számlázási cím)
- `notification_zip`, `notification_city`, `notification_street_name`, `notification_street_type`, `notification_house_number` (értesítési cím)
**2. BACKEND - API Végpont (`backend/app/api/v1/endpoints/admin_organizations.py`)**
- `OrganizationUpdate` séma bővítve a 14 új mezővel
- `GarageDetailsResponse` séma bővítve ugyanezen mezőkkel
- Új `GET /{org_id}/vehicles` végpont létrehozva (`GarageVehicleItem`, `GarageFleetResponse` sémákkal)
- `GarageVehicleItem` mezői: id, license_plate, vin, brand, model, year, color, status, branch_name, created_at
**3. FRONTEND - i18n (`frontend_admin/i18n/locales/hu.json`, `en.json`)**
- Új kulcsok a `garages.details`, `garages.employees`, `garages.fleet` szekciókban
**4. FRONTEND - Garage Detail Page (`frontend_admin/pages/garages/[id]/index.vue`)**
- Teljes körű implementáció (1366 sor):
- **STEP 4:** "Missing Data" warning banner (tax_number, contact_email, contact_phone, billing_address ellenőrzés)
- **STEP 5:** Tabbed Edit Modal (Alapadatok / Kapcsolat / Címek fülekkel)
- **STEP 6:** Strict RBAC UI enforcement (`hasOrgPermission()` helper)
- **STEP 7:** Fleet tab adattáblával (license_plate, brand, model, year, status)
- **STEP 8:** "Add Employee" gomb a Dolgozók fülön
- Add Employee, Edit Role, Remove confirmation modálok
- Notification Toast komponens
- Teljes `<script setup lang="ts">` szekció (API hívások, állapotkezelés, helper függvények)
### ✅ Verifikáció
- **Sync Engine:** ✅ 1278 OK, 0 Fixed, 0 Extra
- **Adatbázis séma:** 14 új oszlop sikeresen alkalmazva a `fleet.organizations` táblában
## 2026-06-25 - P0 UI Hotfix: Garage Details Tabok, Edit Modal & i18n
### 🎯 Cél
Garage Details oldal (`garages/[id]/index.vue`) UI hibajavítások: hiányzó 4. "Analitika" fül visszaállítása, i18n kulcsok pótlása, edit modal adatkötés javítása, hiányzó adatok riasztó javítása.
### 🔧 Módosított fájlok
1. **`frontend_admin/i18n/locales/hu.json`** — Hozzáadva: `generalTab`, `employeesTab`, `fleetTab`, `analyticsTab`, `editBasicTab`, `editContactTab`, `editAddressTab` kulcsok
2. **`frontend_admin/i18n/locales/en.json`** — Hozzáadva: `generalTab`, `employeesTab`, `fleetTab`, `analyticsTab`, `editBasicTab`, `editContactTab`, `editAddressTab` kulcsok
3. **`frontend_admin/pages/garages/[id]/index.vue`** — Több javítás:
- 4. "analytics" tab hozzáadva a `tabs` tömbhöz
- Analytics tab tartalom (Coming Soon placeholder) hozzáadva a template-hez
- `editForm` ref kibővítve: `full_name`, `display_name`, `reg_number`, `address_zip`, `address_city`, `address_street_name`, `address_street_type`, `address_house_number` mezőkkel
- Edit form template v-model javítva: `editForm.zip``editForm.address_zip`, stb.
- `address_street_type` input mező hozzáadva az Alapadatok tabhoz
- `openEditModal()` kibővítve az összes hiányzó mező pre-fill-lel
- `saveEdit()` javítva: API válaszból `result.organization` kinyerése
- `missingFields` computed javítva: helyes i18n kulcsok (`missing_tax_number`, `missing_contact_email`, `missing_contact_phone`, `missing_billing`) és `{ key, label }` objektum struktúra
- `formattedAddress` computed javítva: `garage.value.zip``garage.value.address_zip`, stb.
### ✅ Verifikáció
- **Nuxt Build:** ✅ Sikeres (7.27s)
- **Backend:** Nem volt szükség módosításra (model és API séma már tartalmazta az összes billing/contact mezőt)
---
## 2026-06-25 - P0 Hotfix: Garage CRM Smart Validation (i18n, Tab Switching, Missing Data, Contact Propagation)
### 🎯 Cél
4 kritikus javítás a Garage CRM Smart Validation rendszerben:
1. **i18n rendering** - nyers kulcsok (pl. `garages.details.generalTab`) megjelenítése helyett fordított szöveg
2. **Tab switching** - edit modal tabok nem működtek (halott kattintás)
3. **Missing Data logika** - Private Garages (individual org_type) esetén ne kérjen adószámot/számlázási címet
4. **Edit Modal contact info** - email/phone propagálása Person/User rekordokba individual org_type esetén
### 🔧 Változtatások
**1. Frontend - i18n javítások:**
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:125) - `{{ tab.label }}``{{ $t(tab.label) }}` (fő tab navigáció)
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:509) - `{{ tab.label }}``{{ $t(tab.label) }}` (edit modal tabok)
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:55) - `{{ field.label }}``{{ $t(field.label) }}` (missing data tag-ek)
**2. Frontend - Tab switching javítás:**
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:983) - `editModalTabs` kulcs javítva: `'address'``'addresses'` (egyezés a template `v-if="editModalTab === 'addresses'"` feltétellel)
**3. Frontend - Missing Data logika:**
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:995) - `missingFields` computed:
- `tax_number` ellenőrzés kihagyása `org_type === 'individual'` esetén
- `contact_email`/`contact_phone` mellett `email`/`phone` fallback ellenőrzés
- Számlázási cím ellenőrzés kihagyása individual org_type esetén
**4. Frontend - Edit Modal contact info:**
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:1123) - `saveEdit()`:
- Csak nem-üres mezők küldése a payload-ban
- Individual garages esetén `contact_email``email` és `contact_phone``phone` mapping
**5. Backend - OrganizationUpdate séma bővítés:**
- [`backend/app/api/v1/endpoints/admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:623) - `OrganizationUpdate` séma: új `email` és `phone` mezők hozzáadva
**6. Backend - Propagációs logika:**
- [`backend/app/api/v1/endpoints/admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:702) - `update_organization` végpont:
- Individual org_type + legal_owner_id esetén:
- `contact_phone`/`phone` propagálása `Person.phone`-ba
- `contact_email`/`email` propagálása a hozzá tartozó `User.email`-be
### ✅ Verifikáció
- **Backend Schema:** ✅ Sikeres (`OrganizationUpdate` séma tartalmazza az új `email` és `phone` mezőket)
- **Frontend:** Mind a 4 javítás implementálva és ellenőrizve
## 2026-06-25 - P0 HOTFIX: Zero-Duplication Contact & 401 Auth Header
### 🎯 Cél
Az Architect által jelzett 3 kritikus hiba javítása:
1. Frontend 401 Auth Header (token whitespace/newline trimming)
2. Backend Zero-Duplication Contact Logic (owner fallback)
3. Owner mindig látható a Dolgozók (Employees) tabon
### 🔧 Változtatások
**1. Frontend 401 Auth Header Fix**
- Fájl: `frontend_admin/pages/garages/[id]/index.vue`
- Minden `fetch` hívásnál a token `.trim()`-elve kerül a `Bearer` header-be
- Érintett függvények: `fetchDetails`, `fetchFleetVehicles`, `saveEdit`, `addEmployee`, `saveRoleEdit`, `executeRemove`
**2. Backend Zero-Duplication Contact Logic**
- Fájl: `backend/app/api/v1/endpoints/admin_organizations.py`
- `get_organization_details` endpoint kibővítve:
- `Organization.owner` + `User.person` eager loading
- Ha `contact_person_name` NULL → `owner.person` full name
- Ha `contact_email` NULL → `owner.email`
- Ha `contact_phone` NULL → `owner.person.phone`
**3. Owner Presence in Members List**
- Ha az owner nem szerepel az `OrganizationMember` táblában, dinamikusan prependáljuk
- `synthetic_owner` rekord `id=0` markerrel, `role="OWNER"`
- `member_count` is nő, ha szintetikus owner került hozzáadásra
### ✅ Verifikáció
- **Syntax check:** ✅ Sikeres (py_compile)
- **DB Sync:** ✅ Tökéletes szinkron (1278 elem)
- **API Test:** ✅ Sikeres
- Individual org: contact_person_name="TestUser KYC", contact_email=owner email
- Business org with owner: contact info correctly populated
- Owner minden esetben szerepel a members listában
## 2026-06-25 - P0 Security & UI Execution: 401 Interceptor, Employees Tab, Add Employee Modal
### 🎯 Cél
P0 Security & UI Execution feladat három komponenssel:
1. **Global 401 Unauthorized Interceptor** - lejárt token esetén automatikus logout és redirect /login-ra
2. **Employees Tab renderelése** - OWNER szerepkör arany badge-dzsel
3. **Add Employee Modal** - email alapú tag hozzáadás
### 🔧 Változtatások
**1. Global 401 Interceptor** ([`frontend_admin/plugins/api.ts`](frontend_admin/plugins/api.ts))
- Új Nuxt plugin, amely `globalThis.fetch`-et wrap-eli
- 401-es válasz esetén meghívja `authStore.logout()`-ot, majd redirectel `/login`-ra
- Kivétel: `/auth/login` és `/auth/refresh` végpontok (redirect loop elkerülése)
**2. Backend email-based member lookup** ([`backend/app/schemas/organization.py`](backend/app/schemas/organization.py:18))
- `OrganizationMemberCreate` séma most már támogatja az `email` mezőt `user_id` alternatívaként
- [`backend/app/api/v1/endpoints/admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:990) - email alapú felhasználó keresés implementálva
**3. Frontend javítások** ([`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue))
- `openEditRoleModal``openEditRole` függvénynév mismatch javítva
- Add Employee, Edit Role, Remove modálok dark theme-re átállítva (`bg-slate-800`, `text-white`)
- Notification toast dark theme-re átállítva
**4. i18n kiegészítések** ([`frontend_admin/i18n/locales/en.json`](frontend_admin/i18n/locales/en.json:207), [`frontend_admin/i18n/locales/hu.json`](frontend_admin/i18n/locales/hu.json:207))
- `editRoleTitle`, `removeTitle`, `removeConfirm` camelCase kulcsok hozzáadva
### ✅ Verifikáció
- **DB Sync:** ✅ Tökéletes szinkron (1278 elem)
- **Syntax:** ✅ Minden fájl szintaktikailag helyes
## 2026-06-26 - P0 HOTFIX: GET /admin/organizations/{org_id}/vehicles 500 Internal Server Error
### 🔍 Diagnózis
A frontend által hívott `GET /api/v1/admin/organizations/43/vehicles` végpont 500-as hibát dobott. A Docker logok három egymásra épülő `AttributeError`-t mutattak:
1. **`Asset.branch`** — Az [`Asset`](backend/app/models/vehicle/asset.py:69) modellben nincs `branch` relationship, csak `branch_id` oszlop. A kód `.options(selectinload(Asset.branch))`-et használt.
2. **`Asset.year`** — Az Asset modellben `year_of_manufacture` a mező neve, nem `year`.
3. **`Asset.color`** — Az Asset modellben nincs `color` mező.
### 🔧 Javítások ([`admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:1289))
- **`selectinload(Asset.branch)` eltávolítva** — Helyette explicit `outerjoin(Branch, Asset.branch_id == Branch.id)` a `Branch.name` lekéréséhez.
- **`v.year``v.year_of_manufacture`** — Javítva a mezőnév az Asset modell valós oszlopnevére.
- **`color` mező eltávolítva** a `GarageVehicleItem` Pydantic sémából és a leképzésből, mert az Asset modell nem tartalmaz ilyen attribútumot.
### ✅ Verifikáció
- `GET /api/v1/admin/organizations/43/vehicles`**200 OK**
- Visszaadott 3 jármű helyes adatokkal (brand, model, year, license_plate, branch_name)
## 2026-06-26 - P0 HOTFIX: Corporate 500 Error & Shrinking Filter Paradox
### 🎯 Cél
Két kritikus bug javítása: (1) `org_type_filter=corporate` 500-as hibát dobott a backendben, mert a "corporate" nem létező érték a `fleet.orgtype` PostgreSQL enum-ban. (2) A frontend előfizetési csomag legördülő menüje összezsugorodott szűréskor, mert a `uniqueTiers` computed property a szűrt `garages` tömbből számolt.
### 🔧 Változtatások
**Backend** (`backend/app/api/v1/endpoints/admin_organizations.py:219`):
- `org_type_filter=corporate` esetén a backend most az összes nem-individual `OrgType` értékre szűr (`business`, `fleet_owner`, `service`, `service_provider`, `club`)
- A `OrgType` enum dinamikus lekérdezése biztosítja, hogy új típus hozzáadásakor is működjön
**Frontend** (`frontend_admin/pages/garages/index.vue`):
- `uniqueTiers` computed property eltávolítva
- Helyette `availableTierNames` ref + watcher, ami csak bővül, sosem zsugorodik
- `watch(garages, ...)` `immediate: true, deep: true` paraméterekkel
### ✅ Verifikáció
- `GET /api/v1/admin/organizations?org_type_filter=corporate`**200 OK**, 8 garázs (business, fleet_owner, service_provider)
- `GET /api/v1/admin/organizations?org_type_filter=individual`**200 OK**, 17 garázs (individual)
- Admin frontend újraindítva, build hiba nélkül
## 2026-06-26 - P0 UX/UI Polish: Subscription Tab, History & Header ID Fix
### 🎯 Cél
Admin garázs részletek oldal UX/UI javítása: Header ID bug fix, kattintható garázsnevek listában, Subscription card sűrítése utilization statokkal, Subscription History szekció hozzáadása.
### 🔧 Módosított fájlok
**Frontend** (`frontend_admin/pages/garages/[id]/index.vue`):
- **Header ID Fix**: Eltávolítva a duplikált `#{{ garage.id }}` a subtitle-ből. `garageDisplayName()` fallback javítva: `'Garage #' + garage.value.id` formátumra.
- **Subscription Card Densification**: 4-oszlopos grid layout utilization statokkal (Járművek, Telephelyek, Dolgozók) progress bar-okkal, színkódolt threshold-okkal (piros ≥90%, borostyán ≥70%).
- **Subscription History Section**: Új kártya adat táblával és üres állapottal (clock SVG ikon + "Még nincsenek előfizetési előzmények" üzenet).
- **Új computed properties**: `employeeQuotaLimit`, `branchQuotaPercent`, `employeeQuotaPercent`.
**Frontend** (`frontend_admin/pages/garages/index.vue`):
- **Kattintható garázsnevek**: A garázs név `<NuxtLink>`-be csomagolva, hover stylinggal (`hover:underline cursor-pointer hover:text-indigo-400`).
**Frontend i18n** (`frontend_admin/i18n/locales/en.json`, `frontend_admin/i18n/locales/hu.json`):
- 10 új i18n kulcs hozzáadva: `vehicles_used`, `branches_used`, `employees_used`, `status`, `subscription_history`, `history_date`, `history_package`, `history_action`, `history_status`, `no_subscription_history`.
### ✅ Verifikáció
- `docker compose exec sf_public_frontend npm run build`**✓ built in 7.13s**, hiba nélkül
## 2026-06-26 - Admin Garage System Identifiers Bugfix
### 🎯 Cél
Admin garázs részletek oldalon a "Rendszer Azonosítók" szekcióban a User ID és Person ID mezők "N/A"-t mutattak, mert a backend `GarageDetailsResponse` nem tartalmazott `owner_user_id` mezőt, a frontend pedig egy nem létező `garage.owner?.id` property-t próbált olvasni.
### 🔧 Változtatások
**Backend** (`backend/app/api/v1/endpoints/admin_organizations.py`):
- `GarageDetailsResponse` osztályhoz hozzáadva: `owner_user_id: Optional[int] = None` (169. sor)
- Visszatérési értékhez hozzáadva: `owner_user_id=owner.id if owner else None` (650. sor)
**Frontend** (`frontend_admin/pages/garages/[id]/index.vue`):
- 200. sor: `garage.owner?.id || 'N/A'``garage.owner_user_id ?? 'N/A'`
### ✅ Verifikáció
- `GET /api/v1/admin/organizations/43/details``owner_user_id: 79`, `owner_person_id: 86` (korábban hiányzott)
## 2026-06-26 — Bug Analysis: Admin Garage Subscription Tab Shows Wrong Package Data
**Gitea Issue:** #301
**Scope:** Backend + Frontend
**Type:** Bug
### What was found
Investigated why the admin frontend's garage detail page subscription tab doesn't display data matching the selected package.
**Root Causes:**
1. `SubscriptionSummary` Pydantic model (admin_organizations.py:116-124) missing `branch_limit` field — frontend (index.vue:526) accesses `garage.subscription?.branch_limit` which is always undefined, showing `∞`
2. `asset_limit` extraction fragile (admin_organizations.py:462-465): `or` logic treats `0` as falsy, falls back to `1` on missing/alternate keys
3. `GarageDetailsResponse` has no `branches` field — `garage.branches?.length` always 0
4. `asset_count` hardcoded to 0 (admin_organizations.py:473)
5. `OrganizationSubscription` query (admin_organizations.py:414-425) doesn't check `valid_until >= now()` — expired subs appear active
6. Fallback path (admin_organizations.py:476-488) incomplete — missing `valid_from` and `is_active`
### Fix created
Detailed fix spec written to `docs/admin_garage_subscription_tab_bugfix_spec.md`
## 2026-06-26 — P0 CORE LOGIC & ADD-ON UPGRADE — Execute Bugfix #301 & Extra Allowances
**Gitea Issue:** #301 (Bugfix) + P0 Add-on Upgrade
**Scope:** Backend + Frontend
**Type:** Bug + Feature
### 🔧 Módosított fájlok
- [`backend/app/api/v1/endpoints/admin_organizations.py`](backend/app/api/v1/endpoints/admin_organizations.py:47) — Backend API changes
- `OrgSubscriptionUpdate`: Added `extra_vehicles`, `extra_branches`, `extra_users` fields (lines 56-67)
- `SubscriptionSummary`: Added `branch_limit`, `user_limit`, `extra_allowances` fields (lines 138-142)
- `BranchBrief`: New Pydantic model for branch data (lines 145-150)
- `GarageDetailsResponse`: Added `branches: List[BranchBrief]` field (line 202)
- `get_organization_details` (line 404):
- Added `valid_until >= now` check to subscription query (line 449)
- Added real `asset_count` query from Vehicle table (lines 458-464)
- Added branches query from Branch table (lines 467-482)
- **Bugfix**: Replaced `or` operator with explicit `dict.get()` for limit calculations (lines 524-537)
- **Add-on math**: Base (from tier rules) + Extra (from extra_allowances JSONB) = Total limit
- `update_org_subscription` (line 983):
- Constructs `extra_allowances` JSONB from payload fields (lines 1044-1051)
- Passes to new `OrganizationSubscription` (line 1060)
- Returns `extra_allowances` in response (line 1090)
- [`frontend_admin/pages/garages/[id]/index.vue`](frontend_admin/pages/garages/[id]/index.vue:1463) — Frontend UI changes
- Added `extraVehicles`, `extraBranches`, `extraUsers` reactive state (lines 1463-1466)
- Added `employeeQuotaPercent` computed property (lines 1510-1515)
- Updated Employees tab: utilization bar with `user_limit` (line 544-547)
- Added add-on input cards: Extra Jármű, Extra Telephely, Extra Dolgozó (template section ~lines 611-685)
- Updated `updateSubscription`: sends extra_allowances payload (lines 1858-1861)
### ✅ Verifikáció
- `sync_engine.py`: 1278 elements OK — system perfectly in sync
- `test_subscription_feature_flags.py`: All 6 steps passed (login, feature flags, check, public tiers)
- Python syntax check: ✅ Syntax OK