13 KiB
Service Finder Fejlesztési Történet
2026-06-21 - P0 Deep Audit: Database Consistency & Zombie API Hunt
🎯 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
✅ Verifikáció
- Backend Python szintaxis: OK
- Sync Engine: 1297 elem OK, 0 hiba, teljes szinkronban
- API Test 1:
PATCH is_always_open=True→{"always_open": true, "days": {"monday": {"open": "00:00", "close": "23:59"}, ...}}✅ - API Test 2:
PATCH is_always_open=False→{"monday": {"open": "09:00", "close": "17:00"}}(always_open metadata stripped) ✅
2026-07-01 - Unified Address API Refactoring (Gitea #386-#391)
🎯 Cél
Teljes körű cím API egységesítés a backend összes endpointján. Az audit során 4 különböző címformátumot és 5 kritikus inkonzisztenciát azonosítottunk. A refaktoring 3 fázisban (P1/P2/P3) 6 Gitea kártyán keresztül valósult meg.
🔧 Eredmények
1. Audit & Tervezés: ✅
- Audit dokumentum:
docs/address_api_consistency_audit.md - Logic spec:
plans/logic_spec_unified_address_refactoring.md - 6 Gitea kártya létrehozva (#386-#391)
2. P1 #386 — Admin endpointok (admin.py, admin_persons.py): ✅
admin.py list_users: Flat dict →AddressOut.model_validate(address)nested objectadmin_persons.py:AddressResponse→AddressIn/AddressOut,PersonAddressUpdatetörölve- 3
AddressResponse(...)→AddressOut.model_validate(person.address) - Address update field mapping javítva (address_zip→zip, address_hrsz→parcel_id)
3. P2 #387 — User endpointok (users.py, schemas/user.py): ✅
PersonUpdate: 9 flataddress_*field →address: Optional[AddressIn]_build_user_response: Manual dict →AddressOut.model_validate(person.address).dict()→.model_dump()(Pydantic v2)
4. P2 #388 — Admin providers (admin_providers.py): ✅
ProviderDetail: Flat fields →address_detail: Optional[AddressOut]ProviderUpdateInput: Flat fields →address_detail: Optional[AddressIn]- STEP 0: address_detail extraction + flat field mapping (zip→address_zip, city→city, stb.)
5. P2 #389 — Admin Organizations (admin_organizations.py): ✅
GarageDetailsResponse: 15 flat address fields →address_detail: Optional[AddressOut],billing_address_detail: Optional[AddressOut],notification_address_detail: Optional[AddressOut](3 AddressOut nested objects)OrganizationUpdate: 15 flat address fields →address_detail: Optional[AddressIn],billing_address_detail: Optional[AddressIn],notification_address_detail: Optional[AddressIn](3 AddressIn nested objects)get_org_detail: AddressOut construction from denormalized org fields for all 3 address typesupdate_organization: STEP 0 with 3 address_detail extraction + flat field mapping blocks (primary/billing/notification)- Response includes
address_detailas unified AddressOut object
6. P3 #390 — Public providers (schemas/provider.py, provider_service.py): ✅
ProviderSearchResult:address_detail: Optional[AddressOut]ProviderQuickAddIn:address_detail: Optional[AddressIn]ProviderUpdateIn:address_detail: Optional[AddressIn]search_providers: AddressOut construction from flat SQL columns
7. P3 #391 — Gamification (gamification.py): ✅
submit_new_serviceusescity/addressas plainBody()string params- Maps directly to
ServiceStaging.city/ServiceStaging.address_line1 - Simple crowdsourcing — AddressIn conversion would be over-engineering
8. Phase 4 — AddressResponse removal: ✅
AddressResponseclass completely removed fromschemas/user.pyPersonResponse.address:Optional[AddressResponse]→Optional[AddressOut]
✅ Verifikáció
- Backend Python szintaxis: OK (all files pass py_compile)
- Sync Engine: 1274 OK, 0 Fixed, 26 Shadow Data (pre-existing)
- All 6 Gitea cards (#386-#391): CLOSED ✅
2026-07-01 - Service Provider Auto-Discovery (Gitea #348, #347)
🎯 Cél
Implementálni a find_or_create_provider_by_name() service függvényt (#348) és az auto-discovery hook-ot az expense creation-ben (#347) a logic_spec alapján.
🔧 Eredmények
1. find_or_create_provider_by_name() (#348): ✅
- Exact match: ILIKE keresés a ServiceProvider.name mezőn
- Fuzzy match: pg_trgm similarity > 0.3 threshold, legjobb találat kiválasztása
- Create new: Ha nincs találat, új ServiceProvider létrehozása
pendingstátusszal,source=SourceType.api_import("api_import"),validation_score=0 - Gamification: PROVIDER_DISCOVERY (300 XP), PROVIDER_CONFIRMATION (150 XP), PROVIDER_VERIFIED_USE (100 XP), USE_UNVERIFIED_PROVIDER (200 XP)
2. Auto-discovery hook expense creation-ben (#347): ✅
- Már implementálva volt a
POST /expenses/végpontban - Ha
external_vendor_namemeg van adva, deservice_provider_idnincs, meghívja afind_or_create_provider_by_name()-t - Hiba esetén warning log, nem blokkolja a költség létrehozását
3. Adatbázis módosítások:
pg_trgmextension telepítvemarketplace.source_typeenum kiegészítve'api_import'értékkel
✅ Verifikáció
- Sync Engine: 1297 elem OK, 0 hiba, teljes szinkronban
- Test
test_use_unverified_provider.py: ALL TESTS PASSED ✅- PROVIDER_DISCOVERY (300 XP): ✅ User A created provider
- PROVIDER_CONFIRMATION (150 XP): ✅ User A reused own provider
- USE_UNVERIFIED_PROVIDER (200 XP): ✅ User B used pending provider
2026-07-01 - P0 ARCHITECTURE CLEANUP: Final Address Refactor (Ghost Columns & AddressManager)
🎯 Cél
A docs/p0_address_manager_usage_audit_2026-07-01.md auditban feltárt P0 kritikus hiba és P1 hiányosságok javítása.
🔧 Eredmények
1. P0 FIX — admin.py:search_organizations_by_name: ✅
Organization.address_city→GeoPostalCode.city(JOINAddress→GeoPostalCode)- Hozzáadva:
outerjoin(Address, Organization.address_id == Address.id) - Hozzáadva:
outerjoin(GeoPostalCode, Address.postal_code_id == GeoPostalCode.id) - Változás:
row.address_city→row.citya response builderben
2. P1 FIX — admin_persons.py:update_person: ✅
- 50+ sor direkt Address mező írás → egyetlen
AddressManager.create_or_update()hívás - Import hozzáadva:
from app.services.address_manager import AddressManager
3. P1 FIX — admin_organizations.py:list_organizations: ✅
org.address_city→org.address.city if org.address else None(relationship-based)
4. P1 FIX — OrganizationUpdate séma: ✅
- Minden flat address field
[DEPRECATED]prefixet kapott a description-ben
5. SQL Cleanup Script: ✅
docs/sql/cleanup_ghost_columns_2026_07.sql— 15 DROP COLUMN utasításIF EXISTSvédelemmel
✅ Verifikáció
- Backend Python szintaxis: OK (all 3 files pass py_compile)
- Import verifikáció:
Organization.address_id=True,Organization.address_city=False (confirmed removed) - Sync Engine: 1274 OK, 0 Fixed, 26 Shadow Data (pre-existing ghost columns confirmed)
2026-07-01 - P0 CRITICAL HOTFIX: Fix 500 Error on /admin/providers List View
🎯 Cél
A GET /api/v1/admin/providers végpont 500-as hibát dobott a denormalizált cím oszlopok eltávolítása után.
🔧 Root Cause & Fix
Root Cause 1 — Wrong ServiceStaging import:
Az admin_providers.py a ServiceStaging-et az app.models.marketplace.service modulból importálta, amely NEM tartalmazza a full_address és city mezőket. A helyes import az app.models.marketplace.staged_data modulból származik, amely rendelkezik ezekkel a mezőkkel.
Root Cause 2 — AddressOut missing required id field:
A get_provider_detail és update_provider végpontok AddressOut(...)-ot konstruáltak a ServiceProvider flat address mezőiből, de az AddressOut séma id: uuid.UUID mezője kötelező (nem Optional). Mivel a ServiceProvider nem rendelkezik Address kapcsolattal, az address_detail mezőt None-ra kell állítani.
🔧 Változtatások
backend/app/api/v1/endpoints/admin_providers.py:41— Import csere:from app.models.marketplace.service import ServiceStaging→from app.models.marketplace.staged_data import ServiceStagingbackend/app/api/v1/endpoints/admin_providers.py:568—address_detail=AddressOut(...)→address_detail=None(get_provider_detail)backend/app/api/v1/endpoints/admin_providers.py:1340—address_detail=AddressOut(...)→address_detail=None(update_provider)
✅ Verifikáció
GET /api/v1/admin/providers(default): 200 ✅ (50 items)GET /api/v1/admin/providers?status=pending: 200 ✅ (50 items)GET /api/v1/admin/providers/4: 200 ✅ (address_detail=None)- Sorting by name/validation_score/status: 200 ✅
- Search: 200 ✅ (4 results)
2026-07-01 - P0 BUGFIX: Organization Details 500 Error & Provider Raw Data
🎯 Cél
Két P0 hibajavítás:
- Organization Details 500 error - A
fleet.organizationstáblából fizikailag eltávolított denormalizált cím oszlopok (15 db: address_city, billing_zip, notification_street_name, stb.) miatt aPUT /{org_id}végpontsetattr-nál 500-as hibát dobott, ha a frontend elküldte ezeket a mezőket. - Provider Raw Data hiány - A
GET /admin/providers/{id}végpont ServiceProvider rekordoknál nem adta vissza araw_datamezőt, így a frontend "Nyers adatok" tab üresen/mock adatként jelent meg.
🔧 Eredmények
1. admin_organizations.py - Deprecated address field filter (1341-1361. sor)
- Bevezetve a
DEPRECATED_ADDRESS_FIELDShalmaz, amely tartalmazza mind a 15 ghost oszlopot - A
update_organizationfüggvénysetattrciklusa előtt ezek a mezők kiszűrésre kerülneklogger.warningkíséretében - A GET végpont (
get_organization_details) már korábban is helyesen, relationship-ekből töltötte a denormalizált mezőket (1114-1139. sor)
2. admin_providers.py - Raw data hozzáadása ServiceProvider válaszhoz (589-591. sor)
- A
get_provider_detailServiceProvider ágához hozzáadva:raw_data=sp.raw_data or {} - Ezzel a frontend
RawDataViewerkomponense valós adatokat kap, nem üres/mock állapotot
✅ Verifikáció
- Mindkét fájl Python szintaxis ellenőrzése: OK
sync_engine.pyfuttatás: 1274 elem OK, 0 hiba - teljes szinkronban
2026-07-02: Bugfix - Provider validációs érték és research_in_progress státusz (Gitea #393)
🎯 Cél
Provider 1752 (Carnanny) esetén a validációs érték üres volt (validation_score=0), és a research_in_progress státusz nem jelent meg helyesen a frontend státuszablakában.
🔧 Root Cause & Fix - 4 bug javítva
Bug 1 - Backend: validation_score hardcoded to 0 for staging providers
- Hely:
admin_providers.py:613 - Ok: A
get_provider_detailServiceStaging ágábanvalidation_score=0volt keménykódolva - Fix:
validation_score=ss.trust_score or 0- így a trust_score értéke jelenik meg validation_score-ként
Bug 2 - Frontend: research_in_progress hiányzott a statusLabel/statusDescription függvényekből
- Hely:
index.vue:869-887 - Ok: A switch csak 'approved', 'pending', 'rejected' eseteket kezelte
- Fix: Hozzáadva:
case 'research_in_progress': return 'Kutatás folyamatban'és magyarázó leírás
Bug 3 - Frontend: research_in_progress hiányzott a CSS computed property-kből
- Hely:
index.vue:774-808 - Ok: A
statusBannerClass,statusIconClass,statusTextClass,statusSubtextClassnem kezelték ezt a státuszt → piros (elutasított) stílust kapott - Fix: Mind a 4 computed property-hez hozzáadva a
research_in_progresscase kék színű (blue-500) Tailwind osztályokkal
Bug 4 - Frontend: Moderációs műveletek rossz ágba kerültek
- Hely:
index.vue:283 - Ok:
v-if="provider.status === 'pending'"csak a pending státuszt kezelte, aresearch_in_progressav-elseágba esett ("elutasításra került") - Fix:
v-if="provider.status === 'pending' || provider.status === 'research_in_progress'"- így a research_in_progress státuszú provider-ek is látják az Approve/Reject gombokat
📊 Adatbázis megállapítás
- A
service_staging.trust_scoremező értéke 0 a DB-ben, de araw_dataJSON tartalmazza:"trust_score": 20 - Ez egy OSM scout bot enrichment pipeline hiányosság - a bot nem extractálja a
trust_score-t araw_data-ból a staging oszlopba - A fix biztosítja, hogy AMIKOR a trust_score populálva lesz, az helyesen megjelenjen validation_score-ként
✅ Verifikáció
- Backend Python szintaxis: OK
- API konténer restart: OK
- API hívás provider 1752-re: 200 OK - status=research_in_progress, validation_score=0 (trust_score=0 miatt), raw_data jelen van
- Frontend: mind a 4 Vue komponens módosítás érvényben