admin_szolgáltatók_

This commit is contained in:
Roo
2026-07-01 02:27:38 +00:00
parent 189cbfd7ca
commit 6e627d0ebe
491 changed files with 20965 additions and 9703 deletions

View File

@@ -0,0 +1,102 @@
# Logic Spec: Pontszabalyok Admin Oldal Javitasa
## Modul Celja es Masterbook 2 Illeszkedes
- **Modul:** Gamification -> Admin -> Point Rules
- **Masterbook 2 kapcsolat:** Admin felulet a gamification pontszabalyok kezelesere (CRUD)
- **Jelenlegi allapot:** Backend API 100%-ig funkcionalis, frontenden i18n kulcs mismatch es hianyzó inline szerkesztes
## Audit Eredmenyek
### Backend API (admin_gamification.py) - igenyel valtoztatast
- GET /admin/gamification/point-rules - Listazas, minden mezovel
- POST /admin/gamification/point-rules - Letrehozas, 409-es duplicate_key hibaval
- PUT /admin/gamification/point-rules/{id} - Reszleges frissites exclude_unset=True
- DELETE /admin/gamification/point-rules/{id} - Soft-delete (is_active=False)
- PointRule modell: id, action_key (unique), points, description, is_active - minden szerkesztheto
- **Kovetkeztetes:** Backend modositas NEM szukseges
### Frontend i18n Kulcs Mismatch - 13 hibas kulcs
A Vue template (point-rules.vue) rossz i18n kulcsokat hasznal. A locale fajlok (en.json, hu.json) tartalmazzak a helyes kulcsokat.
| # | Template hasznal | Helyes kulcs (locale) | Sor |
|---|-----------------|----------------------|-----|
| 1 | col_id | id | 41 |
| 2 | col_action_key | action_key | 42 |
| 3 | col_points | points | 43 |
| 4 | col_description | description | 44 |
| 5 | col_status | status | 45 |
| 6 | col_actions | actions | 46 |
| 7 | create_btn | create | 32 |
| 8 | empty | no_items | 83 |
| 9 | load_error | error | 21 |
| 10 | duplicate_error | duplicate_key | 316 |
| 11 | delete_confirm_title | delete_title | 168 |
| 12 | delete_confirm_body (param: {action_key}) | delete_confirm (param: {name}) | 170 |
| 13 | active_label | is_active | 143 |
### Hianzo Funkcio: Inline Szerkesztes
- Jelenleg csak modal (popup) alapu szerkesztes erheto el a ceruza ikonra kattintva
- A tablazat cellai csak olvashatoak (read-only)
- A felhasznalo kerese: kattintasra inline szerkesztes
## Tervezett Valtoztatasok
### 1. i18n Kulcsok Javitasa (point-rules.vue)
Csak a frontend_admin/pages/gamification/point-rules.vue fajlban kell a template i18n hivasokat javitani.
**Valtoztatasok (13 helyen):**
1. 41. sor: th col_id -> th id
2. 42. sor: th col_action_key -> th action_key
3. 43. sor: th col_points -> th points
4. 44. sor: th col_description -> th description
5. 45. sor: th col_status -> th status
6. 46. sor: th col_actions -> th actions
7. 32. sor: create_btn -> create
8. 83. sor: empty -> no_items
9. 21. sor: load_error -> error
10. 316. sor: duplicate_error -> duplicate_key
11. 168. sor: delete_confirm_title -> delete_title
12. 170. sor:
- Kulcs: delete_confirm_body -> delete_confirm
- Parameter: { action_key: deletingRule?.action_key } -> { name: deletingRule?.action_key }
13. 143. sor: active_label -> is_active
### 2. Inline Szerkesztes Bevezetese (point-rules.vue)
Megkozelites: Click-to-edit minta. Amikor a felhasznalo rakattingat egy cella ertekere, az egy inline input mezove alakul.
**Mely mezők legyenek inline szerkeszthetoek:**
- action_key (52-54. sor) - szoveges input
- points (55-58. sor) - number input
- description (60. sor) - szoveges input
- is_active statusz (61-64. sor) - toggle/click
**Implementacios terv (Vue 3 Composition API):**
Uj state valtozok:
- editingCell = ref null - { id: number; field: string }
- editValue = ref null - string | number | boolean
Uj metodusok:
- startEdit(rule, field) - beallitja az editingCell-t es editValue-t
- cancelEdit() - torli az editingCell-t
- saveEdit(rule, field) - PUT /admin/gamification/point-rules/{id} a modositott mezovel
Template modositas: Minden cella kap egy @click handler-t, ami elinditja az inline szerkesztest. Az input mezok Enter/Blur eseteben mentenek, Escape eseteben megszakitjak.
## Valtoztatas Nelkuli Fajlok
- backend/app/api/v1/endpoints/admin_gamification.py - backend API teljesen megfelelo
- backend/app/models/gamification/gamification.py - PointRule modell helyes
- frontend_admin/i18n/locales/en.json - kulcsok rendben
- frontend_admin/i18n/locales/hu.json - kulcsok rendben
## Csak Valtoztatando Fajlok
- frontend_admin/pages/gamification/point-rules.vue - i18n javitas + inline szerkesztes
## Tesztelesi Terv
1. i18n: Minden oszlopfejlecben, gombon es uzenetben a forditott szoveg jelenjen meg
2. Inline szerkesztes: Kattintasra jelenjen meg az input mezo, Enter/Blur mentse, Escape szakitsa meg
3. Meglevo funkciok: A modal alap CRUD tovabbra is mukodjon

View File

@@ -0,0 +1,469 @@
# 🔧 Logic Spec: Service Provider Discovery & Admin Integration
**Verzió:** 1.1
**Dátum:** 2026-06-30
**Állapot:** Tervezet (Architect Review)
**Kapcsolódó Mérföldkő:** Service Finder Marketplace & Expense Integration
---
## 1. 🎯 Modul Célja és Masterbook 2.0 Illeszkedés
### Cél
A rendszer jelenleg három párhuzamos szolgáltatói adatforrással dolgozik:
1. **Crowdsourced** (`marketplace.service_providers`) — Közösség által beküldött, moderálandó
2. **Robot-hunted** (`marketplace.service_staging`) — Automata felderítésből
3. **Szervezeti** (`fleet.organizations`) — Hivatalos garázs/szerviz profilok
A jelenlegi hiányosság: **Nincs automatikus felderítés**, amikor egy felhasználó költséget rögzít és egy ismeretlen szolgáltatói névvel találkozik. Emellett **nincs admin felület** a crowdsourced szolgáltatók moderálására.
### Masterbook 2.0 Illeszkedés
- **P0 Hybrid Vendor Refactor** — már megalapozta a `ServiceProvider` modellt és a `quick_add_provider()` szolgáltatást
- **Gross-First Könyvelés** — a költség rögzítés az expense creation flow része
- **Triple Wallet / Gamification** — a felderítés pontozható (XP a discovered provider-ekért)
- **Dual Control (Moderation)** — a feltöltött/felderített szolgáltatóknak moderáción kell átesniük
---
## 2. 📊 Existing Module Map — Teljes Körkép
### 2.1 Modellek
| Modell | Tábla (Schema) | Fájl | Cél |
|--------|---------------|------|-----|
| `ServiceProvider` | `marketplace.service_providers` | `identity/social.py:22` | Crowdsourced providers, moderációval |
| `ServiceProfile` | `marketplace.service_profiles` | `marketplace/service.py:21` | Enriched profile (trust score, location) |
| `ServiceStaging` | `marketplace.service_staging` | `marketplace/service.py:162` | Robot-hunted, approval pending |
| `ExpertiseTag` | `marketplace.expertise_tags` | `marketplace/service.py:83` | 4-level taxonomy |
| `ServiceExpertise` | `marketplace.service_expertise` | `marketplace/service.py:146` | Junction table |
| `AssetCost` | `fleet_finance.asset_costs` | `fleet_finance/models.py:109` | Költség rekord 3 vendor mezővel |
| `Organization` | `fleet.organizations` | `marketplace/organization.py:73` | Hivatalos garázs/szerviz szervezetek |
### 2.2 Service Layer
| Service | Fájl | Funkciók |
|---------|------|----------|
| `search_providers()` | `provider_service.py:138` | Unified search, geo-filter, trust score |
| `quick_add_provider()` | `provider_service.py:473` | Gyors ServiceProvider létrehozás + gamification |
| `update_provider()` | `provider_service.py:804` | Provider adatok frissítése |
| `CostService.record_cost()` | `cost_service.py:23` | Teljes költségrögzítés |
### 2.3 API Endpointok
| Végpont | Prefix | Fájl | Funkció |
|---------|--------|------|---------|
| `GET /providers/search` | `/providers` | `providers.py:184` | Unified service search |
| `POST /providers/quick-add` | `/providers` | `providers.py:243` | Quick add provider |
| `PUT /providers/{id}` | `/providers` | `providers.py:279` | Update provider |
| `POST /expenses/` | `/expenses` | `expenses.py:439` | Create expense (hook pont!) |
| `GET /categories/tree` | `/providers` | `providers.py:46` | Category tree |
| `POST /admin/services/{staging_id}/approve` | `/admin` | `admin.py:238` | Staged service approval |
| `GET/POST/PUT admin/gamification/...` | `/admin/gamification` | `admin_gamification.py:1` | Gamification admin |
| `GET/PATCH admin/organizations/...` | `/admin/organizations` | `admin_organizations.py:1` | Organization CRM |
### 2.4 Frontend Admin (Hiányzó oldalak)
Jelenlegi admin oldalak: `frontend_admin/pages/`
- `dashboard`, `users`, `persons`, `garages`, `packages`, `permissions`
- `gamification/*` (9 oldal)
- **NINCS:** `providers/`, `services/`, `marketplace/` oldal
---
## 3. 🔄 Auto-Discovery Flow: Expense → Provider Creation
### 3.1 Trigger Flow Diagram
```mermaid
flowchart TD
A[POST /expenses/] --> B{external_vendor_name\nmegadva?}
B -->|Nem| C[Normál költség rögzítés]
B -->|Igen| D{service_provider_id\nmegadva?}
D -->|Igen| E[Link meglévő providerhez]
D -->|Nem| F[Név egyeztetés\nServiceProvider táblában]
F --> G{Találat?}
G -->|Igen, pontosan| H[Auto-link meglévőhöz]
G -->|Igen, hasonló| I[Lehetőség: auto-link\nvagy új pending]
G -->|Nem| J[Új ServiceProvider létrehozása]
J --> K[status=pending\nsource=import\nvalidation_score=0]
K --> L[added_by_user_id =\nköltséget rögzítő user]
L --> M[Gamification XP jutalmazás]
M --> N[AssetCost.service_provider_id \n= új provider.id]
N --> O[Commit + response]
```
### 3.2 Implementációs Részletek
**Hook pont:** `expenses.py:566-588` — Az AssetCost példányosítás előtt
**Logikai lépések a `create_expense`-ben (a `try` blokk előtt):**
```python
# P0 SERVICE PROVIDER AUTO-DISCOVERY
resolved_service_provider_id = expense.service_provider_id
if expense.external_vendor_name and not expense.service_provider_id:
# 1. Fuzzy match keresés
from app.services.provider_service import find_or_create_provider_by_name
result = await find_or_create_provider_by_name(
db=db,
name=expense.external_vendor_name,
added_by_user_id=current_user.id,
)
resolved_service_provider_id = result.id
```
**`find_or_create_provider_by_name()` logika:**
```python
async def find_or_create_provider_by_name(
db: AsyncSession,
name: str,
added_by_user_id: int,
) -> ServiceProvider:
"""
1. Exact match keresés (ILIKE)
2. Fuzzy match (trigram similarity, pl. pg_trgm)
3. Ha nincs találat -> új ServiceProvider létrehozása:
- status = "pending"
- source = "import" (API import forrás)
- validation_score = 0
- added_by_user_id = a költséget rögzítő user
4. Gamification XP award (pl. SERVICE_PROVIDER_DISCOVERY)
"""
```
### 3.3 Adatbázis Módosítás
**Nincs új tábla!** A meglévő `ServiceProvider` modell minden szükséges mezőt tartalmaz:
- `name`, `address` (opcionális, az expense-ből nem jön)
- `status` -> `pending` (alapértelmezett)
- `source` -> `import` (új value a `SourceType` enum-ban, már létezik: `manual`, `ocr`, `import`)
- `validation_score` -> `0`
- `added_by_user_id` -> a költséget rögzítő user ID-ja
**Csak a `SourceType` enum ellenőrzése:** A jelenlegi érték `api_import = "import"` — ez megfelelő.
---
## 4. 🏛️ Admin Interface Integration
### 4.1 Backend Endpointok (admin/providers/)
| Végpont | Metódus | Cél |
|---------|---------|-----|
| `GET /admin/providers` | LIST | Szolgáltatók listázása szűréssel (status, source, search) |
| `GET /admin/providers/{id}` | GET | Részletes nézet |
| `POST /admin/providers/{id}/approve` | POST | Provider jóváhagyása (pending -> approved) |
| `POST /admin/providers/{id}/reject` | POST | Provider elutasítása (pending -> rejected) |
| `POST /admin/providers/{id}/flag` | POST | Provider megjelölése (approved -> flagged) |
| `DELETE /admin/providers/{id}` | DELETE | Provider törlése (soft delete) |
| `GET /admin/providers/stats` | GET | Statisztikák (pending count, total, etc.) |
**Új fájl:** `backend/app/api/v1/endpoints/admin_providers.py`
**Router regisztráció:** `api.py:48` — hozzáadni:
```python
from app.api.v1.endpoints import admin_providers
api_router.include_router(admin_providers.router, prefix="/admin/providers", tags=["Admin Provider Moderation"])
```
### 4.2 Frontend Admin Oldalak
**Új oldalak:** `frontend_admin/pages/providers/`
| Oldal | Útvonal | Funkció |
|-------|---------|---------|
| Providers List | `/providers` | Lista szűréssel (pending/approved/rejected), keresés |
| Provider Detail | `/providers/[id]` | Részletes adatok, moderációs akciók |
| Pending Queue | `/providers/pending` | Csak a pending provider-ek (moderációs sor) |
**Sidebar menü módosítás:** `frontend_admin/layouts/default.vue:324` — Új menücsoport "Szolgáltatók":
```javascript
{
title: 'Szolgáltatók',
items: [
{
label: 'Szolgáltatók',
icon: '...',
children: [
{
path: '/providers',
label: 'Összes szolgáltató',
icon: '...',
},
{
path: '/providers/pending',
label: 'Jóváhagyásra váró',
icon: '...',
},
],
},
],
},
```
### 4.3 Admin Endpoint Minta (admin_providers.py)
```python
"""
Admin Provider Moderation API
Végpontok:
GET /admin/providers — Szolgáltatók listázása
GET /admin/providers/{id} — Részletes adatok
POST /admin/providers/{id}/approve — Jóváhagyás (-> approved)
POST /admin/providers/{id}/reject — Elutasítás (-> rejected)
POST /admin/providers/{id}/flag — Megjelölés (-> flagged)
DELETE /admin/providers/{id} — Törlés (soft delete)
GET /admin/providers/stats — Statisztikák
"""
```
---
## 5. 📝 Adatmodell és Alembic Terv
### 5.1 Meglévő Modell — Nincs Változás
A `ServiceProvider` modell már tartalmazza az összes szükséges mezőt. Nincs szükség új migrációra.
**Ellenőrizendő:** A `SourceType` enum tartalmazzon `import` értéket:
```python
class SourceType(str, enum.Enum):
manual = "manual"
ocr = "ocr"
api_import = "import"
```
### 5.2 Twin-technika (Többnyelvűség)
A `ServiceProvider` modellben nincs i18n mező (a név nem lesz fordítva). A kategóriák (ExpertiseTag) már támogatják a többnyelvűséget a `name_hu`, `name_en` mezőkkel.
### 5.3 Soft-delete
A `ServiceProvider` modell jelenleg nem támogatja a soft-delete-t. Ha szükséges, lehet hozzáadni:
```python
is_deleted: Mapped[bool] = mapped_column(Boolean, default=False)
deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
```
---
## 6. ⚙️ Admin Kontroll (Global/Country/Region/User)
A provider moderációhoz az alábbi SystemParameter változók javasoltak:
| Paraméter | Scope | Default | Leírás |
|-----------|-------|---------|--------|
| `PROVIDER_AUTO_APPROVE_TRUSTED_USERS` | global | `false` | Megbízható user-ek provider-ei auto-approved |
| `PROVIDER_MAX_PENDING_PER_USER` | global | `10` | Maximum függőben lévő provider per user |
| `PROVIDER_REQUIRE_VALIDATION_SCORE` | global | `3` | Minimum validation score az auto-approve-hoz |
| `PROVIDER_DISCOVERY_XP` | global/gamification | `25` | XP jutalom provider felfedezésért |
---
## 7. 🌍 Geo-Logika és Service Finder Algoritmus
### 7.1 Meglévő Geo Támogatás
A `ServiceProfile` modell `marketplace/service.py:40` már tartalmaz PostGIS `location` mezőt és geo-keresést. A `ServiceProvider` viszont NEM rendelkezik location mezővel — csak szöveges címmel.
### 7.2 Provider -> ServiceProfile Upgrade Path
Az auto-discovered ServiceProvider-ekből később lehet ServiceProfile-t létrehozni (admin jóváhagyással). Ez a folyamat már létezik a `quick_add_provider()` függvényben, ami egyszerre hozza létre a `ServiceProfile`-t és a `ServiceProvider`-t.
**Javaslat:** Az auto-discovery csak a `ServiceProvider` szintig menjen. A `ServiceProfile` létrehozása maradjon admin feladat.
---
## 8. 🎮 Gamification Pontrendszer Részletes Specifikáció
### 8.1 Meglévő Pontszabályok (point_rules tábla)
Az alábbi pontszabályok már léteznek az adatbázisban:
| action_key | Pont | Aktív | Leírás |
|------------|------|-------|--------|
| `ADD_NEW_PROVIDER` | **500** | ✅ | Új szolgáltató rögzítése a rendszerbe |
| `USE_UNVERIFIED_PROVIDER` | **200** | ✅ | Szervizesemény/költség rögzítése olyan szolgáltatónál, aminek még nincs 5 megerősítése |
| `UPDATE_PROVIDER` | **100** | ✅ | Szolgáltató adatainak szerkesztése (kategóriák, címkék frissítése) |
| `RATE_PROVIDER` | **250** | ✅ | Szolgáltató értékelése (tagekkel) |
| `ASSET_REGISTER` | **100** | ✅ | Jármű regisztráció |
| `ASSET_REVIEW` | **75** | ✅ | Jármű felülvizsgálat |
| `TEST_ACTION` | **100** | ✅ | Test point rule |
### 8.2 Gamification Rendszer Működése
#### Pontozási Folyamat (`process_activity()`)
A `GamificationService.process_activity()` (`gamification_service.py:52`) az alábbi lépéseket hajtja végre:
1. **Admin Konfiguráció Betöltése**`GAMIFICATION_MASTER_CONFIG` JSON a `system_parameters` táblából
2. **Point Rules Lekérés** — Ha `action_key` meg van adva, a `point_rules` táblából olvassa a pontértékeket (admin override)
3. **Büntetés Szűrés** — Ha a user büntetés alatt áll, szorzó alkalmazása
4. **XP Számítás**`final_xp = int(xp_amount * multiplier)`
5. **Szintszámítás** — Hatványfüggvény: `Level = (XP/500)^(1/1.5) + 1`
6. **Social Pont → Kredit Konverzió** — Minden 100 social pont = 1 kredit (Wallet.earned_credits)
7. **Naplózás**`PointsLedger` rekord létrehozása
#### Master Config Alapértékek
```json
{
"xp_logic": {"base_xp": 500, "exponent": 1.5},
"penalty_logic": {
"recovery_rate": 0.5,
"thresholds": {"level_1": 100, "level_2": 500, "level_3": 1000},
"multipliers": {"L0": 1.0, "L1": 0.5, "L2": 0.1, "L3": 0.0}
},
"conversion_logic": {"social_to_credit_rate": 100},
"level_rewards": {"credits_per_10_levels": 50}
}
```
#### Szorzók Büntetési Szintek Szerint
| Szint | Küszöb (penalty_points) | Szorzó | Hatás |
|-------|------------------------|--------|-------|
| L0 | 0 | 1.0 (100%) | Nincs korlátozás |
| L1 | 100+ | 0.5 (50%) | Fele annyi XP jár |
| L2 | 500+ | 0.1 (10%) | Csak 10% XP |
| L3 | 1000+ | 0.0 (0%) | Teljes blokkolás |
### 8.3 Javasolt Új Pontszabályok a Provider Discovery Rendszerhez
Az alábbi új `action_key`-ek létrehozása javasolt a `point_rules` táblában:
| action_key | Javasolt Pont | Leírás |
|------------|--------------|--------|
| `PROVIDER_DISCOVERY` | **25** | Provider felfedezése expense rögzítéskor (external_vendor_name alapján) |
| `PROVIDER_CONFIRMATION` | **50** | Már létező, de nem 100%-ban megerősített provider használata másik user által |
| `PROVIDER_VERIFIED_USE` | **100** | Már jóváhagyott (approved) provider használata |
**Indoklás:**
- A `PROVIDER_DISCOVERY` (25 XP) alacsonyabb, mint a `USE_UNVERIFIED_PROVIDER` (200 XP), mert a discovery csak a név beírásáért jár, míg a használatért több jár
- A `PROVIDER_CONFIRMATION` (50 XP) egy kompromisszum: a user kap valamennyi XP-t, de kevesebbet, mint aki először fedezte fel
- A `PROVIDER_VERIFIED_USE` (100 XP) jutalmazza a már ellenőrzött provider-ek használatát
### 8.4 Megbízhatósági Érték (Trust Score) Rendszer
#### Jelenlegi Állapot
- **`ServiceProvider.validation_score`** (`social.py:58`) — Integer, default=0. A `quick_add_provider()` 50-re állítja.
- **`ServiceProfile.trust_score`** (`service.py:65`) — Integer, default=30. A `quick_add_provider()` nem állítja be expliciten.
#### Javasolt Trust Score Számítás
A `ServiceProvider.validation_score` automatikus számítása:
| Esemény | validation_score változás |
|---------|--------------------------|
| Új provider létrehozása (discovery) | 0 (alapértelmezett) |
| Admin jóváhagyás (approve) | +50 |
| Második user használja (confirmation) | +10 |
| Harmadik user használja | +5 |
| Minden további user | +2 (max +20-ig) |
| ServiceReview (értékelés) | +5 per review (max +30) |
| OCR bizonylat kapcsolódik hozzá | +3 |
**Küszöbértékek:**
- `validation_score >= 30``ServiceProfile.trust_score = 50` (megbízhatónak jelölve)
- `validation_score >= 70``ServiceProfile.trust_score = 80` (nagyon megbízható)
- `validation_score >= 100``ServiceProfile.trust_score = 100` (teljesen megbízható)
### 8.5 Példa: Teljes Pontozási Folyamat
#### Scenario 1: Új provider felfedezése
1. User A rögzíti a költséget `external_vendor_name="János Autószerviz"`
2. A rendszer nem találja a `ServiceProvider` táblában
3. Létrejön: `ServiceProvider(name="János Autószerviz", status=pending, source=import, validation_score=0, added_by_user_id=A)`
4. Gamification: `PROVIDER_DISCOVERY`**25 XP** (ha a point_rules-ban van)
5. Gamification: `USE_UNVERIFIED_PROVIDER`**200 XP** (már létező szabály)
6. **Összesen: 225 XP** a user-nek
7. A provider `validation_score` = 0 (még nincs megerősítve)
#### Scenario 2: Meglévő provider megerősítése másik user által
1. User B rögzíti a költséget `external_vendor_name="János Autószerviz"`
2. A rendszer megtalálja a meglévő `ServiceProvider`-t (status=pending, validation_score=0)
3. Auto-link a meglévő provider-hez
4. Gamification: `PROVIDER_CONFIRMATION`**50 XP** (új szabály)
5. Gamification: `USE_UNVERIFIED_PROVIDER`**200 XP** (már létező szabály)
6. **Összesen: 250 XP** a user-nek
7. A provider `validation_score` += 10 → most **10**
#### Scenario 3: Már jóváhagyott provider használata
1. Admin jóváhagyta a provider-t (validation_score = 50)
2. User C rögzíti a költséget és kiválasztja a provider-t
3. Gamification: `PROVIDER_VERIFIED_USE`**100 XP**
4. A provider `validation_score` += 2 → most **52**
### 8.6 Kredit Rendszer
- **Social pont → Kredit konverzió:** 100 social pont = 1 kredit (Wallet.earned_credits)
- A kredit a `Wallet` modellben (`identity/identity.py:248`) tárolódik
- A kredit felhasználható: prémium funkciók, szolgáltatások vásárlása
- **Szintlépési jutalom:** Minden 10. szintnél +50 kredit
---
## 9. 🚀 Továbbfejlesztési Javaslatok
### 9.1 Rövidtávú (P0 — Kötelező)
1. **Auto-discovery hook** az `expenses.py:439` `create_expense` végpontban
2. **`find_or_create_provider_by_name()`** szolgáltatás a `provider_service.py`-ben
3. **Admin provider moderation endpointok** — új `admin_providers.py`
4. **Frontend admin providers oldal** — új `providers/` oldalak
5. **Új point_rules létrehozása:** `PROVIDER_DISCOVERY` (25), `PROVIDER_CONFIRMATION` (50), `PROVIDER_VERIFIED_USE` (100)
### 9.2 Középtávú (P1 — Javasolt)
6. **Trigram similarity index** a `service_providers.name` oszlopon a jobb fuzzy match-hez
7. **Duplikáció detektálás** — ha két user ugyanazt a provider-t tölti fel, merge logika
8. **Bulk import** CSV-ből a meglévő provider-ek batch feltöltésére
9. **Trust score automatizálás** — a `validation_score` automatikus számítása a használati statisztikák alapján
### 9.3 Hosszútávú (P2 — Jövőbeli)
10. **Provider reputation score** — az AssetCost tranzakciókból számolt automata reputáció
11. **Automata ServiceProfile upgrade** — ha egy provider-nek X db sikeres tranzakciója van
12. **Provider matching OCR-ből** — ha egy OCR bizonylaton szereplő cégnév ismeretlen
---
## 10. 🔐 Biztonsági és Naplózási Szempontok
### Audit Log
Minden moderációs akciót (approve, reject, flag) naplózni kell az `AuditLog` táblába:
- `action`: "PROVIDER_APPROVED" / "PROVIDER_REJECTED" / "PROVIDER_FLAGGED"
- `entity_type`: "service_provider"
- `entity_id`: provider.id
- `actor_id`: admin user ID
- `details`: JSON with reason
### RBAC
- `providers:moderate` — képeség a provider moderációs endpointokhoz
- `providers:view` — csak olvasási jog a provider listához
---
## 11. ✅ Jóváhagyási Pont (Architect Review)
**Jelen dokumentum jóváhagyása után az alábbi Gitea kártyák kerülnek létrehozásra:**
| # | Cím | Scope | Type |
|---|-----|-------|------|
| 1 | Auto-discovery hook expense creation-ben | Backend | Feature |
| 2 | `find_or_create_provider_by_name()` service | Backend | Feature |
| 3 | Admin provider moderation API (admin_providers.py) | Backend, API | Feature |
| 4 | Frontend admin providers oldal (list + detail + pending) | Frontend | Feature |
| 5 | Sidebar menü bővítés providers modullal | Frontend | Feature |
---
*Jóváhagyás után a Code módban történő implementáció megkezdhető.*

View File

@@ -0,0 +1,346 @@
# 🔧 Provider Admin Szerkesztés — Teljes Elemzés és Terv
## 🎯 Összefoglaló
**Kérdés:** Hogyan lehet a szolgáltatói adatokat módosítani? Hol van a jóváhagyás/adatmódosítás előzménye? Ki mikor rögzítette? Kik validálták? Admin felületről módosítható-e?
**Válasz röviden:** Az adatok **NINCSENEK bekódolva** — teljes egészében az adatbázisban vannak. A moderáció (approve/reject/flag/delete) **admin felületről működik**, de a provider adatmezőinek szerkesztése (név, cím, telefonszám, email módosítása) **még NINCS implementálva** az admin felületen. Javaslat: új PUT végpont + frontend edit modal.
---
## ✅ 1. ADATOK TÁROLÁSA (NINCSENEK bekódolva)
### `marketplace.service_providers` — Alap szolgáltató adatok
| Oszlop | Típus | Leírás |
|--------|-------|--------|
| `id` | integer (PK) | Automatikus ID |
| `name` | varchar(255) | **Szolgáltató neve** |
| `address` | varchar(255) | Teljes cím (legacy, deprecated) |
| `city` | varchar(100) | **Város** |
| `address_zip` | varchar(20) | **Irányítószám** |
| `address_street_name` | varchar(255) | **Utcanév** |
| `address_street_type` | varchar(50) | Utcatípus (utca, tér, stb.) |
| `address_house_number` | varchar(20) | **Házszám** |
| `plus_code` | varchar(100) | Google Plus Code |
| `contact_phone` | varchar(50) | **Telefonszám** |
| `contact_email` | varchar(255) | **Email** |
| `website` | varchar(255) | **Weboldal** |
| `category` | varchar(100) | **Kategória** (ExpertiseTag ID string) |
| `status` | ENUM (ModerationStatus) | `pending` / `approved` / `rejected` / `flagged` |
| `source` | ENUM (SourceType) | `crowd` / `admin` / `robot` |
| `validation_score` | integer | Validációs pontszám |
| `evidence_image_path` | varchar(500) | Kép bizonyíték |
| `added_by_user_id` | integer (FK→users) | **Ki vette fel** |
| `created_at` | timestamptz | **Mikor vették fel** |
### `marketplace.service_profiles` — Részletes profil és értékelések
**Kapcsolat:** `service_profiles.service_provider_id``service_providers.id`
| Oszlop | Típus | Leírás |
|--------|-------|--------|
| `id` | integer (PK) | Automatikus ID |
| `service_provider_id` | integer (FK) | Kapcsolódó service_provider |
| `organization_id` | integer (FK) | Opcionális szervezeti kapcsolat |
| `location` | GEOMETRY (PostGIS) | Földrajzi hely |
| `status` | ENUM (ServiceStatus) | `active` / `inactive` / `suspended` |
| `trust_score` | integer | **Bizalmi pontszám** |
| `is_verified` | boolean | Ellenőrzött-e |
| `verification_log` | jsonb | Validációs napló |
| `rating` | double precision | Google átlagértékelés |
| `user_ratings_total` | integer | Google értékelések száma |
| `rating_verified_count` | integer | Ellenőrzött értékelések száma |
| `rating_price_avg` | double precision | **Ár átlag pontszám** |
| `rating_quality_avg` | double precision | **Minőség átlag pontszám** |
| `rating_time_avg` | double precision | **Idő átlag pontszám** |
| `rating_communication_avg` | double precision | **Kommunikáció átlag pontszám** |
| `rating_overall` | double precision | **Összesített átlag pontszám** |
| `specialization_tags` | jsonb | Specializációs címkék |
| `opening_hours` | jsonb | Nyitvatartás |
| `contact_phone` | varchar(50) | Profil telefonszám |
| `contact_email` | varchar(255) | Profil email |
| `website` | varchar(255) | Profil weboldal |
| `bio` | text | Leírás |
| `created_at` | timestamptz | Létrehozva |
| `updated_at` | timestamptz | **Utolsó módosítás** |
### `marketplace.service_reviews` — Felhasználói értékelések ⭐
**Kapcsolat:** `service_reviews.service_id``service_profiles.id`
| Oszlop | Típus | Leírás |
|--------|-------|--------|
| `id` | integer (PK) | Automatikus ID |
| `service_id` | integer (FK) | Melyik service_profile-ra |
| `user_id` | integer (FK→users) | **Ki értékelt** |
| `price_rating` | integer | **Ár pontszám** (1-5) |
| `quality_rating` | integer | **Minőség pontszám** (1-5) |
| `time_rating` | integer | **Idő/gördülékenység pontszám** (1-5) |
| `communication_rating` | integer | **Kommunikáció pontszám** (1-5) |
| `comment` | text | Szöveges vélemény |
| `is_verified` | boolean | Ellenőrzött tranzakcióhoz tartozik |
| `transaction_id` | uuid | Kapcsolódó tranzakció |
| `created_at` | timestamptz | Értékelés ideje |
### `marketplace.provider_validations` — Validációs előzmények
| Oszlop | Típus | Leírás |
|--------|-------|--------|
| `id` | integer (PK) | Automatikus ID |
| `provider_id` | integer (FK) | Melyik provider |
| `voter_user_id` | integer (FK→users) | **Ki validált** |
| `validation_type` | varchar(20) | `approve` / `reject` / `flag` |
| `weight` | integer | Súly érték |
| `metadata` | jsonb | Extra adatok (reason, stb.) |
| `created_at` | timestamptz | Validáció ideje |
**UNIQUE:** `(voter_user_id, provider_id)` — egy user csak egyszer szavazhat.
### `marketplace.votes` — Szavazatok
| Oszlop | Leírás |
|--------|--------|
| `vote_value` | integer (+1/-1) |
### `marketplace.ratings` — Általános értékelés
| Oszlop | Leírás |
|--------|--------|
| `score` | numeric(3,2) (max 9.99) |
| `comment` | text |
| `images` | jsonb |
### `gamification.point_rules` — Pontszabályok
| ID | action_key | points | description | is_active |
|----|-----------|--------|-------------|-----------|
| 3 | `ADD_NEW_PROVIDER` | 500 | Új szolgáltató rögzítése | ✅ |
| 4 | `USE_UNVERIFIED_PROVIDER` | 200 | Szervizesemény nem ellenőrzött szolgáltatónál | ✅ |
| 5 | `RATE_PROVIDER` | 250 | Szolgáltató értékelése (tagekkel) | ✅ |
| 6 | `UPDATE_PROVIDER` | 100 | Szolgáltató adatainak szerkesztése | ✅ |
---
## ✅ 2. AUDIT TRAIL — Ki mit csinált, mikor?
### `audit.audit_logs` — Központi audit napló
```sql
user_id FK users (ki)
severity ENUM (info, warning, error)
action varchar (pl. "admin_provider_approve")
target_type varchar (pl. "service_provider")
target_id varchar (pl. "42")
old_data JSON (előző állapot)
new_data JSON (új állapot)
ip_address varchar
user_agent text
timestamp timestamptz (mikor)
```
Az [`admin_providers.py`](backend/app/api/v1/endpoints/admin_providers.py:147) `_log_moderation_action()` függvénye minden moderációs műveletet naplóz ide.
### Kapcsolati háló
```
identity.users
├── added_by_user_id ──→ marketplace.service_providers (ki adta hozzá)
├── user_id ──→ marketplace.service_reviews (ki értékelt)
│ └── service_id ──→ service_profiles
├── author_id ──→ marketplace.ratings (ki értékelt általában)
├── user_id ──→ marketplace.votes (ki szavazott)
│ └── provider_id ──→ service_providers
└── voter_user_id ──→ marketplace.provider_validations (ki validált)
└── provider_id ──→ service_providers
```
---
## ✅ 3. ADMIN FELÜLETRŐL MÓDOSÍTHATÓ? — ÁLLAPOTFELMÉRÉS
### ✅ MEGLÉVŐ — Moderációs műveletek admin felületről
| Művelet | Backend végpont | Frontend oldal |
|---------|----------------|----------------|
| Listázás | `GET /admin/providers` | `/providers` (index.vue) |
| Statisztika | `GET /admin/providers/stats` | `/providers` (index.vue) |
| Részletek | `GET /admin/providers/{id}` | `/providers/[id]` |
| **Jóváhagyás** | `POST /admin/providers/{id}/approve` | `/providers/[id]` |
| **Elutasítás** | `POST /admin/providers/{id}/reject` | `/providers/[id]` |
| **Megjelölés** | `POST /admin/providers/{id}/flag` | `/providers/[id]` |
| **Törlés** | `DELETE /admin/providers/{id}` | `/providers/[id]` |
| Függőben queue | — | `/providers/pending` |
### ❌ HIÁNYZÓ — Adatok szerkesztése admin felületről
| Funkció | Backend | Frontend |
|---------|---------|----------|
| **Provider adatok szerkesztése** (név, cím, tel., email, web, kategória) | ❌ Nincs PUT/PATCH végpont | ❌ Nincs edit form |
| **Provider history/log nézet** | ❌ Nincs GET history végpont | ❌ Nincs history panel |
| **Pontszabályok bővítése** (PROVIDER_DISCOVERY, stb.) | ❌ Hiányzó DB rekordok | — |
---
## 📋 4. TERV — JAVASOLT FEJLESZTÉSEK
### 🟢 P0 — Admin Provider Edit (Kötelező — Hiány #1)
#### Backend: Új PUT végpont (admin_providers.py)
```python
class ProviderUpdateInput(BaseModel):
name: Optional[str] = None
city: Optional[str] = None
address_zip: Optional[str] = None
address_street_name: Optional[str] = None
address_street_type: Optional[str] = None
address_house_number: Optional[str] = None
plus_code: Optional[str] = None
contact_phone: Optional[str] = None
contact_email: Optional[str] = None
website: Optional[str] = None
category: Optional[str] = None
@router.put("/{provider_id}", response_model=ModerationResponse)
async def update_provider(
provider_id: int,
data: ProviderUpdateInput,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(require_admin),
):
"""Admin általi provider adatmódosítás. AuditLog capture old vs new values."""
# 1. Lekéri a meglévő provider-t
# 2. Elmenti a régi értékeket (old_data JSON)
# 3. Frissíti a megadott mezőket
# 4. AuditLog írás: action="admin_provider_update", old_data → new_data
# 5. ProviderValidation létrehozása: validation_type="admin_edit"
# 6. validation_score reset 0-ra (újra kell validálni)
# 7. Ha van service_profile, annak updated_at frissítése
```
**Adatbázis érintettség:**
- `marketplace.service_providers` → UPDATE
- `audit.audit_logs` → INSERT (old_data → new_data JSON capture)
- `marketplace.provider_validations` → INSERT (admin_edit record)
- `marketplace.service_profiles.updated_at` → UPDATE (ha van kapcsolódó profil)
#### Frontend: Edit modal (providers/[id].vue)
- **"Szerkesztés" gomb** a provider detail nézetben (csak approved státuszúaknál)
- **Modal vagy inline form** a következő mezőkkel:
- **Név** (name) — text input
- **Cím blokk**: város, irányítószám, utcanév, utcatípus, házszám, plus_code
- **Kapcsolat**: telefon, email, weboldal
- **Kategória** (category) — select a meglévő kategóriákból
- **Mentés gomb** → `PUT /admin/providers/{id}` hívás
- **Sikeres mentés** után: adatok frissítése a nézetben + toast "Sikeres módosítás"
- **Validation**: mezők validálása mentés előtt
### 🟢 P0 — Pontszabályok bővítése (Kötelező — Hiány #4)
Új rekordok beszúrása a `gamification.point_rules` táblába:
| action_key | points | description |
|-----------|--------|-------------|
| `PROVIDER_DISCOVERY` | 300 | Új, még nem létező provider felfedezése |
| `PROVIDER_CONFIRMATION` | 150 | Meglévő provider adatainak megerősítése |
| `PROVIDER_VERIFIED_USE` | 100 | Már validált provider használata költség rögzítésnél |
**Létrehozás:** Seed script vagy egyszerű SQL INSERT.
### 🟡 P1 — Provider History Panel (Javasolt — Hiány #3)
#### Backend: Új GET végpont
```python
@router.get("/{provider_id}/history", response_model=List[AuditLogEntry])
async def get_provider_history(...):
"""Visszaadja a provider-hez kapcsolódó összes audit log rekordot."""
```
- Lekérdezés az `audit.audit_logs` táblából: `target_type='service_provider' AND target_id='{provider_id}'`
- Rendezés: `timestamp DESC`
#### Frontend: History tab
- Új "Előzmények" fül a provider detail oldalon (`providers/[id].vue`)
- Táblázatos nézet:
| Dátum | Művelet | Ki | Részletek |
|-------|---------|-----|-----------|
| 2026-06-30 | Létrehozás | János | új provider |
| 2026-06-30 | Jóváhagyás | Admin | +50 score |
| 2026-06-30 | Szerkesztés | Admin | név, cím módosítva |
---
## 📊 5. ADATBÁZIS ÉRINTETTSÉG ÖSSZESÍTÉS
| Séma | Tábla | Művelet | Leírás |
|------|-------|---------|--------|
| `marketplace` | `service_providers` | UPDATE | Admin általi mezőmódosítás |
| `marketplace` | `service_profiles` | UPDATE | `updated_at` frissítés |
| `marketplace` | `provider_validations` | INSERT | Admin edit naplózása |
| `audit` | `audit_logs` | INSERT | Változásnaplózás (old→new) |
| `gamification` | `point_rules` | INSERT | Új pontszabályok |
---
## 🗂️ 6. ÉRINTETT FÁJLOK
| Fájl | Művelet |
|------|---------|
| [`backend/app/api/v1/endpoints/admin_providers.py`](backend/app/api/v1/endpoints/admin_providers.py) | **MÓDOSÍTÁS**: ÚJ PUT végpont + ProviderUpdateInput schema |
| [`frontend_admin/pages/providers/[id].vue`](frontend_admin/pages/providers/[id].vue) | **MÓDOSÍTÁS**: Edit modal/űrlap hozzáadása (P0) + History tab (P1) |
| [`frontend_admin/i18n/locales/hu.json`](frontend_admin/i18n/locales/hu.json) | **MÓDOSÍTÁS**: Magyar szövegek |
| [`frontend_admin/i18n/locales/en.json`](frontend_admin/i18n/locales/en.json) | **MÓDOSÍTÁS**: Angol szövegek |
| `backend/app/scripts/seed_provider_point_rules.py` | **LÉTREHOZÁS**: Seed script az új pontszabályokhoz |
| [`backend/app/models/identity/social.py`](backend/app/models/identity/social.py) | **NINCS változás** — meglévő modell használható |
---
## 🚀 7. JAVASOLT GITEA KÁRTYÁK (Jóváhagyás után)
### 1. kártya — Backend: Admin provider edit PUT végpont
**Cím:** `Backend: Admin provider edit PUT /admin/providers/{id} végpont`
**Mérföldkő:** P0 Service Provider Admin
**Cél:** Admin általi provider adatmódosítás lehetővé tétele
**Függőségek:**
- **Bemenet:** `admin_providers.py`, `ServiceProvider` modell, `AuditLog` modell
- **Kimenet:** Admin frontend edit form (2. kártya)
**Leírás:** ÚJ PUT végpont a `admin_providers.py`-ban, ami lehetővé teszi admin számára a provider adatmezők szerkesztését (name, city, address_*, contact_*, website, category). AuditLog capture (old_data → new_data JSON). ProviderValidation record létrehozása `validation_type='admin_edit'`. validation_score reset 0-ra.
### 2. kártya — Frontend: Admin provider edit modal
**Cím:** `Frontend: Admin provider edit modal/űrlap`
**Mérföldkő:** P0 Service Provider Admin
**Cél:** Admin felületi lehetőség a provider adatok szerkesztésére
**Függőségek:**
- **Bemenet:** 1. kártya (PUT végpont)
- **Kimenet:** — (frontend feature)
**Leírás:** Edit modal hozzáadása a `providers/[id].vue` oldalhoz. "Szerkesztés" gomb, form mezők (név, cím, kapcsolat, kategória), validálás, PUT hívás, sikeres mentés utáni frissítés. Magyar és angol i18n szövegek.
### 3. kártya — Pontszabályok bővítése
**Cím:** `Seed: Új gamification pontszabályok provider rendszerhez`
**Mérföldkő:** P0 Gamification
**Cél:** Provider discovery és confirmation pontozás bevezetése
**Függőségek:**
- **Bemenet:** `gamification.point_rules` tábla
- **Kimenet:** Gamification motor (pontozás működése)
**Leírás:** 3 új pontszabály beszúrása: PROVIDER_DISCOVERY (300p), PROVIDER_CONFIRMATION (150p), PROVIDER_VERIFIED_USE (100p). Seed script létrehozása.
### 4. kártya — Provider history nézet (P1)
**Cím:** `Backend+Frontend: Provider audit history megjelenítése`
**Mérföldkő:** P1 Admin Experience
**Cél:** Provider teljes életciklusának áttekinthetősége
**Függőségek:**
- **Bemenet:** `audit.audit_logs` tábla
- **Kimenet:** Jobb admin áttekinthetőség
**Leírás:** GET `/admin/providers/{id}/history` végpont az `audit.audit_logs`-ból. History tab a frontenden: dátum, művelet, ki, részletek.