# 🔍 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 212–254. ### 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 267–308), valamint a `subscription_display_name` feloldására (sor 311–312). ### 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 |