Files
service-finder/docs/subscription_limit_bug_root_cause_analysis.md

143 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🔍 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 |