Files
service-finder/.roo/history.md

228 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 ✅