diff --git a/.roo/history.md b/.roo/history.md index 27aeaad..e3c5949 100644 --- a/.roo/history.md +++ b/.roo/history.md @@ -1,428 +1,240 @@ -# Service Finder Fejlesztési Történet + 1 | # Service Finder Fejlesztési Történet + 2 | + 3 | ## 2026-06-21 - P0 Deep Audit: Database Consistency & Zombie API Hunt + 4 | + 5 | ### 🎯 Cél + 6 | Teljes körű adatbázis konzisztencia ellenőrzés és zombie API végpontok felderítése a `vehicle`, `finance`, `fleet_finance` sémákban, mielőtt a frontend fejlesztés elkezdődik. + 7 | + 8 | ### 🔧 Eredmények + 9 | +10 | **1. ADATBÁZIS TISZTASÁG:** ✅ PASS +11 | - API modul import: ✅ Sikeres (2 route: GET, POST) +12 | - Sync Engine: ✅ 1210 OK, 0 Fixed, 0 Extra +13 | - E2E test: ⚠️ Pre-existing conftest hiba (verification token timeout - nem kapcsolódó) +14 | +15 | ## 2026-06-23 - Cost Entry Wizard (CostEntryWizard.vue) - 4-lépéses Számla Űrlap +16 | +17 | ### 🎯 Cél +18 | 4-lépéses stepper wizard építése részletes számla/invoice költségek rögzítésére a CostsActionsCard-ból indíthatóan. +19 | +20 | ### 🔧 Módosított fájlok +21 | +22 | ## 2026-06-24 - P0 Fix & Enhance: Permissions Page Data Flow, Editing & i18n +23 | +24 | ### 🎯 Cél +25 | Permissions oldal adatáramlás javítása, szerkesztés/mentés funkció bevezetése, és @nuxtjs/i18n telepítése/konfigurálása. +26 | +27 | ### 🔧 Módosított fájlok +28 | - `frontend_admin/pages/permissions/index.vue` - Teljes átírás: client-side data fetch onMounted-ben, szerkeszthető toggle-ok (modifiedPermissions Map), PATCH mentés, toast notification, $t() hívások +29 | - `frontend_admin/nuxt.config.ts` - @nuxtjs/i18n modul hozzáadása, locales konfiguráció (hu/en) +30 | - `frontend_admin/i18n/locales/hu.json` - Magyar fordítási fájl (permissions oldal összes szövege) +31 | - `frontend_admin/i18n/locales/en.json` - Angol fordítási fájl +32 | +33 | ### ✅ Eredmények +34 | - Build: ✅ Sikeres (hu-DbjfOUfH.mjs, en-DnJ23n0t.mjs locale chunk-ok) +35 | - i18n modul: @nuxtjs/i18n v10.4.0 telepítve, no_prefix stratégiával +36 | - Szerkesztés: modified/original Map-ek, handleToggle, savePermissions (PATCH /admin/permissions/override/{org_id}) +37 | - Adatmentés: success/error toast notification auto-clear-el +38 | +39 | ## 2026-06-24 - P0 Execution: Wire Packages UI to Real Database +40 | +41 | ### 🎯 Cél +42 | A frontend_admin Packages oldal (packages/index.vue) mock adatok helyett valós API adatbázisból töltse a SubscriptionTier csomagokat. "Új Csomag Létrehozása" gomb és modal hozzáadása. +43 | +44 | ### 🔧 Módosított fájlok +45 | - `backend/app/schemas/subscription.py` - `tier_level` és `feature_capabilities` mezők hozzáadva a SubscriptionTierResponse, SubscriptionTierCreate, SubscriptionTierUpdate modellekhez +46 | - `backend/app/api/v1/endpoints/admin_packages.py` - create/update végpontok frissítve az új mezők kezelésére +47 | - `frontend_admin/pages/packages/index.vue` - Teljes átírás: mock adatok eltávolítva, fetchPackages() API hívás, create/edit/delete modal-ok, loading/error/empty állapotok, i18n támogatás +48 | - `frontend_admin/locales/hu.json` - packages i18n kulcsok (magyar) +49 | - `frontend_admin/locales/en.json` - packages i18n kulcsok (angol) +50 | +51 | ### ✅ Eredmények +52 | - Backend API: GET /api/v1/admin/packages → 200 OK, 10 tier (tier_level, feature_capabilities mezőkkel) +53 | - Frontend: mock adatok eltávolítva, valós API hívás onMounted-ben, loading/error/empty állapotok +54 | - CRUD: Létrehozás (POST), Szerkesztés (PATCH), Törlés (DELETE soft-delete) teljes körűen implementálva +55 | - i18n: Minden UI szöveg magyar és angol nyelven elérhető +56 | +57 | ## 2026-06-24 - P0 CRITICAL FIX: Deep Merge JSONB (Multi-zone Pricing Data Loss) +58 | +59 | ### 🎯 Cél +60 | Javítani a `PATCH /api/v1/admin/packages/{tier_id}` végpontot, hogy a `rules` JSONB oszlop frissítésekor a meglévő nested kulcsok (pl. `pricing_zones.HU`, `pricing_zones.US`, `lifecycle.available_until`) ne vesszenek el, ha a frontend csak egy részhalmazt küld (pl. csak `pricing_zones.DEFAULT`). +61 | +62 | ### 🔧 Módosított fájlok +63 | - `backend/app/api/v1/endpoints/admin_packages.py` — `deep_merge_dict()` függvény hozzáadva, `update_package` endpoint átírva deep merge szemantikára +64 | - `tests/active/test_deep_merge_fix.py` — Verifikációs teszt (unit + API PATCH) +65 | +66 | ### ✅ Eredmények +67 | - **Unit test:** ✅ PASS — `deep_merge_dict()` helyesen működik: nested dict-ek rekurzív merge, None értékek megőrzése, üres override megőrzése +68 | - **API test:** ✅ PASS — `private_pro_v1` (id=14) csomagon: HU, US, DEFAULT zónák mind megmaradtak a PATCH után, DEFAULT ára frissült, lifecycle.available_until megőrződött +69 | - **Sync Engine:** ✅ 1220 OK, 0 Fixed — adatbázis séma konzisztens +70 | - **Root cause:** A frontend `packages/index.vue` `rulesPayload` függvénye csak `pricing_zones.DEFAULT`-ot állítja elő, a backend pedig wholesale replace-t végzett → multi-zone adatvesztés -## 2026-06-21 - P0 Deep Audit: Database Consistency & Zombie API Hunt +## 2026-06-24 - P0 System Architecture: Global Region Config & Smart Pricing ### 🎯 Cél -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. - -### 🔧 Eredmények - -**1. ADATBÁZIS TISZTASÁG:** ✅ PASS -- API modul import: ✅ Sikeres (2 route: GET, POST) -- Sync Engine: ✅ 1210 OK, 0 Fixed, 0 Extra -- E2E test: ⚠️ Pre-existing conftest hiba (verification token timeout - nem kapcsolódó) - -## 2026-06-23 - Cost Entry Wizard (CostEntryWizard.vue) - 4-lépéses Számla Űrlap - -### 🎯 Cél -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. +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 -- **`frontend/src/components/cost/CostEntryWizard.vue`** (ÚJ) - 4-step stepper wizard komponens -- **`frontend/src/components/dashboard/CostsActionsCard.vue`** - "🧾 Részletes Számla" gomb hozzáadva, CostEntryWizard import és modal state -- **`frontend/src/i18n/en.ts`** - costWizard i18n szekció hozzáadva -- **`frontend/src/i18n/hu.ts`** - costWizard i18n szekció hozzáadva +- `backend/app/models/core_logic.py` — `RegionConfig` osztály hozzáadva (`system.region_config` séma, mezők: country_code, name, currency, default_vat_rate, locale_code, timezone, is_active) +- `backend/app/models/__init__.py` — `RegionConfig` import hozzáadva +- `backend/app/api/v1/endpoints/regions.py` — **LÉTREHOZVA**: `GET /system/regions` publikus végpont +- `backend/app/api/v1/api.py` — regions router regisztrálva `/system` prefix-szel +- `backend/scripts/seed_regions.py` — **LÉTREHOZVA**: 3 régió seedelése (HU, GB, DEFAULT) +- `backend/app/api/v1/endpoints/auth.py` — `PATCH /auth/me/language` végpont hozzáadva nyelvi preferencia perzisztáláshoz +- `frontend_admin/stores/region.ts` — **LÉTREHOZVA**: Pinia store régiók lekérésére, aktív régió getterekkel (currency, locale, VAT, timezone) +- `frontend_admin/composables/useFormatter.ts` — **LÉTREHOZVA**: Lokalizált formatter (number, currency, date, datetime, percent, VAT számítás) +- `frontend_admin/pages/packages/index.vue` — Tabbed modal refaktor (Basic Info, Pricing, Features), per-régió árazási grid, Smart Pricing Calculator net/VAT/gross kijelzéssel +- `frontend_admin/layouts/default.vue` — Nyelvváltó perzisztálás PATCH hívással, region store inicializálás onMounted-ban -### 🧩 CostEntryWizard lépések -1. **Alapadatok**: Jármű (read-only), kategória cascade (fő+alkategória), dátum -2. **Pénzügyek**: Nettó összeg, ÁFA kulcs (0/5/10/20/27%), Bruttó összeg (GROSS-FIRST), Pénznem -3. **Admin & Szállító**: Dinamikus vendor autocomplete (GET /organizations?org_type=SERVICE_PROVIDER) szabad szöveges fallbackkel, számlaszám, számla dátuma, fizetési határidő -4. **Fájlok**: Drag & drop fájl feltöltő UI (csak UI szintű file picker) +### ✅ 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 -### 🔌 API Integráció -- POST `/expenses/` a `costStore.addExpense()`-on keresztül AssetCostBase payload-dal -- Payload tartalmazza: amount_gross (GROSS-FIRST), category_id, currency, date, data JSONB (net_amount, vat_rate, invoice_number, invoice_date, payment_deadline, vendor_id, vendor_name, file_names) - -### ✅ Verifikáció -- Vite build: ✅ Sikeres (253 modules, 6.94s) -- Gitea kártya: #277 - -## 2026-06-23 - Dashboard Cost Card Navigation Fix & Dedicated Costs Page +## 2026-06-25 - P0 CRITICAL SECURITY & UI FIX - RBAC Middleware & Mock Data Removal ### 🎯 Cél -A dashboard költség kártya üres területére kattintva és a "További költségek" gombbal is a költségek oldalra navigálás. Dedikált CostsView oldal létrehozása vissza gombbal és garázs háttérrel. +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/src/views/costs/CostsView.vue`** (ÚJ) - Teljes költség oldal garázs háttérrel, vissza gombbal, költség táblázattal és paginációval -- **`frontend/src/router/index.ts`** - `/dashboard/costs` route hozzáadva a CostsView-hoz -- **`frontend/src/components/dashboard/CostsActionsCard.vue`** - Header bar kattinthatóvá téve + "További költségek" gomb átirányítva a `/dashboard/costs` oldalra -- **`frontend/src/layouts/PrivateLayout.vue`** - Hamburger menü "Költségek" navigáció `/dashboard/costs`-ra módosítva -- **`frontend/src/i18n/hu.ts`** - `costs.backToDashboard` kulcs hozzáadva -- **`frontend/src/i18n/en.ts`** - `costs.backToDashboard` kulcs hozzáadva +- `frontend_admin/middleware/auth.ts` — Teljes átírás: token cookie ellenőrzés után `authStore.fetchUser()` hívás, majd `authStore.user.role` ellenőrzés az allowed staff role-ok listája (`SUPERADMIN`, `ADMIN`, `MODERATOR`, `SALES_REP`, `SERVICE_MGR`) alapján. Ha a role nem staff szintű → `authStore.logout()` + `navigateTo('/login')`. +- `frontend_admin/layouts/default.vue` — `userEmail` computed fallback `'admin@servicefinder.hu'` → `'Ismeretlen Felhasználó'`, `userInitials` fallback `'AD'` → `'??'`, dropdown role label `'Administrator'` → dinamikus `authStore.userRole` alapú. -### ✅ Verifikáció -- Vite build: ✅ Sikeres (CostsView-DaFsqPnD.js chunk generálva) +### ✅ 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-23 - Hotfix: Backend Expenses GET / endpoint & AssetCost.organization FK fix +## 2026-06-25 - P0 Data Architecture: Populate Full EU Region Registry ### 🎯 Cél -Két kritikus backend hiba javítása: -1. A `GET /api/v1/expenses/` hívás 404-et adott (nem létezett `GET /` végpont), amit a reverse proxy 307-es HTTPS→HTTP átirányítással válaszolt, ami Mixed Content blokkolást okozott a böngészőben. -2. A backend indításkor `InvalidRequestError`-ral összeomlott az `AssetCost.organization` relationship hibás konfigurációja miatt (két FK ugyanarra a táblára, de a `foreign_keys` paraméter hiányzott). +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/app/api/v1/endpoints/expenses.py`** - `GET /` végpont hozzáadva: list_all_expenses() - szervezet összes költségének listázása paginációval, Asset, CostCategory, Organization JOIN-okkal -- **`backend/app/models/fleet_finance/models.py`** - `AssetCost.organization` relationship javítva: `foreign_keys=[organization_id]` paraméter hozzáadva a kétértelmű FK kapcsolat feloldásához +- `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 -- Backend konténer: ✅ Tisztán indul, nincs SQLAlchemy hiba -- Login: ✅ Működik (nem omlik össze) -- `GET /api/v1/expenses/`: ✅ Végpont elérhető, paginált költség listát ad vissza +### ✅ 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-23 - Hotfix #2: Expenses API 307 redirect / Mixed Content - trailing slash fix +## 2026-06-25 - Garages CRM Wiring & Custom B2B Deals UI ### 🎯 Cél -A `GET /api/v1/expenses` hívás 307-es HTTPS→HTTP átirányítást kapott, mert a backend route `@router.get("/")` (perjellel) volt definiálva, de a frontend `/expenses` (perjel nélkül) hívta. A Starlette automatikus 307 redirect-je a külső openresty proxy miatt `http://` címmé alakult → Mixed Content blokk. +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 fájlok -- **`backend/app/api/v1/endpoints/expenses.py`** - `@router.get("/")` → `@router.get("")` (perjel eltávolítva a route-ból) +### 🔧 Módosított/Létrehozott fájlok -### 🔧 Eredmények -- Backend konténer: ✅ Tisztán indul -- `GET /api/v1/expenses` most direkt egyezik a route-tal → nincs 307 redirect → nincs Mixed Content +**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) -## 2026-06-23 - Hotfix #3: Expenses API 500 Internal Server Error - AssetCost.cost_date → AssetCost.date +**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 -A `GET /api/v1/expenses` végpont 500-as hibát dobott: `AttributeError: type object 'AssetCost' has no attribute 'cost_date'`. Az `AssetCost` modellben a mező neve `date` (110. sor), de a kód `cost_date`-t használt. - -### 🔧 Módosított fájlok -- **`backend/app/api/v1/endpoints/expenses.py`** - 2 helyen javítva: - - 157. sor: `AssetCost.cost_date` → `AssetCost.date` - - 193. sor: `cost.cost_date.isoformat()` → `cost.date.isoformat()` - -### 🔧 Eredmények -- Backend konténer: ✅ Tisztán indul -- `GET /api/v1/expenses`: ✅ Várhatóan 200 OK (nem 500) - ---- - -## 2026-06-23: Dashboard üres AdPlacementWidget elrejtése - -### 🎯 Cél -A felhasználó kérésére: a dashboardon a "PRO" feliratú `SubscriptionStatusWidget` mellett egy üres csempe volt látható (`AdPlacementWidget`), mert nincs hirdetés beállítva a rendszerben. A kérés az volt, hogy rejtsük el ezt az üres csempét. - -### 🔧 Módosított fájlok -- **`frontend/src/components/dashboard/AdPlacementWidget.vue`** - `defineEmits` hozzáadva: `ads-loaded` esemény, amely jelzi a szülőnek, hogy van-e hirdetés (`hasAds: boolean`). Az esemény a `fetchAds` siker és hiba ágában is meghívásra kerül. -- **`frontend/src/views/DashboardView.vue`** - `adWidgetHasAds` ref hozzáadva (alapértelmezett: `false`). A hirdetési csempe wrapper `