12 KiB
🔴 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 uses ProfileTrustCard (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 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
ProfileTrustCardcorrectly fetches livefinanceStoredata already. - The
GamificationCardatGamificationCard.vuewas changed from hardcoded2,450tocomputed(() => 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.
Evidence:
<!-- 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. 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 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.vuewraps EVERYTHING inclass="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 seed script inserts lowercase "credit" and "debit" strings into the PostgreSQL audit.ledger_entry_type enum column, but the enum definition at audit.py only allows "CREDIT" and "DEBIT" (UPPERCASE).
Evidence:
audit.py:58-60:class LedgerEntryType(str, enum.Enum): DEBIT = "DEBIT" CREDIT = "CREDIT"seed_financial_ledger.py:18:DB_ENTRY_TYPES = ["credit", "debit"] # ❌ lowercase!- The seed script uses
psycopg2(sync) with explicit::audit.ledger_entry_typecast 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 allFinancialLedgerrows 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: Change["credit", "debit"]→["CREDIT", "DEBIT"]
Part B — Fix existing bad data in the database: Run SQL to normalize all lowercase entries:
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
-
DELETE lines 37-46 — the entire
HeaderBackButtonblock and its comment:<!-- 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')" /> -
DELETE the
backTargetcomputed (lines 90-100):const backTarget = computed(() => { if (route.path === '/finance') { return '/dashboard' } return '/finance' }) -
Clean up imports: Remove
import { computed } from 'vue'(line 78) andimport { useRoute } from 'vue-router'(line 79) if they're no longer used. Also removeconst route = useRoute()(line 87). Removeimport 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
-
DELETE lines 39-55 (the standalone header div)
-
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">:<!-- ── 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
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
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
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
- Line 18: Change:
To:
DB_ENTRY_TYPES = ["credit", "debit"]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:
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
-
Frontend build:
docker compose exec sf_public_frontend npm run build 2>&1 | tail -5 -
Backend wallet endpoint:
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 still has <HeaderBackButton> in #left slot |
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 uses lowercase "credit"/"debit" but enum only accepts "CREDIT"/"DEBIT" |
seed_financial_ledger.py + DB cleanup SQL |
⚠️ DO NOT MODIFY
FleetView.vue— reference onlyPrivateLayout.vue— workingBaseHeader.vue— workingHeaderBackButton.vue— working component, just needs to not be used in FinanceLayoutrouter/index.ts— correctDashboardView.vue— working