frontend költség beállítások
This commit is contained in:
238
.roo/history.md
238
.roo/history.md
@@ -1,74 +1,204 @@
|
||||
# Service Finder Fejlesztési Történet
|
||||
|
||||
## 2026-06-14 - Admin Search Bugs Fix & Sticky UX
|
||||
## 2026-06-21 - P0 Deep Audit: Database Consistency & Zombie API Hunt
|
||||
|
||||
### 🎯 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).
|
||||
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.
|
||||
|
||||
### 🔧 Változtatások
|
||||
### 🔧 Eredmények
|
||||
|
||||
**1. BACKEND - [`admin.py`](backend/app/api/v1/endpoints/admin.py:502):**
|
||||
- `GET /admin/users` SQL javítás: `outerjoin(Person).outerjoin(Address)` → `outerjoin(Person).outerjoin(Address, ...)` (explicit ON clause a person_id-n)
|
||||
- `phone` keresés hozzáadva a `search_category`-hez (LIKE `person.phone`)
|
||||
- `is_active` és `is_deleted` filterek külön kezelése (nem zárják ki egymást)
|
||||
**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ó)
|
||||
|
||||
**2. FRONTEND - [`AdminUsersView.vue`](frontend/src/views/admin/AdminUsersView.vue):**
|
||||
- Bulk action bar: `sticky` pozícionálás (top-0, z-30)
|
||||
- Clear/X gomb a keresőmezőben
|
||||
- Üres állapot kezelés: "No users match your search" / "No users in the database yet."
|
||||
- HeaderProfile komponens hozzáadva az AdminLayout-hoz
|
||||
|
||||
### ✅ Verifikáció
|
||||
- `docker compose exec sf_api python3 -m pytest backend/tests/test_04_business_onboarding.py -v` → 7 passed
|
||||
- Manuális teszt: GET /admin/users?search_term=...&search_category=phone működik
|
||||
|
||||
## 2026-06-19 - P0 BUG FIX: VehicleDetails Blank Page & OverviewTab
|
||||
## 2026-06-23 - Cost Entry Wizard (CostEntryWizard.vue) - 4-lépéses Számla Űrlap
|
||||
|
||||
### 🎯 Cél
|
||||
A VehicleDetailsView üres oldalt (blank page) mutatott, amikor a Dashboardról vagy FleetView-ról navigáltak rá. A hiba oka a nem-reaktív tab definíciók és a hiányzó loading/error állapotkezelés volt. Emellett az OverviewTab csak egy placeholdert tartalmazott.
|
||||
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.
|
||||
|
||||
### 🔧 Változtatások
|
||||
### 🔧 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
|
||||
|
||||
**1. [`VehicleDetailsView.vue`](frontend/src/views/vehicles/VehicleDetailsView.vue) - Blank Page Fix:**
|
||||
- **Root Cause:** A `tabs` tömb `const`-ként volt definiálva, benne `computed()` ref-ekkel, amelyek sosem frissültek. A `v-for="tab in tabs"` nem volt reaktív.
|
||||
- **Fix:** A `tabs` tömböt `computed<TabDefinition[]>(() => [...])`-re cseréltük, így a teljes tömb reaktív.
|
||||
- **Loading State:** `v-if="isLoading"` spinner hozzáadva, ami akkor jelenik meg, ha `vehicleStore.isLoading` true VAGY a vehicles tömb üres és a vehicle még nincs betöltve.
|
||||
- **Error/Empty State:** `v-else-if="!vehicle"` üres állapot ikonnal és `t('vehicleDetail.notFound')` üzenettel.
|
||||
- **Vehicle Data Flow:** `provide('vehicle', vehicle)` használatával a jármű adatokat átadjuk a child tab komponenseknek.
|
||||
- **Async onMounted:** `await vehicleStore.fetchVehicles()` hívás, hogy direkt URL-es navigációnál (F5) is betöltődjenek az adatok.
|
||||
### 🧩 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)
|
||||
|
||||
**2. [`OverviewTab.vue`](frontend/src/components/vehicles/tabs/OverviewTab.vue) - Full Layout:**
|
||||
- **Photo Section:** 16:9 / négyzet alakú placeholder szürke háttérrel, kamera ikonnal és "Photo upload coming soon" felirattal.
|
||||
- **Basic Info:** Nagy, hangsúlyos rendszám (4xl), alatta brand/model (2xl), évjárat, majd elválasztó után VIN, üzemanyag típus, futásteljesítmény.
|
||||
- **Vital Signs (3 kártya):**
|
||||
- **MOT Expiry:** Naptár ikon, dátum megjelenítés, színkódolás (piros=lejárt, sárga=<30 nap, zöld=rendben).
|
||||
- **Current Mileage:** Villám ikon, formázott km érték.
|
||||
- **Next Service:** Dokumentum ikon, "Coming soon" placeholder (később a service book-hoz kapcsolva).
|
||||
- **Data Flow:** `inject<computed<Vehicle | null>>('vehicle')` a szülő komponensből.
|
||||
|
||||
**3. [`en.ts`](frontend/src/i18n/en.ts) - New i18n keys:**
|
||||
- `vehicleDetail.notFound`, `vehicleDetail.noPlate`, `vehicleDetail.photoPlaceholder`, `vehicleDetail.vin`, `vehicleDetail.fuelType`, `vehicleDetail.mileage`, `vehicleDetail.motExpiry`, `vehicleDetail.nextService`, `vehicleDetail.noData`, `vehicleDetail.comingSoon`
|
||||
### 🔌 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ó
|
||||
- A tab navigáció most már reaktív (`computed`-be csomagolt `tabDefinitions`)
|
||||
- A loading spinner megjelenik adatok betöltése közben
|
||||
- Az OverviewTab teljes layout-ja renderelődik: fotó placeholder + alapadatok + 3 vital signs kártya
|
||||
- A jármű adatok `provide`/`inject` mechanizmussal jutnak el a tab komponensekhez
|
||||
- Vite build: ✅ Sikeres (253 modules, 6.94s)
|
||||
- Gitea kártya: #277
|
||||
|
||||
## 2026-06-19 - FleetView jármű részletek navigációs hiba javítása
|
||||
## 2026-06-23 - Dashboard Cost Card Navigation Fix & Dedicated Costs Page
|
||||
|
||||
### 🎯 Cél
|
||||
A privát jármű oldalon (FleetView) a kártyákra kattintva nem nyílt meg a jármű teljes adatlapja az 5 aloldallal (Overview, TechData, ServiceBook, Financials, Documents).
|
||||
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.
|
||||
|
||||
### 🔧 Változtatások
|
||||
|
||||
**1. [`FleetView.vue`](frontend/src/views/vehicles/FleetView.vue:62):** A `@click` handler `router.push(\`/vehicles/\${vehicle.id}\`)` útvonalat használt, ami nem egyezik egyetlen regisztrált route-pal sem. A helyes útvonalak:
|
||||
- Privát mód: `/dashboard/vehicles/:id`
|
||||
- Céges mód: `/organization/:id/vehicles/:id`
|
||||
|
||||
Javítás: Az `openVehicleDetail()` függvény az `authStore.isCorporateMode` és `active_organization_id` alapján dinamikusan választja ki a megfelelő útvonalat, megegyező logikával, mint a [`MyVehiclesCard.vue`](frontend/src/components/dashboard/MyVehiclesCard.vue:72)-ben lévő `openVehicleDetail()`.
|
||||
### 🔧 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
|
||||
|
||||
### ✅ Verifikáció
|
||||
- A kártyára kattintás után a böngésző a `/dashboard/vehicles/:id` (privát) vagy `/organization/:id/vehicles/:id` (céges) útvonalra navigál
|
||||
- A `VehicleDetailsView.vue` betöltődik és megjeleníti az 5 tabot
|
||||
- A TypeScript fordítás hibátlan (csak pre-existing `.js` fájl warningok)
|
||||
- Vite build: ✅ Sikeres (CostsView-DaFsqPnD.js chunk generálva)
|
||||
|
||||
## 2026-06-23 - Hotfix: Backend Expenses GET / endpoint & AssetCost.organization FK fix
|
||||
|
||||
### 🎯 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).
|
||||
|
||||
### 🔧 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
|
||||
|
||||
### 🔧 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
|
||||
|
||||
## 2026-06-23 - Hotfix #2: Expenses API 307 redirect / Mixed Content - trailing slash fix
|
||||
|
||||
### 🎯 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.
|
||||
|
||||
### 🔧 Módosított fájlok
|
||||
- **`backend/app/api/v1/endpoints/expenses.py`** - `@router.get("/")` → `@router.get("")` (perjel eltávolítva a route-ból)
|
||||
|
||||
### 🔧 Eredmények
|
||||
- Backend konténer: ✅ Tisztán indul
|
||||
- `GET /api/v1/expenses` most direkt egyezik a route-tal → nincs 307 redirect → nincs Mixed Content
|
||||
|
||||
## 2026-06-23 - Hotfix #3: Expenses API 500 Internal Server Error - AssetCost.cost_date → AssetCost.date
|
||||
|
||||
### 🎯 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 `<div>`-je `v-if="adWidgetHasAds"` feltételt kapott, így csak akkor jelenik meg, ha az API ténylegesen adott vissza hirdetéseket. Az `@ads-loaded` esemény frissíti a ref értékét.
|
||||
|
||||
### ✅ Verifikáció
|
||||
- Frontend build: ✅ Sikeres (Vite build, 0 hiba)
|
||||
|
||||
## 2026-06-23 - P0 Fix: cost_date vs date mezőnév mismatch + CostsView.vue upgrade
|
||||
|
||||
### 🎯 Cél
|
||||
Két produkciós hiba javítása a cost rögzítésben:
|
||||
1. **P0 - 500 Internal Server Error** POST `/api/v1/expenses/` végponton: négyrétegű mezőnév-eltérés (`cost_date` vs `date`) a frontend, Pydantic séma, endpoint és SQLAlchemy model között.
|
||||
2. **P1 - `/dashboard/costs` oldal** nem mutatott semmilyen információt és nem volt költség hozzáadási lehetőség.
|
||||
|
||||
### 🔧 Módosított fájlok
|
||||
|
||||
**Fix 1a - Backend endpoint** (`backend/app/api/v1/endpoints/expenses.py:464`):
|
||||
- `cost_date=expense.cost_date` → `date=expense.cost_date` (SQLAlchemy model mezőneve `date`)
|
||||
|
||||
**Fix 1b - Backend Pydantic schema** (`backend/app/schemas/asset_cost.py:37`):
|
||||
- `validation_alias="date"` hozzáadva a `cost_date` mezőhöz, hogy mind a `date`, mind a `cost_date` kulcsot elfogadja
|
||||
|
||||
**Fix 2 - Frontend CostsView.vue** (`frontend/src/views/costs/CostsView.vue`):
|
||||
- Vezérlősáv hozzáadva járműszűrő dropdown-nal
|
||||
- "➕ Új Költség" gomb hozzáadva
|
||||
- CostEntryWizard integráció (modal formában)
|
||||
- Mezőnevek javítva: `cost_type` → `category_name`, `amount` → `amount_gross`, `vehicle_label` → `vehicle_name`
|
||||
- `useVehicleStore` importálva a járművek listájához
|
||||
|
||||
### ✅ Verifikáció
|
||||
- Python szintaxis: ✅ asset_cost.py OK, expenses.py OK
|
||||
- Backend indítás: ✅ Uvicorn fut, nincs hiba
|
||||
- Frontend build: ✅ Sikeres (Vite build 6.77s, 0 hiba)
|
||||
- Gitea kártyák: #278 (P0) és #279 (P1) lezárva
|
||||
|
||||
## 2026-06-23 - #280 Vizsgálat: Miért nem jelennek meg költségek?
|
||||
|
||||
### 🎯 Cél
|
||||
Annak kivizsgálása, hogy az admin@profibot.hu teszt felhasználó miért nem lát költségeket.
|
||||
|
||||
### 🔍 Vizsgálat
|
||||
- `fleet_finance.asset_costs` táblában összesen **1 rekord** van (org_id=43, asset=PTB162 Mazda 2, 18118 HUF, "Finanszírozás")
|
||||
- admin@profibot.hu (user_id=2) tagja: org 1 (Test Company), 57, 58, 62, 67
|
||||
- admin **NEM tagja** org 43-nak ("Accipe garage"), ahova az egyetlen költség tartozik
|
||||
- admin szervezeteiben (1, 57, 58, 62, 67) összesen **0 db költség** van
|
||||
|
||||
### ✅ Következtetés
|
||||
**NINCS backend/frontend hiba.** A probléma egyszerű **adathiány**:
|
||||
1. Nincs rögzítve költség admin egyetlen járművéhez sem
|
||||
2. Az egyetlen DB-ben lévő költség egy másik szervezethez tartozik
|
||||
3. A #278 és #279 javítások után most már lehetővé vált a költségrögzítés
|
||||
- Dokumentáció: `/opt/docker/docs/cost_visibility_investigation_280.md`
|
||||
|
||||
## 2026-06-23 - #281 Hotfix: Hiányos #278 javítás - expenses.py:533 new_cost.cost_date → new_cost.date
|
||||
|
||||
### 🎯 Cél
|
||||
A #278-as javítás hiányos volt: a konstruktor paramétert kijavítottuk (expenses.py:464: cost_date= → date=), de a response dict-ben (expenses.py:533) továbbra is `new_cost.cost_date`-et használtunk az SQLAlchemy AssetCost modellen, aminek a mezőneve `date`. Ez `AttributeError: 'AssetCost' object has no attribute 'cost_date'` hibát okozott minden POST /api/v1/expenses/ híváskor.
|
||||
|
||||
### 🔧 Módosított fájlok
|
||||
- **`backend/app/api/v1/endpoints/expenses.py:533`** - `new_cost.cost_date.isoformat()` → `new_cost.date.isoformat()`
|
||||
|
||||
### ✅ Verifikáció
|
||||
- Python szintaxis: ✅ OK
|
||||
- Backend újraindítás: ✅ OK (Application startup complete)
|
||||
- POST /api/v1/expenses/ teszt: ✅ **201 Created** - sikeres költség rögzítés a QWE432 járműre
|
||||
- Response tartalmazza: `"date":"2026-06-23T13:07:34.785065+00:00"` (helyes)
|
||||
- Gitea kártya: #281 lezárva
|
||||
|
||||
## 2026-06-23 - P0 Fix: User 28 Data Anomaly Resolution
|
||||
|
||||
### 🎯 Cél
|
||||
User 28 (tester_pro@profibot.hu) adat-anomália javítása ORM szkript segítségével.
|
||||
|
||||
### 🔧 Végrehajtott műveletek
|
||||
|
||||
**A) Org 1 javítása:** `fleet.organizations` ID=1 org_type átállítva `fleet_owner` → `individual`
|
||||
|
||||
**B) Tag hozzáadása:** `fleet.organization_members` rekord létrehozva: org=1, user=28, role=OWNER, status=active. Org 1 owner_id=28 beállítva.
|
||||
|
||||
**C) Scope törlése:** User 28 `scope_level` visszaállítva `individual`-ra (NOT NULL constraint miatt), `scope_id` None-ra.
|
||||
|
||||
**D) Fantom garázs törlése:** Org 68 ("Tester Garázsa") és hozzá tartozó OrganizationMember rekordok törlése.
|
||||
|
||||
### ✅ Verifikáció
|
||||
- Org 1: org_type=individual, owner_id=28
|
||||
- Org 1 Member: role=OWNER, status=active, is_verified=True
|
||||
- User 28: scope_level=individual, scope_id=None
|
||||
- Org 68: nem létezik (deleted)
|
||||
- Ideiglenes szkript törölve: `backend/scripts/fix_user_28.py`
|
||||
|
||||
## 2026-06-23 - P0 Cost Pipeline Visibility Audit (#282)
|
||||
|
||||
### 🔍 Felfedezés
|
||||
A `/dashboard/costs` oldal üres User 28 számára, annak ellenére, hogy Org 1-ben 5 db asset_cost rekord van (BMW123, QWE432).
|
||||
|
||||
### 🐛 Gyökér Ok
|
||||
A `GET /expenses/` endpoint (`backend/app/api/v1/endpoints/expenses.py:130-139`) a user első aktív tagságát használja org feloldáshoz (`.limit(1)` ORDER BY nélkül). User 28-nak 3 tagsága van: org 63 (ADMIN, nincs költség), org 21 (OWNER), org 1 (OWNER, 5 költség). Az első tagság org 63-ra mutat, ami üres.
|
||||
|
||||
### 📄 Dokumentáció
|
||||
`docs/cost_pipeline_audit.md` - Teljes pipeline audit a frontendtől a DB-ig.
|
||||
|
||||
Reference in New Issue
Block a user