pénzügyi modul továbbfejlesztése (csomagkezelés)

This commit is contained in:
Roo
2026-07-29 09:46:10 +00:00
parent 6f28d3e70d
commit 75904cd2f8
50 changed files with 5851 additions and 312 deletions

View File

@@ -0,0 +1,142 @@
# 🔍 Subscription Limit Data Binding Bug — Root Cause Analysis
**Dátum:** 2026-07-28
**Issue:** #431 (Gitea)
**Súlyosság:** P1 — A felhasználó rossz limiteket lát a frontenden
---
## 1. A Felhasználó Által Jelentett Hiba
A frontend "Előfizetés Információ" modális ablakon (SubscriptionStatusWidget) és a FinanceMainView Card 2-n a következő látszik:
- **Jármű Limit:** 1/1
- **Garázs Limit:** 2/1
Egy Pro/VIP csomag esetén a valós limit `max_vehicles=3` (Pro) vagy `max_vehicles=10` (VIP) lenne.
---
## 2. Adatbázis Réteg — Valós Állapot
| Tábla | Rekord | Kulcs mező | Érték |
|---|---|---|---|
| `identity.users` | id=2 (admin@profibot.hu) | `subscription_plan` | `private_vip_v1` |
| `identity.users` | id=2 | `scope_id` | `67` |
| `identity.users` | id=2 | `scope_level` | `system` |
| `identity.users` | id=2 | `ui_mode` | `personal` |
| `finance.user_subscriptions` | id=34 | `tier_id` | **15** (VIP) ✅ AKTÍV |
| `finance.user_subscriptions` | id=33 | `tier_id` | 14 (Pro) ❌ inaktív |
| `finance.org_subscriptions` | org_id=67 | — | **NINCS REKORD** |
| `system.subscription_tiers` | id=14 (private_pro_v1) | `allowances.max_vehicles` | 3 |
| `system.subscription_tiers` | id=14 | `allowances.max_garages` | 1 |
| `system.subscription_tiers` | id=14 | `display_name` | **NULL** ❌ |
| `system.subscription_tiers` | id=15 (private_vip_v1) | `allowances.max_vehicles` | 10 |
| `system.subscription_tiers` | id=15 | `allowances.max_garages` | 2 |
| `system.subscription_tiers` | id=15 | `display_name` | "Privát VIP" ✅ |
---
## 3. ROOT CAUSE #1 (Elsődleges) — Hibás Vezérlési Logika
**Fájl:** [`backend/app/api/v1/endpoints/users.py`](backend/app/api/v1/endpoints/users.py), `read_users_me()` függvény, sorok 212254.
### A problémás kódszakasz (pszeudokód):
```python
if active_org_id is not None: # ← scope_id=67 → active_org_id=67 → IGAZ
# 1. Org subscription keresés
tier = org_sub_query(scalar_one_or_none)
if tier and tier.rules: # ← NINCS org subscription (üres finance.org_subscriptions org_id=67-re)
allowances = tier.rules.get("allowances", {})
max_vehicles = int(allowances.get("max_vehicles", 1))
max_garages = int(allowances.get("max_garages", 1))
else:
# 2. Fallback: Organization.base_asset_limit
org = select(Organization).where(id == active_org_id)
max_vehicles = org.base_asset_limit or 1 # ← 1-et ad!
max_garages = 1 # ← 1-et ad!
# ❌ HIBA: Soha nem nézi meg a user_subscriptions táblát!
else:
# 3. Personal mode: user subscription keresés
# ← SOHA NEM FUT LE, mert active_org_id != None
tier = user_sub_query(scalar_one_or_none)
if tier and tier.rules:
allowances = tier.rules.get("allowances", {})
max_vehicles = int(allowances.get("max_vehicles", 1)) # ← 10 lenne!
max_garages = int(allowances.get("max_garages", 1)) # ← 2 lenne!
```
### Miért hibás?
A user-nek van `scope_id=67`-e (egy szervezet ID), de az adott szervezethez **nincs org subscription** rekord. A felhasználónak viszont van **aktív user subscription**-e a VIP tier-re (tier_id=15, max_vehicles=10, max_garages=2).
A kód hibásan feltételezi, hogy ha van `active_org_id`, akkor:
1. vagy van org subscription (→ abból olvassa a limiteket),
2. vagy nincs (→ `Organization.base_asset_limit` fallback, ami 1).
**Soha nem esik át a user subscription ágra**, mert `active_org_id is not None`.
### Hatás
A `GET /auth/me` válaszban:
```json
{
"max_vehicles": 1, // ← 10 helyett
"max_garages": 1, // ← 2 helyett
"subscription_display_name": null // ← mert a tier változó None
}
```
---
## 4. ROOT CAUSE #2 (Másodlagos) — private_pro_v1 display_name NULL
**Tábla:** `system.subscription_tiers` id=14
**Mező:** `rules->>'display_name'` = NULL
A seederben (`seed_packages.py:131`) a `display_name` "Privát Pro"-ként van definiálva, de az éles adatbázisban NULL. Valószínűleg egy korábbi migráció vagy kézi módosítás írta felül.
Ez jelenleg nem okoz közvetlen hibát a felhasználónál (mert ő VIP-n van), de a Pro csomagra váltó felhasználóknál a display_name üres lenne.
---
## 5. Javítási Terv
### 5.1 Backend Fix (`users.py`)
A `read_users_me()` függvényben a fallback láncot ki kell egészíteni:
```
if active_org_id is not None:
1. Org subscription keresés (MEGLÉVŐ)
2. Ha nincs → User subscription keresés (ÚJ!)
3. Ha user subscription sincs → Organization.base_asset_limit (MEGLÉVŐ fallback)
else:
4. User subscription keresés (MEGLÉVŐ)
```
Ugyanez a logika kell a `subscription_valid_until` / `subscription_tier_id` feloldására is (sorok 267308), valamint a `subscription_display_name` feloldására (sor 311312).
### 5.2 DB Fix
```sql
UPDATE system.subscription_tiers
SET rules = jsonb_set(rules, '{display_name}', '"Privát Pro"')
WHERE id = 14 AND rules->>'display_name' IS NULL;
```
### 5.3 Frontend
A frontend komponensek (`FinanceMainView.vue`, `SubscriptionStatusWidget.vue`) már helyesen olvassák az `authStore.user?.max_vehicles` és `authStore.user?.max_garages` értékeket. A backend fix után automatikusan a helyes értékek jelennek meg.
---
## 6. Érintett Fájlok
| Fájl | Változtatás |
|---|---|
| `backend/app/api/v1/endpoints/users.py` | `read_users_me()`: fallback lánc javítása |
| Adatbázis (SQL) | `private_pro_v1` display_name beállítása |
| `frontend_app/src/views/FinanceMainView.vue` | Nincs változtatás szükséges (már a helyes mezőket olvassa) |
| `frontend_app/src/components/dashboard/SubscriptionStatusWidget.vue` | Nincs változtatás szükséges |