Files
service-finder/.roo/history.md
2026-07-01 19:49:58 +00:00

132 lines
7.1 KiB
Markdown

# 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)