Files
service-finder/.roo/history.md
2026-07-02 11:52:22 +00:00

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 object
  • admin_persons.py: AddressResponseAddressIn/AddressOut, PersonAddressUpdate tö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 flat address_* 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 types
  • update_organization: STEP 0 with 3 address_detail extraction + flat field mapping blocks (primary/billing/notification)
  • Response includes address_detail as 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_service uses city/address as plain Body() string params
  • Maps directly to ServiceStaging.city/ServiceStaging.address_line1
  • Simple crowdsourcing — AddressIn conversion would be over-engineering

8. Phase 4 — AddressResponse removal:

  • AddressResponse class completely removed from schemas/user.py
  • PersonResponse.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 pending stá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_name meg van adva, de service_provider_id nincs, meghívja a find_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_trgm extension telepítve
  • marketplace.source_type enum 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_cityGeoPostalCode.city (JOIN AddressGeoPostalCode)
  • Hozzáadva: outerjoin(Address, Organization.address_id == Address.id)
  • Hozzáadva: outerjoin(GeoPostalCode, Address.postal_code_id == GeoPostalCode.id)
  • Változás: row.address_cityrow.city a 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_cityorg.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ás IF EXISTS vé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

  1. backend/app/api/v1/endpoints/admin_providers.py:41 — Import csere: from app.models.marketplace.service import ServiceStagingfrom app.models.marketplace.staged_data import ServiceStaging
  2. backend/app/api/v1/endpoints/admin_providers.py:568address_detail=AddressOut(...)address_detail=None (get_provider_detail)
  3. backend/app/api/v1/endpoints/admin_providers.py:1340address_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:

  1. Organization Details 500 error - A fleet.organizations táblából fizikailag eltávolított denormalizált cím oszlopok (15 db: address_city, billing_zip, notification_street_name, stb.) miatt a PUT /{org_id} végpont setattr-nál 500-as hibát dobott, ha a frontend elküldte ezeket a mezőket.
  2. Provider Raw Data hiány - A GET /admin/providers/{id} végpont ServiceProvider rekordoknál nem adta vissza a raw_data mező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_FIELDS halmaz, amely tartalmazza mind a 15 ghost oszlopot
  • A update_organization függvény setattr ciklusa előtt ezek a mezők kiszűrésre kerülnek logger.warning kí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_detail ServiceProvider ágához hozzáadva: raw_data=sp.raw_data or {}
  • Ezzel a frontend RawDataViewer komponense valós adatokat kap, nem üres/mock állapotot

Verifikáció

  • Mindkét fájl Python szintaxis ellenőrzése: OK
  • sync_engine.py futtatá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_detail ServiceStaging ágában validation_score=0 volt 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, statusSubtextClass nem kezelték ezt a státuszt → piros (elutasított) stílust kapott
  • Fix: Mind a 4 computed property-hez hozzáadva a research_in_progress case 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, a research_in_progress a v-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_score mező értéke 0 a DB-ben, de a raw_data JSON tartalmazza: "trust_score": 20
  • Ez egy OSM scout bot enrichment pipeline hiányosság - a bot nem extractálja a trust_score-t a raw_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