# 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`: `AddressResponse` → `AddressIn`/`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_city` → `GeoPostalCode.city` (JOIN `Address` → `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.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_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á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)