felhasználói felületre pü

This commit is contained in:
Roo
2026-07-27 08:39:18 +00:00
parent c9118bf52f
commit 6f28d3e70d
72 changed files with 6311 additions and 749 deletions

View File

@@ -0,0 +1,257 @@
# 🔴 Finance Module — Corrective Blueprint (4 Failures)
**Date:** 2026-07-26
**Author:** Architect Mode
**Status:** Pending Code Mode Execution
**Priority:** HIGH — Visual misalignment, duplicate back button, mock data, backend enum crash
---
## STEP 1: FAILURE ANALYSIS
### FAILURE 1: Wrong Dashboard Card — Mock Data Remains
**Finding:** The dashboard at [`DashboardView.vue`](frontend_app/src/views/DashboardView.vue:72) uses [`ProfileTrustCard`](frontend_app/src/components/dashboard/ProfileTrustCard.vue) (Card 5). This IS the correct card and it WAS correctly modified by the previous blueprint — it now fetches live `financeStore` data and shows `subscriptionPlanName` from `authStore`.
However, [`FinancialCard.vue`](frontend_app/src/components/dashboard/FinancialCard.vue) is a **separate, unused** component that also fetches live wallet data and has a "Top Up" button. It is NOT imported or rendered anywhere on the dashboard. It appears to be a legacy/standalone variant.
**The actual source of "mock data" on the dashboard is the `transactionCount` computed (always 0) and the `subscriptionPlanName` which shows `—` if the user has no subscription plan set.**
**Fix plan:**
- The `ProfileTrustCard` correctly fetches live `financeStore` data already.
- The `GamificationCard` at [`GamificationCard.vue`](frontend_app/src/components/dashboard/GamificationCard.vue:18) was changed from hardcoded `2,450` to `computed(() => 0)` — specifically requested by the previous blueprint as a "placeholder ready to wire up."
- If the user sees mock data, it's the gamification score (0) and badges (empty array). These ARE mock/placeholder by design until a gamification store is created.
**No additional changes needed for the dashboard card itself.**
### FAILURE 2: Back Button Still in Top Global Navbar
**Root Cause:** The previous blueprint removed `<Teleport>` from all 4 child views BUT did NOT remove `<HeaderBackButton>` from [`FinanceLayout.vue`](frontend_app/src/layouts/FinanceLayout.vue:42-45).
**Evidence:**
```html
<!-- FinanceLayout.vue:42-45 -->
<HeaderBackButton
:to="backTarget"
:label="t('common.back')"
/>
```
This `HeaderBackButton` is rendered in the `#left` slot of `BaseHeader`, which is the global sticky top navbar. Removing the Teleport only removed the page title — the back button in the layout persists.
**Fix:** Delete lines 42-45 from [`FinanceLayout.vue`](frontend_app/src/layouts/FinanceLayout.vue). Also remove the unused `backTarget` computed (lines 95-100) and clean up the `useRoute` import if no longer needed.
### FAILURE 3: Title Misalignment — Header Outside Content Container
**Root Cause:** The newly added local header in [`FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue:39-55) is placed OUTSIDE the main content container.
**Evidence:**
- Header at line 40: `<div class="mb-8 flex items-center justify-between">`**no max-w, no px, no mx-auto**
- Content container at line 59: `<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full">`
- The FleetView pattern at [`FleetView.vue`](frontend_app/src/views/vehicles/FleetView.vue:12) wraps EVERYTHING in `class="relative z-10 mx-auto max-w-7xl px-4 py-8 sm:px-6 lg:px-8"` — including the header.
**Fix:** Wrap the local header in the same responsive container, OR add matching `mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full` classes to the header div. The cleanest approach: restructure so header + cards share the same container.
Apply the same fix to all 4 finance views (FinanceWalletsView, FinancePackagesView, FinanceTransactionsView).
### FAILURE 4: Backend Enum Error — 'credit' is not among defined enum values
**Root Cause:** The [`seed_financial_ledger.py`](backend/scripts/seed_financial_ledger.py:18) seed script inserts lowercase `"credit"` and `"debit"` strings into the PostgreSQL `audit.ledger_entry_type` enum column, but the enum definition at [`audit.py`](backend/app/models/system/audit.py:58-60) only allows `"CREDIT"` and `"DEBIT"` (UPPERCASE).
**Evidence:**
- [`audit.py:58-60`](backend/app/models/system/audit.py:58-60):
```python
class LedgerEntryType(str, enum.Enum):
DEBIT = "DEBIT"
CREDIT = "CREDIT"
```
- [`seed_financial_ledger.py:18`](backend/scripts/seed_financial_ledger.py:18):
```python
DB_ENTRY_TYPES = ["credit", "debit"] # ❌ lowercase!
```
- The seed script uses `psycopg2` (sync) with explicit `::audit.ledger_entry_type` cast at line 105 — but psycopg2 may allow case-insensitive casting or the data was inserted before the enum was strict.
- When the frontend calls `GET /billing/wallet/balance`, SQLAlchemy reads all `FinancialLedger` rows and tries to map `"credit"` to the enum — this crashes with the error seen in the screenshot.
**Fix (TWO parts):**
**Part A — Fix the seed script:**
- [`seed_financial_ledger.py:18`](backend/scripts/seed_financial_ledger.py:18): Change `["credit", "debit"]` → `["CREDIT", "DEBIT"]`
**Part B — Fix existing bad data in the database:**
Run SQL to normalize all lowercase entries:
```sql
UPDATE audit.financial_ledger SET entry_type = 'CREDIT' WHERE entry_type::text = 'credit';
UPDATE audit.financial_ledger SET entry_type = 'DEBIT' WHERE entry_type::text = 'debit';
```
Also check and fix wallet_type and status similarly.
---
## STEP 2: CODE MODE HAND-OFF — Explicit Task List
Execute in order. Do NOT modify FleetView.vue, PrivateLayout.vue, BaseHeader.vue, HeaderBackButton.vue, or router/index.ts.
### Task 1: Remove HeaderBackButton from FinanceLayout.vue (FAILURE 2)
**File:** [`frontend_app/src/layouts/FinanceLayout.vue`](frontend_app/src/layouts/FinanceLayout.vue)
1. **DELETE lines 37-46** — the entire `HeaderBackButton` block and its comment:
```html
<!--
Dynamic back button:
- On /finance exactly → back to /dashboard
- On any sub-route (/finance/wallets, etc.) → back to /finance
-->
<HeaderBackButton
:to="backTarget"
:label="t('common.back')"
/>
```
2. **DELETE the `backTarget` computed** (lines 90-100):
```ts
const backTarget = computed(() => {
if (route.path === '/finance') {
return '/dashboard'
}
return '/finance'
})
```
3. **Clean up imports:** Remove `import { computed } from 'vue'` (line 78) and `import { useRoute } from 'vue-router'` (line 79) if they're no longer used. Also remove `const route = useRoute()` (line 87). Remove `import HeaderBackButton from '../components/header/HeaderBackButton.vue'` (line 84).
### Task 2: Fix Header Alignment in FinanceMainView.vue (FAILURE 3)
**File:** [`frontend_app/src/views/FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue)
1. **DELETE lines 39-55** (the standalone header div)
2. **INSERT the header INSIDE the content container**: Move it to be the first child of line 59's `<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full">`:
```html
<!-- ── Bottom-aligned card grid — matches DashboardView.vue exactly ── -->
<div class="flex flex-col justify-end min-h-[85vh] pb-8">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full">
<!-- ── Page header (FleetView.vue pattern) ── -->
<div class="mb-8 flex items-center justify-between">
<div>
<h1 class="text-3xl font-bold text-white">💰 {{ t('menu.finance') }}</h1>
</div>
<div class="flex items-center gap-3">
<button
@click="router.push('/dashboard')"
class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2 text-sm text-white/80 transition-all duration-200 hover:bg-white/20 hover:text-white"
>
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
{{ t('garage.backToDashboard') }}
</button>
</div>
</div>
<!-- 4-card grid — identical to DashboardView grid -->
<div class="grid ...">
...
</div>
</div>
</div>
```
### Task 3: Fix Header Alignment in FinanceWalletsView.vue (FAILURE 3)
**File:** [`frontend_app/src/views/FinanceWalletsView.vue`](frontend_app/src/views/FinanceWalletsView.vue)
Same pattern as Task 2: Move the header inside the `mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full` container. The current structure:
```
<div class="mb-8 flex items-center justify-between"> ...header... </div>
<div class="flex flex-col justify-start min-h-[85vh] py-8">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full">
...content...
</div>
</div>
```
Should become:
```
<div class="flex flex-col justify-start min-h-[85vh] py-8">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 w-full">
<div class="mb-8 flex items-center justify-between"> ...header... </div>
...content...
</div>
</div>
```
### Task 4: Fix Header Alignment in FinancePackagesView.vue (FAILURE 3)
**File:** [`frontend_app/src/views/FinancePackagesView.vue`](frontend_app/src/views/FinancePackagesView.vue)
Same pattern as Task 3 — move header inside the container.
### Task 5: Fix Header Alignment in FinanceTransactionsView.vue (FAILURE 3)
**File:** [`frontend_app/src/views/FinanceTransactionsView.vue`](frontend_app/src/views/FinanceTransactionsView.vue)
Same pattern as Task 3 — move header inside the container.
### Task 6: Fix Backend Enum Error — Seed Script (FAILURE 4A)
**File:** [`backend/scripts/seed_financial_ledger.py`](backend/scripts/seed_financial_ledger.py)
1. **Line 18:** Change:
```python
DB_ENTRY_TYPES = ["credit", "debit"]
```
To:
```python
DB_ENTRY_TYPES = ["CREDIT", "DEBIT"]
```
### Task 7: Fix Backend Enum Error — Existing Database Data (FAILURE 4B)
**Run these SQL commands** to normalize any existing lowercase entries:
```bash
docker compose exec shared-postgres psql -U service_finder_app -d service_finder -c "
UPDATE audit.financial_ledger SET entry_type = 'CREDIT' WHERE entry_type::text = 'credit';
UPDATE audit.financial_ledger SET entry_type = 'DEBIT' WHERE entry_type::text = 'debit';
-- Also check wallet_type
SELECT DISTINCT entry_type::text, wallet_type::text, status::text FROM audit.financial_ledger;
"
```
### Task 8: Verify
1. **Frontend build:**
```bash
docker compose exec sf_public_frontend npm run build 2>&1 | tail -5
```
2. **Backend wallet endpoint:**
```bash
docker compose exec sf_api python3 -c "
import requests
r = requests.post('http://localhost:8000/api/v1/auth/login', data={'username': 'admin@profibot.hu', 'password': 'Admin123!'})
token = r.json()['access_token']
resp = requests.get('http://localhost:8000/api/v1/billing/wallet/balance', headers={'Authorization': f'Bearer {token}'})
print(f'Status: {resp.status_code}')
print(resp.json())
"
```
---
## 📋 Summary Table
| # | Failure | Root Cause | File(s) to Fix |
|---|---------|-----------|-----------------|
| 1 | Mock data on dashboard | `GamificationCard` score is placeholder 0; `transactionCount` is placeholder 0 — by design from previous blueprint, pending gamification/transaction stores | None needed now (wiring to stores is future work) |
| 2 | Back button still in top menu | [`FinanceLayout.vue`](frontend_app/src/layouts/FinanceLayout.vue:42-45) still has `<HeaderBackButton>` in `#left` slot | [`FinanceLayout.vue`](frontend_app/src/layouts/FinanceLayout.vue) |
| 3 | Title misaligned to edge | Header is outside `mx-auto max-w-7xl px-4...` container | All 4 finance views |
| 4 | Backend enum crash: `'credit' is not among defined enum values` | [`seed_financial_ledger.py:18`](backend/scripts/seed_financial_ledger.py:18) uses lowercase `"credit"/"debit"` but enum only accepts `"CREDIT"/"DEBIT"` | [`seed_financial_ledger.py`](backend/scripts/seed_financial_ledger.py) + DB cleanup SQL |
## ⚠️ DO NOT MODIFY
- [`FleetView.vue`](frontend_app/src/views/vehicles/FleetView.vue) — reference only
- [`PrivateLayout.vue`](frontend_app/src/layouts/PrivateLayout.vue) — working
- [`BaseHeader.vue`](frontend_app/src/components/layout/BaseHeader.vue) — working
- [`HeaderBackButton.vue`](frontend_app/src/components/header/HeaderBackButton.vue) — working component, just needs to not be used in FinanceLayout
- [`router/index.ts`](frontend_app/src/router/index.ts) — correct
- [`DashboardView.vue`](frontend_app/src/views/DashboardView.vue) — working