62 KiB
Service Finder Fejlesztési Történet
2026-06-14 - Admin Search Bugs Fix & Sticky UX
🎯 Cél
Backend SQL hibák javítása a GET /admin/users végponton (Address outerjoin, phone search), valamint frontend UX fejlesztések (sticky bulk action bar, clear/X gomb, üres állapot üzenet, HeaderProfile az AdminLayout-ban).
🔧 Változtatások
1. BACKEND - admin.py:
GET /admin/usersSQL javítás:Addressouterjoin-ra változtatva (isouter=True), hogy a cím nélküli userek is visszajöjjenek- Telefonszám keresés:
phonemező hozzáadva aor_()feltételhez
2. FRONTEND - AdminLayout.vue:
HeaderProfilekomponens beillesztve a jobb felső sarokba (belépett user avatar + név)- A
SidebarTogglegomb fixálva a sidebar szélén
3. FRONTEND - AdminUsersView.vue:
- Sticky Bulk Action Bar: A tömeges műveletek sáv (
BulkActionBar)stickypozícionálást kapott, hogy görgetéskor is látszódjon - Clear/X gomb: A keresőmezőbe egy
Xgomb került, ami egy kattintással törli a keresési feltételt
2026-06-17 - P0 UI Card Cleanup & Custom Tag 500 Fix
🎯 Cél
Három kritikus hiba javítása: (1) "Nincs kategória" fantom badge eltüntetése a provider kártyákról, (2) Telefon/Weboldal ikonok megjelenítése a kártyákon, (3) 500-as hiba javítása custom tag mentéskor.
🔧 Változtatások
1. FRONTEND - ServiceFinderView.vue:
- "Nincs kategória" javítás: A
v-if="provider.category"feltétel helyettv-if="provider.categories && provider.categories.length > 0"lett beállítva. Ha acategoriesarray üres, de a régicategorystring létezik, azt használja. Csak ha egyik sincs, akkor jelenik meg a "Nincs kategória" felirat. - Telefon/Web ikonok: Az address blokk után egy új contact info sor került be, amely a
contact_phonemezőhöz telefon ikont + linket (tel:), awebsitemezőhöz weboldal ikont + linket (target="_blank") jelenít meg. - TypeScript interface bővítés: A
ProviderSearchResultinterfész kibővítve a hiányzó mezőkkel:contact_phone,contact_email,website,tags,address_zip,address_street_name,address_street_type,address_house_number.
2. BACKEND - provider_service.py:
_slugify()függvény: Új segédfüggvény, amely biztonságos slug-ot generál magyar ékezetes karakterekből (á→a, é→e, í→i, ó→o, ö→o, ő→o, ú→u, ü→u, ű→u), majd nem-alfanumerikus karaktereket alulvonásra cserél._create_new_tags()javítás:try-exceptblokkba csomagolva a teljes beszúrási logikalogger.error(..., exc_info=True)hibanaplózás hozzáadvaparent_id=Noneéspath=Noneexplicit beállítva- A kulcs generálás most a
_slugify()függvényt használja - Egyetlen hibás címke nem szakítja meg a teljes folyamatot (
continue)
✅ Eredmény
- "Nincs kategória" fantom badge megszűnt: a feltétel most a
categoriestömböt ellenőrzi - Telefon és weboldal linkek megjelennek a kártyákon (ha vannak)
- Custom tag mentés 500 helyett try-except blokkban fut, hibanaplózással
- Python szintaxis ellenőrzés: OK
2026-06-17 - P0 UI Overhaul: Plus Code, Universal Categories, Detail Modal
🎯 Cél
Három területet fed le: (1) Plus Code integráció a backendben és adatbázisban, (2) Univerzális kategóriák megjelenítése a ProviderEditModal és QuickAdd modalokban, (3) ProviderDetailModal gazdag újraírása kategória chipekkel, kontakt grid-del és navigációs gombbal.
🔧 Változtatások
1. BACKEND - Plus Code mező:
Organizationmodel:plus_code: Mapped[Optional[str]] = mapped_column(String(20))ProviderSearchResult:plus_code: Optional[str] = NoneProviderQuickAddIn:plus_code: Optional[str] = Field(None, max_length=20)ProviderUpdateIn:plus_code: Optional[str] = Field(None, max_length=20)provider_service.py: plus_code hozzáadva a search SELECT-hez, quick_add Organization creation-höz, és update null-safety checkhezsync_enginesikeresen lefuttatva, aplus_codeoszlop létrejött
2. FRONTEND - Univerzális kategóriák:
ProviderEditModal.vue:allLevel1Categoriescomputed property, amely a checked Level 0 szülők Level 1 gyermekeit gyűjti össze deduplikálvaProviderQuickAddModal.vue: Ugyanaz aallLevel1Categorieslogika- Plus Code input mező hozzáadva mindkét modal "Alapadatok" tabjához
3. FRONTEND - Detail Modal Rework:
ProviderDetailModal.vue: Teljes újraírás- Kategória chipek (szintenként eltérő színnel: Level0=lila, Level1=kék, Level2=teal, Level3=szürke)
- Kontakt grid: Telefon (tel: link), Email (mailto: link), Weboldal (_blank, external icon)
- Helyszín szekció: cím + plus_code + "Navigáció" gomb (Google Maps URL)
- Hiányzó adatok esetén i18n fallback szövegek
4. i18n:
✅ Eredmény
- Backend Python import ellenőrzés: OK (provider.py, provider_service.py, providers.py endpoints)
- Frontend Vite build: OK (87 modules, 6.07s)
- Adatbázis sync_engine: OK (plus_code oszlop létrejött)
2026-06-17 - P0 Triage Fix: Data Persistence & UNION ALL Column Mismatch
🎯 Cél
Két kritikus hiba javítása a Provider Search/Update folyamatban:
- Data Persistence Black Hole: Organization ID 4859 (Shell Dunakeszi)
plus_codeéscontact_phonemezői nem perzisztáltak mentés után - UNION ALL 500 error:
CompoundSelect must have identical numbers of columnshiba a search végponton
🔧 Változtatások
1. BACKEND - provider_service.py:
plus_codehozzáadva aProviderSearchResultkonstruktorhoz (getattr(row, "plus_code", None)) - a mező SELECT-ben volt, de a Python objektumba nem került átplus_codeoszlop (literal(None).label("plus_code")) hozzáadva aUNION ALLmásodik (staging_stmt) és harmadik (crowd_stmt) ágához, hogy a 15 oszlopszám konzisztens legyen- P0 CRITICAL BUGFIX: Ha nincs
ServiceProfilerekord az Organization-höz, aupdate_providermost létrehozza azt (fingerprint + location + contact adatokkal), ahelyett hogy csak logolná a hiányt és eldobná a contact/category adatokat ServiceStatusimport hozzáadva a provider_service.py-hoz
2. FRONTEND - ProviderEditModal.vue:
allLevel1CategoriesszétbontvavehicleLevel1Categories-re (Level 0 checkboxoktól függő) ésuniversalLevel1Categories-re (mindig látható,categoryTree.value.filter(c => c.level === 1))- Új UI blokk "Iparágak és Univerzális Szolgáltatások" címmel, amber színű dashed border-rel
✅ Verifikáció
plus_code=8FVX+3W,contact_phone=+36 20 123 4567,contact_email=shell.dunakeszi@example.comsikeresen mentve és visszaolvasva ID 4859-hez- API
/api/v1/providers/searchhibátlanul fut (nincs 500-as UNION ALL hiba) - Adatbázis szinten ellenőrizve:
fleet.organizations.plus_codeésmarketplace.service_profiles.contact_phone/contact_emailhelyesen perzisztálva
2026-06-17 - P0 Ownership & Access Control Fix: OrganizationMember + owner_id
🎯 Cél
Két P0 kritikus hiba javítása a Provider Quick-Add és Update folyamatban:
- Ownerless Providers: A
quick_add_providerowner_id=None-t használt, így az újonnan létrehozott szolgáltatóknak nem volt tulajdonosa - Missing OrganizationMember: A 6-lépéses folyamat 5. lépésnél megállt - nem jött létre
OrganizationMemberrekord, így senki sem volt kapcsolatban a céggel - No Access Control: A
update_providervégpont bárki által hívható volt - nem ellenőrizte, hogy a hívó user jogosult-e szerkeszteni az adott szervezetet
🔧 Változtatások
1. BACKEND - provider_service.py:
owner_id=None→owner_id=user_id(531. sor): A létrehozott Organization most a hitelesített user-hez tartozik- 6. 👤 ORGANIZATION MEMBER LÉTREHOZÁSA (585-600. sor): Teljesen új blokk a gamifikáció előtt:
member = OrganizationMember( organization_id=org.id, user_id=user_id, role=OrgUserRole.OWNER, is_permanent=True, is_verified=True, ) db.add(member) await db.flush() - 🔐 ACCESS CONTROL ELLENŐRZÉS (841-863. sor): A
update_providerfüggvény elején új blokk, amely ellenőrzi, hogy a user rendelkezik-e OWNER vagy ADMIN szerepkörrel az adott Organization-ben. Ha nem,PermissionError-t dob.
2. BACKEND - providers.py:
PermissionError→HTTPException(403)kezelés hozzáadva aupdate_service_providervégponthoz
✅ Verifikáció
owner_id=2(admin user) sikeresen beállítva a létrehozott Organization-benOrganizationMember(user_id=2, role=OWNER)rekord sikeresen létrejött- Admin user sikeresen frissítheti a provider adatokat (200 OK)
- Érvénytelen token esetén 401 Unauthorized
- Docker konténer újraépítve:
docker compose up -d --build sf_api - Tesztadatok (org 59, 60, 61) tisztítva
2026-06-17 - P0 Critical Bugfix: Quick-Add Provider 422 category_id null
🎯 Cél
A POST /api/v1/providers/quick-add endpoint 422-es hibát dobott, amikor a frontend category_id: null-t küldött. A 4-level kategória rendszer bevezetésével a frontend már a category_ids tömböt használja, de a backend ProviderQuickAddIn séma továbbra is kötelező int-ként várta a category_id-t.
🔧 Változtatások
1. BACKEND - provider.py:
ProviderQuickAddIn.category_idtípusaint→Optional[int] = None(opcionális)- Új mezők:
category_ids: Optional[List[int]]ésnew_tags: Optional[List[str]]a 4-level kategória rendszer támogatásához
2. BACKEND - provider_service.py:
quick_add_provider()most már kezeli acategory_id=Noneesetet (kihagyja az elsődleges kategória lekérdezést)- A
category_idsésnew_tagsmezők feldolgozása: ServiceExpertise kapcsolatok létrehozása a 4-level kategória rendszerből - Deduplikáció: az összes kategória ID egyesítve, duplikátumok eltávolítva
3. FRONTEND - ProviderQuickAddModal.vue:
phone→contact_phoneésemail→contact_emailmezőnevek javítva (illeszkedés a backend Pydantic sémához)
✅ Teszt eredmény
- A pontosan reprodukált hiba (Bokebo Kft., category_id=null, category_ids=[149]) HTTP 201 választ ad
- Adatbázisban: Organization létrejött, ServiceProfile létrejött, ServiceExpertise kapcsolat a 149-es kategóriával létrejött
- Gamification: 500 pont jóváírva
2026-06-17: Bug investigation - Quick-add provider cégek megjelennek a Cégeim menüben
Kártya: #266 Szerepkör: Architect Állapot: Tervezés kész
Felfedezett hibák
-
GET /organizations/myendpoint (backend/app/api/v1/endpoints/organizations.py:183-186): Nincsorg_typeszűrés, minden szervezetet visszaad, ahol a user tag azOrganizationMembertáblában. -
HeaderCompanySwitcher.vue:142-146: AcompanyOrganizationscomputed property csak azindividualtípust szűri ki, aservice_providertípusú szervezeteket nem. -
quick_add_provider()(backend/app/services/provider_service.py:638-646): LétrehozOrganizationMember-etrole=OWNER-rel, ami miatt aGET /myvisszaadja a szolgáltatót.
Javítási terv
organizations.py:183-186:org_typeszűrés hozzáadása (csakbusiness,fleet_owner,individual)organizations.py:193-206:owner_idmező hozzáadása a response-hozHeaderCompanySwitcher.vue:142-146:service_providerésservicetípusok kiszűrése- Adatbázis audit: hiányzó
owner_id-k ellenőrzése a régi service_providereknél
Kapcsolódó fájlok
plans/logic_spec_provider_cegeim_bugfix.md- Részletes logic_spec
2026-06-17: Bugfix implementáció - Quick-add provider cégek a Cégeim menüben (#266)
Szerepkör: Code (Fast Coder) Állapot: Implementálva és tesztelve
Végrehajtott módosítások
-
backend/app/api/v1/endpoints/organizations.py:183-186—GET /myendpoint:- Hozzáadva
org_typeszűrés: csakbusiness,fleet_owner,individualtípusú szervezetek visszaadása owner_idmező hozzáadva a response dict-hez
- Hozzáadva
-
frontend/src/components/header/HeaderCompanySwitcher.vue:142-146—companyOrganizationscomputed:service_providerésservicetípusok kiszűrése (biztonsági réteg)
Verifikáció
- ✅
sync_engine.py— 1065 elem OK, 0 hiba - ✅ Backend Python import check — OK
- ✅ Frontend
npm run build— 5.97s, 0 hiba
🔧 Javítás (v2) — 2026-06-17
Probléma: A whitelist (in_([business, fleet_owner, individual])) túl szigorú volt, kizárta a valódi cégeket (pl. club típus).
Megoldás:
backend/app/api/v1/endpoints/organizations.py:193—in_([...])→notin_([OrgType.service_provider, OrgType.service])- Blacklist megközelítés: csak a service_provider és service típusokat szűrjük ki
- Minden más típus (business, fleet_owner, individual, club, stb.) megjelenik
Verifikáció
- ✅
sync_engine.py— 1065 elem OK, 0 hiba - ✅ Backend Python import check — OK
- ✅
notin_szintaxis ellenőrizve — OK
2026-06-17 - Garázsválasztó Bugfix: service_provider org-ok nem látszottak OWNER-nek sem
🎯 Cél
A saját tulajdonú cégek (service_provider org_type) megjelenítése a garázsválasztó gombban, ha a felhasználó OWNER joggal rendelkezik.
🔧 Változtatások
1. BACKEND - organizations.py:
- A
GET /myvégpont most márselect(Organization, OrganizationMember.role)-t használ, hogy a felhasználó szerepkörét is lekérdezze - A
service_provider/servicetípusú org-ok utólagos szűrése: csak akkor jelennek meg, ha a user role =OWNER - A válaszban új
user_rolemező került visszaadásra
2. FRONTEND - HeaderCompanySwitcher.vue:
- A
companyOrganizationscomputed property most már auser_rolemezőt is figyelembe veszi service_provider/servicetípus csakuser_role === 'OWNER'esetén jelenik meg
3. FRONTEND - organization.ts:
- Új
user_role?: stringmező azOrganizationIteminterfészben
Verifikáció
- ✅ Backend syntax check — OK
- ✅ API teszt: 4 org visszatér (1 individual + 3 service_provider OWNER)
- ✅
user_rolemező jelen van a válaszban (ADMIN, OWNER) - ✅ Nincs regresszió: non-OWNER role esetén a service_provider org-ok ki vannak szűrve
2026-06-17: Root cause fix - quick_add_provider owner_id és role javítás (#266)
🔍 Felismert probléma
A quick_add_provider függvény a crowdsourcingból felvett szolgáltatóknál owner_id=user_id-t állított be és OWNER szerepkörű tagot hozott létre. Ez hibás, mert:
- A közösségi jelöléssel felvett cégeknek NINCS tulajdonosa (
owner_id=NULL) - Aki felvesz egy céget a Service Finder-be, az NEM lesz a cég tulajdonosa
- Az
OWNERszerepkör miatt ezek a cégek megjelentek a "Cégeim" garázsválasztóban
🔧 Végrehajtott módosítások
1. BACKEND - provider_service.py:
owner_id=user_id→owner_id=None— crowdsourcingból felvett szolgáltatónak nincs tulajdonosa
2. BACKEND - provider_service.py:
role=OrgUserRole.OWNER→role=OrgUserRole.ADMIN— a felhasználó ADMIN jogot kap (szerkesztheti), de nem tulajdonos
✅ Verifikáció
- ✅ Sync engine: séma konzisztens (1065 elem OK)
- ✅ API teszt:
GET /api/v1/organizations/my→ 1 org (Test Company, individual) - ✅ service_provider org-ok (57, 58, 62) NEM jelennek meg a garázsválasztóban
- ✅ A meglévő adatok (owner_id=2, role=OWNER) a régi kóddal jöttek létre, az új kód már helyesen hozza létre az új provider-eket
2026-06-17 - P1 Garage Selector Implementation & OrganizationMember Audit
🎯 Cél
Dashboard "Garage Selector" (cégválasztó) pontosítása, hogy a bejelentkezett felhasználó azon Organization rekordokat lássa, ahol:
a) Technikai tulajdonos (owner_id) VAGY
b) Aktív tag (OrganizationMember)
Emellett az OrganizationMember tábla hiányzó oszlopainak pótlása és audit jelentés készítése.
🔧 Változtatások
1. BACKEND - organizations.py:
get_my_organizationsquery javítva:INNER JOIN→LEFT JOIN+ORfeltétel (owner_idVAGYOrganizationMember.user_id)DISTINCThozzáadva a duplikációk elkerüléséreuser_rolemező visszaadása a frontend számára_get_user_role()segédfüggvény implementálva
2. BACKEND - organization.py:
OrganizationMembermodellhez hozzáadva:status(String(20)),created_at,updated_atoszlopok- Ezek az oszlopok hiányoztak az adatbázisból, de a kód már hivatkozott rájuk
3. ADATBÁZIS - sync_engine:
- 3 hiányzó oszlop sikeresen hozzáadva a
fleet.organization_memberstáblához
4. DOKUMENTÁCIÓ - organization_member_audit_report_2026-06-17.md:
- Részletes audit jelentés az OrganizationMember tábláról
- Hiányzó API végpontok azonosítása (tagkezelés, meghívókezelés)
- Javasolt javítási sorrend
✅ Eredmény
GET /api/v1/organizations/myhelyesen adja vissza a tulajdonosi és tagsági viszonyokatuser_rolemező elérhető a frontend számára- Adatbázis séma konzisztens a kóddal
- Audit jelentés elkészítve a docs mappában
2026-06-17 - P0 Garage Selector Fix & Team Management API Implementation
🎯 Cél
A P0 Garage Selector hiba végleges javítása (a GET /organizations/my 500-as hibát dobott JSON oszlopok miatt) és a hiányzó Team Management API végpontok implementálása.
🔧 Változtatások
1. BACKEND - organization.py:
OrganizationMembermodellhez hozzáadva:invited_email(String(255)) ésexpires_at(DateTime(timezone=True)) oszlopokOrgUserRoleenum szinkronizálva az adatbázisban lévő értékekkel:OWNER, ADMIN, MANAGER, MEMBER, AGENTdefault=OrgUserRole.DRIVER→default=OrgUserRole.MEMBER
2. BACKEND - organizations.py:
GET /organizations/mySQL javítás: ADISTINCTa teljes Organization modellen JSON oszlopok miatt hibát dobott (could not identify an equality operator for type json)- Megoldás: Subquery approach: először csak az ID-kat szedjük DISTINCT-tel, majd a második query-ben
selectinload(Organization.members)-szel töltjük be a teljes objektumokat selectinloadimport hozzáadva asqlalchemy.orm-ból
3. BACKEND - organizations.py:
GET /{org_id}/members— Tagok listázása (user email + role + status)POST /{org_id}/invitations— Meghívó küldése (invited_email, expires_at=+7 nap)PATCH /{org_id}/members/{member_id}— Szerepkör módosítása (utolsó OWNER védelme)DELETE /{org_id}/members/{member_id}— Tag eltávolítása / meghívó visszavonása_check_org_admin_access()— Segédfüggvény: csak OWNER/ADMIN férhet hozzá- Pydantic modellek:
MemberResponse,MemberRoleUpdate,InvitationCreate - Régi duplikált
POST /invitationsésPOST /invitations/{token}/acceptvégpontok eltávolítva
4. ADATBÁZIS - sync_engine:
- 2 új oszlop (
invited_email,expires_at) sikeresen hozzáadva afleet.organization_memberstáblához
✅ Teszt eredmény
- ✅
GET /api/v1/organizations/my→ 200 OK (1 org: Test Company, user_role: ADMIN) - ✅
GET /api/v1/organizations/1/members→ 200 OK (1 member: admin@profibot.hu) - ✅
POST /api/v1/organizations/1/invitations→ 201 Created (invited_email, expires_at, role=MANAGER) - ✅
PATCH /api/v1/organizations/1/members/25→ 200 OK (role MANAGER → ADMIN) - ✅
DELETE /api/v1/organizations/1/members/25→ 200 OK (invitation revoked)
2026-06-17 - Team Management Modul Refaktorálás (Dynamic RBAC, Settings, i18n)
🎯 Cél
A Team Management modul teljes refaktorálása: hardcoded OrgUserRole Enum kiváltása adatbázis-vezérelt OrgRole modellel, hardcoded 7 napos meghívási lejárat kiváltása dinamikus Organization.settings JSONB mezővel, és az összes hardcoded magyar szöveg kiváltása i18n kulcsokkal a TranslationService.get_text() segítségével.
🔧 Változtatások
1. MODELL - organization.py:
OrgRoleúj modell létrehozva afleet.org_rolestáblában (id, name_key, display_name, description, is_system, priority, is_active, created_at)Organization.settingsJSONB oszlop hozzáadva alapértelmezett értékekkel:{"invite_expiry_days": 7, "max_members": 50, "allow_public_join": false}OrganizationMember.roletípusa megváltoztatvaPG_ENUM(OrgUserRole)-rólString(50)-re, alapértelmezett"MEMBER"
2. MODELL EXPORT - __init__.py:
OrgRolehozzáadva az importokhoz és az__all__listához
3. API VÉGPONTOK - organizations.py:
_()helper függvény hozzáadva aTranslationService.get_text()rövidítésére_get_org_settings()helper hozzáadva a dinamikus beállítások olvasásához- Összes hardcoded magyar szöveg kiváltva i18n kulcsokkal (pl.
ORGANIZATION.ERROR.INVALID_TAX_FORMAT,ORGANIZATION.SUCCESS.ONBOARDED,ORGANIZATION.CLAIM.OTP_SENT) - Összes
OrgUserRole.OWNER/OrgUserRole.ADMINEnum referencia kiváltva string literálokkal ("OWNER","ADMIN") member.role.value→str(member.role)timedelta(days=7)→timedelta(days=invite_expiry_days)a_get_org_settings()-ből
4. LOCALE FÁJLOK - hu.json, en.json:
ORGANIZATIONnévtér hozzáadva mindkét nyelvhez a következő alkulcsokkal:ERROR.*(11 hibaüzenet),SUCCESS.*(5 sikerüzenet),INVITATION.*(3 meghívó üzenet),JOIN_REQUEST.*(1 csatlakozási üzenet),CLAIM.*(2 átvételi üzenet)
5. ADATBÁZIS SZINKRONIZÁCIÓ:
sync_engine.pysikeresen lefuttatva:fleet.org_rolestábla létrehozva,fleet.organizations.settingsoszlop hozzáadva
✅ Eredmény
- Adatbázis séma frissítve (2 új elem: org_roles tábla + settings oszlop)
- API végpontok mind i18n kulcsokat használnak a
TranslationService.get_text()-en keresztül - Nincs több hardcoded
OrgUserRoleEnum a Team Management modulban - Nincs több hardcoded 7 napos lejárat
- Nincs több hardcoded magyar szöveg az API válaszokban
- Business onboarding teszt: ✅ PASS
2026-06-17 - Seed: Master Taxonomy i18n (JSONB kétnyelvű taxonómia)
🎯 Cél
4-szintű, kétnyelvű (HU/EN) autóipari taxonómia seed scriptjének elkészítése JSONB name_translations mezővel, 8 járműtípusra kiterjedően.
🔧 Változtatások
1. MODELL - service.py:
name_translationsJSONB oszlop hozzáadva azExpertiseTagmodellhez ({"hu": "...", "en": "..."}formátumban)
2. SEED SCRIPT - seed_master_taxonomy_i18n.py:
- Új seed script létrehozva
backend/scripts/seed_master_taxonomy_i18n.py - 4-szintű hierarchia: Level 0 (Járműtípus), Level 1 (Iparág), Level 2 (Szakma), Level 3 (Specifikus címke)
- 8 járműtípus: Személygépjármű, Motorkerékpár, Kishaszonjármű, Kamion, Munkagép, Pótkocsi, Busz, Lakóautó
- Idempotens: törli a régi
is_official=Truerekordokat, meghagyja a felhasználóiakat - Adjacency List (
parent_id) + Materialized Path (path) struktúra
✅ Eredmény
- 161 hivatalos kategória beszúrva (8 L0, 23 L1, 46 L2, 84 L3)
- 161 JSONB
name_translationskitöltve - 12 felhasználói címke megőrizve
- Adatbázis verifikáció: ✅ PASS
2026-06-17 - P0 UI Regression Fix: Universal Categories Restoration
🎯 Cél
Restore the "Universal Categories" (e.g., Benzinkút / Gas Station) independent checkbox block in Provider modals, which was accidentally removed during RBAC/i18n refactoring.
🔧 Változtatások
frontend/src/components/provider/ProviderQuickAddModal.vue:- Replaced
allLevel1Categoriescomputed with two separate computeds:vehicleLevel1Categories(children of checked Level 0) anduniversalLevel1Categories(root Level 1 categories, independent of vehicle type). - Added the amber-colored universal categories UI block with dashed border, globe icon, and independent checkbox styling.
- Universal categories are now always visible regardless of vehicle type selection.
- Replaced
frontend/src/components/provider/ProviderEditModal.vue: Already had correct structure — verified and left unchanged.
✅ Verifikáció
- Vite build: ✅ PASS (exit code 0)
- TypeScript check: ✅ PASS (no new errors)
- Universal categories IDs are correctly included in
selectedCategoryIdsarray → sent in payload ascategory_ids.
2026-06-17 - P0 UI Polish: i18n Fix & Master Taxonomy Autocomplete
🎯 Cél
Két P0 szintű probléma javítása: (1) "Univerzális Szolgáltatások" blokkban raw i18n kulcsok (universal_title, universal_hint) megjelenítése a fordítás helyett, (2) "Benzinkút" és "Étterem" hiányzó Level 2 kategóriák felvétele a Master Taxonomy-ba az autocomplete kereshetőséghez.
🔧 Változtatások
1. FRONTEND i18n - hu.ts:
categories.universal_titlekulcs hozzáadva:"Univerzális Szolgáltatások"categories.universal_hintkulcs hozzáadva:"Járműtípustól független infrastruktúra"
2. FRONTEND i18n - en.ts:
categories.universal_titlekulcs hozzáadva:"Universal Services"categories.universal_hintkulcs hozzáadva:"Vehicle-independent infrastructure"
3. BACKEND Taxonomy - seed_expertise_taxonomy.py:
UNIVERSAL_CATEGORIESbővítve Level 2 gyermek kategóriákkal:uzemanyag_toltoallomas→benzinkut(Benzinkút),elektromos_toltoallomas(EV Charging Station)etel_ital→etterem(Étterem),gyorsetterem_bufe(Gyorsétterem / Büfé)szallas→hotel(Hotel),motel_panzio(Motel / Panzió)orzes_parkolas→uni_orzott_parkolo(Őrzött Parkoló),uni_garazs(Garázs)
- Univerzális kategóriák beszúró ciklusa kiegészítve rekurzív gyermek feldolgozással (
_flatten_and_inserthívás)
✅ Verifikáció
- Seed script: ✅ PASS (134 rekord, ebből 12 univerzális: 4 Level 1 + 8 Level 2)
- Autocomplete API
q=Benzinkút: ✅ PASS (1 találat: Benzinkút, level=2) - Autocomplete API
q=Étterem: ✅ PASS (3 találat: Étterem, Gyorsétterem / Büfé, Étterem / Büfé)
2026-06-18 - P0 Critical: Financial Math Reversal (Gross-First Accounting)
🎯 Cél
A Phase 2 Financial Architecture felülvizsgálata során a Vezető Tervező (Architect) jelezte, hogy a pénzügyi logika fordítva van: az EU-s számvitelben a BRUTTÓ (Gross) az elsődleges forrásigazság (Source of Truth), nem a Nettó. A teljes matematika megfordítása: _calculate_gross_from_net() → _calculate_net_from_gross(), amount_gross kötelező, amount_net opcionális.
🔧 Változtatások
1. SCHEMA - asset_cost.py:
amount_grossáthelyezve kötelező mezővé (Field(..., description="Bruttó összeg — KÖTELEZŐ, elsődleges forrás"))amount_netopcionális (Optional[Decimal] = Field(None, ...))@model_validator(mode='after')hozzáadva: haamount_net=Noneésvat_rate=None, akkoramount_net = amount_grossésvat_rate = 0
2. SCHEMA - asset_event.py:
model_validatefrissítve:cost_amountelsődlegesenamount_gross-ból, fallbackamount_net-ből
3. SCHEMA - asset.py:
model_validatefrissítve:cost_amountelsődlegesenamount_gross-ból, fallbackamount_net-ből
4. ENDPOINT - expenses.py:
_calculate_gross_from_net()→_calculate_net_from_gross(amount_gross, vat_rate)átnevezve- Képlet megfordítva:
net = gross / (1 + vat_rate/100) - VAT handling logika átírva: ha
vat_rateadott ésamount_netnincs, net kiszámítása gross-ból - Ha
amount_netésvat_rateis adott,vat_ratefelülírva a back-számított értékkel - Ha egyik sincs,
amount_net = amount_gross,vat_rate = 0
5. ENDPOINT - assets.py:
create_maintenance_record:costmező gross-ként kezelve,amount_grossésamount_netis a cost értékkel töltvecreate_asset_event:cost_amountgross-ként kezelvelist_asset_costs: response-banamount_grossazamount_netelőtt
✅ Verifikáció
- Python szintaxis ellenőrzés: ✅ 5/5 fájl OK
- Sync engine: ✅ 1087/1087 OK, 0 fix, 0 extra
- Unit math tesztek: ✅ 5/5 passed (Gross=12700→Net=10000 27% VAT, Gross=10500→Net=10000 5% VAT, stb.)
- E2E API tesztek: ✅ 3/3 passed (Gross only, Gross+27%, Gross+5%)
- A teljes Gross-first matematika helyesen működik: a bruttó összeg a Source of Truth, a nettó és ÁFA visszaszámolva
2026-06-18 - P0 Frontend Cost Payload Audit & Fix (Gross-First Compliance)
🎯 Cél
A backend már szigorúan Gross-first rendszer a pénzügyi adatokra, de a frontend űrlapok még amount_net-et küldtek a payloadban, ami amount_gross: null-t eredményezett az adatbázisban. Teljes audit és javítás.
🔧 Változtatások
1. FRONTEND - cost.ts:
AddExpensePayloadinterface:amount_net→amount_gross(elsődleges mező)ExpenseResponseinterface:amount_net→amount_grossaddExpense()body builder:amount_net: payload.amount_net→amount_gross: payload.amount_gross
2. FRONTEND - ComplexExpenseModal.vue:
- Payload
amount_net: form.amount→amount_gross: form.amount
3. FRONTEND - SimpleFuelModal.vue:
- Payload
amount_net: form.amount→amount_gross: form.amount
4. BACKEND - asset_cost.py:
@model_validator(mode='before')safety net hozzáadva: ha a bejövő JSONamount_net-et tartalmaz, deamount_grosshiányzik, automatikusan átmásolja azamount_netértékét azamount_gross-ba. Ez véd a régebbi cache-elt böngészők ellen.
✅ Verifikáció
- Vite build: ✅ Sikeres (216 module transformed, 0 error)
- Backend schema import: ✅ Sikeres
- Safety net tesztek: ✅ 3/3 passed
amount_netonly →amount_grossauto-copy: ✅- Both fields present → no interference: ✅
amount_grossonly → no change: ✅
🔍 Utólagos Adatjavítás (Data Fix)
A felhasználó jelentése alapján az UOK795 (Honda CB1000R) járműnél az utolsó 2 rögzített költség 0 Ft-ot mutatott. Vizsgálat után kiderült:
Gyökér ok: A P0 audit előtt rögzített rekordoknál a frontend amount_net-et küldött, de a backend amount_gross-t 0-ra állította (a validate_gross_first mode='after' validátor None → Decimal("0")-ra állította a hiányzó gross mezőt).
Érintett rekordok (országosan 2 db):
3468e81a- UOK795 (Honda CB1000R) - 12 000 Ft tankolás →amount_grossjavítva 0→12000ea0395ea- QWE123 (APRILIA af1) - 4 000 Ft →amount_grossjavítva 0→4000
Javítás: UPDATE vehicle.asset_costs SET amount_gross = amount_net, vat_rate = 0.00 WHERE amount_gross=0 AND amount_net>0
2026-06-18 - Jogosultságkezelés Audit (Permission System Audit)
🎯 Cél
Teljes körű audit a jogosultsági szintek kezeléséről, kiterjedve az adatbázis táblákra, a backend kódra és a frontend rétegre.
🔍 Vizsgált Területek
- Adatbázis (6 tábla): identity.users, fleet.org_roles, fleet.organization_members, system.system_parameters, system.pending_actions, system.subscription_tiers
- Backend: UserRole enum, DEFAULT_RANK_MAP, RBAC osztály, get_current_admin, scoped RBAC, Dual Control (SecurityService), JWT token
- Frontend: authStore.ts (UserRole típus), Router Guard
🔴 Feltárt Kritikus Problémák
- P1: fleet.org_roles tábla ÜRES - dinamikus szerepkör rendszer nem seedelt
- P2: DEFAULT_RANK_MAP inkonzisztens a UserRole enum-mal (6 rang soha nem kerül kiosztásra)
- P3: Enum duplikáció az adatbázisban (kis/nagybetű variánsok)
- P4: Frontend/backend UserRole eltérés (5 vs 10 role)
- P5: parameter_scope enum 3 különböző sémában definiálva
📄 Dokumentáció
docs/permission_system_audit_2026-06-18.md- Teljes audit jelentés Mermaid diagrammal
2026-06-18 - RBAC Phase 1: Foundation & Seeding (P0 Critical)
🎯 Cél
RBAC Phase 1 migráció Fine-Grained, Capability-Driven architektúrára. System-level (UserRole) és Organization-level (OrgUserRole) szerepkörök szétválasztása, SYSTEM_CAPABILITIES_MATRIX létrehozása, fleet.org_roles tábla seedelése.
🔧 Változtatások
1. UserRole enum tisztítás:
- 10 régi érték helyett 6 system-level role:
SUPERADMIN, ADMIN, MODERATOR, SALES_REP, SERVICE_MGR, USER - Eltávolítva:
region_admin, country_admin, sales_agent, service_owner, fleet_manager, driver - Hozzáadva:
SALES_REP, SERVICE_MGR - Értékek UPPERCASE-re változtatva
2. SYSTEM_CAPABILITIES_MATRIX létrehozása:
- Új fájl:
backend/app/core/capabilities.py Capabilityosztály konstansokkal (~26 capability key)SYSTEM_CAPABILITIES_MATRIXdict minden role-hoz boolean capability mátrix- Segédfüggvények:
get_capabilities_for_role(),role_has_capability()
3. OrgUserRole enum frissítés:
- Új értékek:
OWNER, ADMIN, ACCOUNTANT, DRIVER, VIEWER - Eltávolítva:
MANAGER, MEMBER, AGENT
4. DEFAULT_RANK_MAP tisztítás:
- Csak az új 6 system-level role + GUEST maradt
- SERVICE_MGR(40), SALES_REP(30) hozzáadva
5. Függő kódok frissítése:
deps.py-check_resource_access()ésget_current_admin()frissítverbac.py-UserRole.SUPERADMINreferencia javítvabilling_engine.py-RBAC_DISCOUNTStisztítva
6. PostgreSQL enum migráció:
migrate_rbac_phase1_enums.py- CREATE TYPE → ALTER COLUMN → DROP TYPE minta- Régi értékek mapelése:
superadmin→SUPERADMIN, admin→ADMIN, moderator→MODERATOR, sales_agent→SALES_REP, user/service_owner/fleet_manager/driver→USER - ✅ Sikeres:
identity.userroleenum 6 értékkel, meglévő user role-ok helyesen átkonvertálva
7. seed_org_roles.py - fleet.org_roles seedelés:
- 5 org role: OWNER(100), ADMIN(80), ACCOUNTANT(60), DRIVER(40), VIEWER(20)
- Minden role JSON permissions objektummal
- ✅ Sikeres: 5 rekord beszúrva
✅ Verifikáció
- Schema sync: 1087 items OK, 0 fixed, 0 shadow data
identity.userroleenum:SUPERADMIN, ADMIN, MODERATOR, SALES_REP, SERVICE_MGR, USERfleet.org_roles: 5 rekord (OWNER, ADMIN, ACCOUNTANT, DRIVER, VIEWER)- Meglévő user role-ok:
USER, SUPERADMIN, ADMIN- helyesen konvertálva
2026-06-18 - P0 EMERGENCY: Superadmin User ID 1 Recreated from Scratch
🎯 Cél
A hard-deletelt User ID 1 rekord fizikai újraélesztése: SUPERADMIN joggal, a meglévő Person ID 1-hez kapcsolva, és a Profibot Test Fleet (Organization ID 15) garázshoz OWNER szerepkörrel hozzárendelve.
🔧 Változtatások
1. Jelszó hash generálás:
security.py:get_password_hash('Superadmin123!')használatával bcrypt hash generálva- Hash:
$2b$12$ozXD07/qiFl4eKg.RbadDeGcnMukY3tOpBPEgOza7VsqcbuUW7iq2 - Verifikáció:
verify_password('Superadmin123!', hash)→True
2. Email konfliktus feloldása:
- User ID 29 (korábbi
superadmin@profibot.hu) átnevezve →superadmin_old@profibot.hu
3. User ID 1 létrehozása (identity.users):
INSERT INTO identity.users (id=1, email='superadmin@profibot.hu', role='SUPERADMIN', person_id=1, ...)- Kapcsolat a Person ID 1-hez (Super Admin személy)
4. Garázs hozzárendelés (fleet.organization_members):
INSERT INTO fleet.organization_members (organization_id=15, user_id=1, person_id=1, role='OWNER', ...)- Organization: "Profibot Test Fleet" (ID 15)
✅ Verifikáció
identity.users WHERE id=1:email=superadmin@profibot.hu, role=SUPERADMIN, person_id=1, is_active=truefleet.organization_members WHERE user_id=1:org_id=15 (Profibot Test Fleet), role=OWNER, status=activeidentity.persons WHERE id=1:last_name=Admin, first_name=Super(meglévő személy)- Jelszó hash verifikáció:
True - Belépési adatok:
superadmin@profibot.hu/Superadmin123!
2026-06-18: P0 CRITICAL DEBUG - 500 Internal Server Error on POST /api/v1/auth/login (UserRole UPPERCASE migration fix)
🎯 Cél
A Phase 1 RBAC Enum UPPERCASE migráció után a /api/v1/auth/login endpoint 500-as hibát dobott LookupError: 'ADMIN' is not among the defined enum values üzenettel. A régi konténer cache-elt SQLAlchemy metaadatokat használt, és a billing_engine.py-ben lévő UserRole.user (kisbetűs) hivatkozás miatt az új konténer sem indult el.
🔧 Változtatások (25 javítás 14 fájlban)
Kritikus javítások (startup-blokkoló):
backend/app/services/billing_engine.py:70—UserRole.user→UserRole.USER(2 helyen)backend/app/services/social_auth_service.py:33—UserRole.user→UserRole.USERbackend/app/services/search_service.py:41—UserRole.superadmin, UserRole.admin→UserRole.SUPERADMIN, UserRole.ADMINbackend/app/services/auth_service.py:110—UserRole.user→UserRole.USERbackend/app/api/v1/endpoints/system_parameters.py:125—UserRole.superadmin, UserRole.admin→UserRole.SUPERADMIN, UserRole.ADMINbackend/app/schemas/admin.py:23—UserRole.admin, UserRole.superadmin→UserRole.ADMIN, UserRole.SUPERADMINbackend/app/api/v1/endpoints/finance_admin.py:27—UserRole.superadmin, UserRole.admin→UserRole.SUPERADMIN, UserRole.ADMINbackend/app/api/v1/endpoints/admin.py:195—UserRole.superadmin→UserRole.SUPERADMIN(2 helyen)backend/app/api/v1/endpoints/security.py:39—UserRole.admin, UserRole.superadmin→UserRole.ADMIN, UserRole.SUPERADMIN(5 helyen)backend/app/core/security.py:56—DEFAULT_RANK_MAPmár helyes (UPPERCASE kulcsok)backend/app/tests/e2e/test_admin_security.py:21—UserRole.user→UserRole.USER,UserRole.admin→UserRole.ADMINbackend/app/scripts/seed_integration_data.py:158—UserRole.admin→UserRole.ADMIN,UserRole.superadmin→UserRole.SUPERADMIN
✅ Verifikáció
POST /api/v1/auth/loginwithadmin@profibot.hu/Admin123!→ 200 OK- JWT token payload:
{"sub": "2", "role": "ADMIN", "rank": 90, "scope_level": "system", "scope_id": "2"} - Konténer indítás: sikeres (nem omlik össze
AttributeError-rel) - 3 db seed script nem javítható (EACCES jogosultsági hiba) — nem kritikus
2026-06-18 - RBAC Phase 2: Capability Dependencies (Kapuőrök)
🎯 Cél
P0 kritikus feladat: JSONB-alapú capability dependency-k bevezetése a hardcoded szerepkör-ellenőrzések helyett. Két új FastAPI dependency: RequireSystemCapability (system-level) és RequireOrgCapability (org-level).
🔧 Változtatások
1. MODELL - organization.py:
permissionsJSONB oszlop hozzáadva azOrgRolemodellhez (server_default='{}'::jsonb)
2. DEPENDENCY - deps.py:
RequireSystemCapability(capability_name: str)— Ellenőrzi aSYSTEM_CAPABILITIES_MATRIX-ot a system-level role-okhoz. SUPERADMIN automatikusan átmegy.RequireOrgCapability(capability_name: str)— Lekérdezi afleet.org_roles.permissionsJSONB oszlopot. Fallback:OrganizationMember.permissions. SUPERADMIN bypass.
3. EXPENSES - expenses.py:
AUTO_APPROVED_ROLES = {"OWNER", "ADMIN"}eltávolítva_check_org_capability()helper hozzáadva — JSONB-ből olvassa acan_approve_expenseflag-et- Költség státusz meghatározása:
can_approve→ APPROVED, fuel (category_id=1) → APPROVED, egyéb → PENDING_APPROVAL
4. ASSETS - assets.py:
AUTO_APPROVED_ROLES = {"OWNER", "ADMIN"}eltávolítva_check_org_capability()helper hozzáadvacreate_asset_eventvégpontban az esemény státusz JSONB-alapú ellenőrzésre váltva
5. SEED - seed_org_roles.py:
permissionsparaméter hozzáadva azOrgRolekonstruktorhoz- Meglévő role-ok permissions mezőjének frissítése (RBAC Phase 2 update loop)
🗄️ Adatbázis
sync_enginefuttatva:permissionsJSONB oszlop létrehozva afleet.org_rolestáblában- 5 org role permissions adata feltöltve: OWNER, ADMIN, ACCOUNTANT, DRIVER, VIEWER
✅ Verifikáció
- Backend indítás: sikeres (nincs import error)
POST /api/v1/expenses/ADMIN userrel → 201 CREATED,expense_status: "APPROVED"(mert ADMIN rendelkezikcan_approve_expense: Trueképességgel)fleet.org_rolesJSONB permissions: mind az 5 role helyesen tárolva
2026-06-18: RBAC Phase 3 - Frontend Reactivity & UI Capabilities Integration
🎯 Cél
P0 kritikus feladat: Frontend reaktivitás javítása (F5 Bug) és UI képesség-alapú megjelenítés bevezetése.
🔧 Változtatások
Task 1 - F5 Bug javítás (Direct Mutation / Explicit Fetch pattern):
CostsActionsCard.vue:cost-savedevent emit hozzáadva, ami a költség mentése után értesíti a szülőtDashboardView.vue:refreshCostsTriggerref (számláló) ésonCostSaved()handler hozzáadvaDashboardView.vue::refresh-trigger="refreshCostsTrigger"prop átadva a VehicleDetailModal-nakVehicleDetailModal.vue:refreshTriggerprop éswatchhozzáadva a költségek újratöltéséhez
Task 2 - Backend /users/me exposure:
schemas/user.py:system_capabilities: Dict[str, bool]ésorg_capabilities: Dict[str, Dict[str, bool]]mezők hozzáadva aUserResponse-hozendpoints/users.py:_build_user_response()kiegészítvesystem_capabilitiesfeloldással aSYSTEM_CAPABILITIES_MATRIX-bólendpoints/users.py:read_users_me()kiegészítveorg_capabilitiesaszinkron feloldásával az aktív org tagságokból
Task 3 - Frontend Auth Store capability helpers:
stores/auth.ts:UserProfileinterface kiegészítvesystem_capabilitiesésorg_capabilitiesmezőkkelstores/auth.ts:hasSystemCapability(capability)helper - ellenőrzi a rendszerszintű képességetstores/auth.ts:hasOrgCapability(orgId, capability)helper - ellenőrzi a szervezeti képességetstores/auth.ts:getOrgCapabilities(orgId)helper - visszaadja az összes szervezeti képességet
Task 4 - UI Integration Pilot:
VehicleDetailModal.vue: "Szerkesztés" gombv-if-je kiegészítveauthStore.hasOrgCapability(orgId, 'can_approve_expense')ellenőrzéssel
✅ Verifikáció
- Backend Python szintaxis:
user.pyésusers.pyhibátlanul lefordul - Frontend TypeScript:
vue-tsc --noEmitsikeres (csak pre-existing.vue.jsfile hibák) - Event propagation chain teljes: Cost modal → CostsActionsCard → DashboardView → VehicleDetailModal
2026-06-18 - P0 Legacy Garage Migration (RBAC Phase 3)
🎯 Cél
Adatbázis backfill szkript elkészítése és futtatása, amely a legacy person_id-alapú ownership struktúrát áttelepíti az új organization_id/organization_members RBAC struktúrába. Három feladat: (A) hiányzó személyes garázsok létrehozása, (B) userek bindolása a garázsukhoz OWNER role-lal, (C) gazdátlan járművek megmentése.
🔧 Változtatások
1. BACKEND - migrate_legacy_garages.py:
- Task A: Lekérdezi a
identity.userstáblában lévő usereket, akiknek nincsINDIVIDUALtípusú személyes garázsuk (fleet.organizations). Létrehozza a garázst minden szükséges oszloppal. - Task B: Minden userhez hozzárendeli a személyes garázsát
organization_memberstáblábanOWNERszerepkörrel. Frissíti ascope_idmezőt, ha az NULL. - Task C: Megkeresi a gazdátlan járműveket (
vehicle.assetstáblában aholowner_person_idkitöltött, decurrent_organization_idvagyowner_org_idNULL), és átvezeti őket a tulajdonos személyes garázsába. - Technikai részletek:
asyncpg-t használ közvetlen adatbázis kapcsolattal. Dinamikus schema discovery (information_schema.columns) a NOT NULL constraint-ek kezelésére.
2. BACKEND - verify_migration.py:
- Verifikációs szkript, amely a migráció után lekérdezi a kulcs metrikákat.
✅ Eredmény
- 6 új személyes garázs létrehozva (Task A)
- 16 member hozzáadva
organization_members-hez (Task B) - 10 scope_id frissítve (Task B)
- 1 gazdátlan jármű megmentve (Task C)
- 0 user maradt személyes garázs nélkül
- 0 user NULL scope_id-vel
- 0 orphaned jármű maradt
- 17 total INDIVIDUAL garázs
- 22 organization member OWNER role-lal
- 38/41 jármű organization-höz rendelve
2026-06-18 - P0 Feature: Subscription & Package Assignment Bridge
🎯 Cél
Subscription Tier hozzárendelés szervezetekhez (fleet.organizations) a subscription_tier_id FK oszlopon keresztül. Teljes admin API + frontend integráció a csomagok kezeléséhez.
🔧 Változtatások
1. ADATBÁZIS - Organization:
subscription_tier_idFK oszlop hozzáadva (nullable, FK →system.subscription_tiers.id)- Sync engine sikeresen lefuttatva → oszlop létrejött
2. CAPABILITIES - capabilities.py:
CAN_MANAGE_SUBSCRIPTIONS = "can_manage_subscriptions"új capability- SUPERADMIN és ADMIN mátrixba bevéve
3. API ENDPOINT - organizations.py:
PUT /{org_id}/subscriptionvégpontRequireSystemCapability(Capability.CAN_MANAGE_SUBSCRIPTIONS)RBAC-calSubscriptionAssignInPydantic schema a body-hoz
4. BILLING ENGINE - billing_engine.py:
upgrade_org_subscription()függvény: beállítja asubscription_tier_id-t, frissíti asubscription_planésbase_asset_limitmezőket, létrehozza azOrganizationSubscriptionaudit rekordot
5. QUOTA ENGINE - evidence.py:
- scan-registration végpont most az org
subscription_tier_id→SubscriptionTier.rules.allowances.max_vehiclesértéket olvassa - Fallback:
org.base_asset_limitha nincs tier hozzárendelve
6. SCHEMA - organization.py:
subscription_tier_id: Optional[int]hozzáadvaOrganizationUpdateésOrganizationResponsemodellekhez
7. FRONTEND TYPES - organization.ts:
subscription_tier_id?: number | nullhozzáadvaOrganizationIteminterfészhez
8. FRONTEND UI - OrganizationSettingsModal.vue:
- Subscription tier dropdown (select + assign gomb)
availableTiersbetöltéseGET /admin/packages/-bőlassignSubscription()hívásPUT /organizations/{id}/subscription-ra
✅ Verifikáció
subscription_tier_idoszlop létezik (information_schemaellenőrizve)- Org 45:
corp_premium_plus_v1(tier_id=17, max_vehicles=50) ✅ - Org 49:
corp_premium_v1(tier_id=16, max_vehicles=20) ✅ - 8 subscription tier elérhető a
system.subscription_tierstáblában
2026-06-18 - P0 Critical: Admin Button Fix & Orphaned Vehicle Rescue
🎯 Cél
5-lépéses P0 kritikus feladat: (1) Törött Admin/Vezérlőpult gomb javítása a frontenden, (2) Adatbázis felderítés: gazdátlan járművek keresése, (3) Admin felhasználó garázsainak ellenőrzése, (4) Gazdátlan járművek megmentése (UPDATE), (5) Verifikáció és jelentés.
🔧 Változtatások
1. FRONTEND - auth.ts:
- Root Cause: A
ModeSwitcher.vueastores/auth-ból importálja azauthStore.isAdmin-et, de a store-ból hiányzott azisAdmincomputed getter. Mindigundefined-et adott vissza, így a gomb sosem jelent meg. - Fix:
isAdmincomputed property hozzáadva, amely ellenőrzi asuperadmin,admin,region_admin,country_admin,moderatorszerepköröket (kisbetűs összehasonlítással).
2. ADATBÁZIS - Gazdátlan járművek felderítése:
- 3 db orphaned vehicle találva: TEST-API-01, ABB112, ABC-123 (mind
archivedstátuszú,owner_person_id = NULL,current_organization_id = NULL) - Admin user (admin@profibot.hu, user_id=2, person_id=2, role=ADMIN) nem rendelkezik Corporate (fleet_owner/business) garázzsal OWNER joggal - csak "Admin Garázsa" (Org 67, individual típus)
- Admin 17 járműve már helyesen a Test Company (Org 1, fleet_owner) alá van rendelve
3. ADATBÁZIS - Rescue UPDATE:
- 3 gazdátlan jármű átvezetve az Admin Garázsába (Org 67):
owner_person_id=2, owner_org_id=67, current_organization_id=67 - Parancs:
docker compose exec -T shared-postgres psql ... UPDATE vehicle.assets SET ... WHERE current_organization_id IS NULL AND owner_person_id IS NULL - Eredmény:
UPDATE 3
✅ Verifikáció
SELECT ... WHERE current_organization_id IS NULL→ üres eredmény (0 gazdátlan jármű) ✅- 3 rescued vehicle: TEST-API-01, ABB112, ABC-123 → Admin Garázsa (Org 67) ✅
- Admin 17 egyéb járműve: Test Company (Org 1) alatt maradt ✅
2026-06-18 - P0 CRITICAL: Fix Admin Panel Case Sensitivity (SUPERADMIN/ADMIN)
🎯 Cél
A backend UPPERCASE role értékei (SUPERADMIN, ADMIN) és a frontend lowercase összehasonlításai közötti mismatch javítása.
🔧 Változtatások
frontend/src/stores/auth.ts—isAdmingetter: lowercase[superadmin,admin,...]→ UPPERCASE[SUPERADMIN,ADMIN,MODERATOR]+role.toUpperCase()frontend/src/router/index.ts— Router guard: ugyanez a javítás arequiresAdminmeta ellenőrzésbenfrontend/src/stores/authStore.ts— Secondary auth storeisAdmin/isSuperAdmingetterek:role.toUpperCase()frontend/src/components/header/HeaderProfile.vue— InlineisAdmincomputed: lowercase → UPPERCASE +toUpperCase()frontend/src/views/admin/AdminUsersView.vue— Két inline=== superadmincheck →=== SUPERADMIN+toUpperCase()
✅ Verifikáció
- Backend admin ping endpoint:
role: "ADMIN"(UPPERCASE) ✅ - Frontend Vite HMR: minden módosított fájl újratöltve ✅
- Admin felület minden ponton (store getter, router guard, header button, users view) case-insensitive módon ellenőrzi a SUPERADMIN/ADMIN szerepköröket ✅
2026-06-18 - P0 Critical: Precise Subscription Backfill & Legacy Cleanup
🎯 Cél
Admin garázsok VIP csomag hozzárendelése, tömeges free tier fallback, legacy string oszlopok kivezetése a kvóta logikából.
🔧 Változtatások
-
Adatbázis backfill (
backend/app/scripts/p0_subscription_backfill.py):- VIP: Admin Garázsa (org_id=67) →
private_test_v01(tier_id=19, max_vehicles=100) ✅ - VIP: Test Company (org_id=1) →
org_test_v01(tier_id=20, max_vehicles=100) ✅ - Free Tier Fallback: 14 individual org →
private_free_v1, 13 other org →corp_free_v1✅ - Eredmény: 31/31 org assigned, 0 NULL ✅
- VIP: Admin Garázsa (org_id=67) →
-
Kvóta Motor refaktor (
backend/app/services/asset_service.py):get_user_vehicle_limit(): Eltávolítva a legacysubscription_planstring lookup- Single Source of Truth:
SubscriptionTier.rules['allowances']['max_vehicles']JSONB - Fallback lánc: user subscription → org subscription tier → org.base_asset_limit → config
-
Dokumentum helper cleanup (
backend/app/api/v1/endpoints/documents.py):_check_premium_or_admin(): Eltávolítva asubscription_planstring alapú premium check
✅ Verifikáció
- Schema szinkron: sync_engine → 1089/1089 OK ✅
- 0 org with NULL subscription_tier_id ✅
- Distribution: private_free_v1(14), corp_free_v1(13), corp_premium_v1(1), private_test_v01(1), corp_premium_plus_v1(1), org_test_v01(1) ✅
2026-06-18 - P0 CRITICAL: PATCH Organization 500 Error Fix
🎯 Cél
A PATCH /api/v1/organizations/{id} végpont 500 Internal Server Error hibájának javítása, amely a subscription backfill után jelentkezett.
🔍 Root Cause Analysis
Kiváltó ok #1: PostgreSQL ENUM típus mismatch.
A fleet.organization_members.role oszlop az adatbázisban fleet.orguserrole ENUM típusként volt definiálva, de a SQLAlchemy modellben OrganizationMember.role String(50)-ként. Amikor a PATCH /organizations/{id} végpont update_organization függvénye lefutott, az SQLAlchemy a következő SQL-t generálta:
WHERE fleet.organization_members.role IN ('OWNER', 'ADMIN')
PostgreSQL nem tud implicit módon összehasonlítani egy ENUM típust (fleet.orguserrole) egy string literállal (character varying), ezért dobta:
operator does not exist: fleet.orguserrole = character varying
HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
Kiváltó ok #2: Hiányzó OrganizationMember rekord az owner_id alapú tulajdonosoknak.
A subscription backfill során számos szervezetnél az owner_id mező be lett állítva, de a fleet.organization_members táblába nem került be a megfelelő OWNER szerepkörű rekord. A PATCH végpont csak a OrganizationMember táblában keresett, így a jogos tulajdonos is 403-as hibát kapott.
Érintett fájlok:
backend/app/models/marketplace/organization.py-OrganizationMember.roleoszlop típusabackend/app/api/v1/endpoints/organizations.py- A PATCH végpont RBAC ellenőrzése
🔧 Javítások
1. MODELL JAVÍTÁS (organization.py):
OrganizationMember.roleoszlop típusaString(50)→PG_ENUM(OrgUserRole, name="orguserrole", schema="fleet", create_type=False)-re változtatvacreate_type=Falseparaméter biztosítja, hogy nem próbáljuk újra létrehozni a már meglévő ENUM típust
2. VÉGPONT JAVÍTÁS (organizations.py):
- Az RBAC ellenőrzés kiegészítve: ha a user nem található
OrganizationMember-ként, deOrganization.owner_id-ként szerepel, akkor is engedélyezve van a módosítás - A szervezet lekérése előrébb került (az RBAC ellenőrzés előtt), hogy elérhető legyen az
owner_idmező - Ezzel elkerültük a duplikált SQL lekérdezést is
✅ Verifikáció
PATCH /api/v1/organizations/44→ 200 OK ✅ (korábban 500, majd 403)- Nincs több
UndefinedFunctionErrora logokban ✅ - Az SQLAlchemy által generált SQL helyesen kezeli az ENUM összehasonlítást ✅
- A tulajdonos (owner_id) sikeresen tudja módosítani a szervezet adatait ✅
2026-06-18: Address fields missing from OrganizationResponse and GET /my (#3-as probléma)
🔍 Root Cause Analysis
A PATCH /api/v1/organizations/{id} végpont 200 OK-val tért vissza, és az adatok az adatbázisba is bekerültek, de a frontend UI-ban nem jelentek meg a cím adatok. A probléma három rétegben jelentkezett:
1. Backend OrganizationResponse séma hiányossága (organization.py):
- A
OrganizationResponsePydantic osztály nem tartalmazta a cím mezőket (address_zip,address_city,address_street_name,address_street_type,address_house_number,address_hrsz) - A PATCH végpont
response_model=OrganizationResponse-et használ, így a válaszból kimaradtak a cím adatok
2. Backend GET /my végpont hiányossága (organizations.py):
- A
get_my_organizationsfüggvény által visszaadott dictionary-ből hiányoztak a cím mezők - A frontend a PATCH után
authStore.fetchMyOrganizations()-t hív, ami ezt a végpontot használja
3. Frontend OrganizationItem típus és onMounted hiányossága (OrganizationSettingsModal.vue):
- A TypeScript
OrganizationIteminterfészből hiányoztak a cím mezők - Az
onMountedhook nem töltötte be a cím mezőket aformobjektumba
További probléma: A OrganizationUpdate séma tartalmazott olyan mezőket (address_stairwell, address_floor, address_door), amelyek nem léteznek az Organization SQLAlchemy modellben. Ezeket a PATCH végpont csendben figyelmen kívül hagyta, de a GET /my végpont AttributeError-t dobott volna rájuk.
🔧 Javítások
1. OrganizationResponse séma bővítése (organization.py):
- Hozzáadva:
address_zip,address_city,address_street_name,address_street_type,address_house_number,address_hrsz - Eltávolítva a nem létező mezők:
address_stairwell,address_floor,address_door
2. OrganizationUpdate séma tisztítása (organization.py):
- Eltávolítva a nem létező mezők:
address_stairwell,address_floor,address_door
3. GET /my végpont bővítése (organizations.py):
- Hozzáadva a cím mezők a visszaadott dictionary-hez
4. Frontend OrganizationItem típus bővítése (organization.ts):
- Hozzáadva a cím mezők az interfészhez
5. Frontend OrganizationSettingsModal.vue javítása (OrganizationSettingsModal.vue):
formobjektum bővítve a cím mezőkkelonMountedhook kiegészítve a cím mezők betöltésével (mindkét ágban)
✅ Verifikáció
GET /api/v1/organizations/my→ 200 OK, tartalmazza a cím mezőket ✅PATCH /api/v1/organizations/{id}→ 200 OK, a válasz tartalmazza a cím mezőket ✅- A cím adatok elérhetők a frontend
OrganizationSettingsModalform-jában ✅