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 `