228 lines
14 KiB
Markdown
228 lines
14 KiB
Markdown
# 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`](backend/app/api/v1/endpoints/admin.py:502):**
|
||
- `GET /admin/users` SQL javítás: `Address` outerjoin-ra változtatva (`isouter=True`), hogy a cím nélküli userek is visszajöjjenek
|
||
- Telefonszám keresés: `phone` mező hozzáadva a `or_()` feltételhez
|
||
|
||
**2. FRONTEND - [`AdminLayout.vue`](frontend/src/layouts/AdminLayout.vue:1):**
|
||
- `HeaderProfile` komponens beillesztve a jobb felső sarokba (belépett user avatar + név)
|
||
- A `SidebarToggle` gomb fixálva a sidebar szélén
|
||
|
||
**3. FRONTEND - [`AdminUsersView.vue`](frontend/src/views/AdminUsersView.vue:1):**
|
||
- **Sticky Bulk Action Bar:** A tömeges műveletek sáv (`BulkActionBar`) `sticky` pozícionálást kapott, hogy görgetéskor is látszódjon
|
||
- **Clear/X gomb:** A keresőmezőbe egy `X` gomb került, ami egy kattintással törli a keresési feltételt
|
||
|
||
## 2026-06-16 - Fix 404 API Router & Redesign Dashboard Launcher Card
|
||
|
||
### 🎯 Cél
|
||
A Dashboard Service Finder kártya (Card 3) átalakítása elegáns, kétgombos indítópulttá (Launcher), valamint a providers API 404 hiba kivizsgálása és javítása.
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. BACKEND AUDIT - [`api.py`](backend/app/api/v1/api.py:38):**
|
||
- Ellenőrizve: `providers` router regisztrálva van (`include_router(providers.router, prefix="/providers")`)
|
||
- Ellenőrizve: providers végpontokon NINCS trailing slash (`/categories`, `/search`, `/quick-add`)
|
||
- **Route-ok élőben is ellenőrizve:** `GET /api/v1/providers/categories`, `GET /api/v1/providers/search`, `POST /api/v1/providers/quick-add` mind aktívak
|
||
|
||
**2. FRONTEND - [`ProviderQuickAddModal.vue`](frontend/src/components/provider/ProviderQuickAddModal.vue:223):**
|
||
- `fetchCategories()` már rendelkezik try/catch blokkal, 11 hardcoded fallback kategóriával
|
||
- Nincs szükség módosításra
|
||
|
||
**3. FRONTEND - [`DashboardView.vue`](frontend/src/views/DashboardView.vue:187):**
|
||
- **Card 3 teljes átalakítása:** A 3-lépéses kontextuális kereső űrlap (input, 2 dropdown, keresés gomb) ELTÁVOLÍTVA
|
||
- **Launcher dizájn:** Két nagy gomb, szépen formázva:
|
||
- `🔍 Szervizek Keresése` — nagy, zöld gradient gomb, `isSearchModalOpen` modalt nyit
|
||
- `➕ Új Szolgáltató Rögzítése` — szekunder, dashed border gomb, `isSfQuickAddOpen` modalt nyit (meglévő ProviderQuickAddModal)
|
||
- **Search Modal (Placeholder):** Teleportált modál, benne: `🔍` ikon, "Részletes kereső térképpel hamarosan..." szöveg, fejlesztés alatt státusz
|
||
- Régi `sfSearchLocation`, `sfSearchCategory`, `sfSearchVehicleId`, `sfCategories`, `fetchSfCategories()`, `onSfSearch()` eltávolítva
|
||
|
||
## 2026-06-17 - P0 Bugfix: Provider Data Persistence & Schema Alignment
|
||
|
||
### 🎯 Cél
|
||
Kritikus adatperzisztencia hiba javítása a Service Finder Provider rendszerében. A frontend edit modal nem hívott backend API-t, így a szerkesztett adatok elvesztek. Emellett a contact mezők (phone, email, website, tags) nem kerültek perzisztálásra a quick-add során, és a search nem adta vissza ezeket.
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. BACKEND - [`provider.py`](backend/app/schemas/provider.py:1) (NEW):**
|
||
- `ProviderQuickAddIn`: `contact_phone`, `contact_email`, `website`, `tags` mezők hozzáadva
|
||
- `ProviderSearchResult`: `address_zip`, `contact_phone`, `contact_email`, `website`, `tags` mezők hozzáadva
|
||
- `ProviderUpdateIn` (NEW): name, city, address_zip, street, contact_phone, contact_email, website, tags
|
||
- `ProviderUpdateResponse` (NEW): id, name, status, message
|
||
|
||
**2. BACKEND - [`provider_service.py`](backend/app/services/provider_service.py:486):**
|
||
- `quick_add_provider()`: contact mezők mentése ServiceProfile-ba
|
||
- `search_providers()`: LEFT JOIN ServiceProfile, contact mezők visszaadása
|
||
- `update_provider()` (NEW): Organization + ServiceProfile atomi frissítése
|
||
|
||
**3. BACKEND - [`providers.py`](backend/app/api/v1/endpoints/providers.py:134):**
|
||
- `PUT /providers/{id}` végpont hozzáadva (authentikált, hibakezeléssel)
|
||
|
||
**4. FRONTEND - [`ProviderEditModal.vue`](frontend/src/components/provider/ProviderEditModal.vue:191):**
|
||
- **CRITICAL FIX**: `handleSave()` most `api.put()`-et hív, nem csak eventet emitál
|
||
- `@save` → `@saved` (past tense, API call után)
|
||
- `address_zip`, `contact_phone`, `contact_email`, `website`, `tags` mezők támogatása
|
||
- `source` kivéve a payload-ból (backend-only)
|
||
|
||
**5. FRONTEND - [`ProviderQuickAddModal.vue`](frontend/src/components/provider/ProviderQuickAddModal.vue:253):**
|
||
- Telefon, email, weboldal, címkék mezők hozzáadva a formhoz
|
||
- Tag management (vessző/pontosvessző parsing, remove gomb)
|
||
- Payload bővítése contact mezőkkel
|
||
|
||
**6. FRONTEND - [`ServiceFinderView.vue`](frontend/src/views/ServiceFinderView.vue:375):**
|
||
- `@save` → `@saved` event binding
|
||
- `handleEditSaved()`: mentés után automatikus keresés újrafuttatás
|
||
|
||
### ✅ Verifikáció
|
||
- `sync_engine` lefuttatva: **1061 elem OK, 0 javítás, 0 shadow data** - rendszer tökéletesen szinkronban
|
||
|
||
## 2026-06-17 - P1 Critical Align: Atomizált címmezők a Provider sémákban
|
||
|
||
### 🎯 Cél
|
||
A `street: Optional[str]` mező eltávolítása és helyette atomizált címmezők (`address_street_name`, `address_street_type`, `address_house_number`) bevezetése a Pydantic sémákban, backend service-ben és frontend űrlapokon. A kapcsolatfelvételi adatok (contact_phone, contact_email, website, tags) a ServiceProfile-ba kerülnek.
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. BACKEND - [`provider.py`](backend/app/schemas/provider.py):**
|
||
- `street` mező ELTÁVOLÍTVA a `ProviderQuickAddIn` és `ProviderUpdateIn` sémákból
|
||
- `address_street_name`, `address_street_type`, `address_house_number` mezők HOZZÁADVA mindkét sémához
|
||
- `ProviderSearchResult` bővítve az atomizált címmezőkkel
|
||
|
||
**2. BACKEND - [`provider_service.py`](backend/app/services/provider_service.py):**
|
||
- `quick_add_provider()`: `data.street` → `data.address_street_name`, `data.address_street_type`, `data.address_house_number` az Organization és Branch táblákban
|
||
- `update_provider()`: ugyanez az atomizált címkezelés
|
||
- `search_providers()`: az org SELECT most már tartalmazza az `address_street_name`, `address_street_type`, `address_house_number` mezőket
|
||
- A Branch létrehozásánál a `street_name`, `street_type`, `house_number` mezők külön-külön töltődnek
|
||
|
||
**3. FRONTEND - [`ProviderQuickAddModal.vue`](frontend/src/components/provider/ProviderQuickAddModal.vue):**
|
||
- A régi egyesített "Cím (Utca, házszám)" mező helyett 3 külön mező: Utca neve (text), Közterület jellege (select/dropdown 15 opcióval), Házszám (text)
|
||
- Payload az új atomizált kulcsokkal megy a backend felé
|
||
|
||
**4. FRONTEND - [`ProviderEditModal.vue`](frontend/src/components/provider/ProviderEditModal.vue):**
|
||
- Ugyanaz a 3 mezős szétbontás, a form populate az atomizált mezőkből történik
|
||
- Payload atomizált kulcsokkal
|
||
|
||
**5. FRONTEND - [`ProviderDetailModal.vue`](frontend/src/components/provider/ProviderDetailModal.vue):**
|
||
- Az intelligens címösszefűzés (`formattedAddress` computed) a `provider.address_street_name + ' ' + provider.address_street_type + ' ' + provider.address_house_number` alapján történik
|
||
- `hasAddress` computed ellenőrzi az atomizált mezők meglétét
|
||
|
||
### ✅ Verifikáció
|
||
- `sync_engine` lefuttatva: **1061 elem OK, 0 javítás, 0 shadow data** - rendszer tökéletesen szinkronban
|
||
- Python syntax check: minden fájl szintaktikailag helyes
|
||
|
||
## 2026-06-17 - Provider Update & Search Fix Csomag (#264)
|
||
|
||
### 🎯 Cél
|
||
Két kritikus hiba javítása a provider endpointokban:
|
||
1. **PUT /providers/{id} → 404**: A konténer nem volt újraindítva a providers modul kódváltoztatásai után
|
||
2. **GET /providers/search → 500**: `.astext` hiba JSONB subscripten + UNION oszlopszám mismatch
|
||
3. **Multi-source update**: Az `update_provider` csak Organization-ben keresett, de a search 3 forrást használ
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. BACKEND - [`provider_service.py:207`](backend/app/services/provider_service.py:207):**
|
||
- `.astext` → `cast()` javítás: `Organization.external_integration_config["source"].astext` → `cast(Organization.external_integration_config["source"], String)`
|
||
- **Root cause**: JSON oszlop subscript-je `BinaryExpression`-t ad vissza, amelyen nincs `.astext`
|
||
|
||
**2. BACKEND - [`provider_service.py:232-274`](backend/app/services/provider_service.py:232):**
|
||
- UNION oszlopszám mismatch javítva: staging és crowd SELECT-ekhez hozzáadva a hiányzó `contact_phone`, `contact_email`, `website`, `specialization_tags` mezők (14 oszlopra egységesítve)
|
||
|
||
**3. BACKEND - [`provider_service.py:477-622`](backend/app/services/provider_service.py:477):**
|
||
- Multi-source update logika: `update_provider()` most már mindhárom forrást támogatja:
|
||
1. `fleet.organizations` (verified orgs) - közvetlen frissítés
|
||
2. `marketplace.service_staging` (robot adatok) - migrálás Organization-be
|
||
3. `marketplace.service_providers` (crowdsourced) - migrálás Organization-be
|
||
|
||
**4. INFRA - [`pre_start.sh`](backend/app/scripts/pre_start.sh):**
|
||
- Dokumentálva: a `uvicorn` `--reload` nélkül fut, kódváltoztatás után `docker compose restart sf_api` szükséges
|
||
|
||
**5. BACKEND - [`provider_service.py:578-596`](backend/app/services/provider_service.py:578):**
|
||
- **Adatvédelmi javítás (2026-06-17):** A címmezők (`address_city`, `address_zip`, `address_street_name`, `address_street_type`, `address_house_number`) most már **csak akkor íródnak felül**, ha a frontend explicit nem-`null` értéket küld. Ez megakadályozza, hogy a meglévő címadatok véletlenül `null`-ra állítódjanak, amikor a felhasználó csak más mezőket szerkeszt.
|
||
- **Trigger:** A Gitea kártya visszautasításra került (`denied` státusz) a felhasználó által: *"az adatok tárolása minden esetben bontottan történjen meg és ha hiányzik valamelyik az alap cím tárolási adatból akkor vissza kell tenni."*
|
||
|
||
### ✅ Verifikáció
|
||
- **PUT /providers/58**: 200 OK ✅
|
||
- **PUT /providers/58 (partial update - csak zip)**: 200 OK ✅ (többi mező nem nullázódik)
|
||
- **GET /providers/search?q=Dunakeszi**: 200 OK ✅ (2 provider)
|
||
- **GET /providers/categories**: 200 OK ✅ (11 categories)
|
||
- **Login**: 200 OK ✅
|
||
|
||
## 2026-06-17 - i18n: Hiányzó provider címmező fordítások hozzáadása
|
||
|
||
### 🎯 Cél
|
||
A ProviderEditModal.vue 6 darab `provider.*` i18n kulcsa hiányzott mindkét nyelvi modulból (`hu.ts`, `en.ts`), így a felhasználói felületen a kulcsnevek (pl. `provider.streetNameLabel`) jelentek meg a lefordított szöveg helyett.
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. FRONTEND - [`hu.ts`](frontend/src/i18n/hu.ts:1300):**
|
||
- `provider.streetNameLabel`: `'Utca neve'`
|
||
- `provider.streetNamePlaceholder`: `'Pl. Egressy'`
|
||
- `provider.streetTypeLabel`: `'Közterület jellege'`
|
||
- `provider.streetTypePlaceholder`: `'Válassz típust...'`
|
||
- `provider.houseNumberLabel`: `'Házszám'`
|
||
- `provider.houseNumberPlaceholder`: `'Pl. 4'`
|
||
|
||
**2. FRONTEND - [`en.ts`](frontend/src/i18n/en.ts:1300):**
|
||
- `provider.streetNameLabel`: `'Street Name'`
|
||
- `provider.streetNamePlaceholder`: `'e.g. Egressy'`
|
||
- `provider.streetTypeLabel`: `'Street Type'`
|
||
- `provider.streetTypePlaceholder`: `'Select type...'`
|
||
- `provider.houseNumberLabel`: `'House Number'`
|
||
- `provider.houseNumberPlaceholder`: `'e.g. 4'`
|
||
|
||
### ✅ Verifikáció
|
||
- Mindkét i18n fájl szintaktikailag helyes (Node.js require sikeres)
|
||
- A ProviderEditModal.vue összes `t('provider.*')` hívása le van fedve
|
||
|
||
## 2026-06-17 - "Dunakeszi, Dunakeszi" duplikáció javítása + irányítószám megjelenítés
|
||
|
||
### 🎯 Cél
|
||
A szervizkereső oldalon a kártyán "Dunakeszi, Dunakeszi" duplikált városnév jelent meg, mert a backend `address` mezője megegyezett a `city` mezővel. A részletes nézetből hiányzott az irányítószám.
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. BACKEND - [`provider_service.py`](backend/app/services/provider_service.py:198):**
|
||
- Az `address` mezőt `Organization.address_city.label("address")`-ről `func.concat(...)`-re változtattuk, ami az összes atomizált címmezőt (irányítószám, város, utca, közterület, házszám) fűzi össze.
|
||
- Példa eredmény: `"2120 Dunakeszi, Egressy utca 4"` a korábbi `"Dunakeszi"` helyett.
|
||
|
||
**2. FRONTEND - [`ServiceFinderView.vue`](frontend/src/views/ServiceFinderView.vue:543):**
|
||
- Új `formatCardAddress(provider)` metódus, ami a kártyán az atomizált címmezőkből építi fel a címet.
|
||
- Fallback: ha nincs atomizált adat, a backend által összefűzött `address` mezőt használja.
|
||
|
||
**3. FRONTEND - [`ProviderDetailModal.vue`](frontend/src/components/provider/ProviderDetailModal.vue:237):**
|
||
- A `formattedAddress` computed property most már tartalmazza az `address_zip` mezőt is.
|
||
- Formátum: `"2120 Dunakeszi, Egressy utca 4"`
|
||
|
||
### ✅ Verifikáció
|
||
- Backend API: `GET /api/v1/providers/search?city=Dunakeszi` → `address` = `"2120 Dunakeszi, Egressy utca 4"` ✅
|
||
- Backend API: Autónyíri Kft. (id=58) → `address_zip=2120`, `address_street_name=Egressy`, `address_street_type=utca`, `address_house_number=4` ✅
|
||
- Frontend build: `npm run build` sikeres, 0 hiba ✅
|
||
- Backend konténer újraindítva: `docker compose restart sf_api` ✅
|
||
|
||
## 2026-06-17 - Kártya fő szolgáltatás (category) mindig megjelenítése
|
||
|
||
### 🎯 Cél
|
||
A szervizkereső kártyákon a fő szolgáltatás (category) mindig látszódjon. Ha van, akkor a kategória neve, ha nincs, akkor egy szaggatott vonalú placeholder.
|
||
|
||
### 🔧 Változtatások
|
||
|
||
**1. FRONTEND - [`ServiceFinderView.vue:263`](frontend/src/views/ServiceFinderView.vue:263):**
|
||
- A category badge `v-if="provider.category"` helyett `v-if`/`v-else` szerkezet:
|
||
- Ha van category: `bg-sf-accent/10` háttér, `text-sf-accent` szín
|
||
- Ha nincs: szaggatott vonalú (`border-dashed`) placeholder "Nincs kategória" / "No category"
|
||
|
||
**2. FRONTEND - [`hu.ts:1237`](frontend/src/i18n/hu.ts:1237):**
|
||
- `serviceFinder.noCategory`: `'Nincs kategória'`
|
||
|
||
**3. FRONTEND - [`en.ts:1237`](frontend/src/i18n/en.ts:1237):**
|
||
- `serviceFinder.noCategory`: `'No category'`
|
||
|
||
### ✅ Verifikáció
|
||
- Frontend build: `npm run build` sikeres, 0 hiba ✅
|