Files
service-finder/.roo/history.md
Roo f2935cbd64 P0 HOTFIX: Subscription asset_limit calculation fix
Root cause: Old code used rules.get('max_vehicles') which only searched
JSONB root level. Corporate tiers store limits under rules['allowances'].

Changes:
1. Added _extract_limit() helper (3-level search: direct → allowances → limits)
2. Replaced single-sub .limit(1) with multi-sub .all() for true aggregation
3. Fixed fallback path to use _extract_limit() instead of rules.get()
4. Added clamping: asset_limit = max(asset_limit, 1) right before
   SubscriptionSummary creation on BOTH code paths
5. Added 'type' column to SubscriptionTier model (base vs addon)
2026-06-28 12:09:56 +00:00

63 KiB
Raw Blame History

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.pydeep_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.pyRegionConfig 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__.pyRegionConfig import hozzáadva
  • backend/app/api/v1/endpoints/regions.pyLÉTREHOZVA: GET /system/regions publikus végpont
  • backend/app/api/v1/api.py — regions router regisztrálva /system prefix-szel
  • backend/scripts/seed_regions.pyLÉTREHOZVA: 3 régió seedelése (HU, GB, DEFAULT)
  • backend/app/api/v1/endpoints/auth.pyPATCH /auth/me/language végpont hozzáadva nyelvi preferencia perzisztáláshoz
  • frontend_admin/stores/region.tsLÉTREHOZVA: Pinia store régiók lekérésére, aktív régió getterekkel (currency, locale, VAT, timezone)
  • frontend_admin/composables/useFormatter.tsLÉ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.vueuserEmail 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.pyservice_provider_id hozzáadva AssetCost-hoz + FK javítás (relációk indentálása)
  • backend/app/models/marketplace/service.pyservice_provider_id hozzáadva ServiceProfile-hoz
  • backend/app/models/identity/social.pyServiceProvider 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.pyquick_add_provider() átírva: ServiceProvider + ServiceProfile létrehozása (NO Organization, NO Branch, NO OrganizationMember)
  • backend/app/schemas/asset_cost.pyservice_provider_id hozzáadva a Pydantic modellekhez
  • backend/app/schemas/provider.pyProviderQuickAddIn kiegészítve új mezőkkel
  • backend/app/api/v1/endpoints/expenses.pyservice_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

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.pyGET /{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 — 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

🔗 Navigáció

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.pysystem_capabilities mindig üres, legacy mátrix eltávolítva, DB lekérdezés nem implementálva
  • backend/app/api/deps.pyRequirePermission() 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

  • 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

  • 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

  • "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/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:
      1. "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.zipeditForm.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.zipgarage.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:

2. Frontend - Tab switching javítás:

3. Frontend - Missing Data logika:

  • frontend_admin/pages/garages/[id]/index.vue - 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:

5. Backend - OrganizationUpdate séma bővítés:

6. Backend - Propagációs logika:

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)

  • Ú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)

3. Frontend javítások (frontend_admin/pages/garages/[id]/index.vue)

  • openEditRoleModalopenEditRole 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/hu.json)

  • 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 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)

  • selectinload(Asset.branch) eltávolítva — Helyette explicit outerjoin(Branch, Asset.branch_id == Branch.id) a Branch.name lekéréséhez.
  • v.yearv.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/vehicles200 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=corporate200 OK, 8 garázs (business, fleet_owner, service_provider)
  • GET /api/v1/admin/organizations?org_type_filter=individual200 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):

    1. sor: garage.owner?.id || 'N/A'garage.owner_user_id ?? 'N/A'

Verifikáció

  • GET /api/v1/admin/organizations/43/detailsowner_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 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 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

2026-06-27 - P0 CORE ARCHITECTURE: Multi-Subscription Aggregation (Base + Add-ons)

🎯 Cél

"1 Base Tier + N Add-on Tiers" modell implementálása. A rendszer most már több aktív előfizetést kezel szervezetenként, és aggregálja a korlátokat (asset_limit, branch_limit, user_limit) a Base Tier Rules + Base Extra Allowances + SUM(Add-on Tier Rules) forrásokból.

🔧 Módosított fájlok

1. backend/app/models/core_logic.pySubscriptionTier.type oszlop hozzáadása

  • Új type: Mapped[Optional[str]] mező (String(20), nullable, default NULL)
  • 'base' = core tier, 'addon' = add-on tier, NULL = backward compat (base)

2. backend/app/api/v1/endpoints/admin_organizations.py — Multi-subscription aggregation

  • SubscriptionSummary.active_addons: List[str] mező hozzáadása
  • get_organization_details: .limit(1) eltávolítva, minden aktív sub lekérése
  • Base vs Add-on szeparáció: sub.tier.type és rules.get("type") alapján
  • Aggregált limit számítás: asset_limit = base_vehicles + extra_vehicles + addon_vehicles
  • max(asset_limit, 1) fallback csak a végösszegre alkalmazva
  • list_organizations: bulk query-ben is base/addon szeparáció

Verifikáció

  • Sync Engine: 1279 OK, 0 Fixed, 0 Extra
  • Python syntax: Mindkét fájl hibátlanul compile-ol
  • Subscription feature flags test: ALL TESTS COMPLETED

2026-06-27 - P0 HOTFIX: Subscription PATCH 422 Error & Add-on Only Update

🎯 Cél

Két bug javítása a Subscription PATCH flow-ban:

  1. Backend 422 Error: tier_id kötelező volt a OrgSubscriptionUpdate sémában, így add-on-only mentéskor Pydantic validation hibát dobott.
  2. Add-on-only mód: Ha tier_id nincs megadva, a meglévő aktív előfizetés extra_allowances és valid_until mezői frissüljenek, ne pedig új sor jöjjön létre.

🔧 Módosított fájlok

  • backend/app/api/v1/endpoints/admin_organizations.py
    • Schema (47-68. sor): tier_id: int = Field(...)tier_id: Optional[int] = Field(default=None, ...)
    • Endpoint (1067-1240. sor): Két üzemmódra bontás:
      • A) tier_id megadva: Teljes csomagváltás (meglévő logika)
      • B) tier_id = None: Aktív előfizetés extra_allowances és valid_until frissítése sa_update-dal
  • frontend_admin/pages/garages/[id]/index.vue — Nem volt szükség módosításra, a frontend payload konstrukciója már helyes volt.

Verifikáció

  • Python syntax: Sikeres compile
  • Sync Engine: 1279 OK, 0 Fixed, 0 Extra — teljes szinkronban

2026-06-27 13:16 UTC — P0 HOTFIX: 422 Tier ID & Missing Expiration Payload

Gitea Card: #302

Problem: PATCH /admin/organizations/{org_id}/subscription returned 422 when tier_id was omitted (add-on-only update). Frontend omitted expires_at when no base tier selected.

Root Cause (BACKEND): OrgSubscriptionUpdate.tier_id was int = Field(...) (required). Changed to Optional[int] = Field(default=None). Endpoint split into Mode A (tier_id present → full switch) and Mode B (tier_id=None → add-on/expiry update).

Root Cause (FRONTEND): Button disabled on !selectedTierId only. Payload construction didn't handle tierless updates. Fixed: linear payload, addonsChanged computed, always send extra_allowances.

CRITICAL Deployment Fix: Code changes were on disk but containers were NOT restarted:

  • sf_api (23h uptime, uvicorn without --reload)
  • sf_admin_frontend (24h uptime) Both restarted at 13:13 UTC to apply fixes.

Verification: All 4 Pydantic schema validation tests PASS.

2026-06-27 - P0 Hotfix: 500 Internal Server Error on GET /admin/organizations/{id}/details

🎯 Cél

A garázs részletek betöltésekor (GET /api/v1/admin/organizations/43/details) 500-as hiba jelentkezett. A korábbi hotfix (422 Tier ID fix) során hozzáadott lazy importok hibás elérési útvonalakat tartalmaztak.

🔧 Javítások (admin_organizations.py)

  1. Line 490: from app.models.fleet.vehicle import Vehiclefrom app.models import Vehicle (Asset class a app.models.vehicle.asset-ben, Vehicle néven exportálva a app.models-ből)
  2. Line 492: Vehicle.organization_idVehicle.current_organization_id (Asset modellben nincs organization_id, helyette current_organization_id)
  3. Line 493: Vehicle.is_deleted == False törölve (Asset modellben nincs is_deleted mező)
  4. Line 499: from app.models.fleet.organization import Branchfrom app.models.marketplace.organization import Branch (Branch a marketplace sémában van)
  5. Line 155 (BranchBrief.id): intstr (Branch elsődleges kulcsa UUID, nem integer)
  6. Line 507: b.idstr(b.id) (UUID konvertálása stringgé)
  7. Line 510: b.is_activenot b.is_deleted (Branch modellben nincs is_active, helyette is_deleted boolean)

Verifikáció

  • GET /api/v1/admin/organizations/43/details200 OK (34 mezővel, köztük branches, members, subscription)
  • Minden import sikeresen betöltődik

2026-06-27 - P0 JSONB NESTING HOTFIX: Allowances Object & i18n Keys

🎯 Cél

Fix the _extract_limit helper to also search inside a nested "allowances" dict within the tier rules JSONB, and add missing i18n keys for the add-on input sub-labels.

🔧 Változtatások

1. Backend — Nested JSONB lookup

  • Fájl: backend/app/api/v1/endpoints/admin_organizations.py (line 601)
  • Módosítás: _extract_limit() helper now checks rules.get("allowances", {}) after checking root-level keys.
  • Hatás: Tier limits stored as {"allowances": {"max_vehicles": 20}} are now correctly extracted.

2. Frontend — Missing i18n keys

  • Fájlok: frontend_admin/i18n/locales/en.json, frontend_admin/i18n/locales/hu.json
  • Hozzáadva: garages.details.branches ("branches"/"telephely") és garages.details.employees ("employees"/"dolgozó")
  • Hatás: A +db {{ $t('garages.details.branches') }} és +db {{ $t('garages.details.employees') }} feliratok már nem jelennek meg nyers kulcsként.

Verifikáció

  • Python syntax check: OK
  • Sync engine: 1279 OK, 0 Fixed, 0 Shadow — teljes szinkronban

2026-06-27 - P0 ARCHITECTURE UNIFICATION: Eradicate Path A & Fix Limit(1)

🎯 Cél

A backend admin_organizations.py fájlban két külön kódút (Path A és Path B) számolta a subscription limiteket. Path A (a get_organization_details végpontban) még a régi rules.get("max_vehicles") logikát használta ahelyett, hogy az _extract_limit() helpert hívta volna, ami a JSONB allowances nested objektumba is belenéz. Emellett a subscription query .limit(1)-et használt, ami megtörte a multi-subscription (Base + Add-on) aggregációt.

🔧 Módosított fájlok

  • backend/app/api/v1/endpoints/admin_organizations.py — Három kritikus változtatás:

1. _extract_limit() helper létrehozása (lines 397-447)

  • Új, robusztus függvény a limit értékek kinyerésére a SubscriptionTier.rules JSONB-ból.
  • Három szinten keres: (1) közvetlenül a rules objektumban, (2) rules["allowances"] nested objektumban, (3) rules["limits"] nested objektumban.
  • Több kulcsot is támogat (pl. ["max_vehicles", "max_assets"]), az első találatot adja vissza.

2. .limit(1) eltávolítása a subscription query-ből (lines 499-514)

  • A subscription lekérdezés most .scalars().all()-t használ .limit(1) helyett.
  • Minden aktív subscription sort visszaad (1 Base + N Add-on).

3. Path A és Path B egyesítése (lines 574-691)

  • A régi Path A (if active_sub and active_sub.tier:) és Path B (elif org.subscription_tier:) logika helyett egységes, _extract_limit()-t használó kód.
  • Base subscription-ok és Add-on subscription-ok szétválasztása a tier.type mező alapján.
  • Add-on tier-ek base limitjeinek aggregálása a primary subscription limitjeihez.
  • extra_allowances aggregálása az összes aktív subscription-ből.

Verifikáció

  • Python syntax check: OK (py_compile sikeres)
  • Sync engine: 1279 OK, 0 Fixed, 0 Shadow — teljes szinkronban
  • A SubscriptionSummary most helyesen kapja meg a Base limit értékeket az _extract_limit()-en keresztül, mielőtt az Extra allowances hozzáadódnak.