# 🏗️ Végrehajtási Terv: Csomagváltási és Fizetési Anomáliák Javítása (4 fázis) **Dátum:** 2026-07-28 **Szerző:** Technical Lead & System Architect **Státusz:** 🔵 Tervezés kész — Gitea Issue-k létrehozva **Kapcsolódó kártyák:** #429, #430, #431, #432 --- ## 📋 Áttekintés A felhasználó csomagot váltott (Ingyenesre), de a tranzakció adatbázis szinten nem ment végbe a `net_amount > 0` validációs hiba miatt. A javítást szigorú sorrendben, a mélyebb rétegektől (Backend/Adatbázis) a felület (Vue.js frontend) felé haladva kell végezni. --- ## 🔴 Fázis 1: Ingyenes csomag (0 Ft) bypass és Adatbázis szinkronizáció **Gitea kártya:** [#429 - Issue #1: Ingyenes csomag (0 Ft) bypass és Adatbázis szinkronizáció javítása](https://gitea.profibot.hu/kincses/service-finder/issues/429) ### Root Cause A [`FinancialManager.purchase_package()`](backend/app/services/financial_manager.py:176) mindig létrehoz egy PaymentIntent-et, még ingyenes (0 Ft) csomagok esetén is. A [`PaymentRouter.create_payment_intent()`](backend/app/services/payment_router.py:34) a 62. sorban elvégzi a `net_amount <= 0` validációt, ami ValueError-t dob. ### Megoldás 1. **Adatbázis modell bővítés:** `pending_tier_id` (FK) és `pending_activated_at` (DateTime) mezők hozzáadása a [`UserSubscription`](backend/app/models/core_logic.py:200) és [`OrganizationSubscription`](backend/app/models/core_logic.py:143) modellekhez. 2. **`is_downgrade()` metódus:** Új statikus metódus a [`SubscriptionService`](backend/app/services/subscription_service.py:74) osztályban, amely összehasonlítja a jelenlegi és a cél tier_level értékeket. 3. **Free tier bypass:** Ha `price <= 0`, a [`FinancialManager.purchase_package()`](backend/app/services/financial_manager.py:176) közvetlenül aktiválja a subscription-t, megkerülve a PaymentRouter-t. 4. **Downgrade logika:** Ha a cél tier_level < current tier_level → `pending_tier_id` beállítása, nem azonnali aktiválás. Upgrade esetén a pending flag törlése. 5. **Downgrade Executor:** Új szolgáltatás [`backend/app/services/downgrade_executor.py`](backend/app/services/downgrade_executor.py) a pending downgrade-ek aktiválására a `valid_until` lejárta után. ### Érintett fájlok | Fájl | Módosítás | |------|-----------| | [`backend/app/models/core_logic.py`](backend/app/models/core_logic.py) | +2 oszlop (pending_tier_id, pending_activated_at) mindkét subscription modellben | | [`backend/app/services/subscription_service.py`](backend/app/services/subscription_service.py) | Új `is_downgrade()` metódus | | [`backend/app/services/financial_manager.py`](backend/app/services/financial_manager.py) | Free tier bypass + downgrade detektálás | | `backend/app/services/downgrade_executor.py` | **ÚJ fájl** — CRON-jellegű pending aktiváló | | [`backend/app/api/v1/endpoints/subscriptions.py`](backend/app/api/v1/endpoints/subscriptions.py) | `has_pending_downgrade` mezők a `/my` végpontban | --- ## 🟠 Fázis 2: Mock Payment Gateway (Szimulált Fizetés) **Gitea kártya:** [#430 - Issue #2: Mock Payment Gateway (Szimulált Fizetés) implementálása](https://gitea.profibot.hu/kincses/service-finder/issues/430) ### Jelenlegi állapot A [`MockPaymentGateway`](backend/app/services/mock_payment_gateway.py:31) három módot támogat: `auto_approve`, `simulate_failure`, `simulate_timeout`. Hiányzik a valósághű fizetési flow (redirect → webhook → completion). ### Megoldás 1. **Új mód: `simulate_redirect`** — Alapértelmezetté tenni. `create_intent()` visszaadja a `checkout_url`-t és a `requires_action` státuszt. 2. **Checkout oldal:** `GET /mock-payment/checkout/{intent_id}` — egyszerű HTML fizetési oldal "Pay Now" gombbal. 3. **Webhook callback:** `POST /mock-payment/callback` — PaymentIntent → COMPLETED státusz, subscription aktiválás. 4. **Logging:** Minden `create_intent()` hívásnál `MOCK_PAYMENT_REQUEST` logolás. ### Érintett fájlok | Fájl | Módosítás | |------|-----------| | [`backend/app/services/mock_payment_gateway.py`](backend/app/services/mock_payment_gateway.py) | Új `simulate_redirect` mód | | [`backend/app/api/v1/endpoints/billing.py`](backend/app/api/v1/endpoints/billing.py) | Új 2 végpont: checkout page + webhook callback | --- ## 🟡 Fázis 3: Subscription Details Card (Flip Card) adatkötés javítása **Gitea kártya:** [#431 - Issue #3: Subscription Details Card adatkötésének javítása](https://gitea.profibot.hu/kincses/service-finder/issues/431) ### Jelenlegi állapot A [`FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue:118-154) Card 2 a raw DB slug-ot (pl. `private_pro_v1`) jeleníti meg, nem mutat lejárati dátumot és járműhasználatot. ### Megoldás 1. **Backend:** [`GET /auth/me`](backend/app/api/v1/endpoints/users.py) bővítése `subscription_display_name`, `subscription_expires_at`, `subscription_tier_id` mezőkkel. 2. **Frontend:** [`auth.ts`](frontend_app/src/stores/auth.ts) `UserProfile` interface bővítése. 3. **Frontend:** [`FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue) Card 2 template teljes átírása: fejléc, csomagnév, lejárati dátum, járműhasználati sáv, dinamikus CTA gomb. 4. **I18n:** `renewNow`, `upgradePlan` kulcsok felvétele. ### Érintett fájlok | Fájl | Módosítás | |------|-----------| | [`backend/app/api/v1/endpoints/users.py`](backend/app/api/v1/endpoints/users.py) | +subscription_display_name, +subscription_expires_at, +subscription_tier_id | | [`frontend_app/src/stores/auth.ts`](frontend_app/src/stores/auth.ts) | `UserProfile` interface bővítése | | [`frontend_app/src/views/FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue) | Card 2 template + computed property rewrite | | [`frontend_app/src/i18n/hu.ts`](frontend_app/src/i18n/hu.ts) | Új kulcsok | | [`frontend_app/src/i18n/en.ts`](frontend_app/src/i18n/en.ts) | Új kulcsok | --- ## 🟢 Fázis 4: Kiegészítő csomagok (Add-ons) kosár-logika **Gitea kártya:** [#432 - Issue #4: Kiegészítő csomagok (Add-ons) kosár-logikájának és UI megjelenítésének integrálása](https://gitea.profibot.hu/kincses/service-finder/issues/432) ### Jelenlegi állapot A [`SubscriptionTier`](backend/app/models/core_logic.py:68) modellben létezik a `type` mező (base/addon), de a frontend nem jeleníti meg az addon csomagokat, és nincs kosár-logika. ### Megoldás 1. **Backend:** [`GET /subscriptions/public`](backend/app/api/v1/endpoints/subscriptions.py:121) bővítése: `base_tiers` és `addon_tiers` külön mezők. 2. **Frontend:** [`SubscriptionPlansView.vue`](frontend_app/src/views/SubscriptionPlansView.vue) base és addon csomagok szétválasztott megjelenítése. 3. **Kosár-logika:** [`PlanDetailsModal.vue`](frontend_app/src/components/subscription/PlanDetailsModal.vue) addon checkboxok + összegzés. 4. **Backend:** [`POST /purchase-package`](backend/app/api/v1/endpoints/financial_manager.py) bővítése `addon_tier_ids` fogadására. ### Érintett fájlok | Fájl | Módosítás | |------|-----------| | [`backend/app/api/v1/endpoints/subscriptions.py`](backend/app/api/v1/endpoints/subscriptions.py) | `base_tiers` + `addon_tiers` szétválasztás | | [`backend/app/api/v1/endpoints/financial_manager.py`](backend/app/api/v1/endpoints/financial_manager.py) | `addon_tier_ids` paraméter fogadása | | [`frontend_app/src/views/SubscriptionPlansView.vue`](frontend_app/src/views/SubscriptionPlansView.vue) | Base + addon szekciók | | [`frontend_app/src/components/subscription/PlanDetailsModal.vue`](frontend_app/src/components/subscription/PlanDetailsModal.vue) | Addon checkboxok + kosár összegzés | | [`frontend_app/src/i18n/hu.ts`](frontend_app/src/i18n/hu.ts) | Addon kulcsok | | [`frontend_app/src/i18n/en.ts`](frontend_app/src/i18n/en.ts) | Addon kulcsok | --- ## 📊 Függőségi Sorrend (Kritikus!) ``` Fázis 1 (Backend: Free tier bypass + pending) │ ▼ Fázis 2 (Backend: Mock Payment Gateway) │ ▼ Fázis 3 (Backend + Frontend: Card adatkötés) │ ▼ Fázis 4 (Frontend: Add-on kosár) ``` **Miért ebben a sorrendben?** 1. **Fázis 1** nélkül a teljes csomagváltás el van törve (minden ingyenes csomagra váltás hibát dob) 2. **Fázis 2** nélkül a fizetési folyamat nem tesztelhető végponttól-végpontig 3. **Fázis 3** nélkül a frontend kártya nem mutat valós adatokat (még ha az API már helyes is) 4. **Fázis 4** csak azután jöhet, hogy a base csomagok kezelése stabil --- ## 🧪 Tesztelési Stratégia ### Egységtesztek - `test_is_downgrade()` — tier_level összehasonlítás - `test_free_tier_bypass()` — 0 Ft-os csomag nem hoz létre PaymentIntent-et - `test_mock_redirect_mode()` — checkout_url generálás - `test_mock_webhook_callback()` — callback feldolgozás - `test_pending_downgrade_executor()` — pending tier aktiválás lejárat után ### Integrációs tesztek - Teljes flow: Prémium vásárlás → azonnali aktiválás - Teljes flow: Váltás Ingyenesre → pending_tier_id beállítás - Teljes flow: Uprade pending downgrade alatt → pending törlés, új tier azonnal - Addon vásárlás base csomaggal együtt ### E2E tesztek (Playwright) - Pending downgrade banner megjelenése a SubscriptionStatusWidget-ban - "Csomagváltás folyamatban" üzenet sikeres downgrade rendelés után - Base + addon kosár összegzés helyes megjelenítése --- ## 📎 Referenciák - [`logic_spec_subscription_downgrade_and_mock_payment.md`](plans/logic_spec_subscription_downgrade_and_mock_payment.md) — Teljes műszaki specifikáció - [`logic_spec_subscription_card_upgrade.md`](plans/logic_spec_subscription_card_upgrade.md) — Card upgrade specifikáció - [`logic_spec_subscription_package_filtering_bug.md`](plans/logic_spec_subscription_package_filtering_bug.md) — Package filtering bug specifikáció - [P0 Subscription JSONB Audit](docs/p0_subscription_jsonb_structural_audit_report.md) — Tier JSONB struktúra audit