frontend kínlódás

This commit is contained in:
Roo
2026-03-31 06:20:43 +00:00
parent 2508ae7452
commit c7cbe60976
46 changed files with 6091 additions and 136 deletions

View File

@@ -0,0 +1,262 @@
# B2C vs B2B UI Architecture Plan
**Date:** 2026-03-30
**Version:** 2.0
**Based on:** User requirements for Vehicle Details/Dashboard
## Executive Summary
This document outlines the architectural strategy for implementing dual-mode UI (B2C Personal vs B2B Fleet) with explicit verification feedback. The plan addresses the user's strict requirements for visual layout differences and verification UI.
## 1. Core Principles
### 1.1 Mode Detection & Switching
- **Source of Truth:** `appModeStore.mode` (`'personal'` | `'fleet'`)
- **Trigger:** User selection via profile selector or organization context
- **Persistence:** LocalStorage with sync to backend active organization
### 1.2 Data Segregation
- **Personal Mode:** `organization_id = NULL` or user's personal scope
- **Fleet Mode:** `organization_id = <selected_org_id>`
- **API Filtering:** All vehicle queries include `organization_id` filter based on mode
## 2. Layout Requirements
### 2.1 B2C Personal Mode - "Cards/Tiles" (Kártyás/Csempés)
**Visual Characteristics:**
- Highly visual, image-focused design
- Card-based grid layout (2-4 columns based on screen size)
- Rich media: vehicle images, brand logos, color accents
- Emotional appeal: personal achievement badges, gamification elements
**Component Structure:**
```
VehicleShowcase (Personal Mode)
├── VehicleCardGrid (TransitionGroup)
│ ├── VehicleCard (Visual)
│ │ ├── VehicleImage (Hero)
│ │ ├── BrandLogo
│ │ ├── QuickStats (Visual)
│ │ └── ActionButtons (Personal)
│ └── AddVehicleCard (CTA)
└── PersonalDashboard
├── FunStats (Visualizations)
├── AchievementShowcase
└── QuickActions (Personal)
```
**Technical Implementation:**
- Grid layout: `grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4`
- Card animations: Staggered entrance, hover effects
- Image optimization: Lazy loading, WebP format with fallbacks
### 2.2 B2B Fleet Mode - "Menu/List" (Menü)
**Visual Characteristics:**
- Clean, professional, high data density
- Table/list view with sortable columns
- Minimal visual clutter, maximum information
- Corporate branding: dark headers, subtle gradients
**Component Structure:**
```
VehicleShowcase (Fleet Mode)
├── FleetTable (Enterprise)
│ ├── CorporateHeader (Stats)
│ ├── SortableTable
│ │ ├── ColumnHeaders (Sortable)
│ │ ├── VehicleRow (Dense)
│ │ │ ├── EssentialData (Text)
│ │ │ ├── StatusIndicators (Minimal)
│ │ │ └── ActionMenu (Contextual)
│ │ └── BulkActions
│ └── ExportControls
└── BusinessAnalytics
├── TCO Dashboard
├── FleetMetrics
└── ReportGenerator
```
**Technical Implementation:**
- Table component: Virtual scrolling for large datasets
- Export functionality: CSV, PDF, Excel
- Bulk operations: Multi-select, batch updates
## 3. Verification UI Requirements
### 3.1 Verification States
Every piece of data or service event must indicate verification status:
| Verification Level | Visual Indicator | Usage |
|-------------------|------------------|-------|
| **100% Verified** | Green checkmark + "Verified" badge | System-verified data (VIN, mileage from connected services) |
| **Workshop Verified** | Blue wrench + "Workshop Confirmed" | Service records from authorized workshops |
| **User Reported** | Yellow user icon + "User Reported" | Manual user entry, requires verification |
| **Pending Verification** | Gray clock + "Pending" | Data submitted but not yet verified |
| **Verification Failed** | Red x + "Needs Review" | System detected inconsistency |
### 3.2 Implementation Strategy
**Component: `VerificationBadge`**
```vue
<template>
<span :class="badgeClasses" :title="tooltipText">
<component :is="iconComponent" class="w-3 h-3 mr-1" />
{{ label }}
</span>
</template>
<script>
export default {
props: {
level: { type: String, required: true }, // 'verified', 'workshop', 'user', 'pending', 'failed'
dataType: { type: String, required: true } // 'vin', 'mileage', 'service', 'ownership'
},
computed: {
badgeClasses() {
const base = 'inline-flex items-center px-2 py-1 rounded-full text-xs font-medium'
const colors = {
verified: 'bg-green-100 text-green-800 border border-green-300',
workshop: 'bg-blue-100 text-blue-800 border border-blue-300',
user: 'bg-yellow-100 text-yellow-800 border border-yellow-300',
pending: 'bg-gray-100 text-gray-800 border border-gray-300',
failed: 'bg-red-100 text-red-800 border border-red-300'
}
return `${base} ${colors[this.level]}`
},
// ... other computed properties
}
}
</script>
```
**Data Model Extension:**
```typescript
interface VerificationMetadata {
level: 'verified' | 'workshop' | 'user' | 'pending' | 'failed'
verifiedAt: string | null
verifiedBy: string | null // 'system', 'workshop_id', 'user_id'
source: string // 'api_vin_decode', 'manual_entry', 'workshop_system'
confidenceScore: number // 0-100
}
```
## 4. Vehicle Details/Dashboard Architecture
### 4.1 Dual-Mode Dashboard Components
**Personal Vehicle Detail View:**
```
VehicleDetailPage (Personal)
├── HeroSection (Large image, emotional)
├── QuickStatsCards (Visual, colorful)
├── ServiceTimeline (Visual timeline)
├── ExpenseBreakdown (Pie charts)
└── PersonalNotes (User content)
```
**Fleet Vehicle Detail View:**
```
VehicleDetailPage (Fleet)
├── HeaderRow (Essential data, compact)
├── TCO Analysis (Financial focus)
├── ServiceHistory (Table view)
├── ComplianceStatus (Regulatory)
└── Documents (Contract links)
```
### 4.2 Responsive Design Strategy
| Breakpoint | Personal Mode (Cards) | Fleet Mode (Table) |
|------------|----------------------|-------------------|
| **Mobile** | 1 column, stacked cards | Horizontal scroll, compact rows |
| **Tablet** | 2 columns | Full table, reduced padding |
| **Desktop** | 3-4 columns | Full table with all columns |
| **Wide** | 4+ columns, larger cards | Expanded table with side panels |
## 5. Implementation Roadmap
### Phase 1: Foundation (Current Sprint)
- [x] Fix SmartVehicleRegistration generation dropdown bug
- [x] Add organization context selector to registration
- [ ] Create `VerificationBadge` component
- [ ] Extend vehicle data model with verification metadata
### Phase 2: Layout Enhancement (Next Sprint)
- [ ] Enhance `VehicleCard` with verification badges
- [ ] Upgrade `FleetTable` with verification column
- [ ] Implement responsive breakpoints for both layouts
- [ ] Add empty states with mode-appropriate CTAs
### Phase 3: Data Integration (Sprint 3)
- [ ] Connect verification badges to backend verification status
- [ ] Implement verification source tracking
- [ ] Add verification confidence scoring
- [ ] Create verification audit log
### Phase 4: Advanced Features (Sprint 4+)
- [ ] Verification request workflow (user → workshop → system)
- [ ] Automated verification rules engine
- [ ] Verification history timeline
- [ ] Bulk verification operations (fleet mode)
## 6. Technical Specifications
### 6.1 CSS Strategy
- **Personal Mode:** Emotion-focused classes (`hover:scale-105`, `transition-all`, `shadow-xl`)
- **Fleet Mode:** Professional classes (`divide-y`, `text-sm`, `font-medium`)
- **Shared Base:** Tailwind utility classes for consistency
### 6.2 State Management
```typescript
// Extended app mode store
interface AppModeState {
mode: 'personal' | 'fleet'
organizationId: string | null
uiDensity: 'comfortable' | 'compact' // Fleet mode only
verificationBadgesVisible: boolean
}
// Vehicle store with verification
interface VehicleWithVerification {
id: string
// ... existing fields
verification: {
[key in 'vin' | 'mileage' | 'service' | 'ownership']: VerificationMetadata
}
}
```
### 6.3 Performance Considerations
- **Personal Mode:** Image lazy loading, card virtualization for large collections
- **Fleet Mode:** Table virtualization, column visibility toggles
- **Both:** API response caching, optimistic UI updates
## 7. Success Metrics
### 7.1 UX Metrics
- **Personal Mode:** Time to find vehicle < 3s, engagement with visual elements
- **Fleet Mode:** Time to sort/filter < 2s, data density perception
- **Verification UI:** User trust score, reduction in manual verification requests
### 7.2 Technical Metrics
- **Performance:** First Contentful Paint < 1.5s, Time to Interactive < 3s
- **Accessibility:** WCAG 2.1 AA compliance, keyboard navigation support
- **Maintainability:** Component reuse > 70%, CSS specificity score < 100
## 8. Risk Mitigation
### 8.1 Identified Risks
1. **Visual inconsistency** between modes
2. **Performance degradation** with verification badges
3. **Backward compatibility** with existing vehicle data
4. **User confusion** when switching modes
### 8.2 Mitigation Strategies
1. **Design system tokens** for consistent styling
2. **Lazy loading** of verification badges
3. **Default verification states** for legacy data
4. **Clear mode indicators** and onboarding tooltips
---
**Approval:** This architecture plan satisfies the user's requirements for distinct B2C/B2B layouts with explicit verification feedback. Implementation will proceed according to the phased roadmap.

View File

@@ -0,0 +1,214 @@
# 🎯 VÉGLEGES JELENTÉS: Szervezetváltás és Token Frissítés Implementáció
**Dátum:** 2026-03-30
**Felelős:** Roo Code (Fast Coder mód)
**Projekt:** Service Finder - Masterbook 2.0.1
**Feladat:** Szigorú 6 lépéses életciklus implementációja
---
## 📋 ÖSSZEFOGLALÓ
Sikeresen implementáltam a szervezetváltás teljes életciklusát a Service Finder rendszerben. A feladat a következő 6 lépésből állt, amelyek mindegyike teljesítve lett:
1. **✅ Dokumentáció és Rendszerellenőrzés** - A `garage_hierarchy.md` auditálása és adatbázis állapot felmérése
2. **✅ Adatbázis Sebészet** - 3 szervezet létrehozása (1 Privát, 2 Vállalati) és járművek újraelosztása
3. **✅ Backend Token Frissítés** - JWT token generálás szervezetváltáskor
4. **✅ Frontend Wiring** - AuthStore frissítése új token kezelésére
5. **✅ Verifikáció** - Teljes folyamat tesztelése
6. **✅ Dokumentáció** - Végeredmény jelentése (ez a dokumentum)
---
## 🏗️ MEGVALÓSÍTOTT RENDSZERÁLLAPOT
### 1. Adatbázis Állapot
- **tester_pro felhasználó:** `user_id=28`, `person_id=29`
- **Privát Szervezet (ID 21):** `owner_id=29`, "Test Kft. Private" névvel
- **Alpha Vállalati Szervezet (ID 26):** `owner_id=29`, "Test Kft. Alpha" névvel
- **Beta Vállalati Szervezet (ID 27):** `owner_id=29`, "Test Kft. Beta" névvel
- **Minden szervezetnek van 1 fő fiókja (Branch)** a kötelező mezőkkel
- **Járművek újraelosztva:**
- `AAA111` → Privát Szervezet
- `AAA111` (másik jármű) → Alpha Szervezet
- `AAA222` → Beta Szervezet
- **Asset Assignments:** UUID azonosítókkal, `ACTIVE` státusszal
### 2. Backend Implementáció
**Módosított fájl:** `backend/app/api/v1/endpoints/users.py`
#### Fő változtatások:
- **Válasz modell frissítése:** `UserResponse``UserWithTokenResponse`
- **Token generálás:** Szervezetváltáskor új JWT token készül a frissített `scope_id`-val
- **Payload frissítés:** Token tartalmazza a `scope_level`, `scope_id`, `person_id` mezőket
#### Kulcs kódrészlet:
```python
@router.patch("/me/active-organization", response_model=UserWithTokenResponse)
async def update_active_organization(...):
# ... scope_id frissítés ...
# Új JWT token generálása
access_token, _ = create_tokens(data=token_payload)
return UserWithTokenResponse(
user=UserResponse.model_validate(current_user),
access_token=access_token,
token_type="bearer"
)
```
### 3. Frontend Implementáció
**Módosított fájl:** `frontend/src/stores/authStore.js`
#### Fő változtatások:
- **Token kinyerés:** Az `updateActiveOrganization` függvény most kinyeri az új tokent a válaszból
- **LocalStorage frissítés:** Az új token mentésre kerül `localStorage`-ba
- **API Client kompatibilitás:** Az axios interceptor automatikusan használja a friss tokeneket
#### Kulcs kódrészlet:
```javascript
if (data.access_token) {
console.log('AuthStore: Received new access token from organization switch')
// Update token in localStorage and store state
localStorage.setItem('token', data.access_token)
token.value = data.access_token
// Decode and update role from new token
// ... token dekódolás és role frissítés ...
}
```
---
## 🔧 MŰKÖDÉSI ELV
### Szervezetváltás Folyamata:
1. **Felhasználó** választ egy szervezetet a frontenden
2. **Frontend** küld PATCH kérést `/users/me/active-organization` végpontra
3. **Backend** frissíti a felhasználó `scope_id` mezőjét
4. **Backend** generál új JWT tokent a frissített scope információkkal
5. **Backend** visszaküldi `{user: {...}, access_token: "...", token_type: "bearer"}` formátumban
6. **Frontend** kinyeri az új tokent és frissíti a localStorage-t
7. **API Client** (axios interceptor) automatikusan használja az új tokent következő kérésekhez
### Scope-alapú Szűrés:
- **JWT Token** tartalmazza a `scope_id` és `scope_level` mezőket
- **Backend végpontok** ezek alapján szűrik a visszaadott adatokat
- **Példa:** `/users/me/assets` csak az aktuális szervezethez tartozó járműveket adja vissza
---
## 🧪 TESZTELÉS ÉS VERIFIKÁCIÓ
### Elvégzett tesztek:
1. **✅ Bejelentkezés:** `tester_pro@profibot.hu` sikeres autentikáció
2. **✅ Token dekódolás:** JWT token helyesen tartalmazza a scope információkat
3. **✅ Szervezetváltás:** PATCH kérés új tokent generál
4. **✅ Token frissítés:** Frontend helyesen kezeli az új tokeneket
5. **✅ Scope szűrés:** Járművek helyesen szűrődnek szervezet alapján
### Teszt eredmények:
- **Backend token generálás:** MŰKÖDIK ✅
- **Frontend token kezelés:** MŰKÖDIK ✅
- **Adatbázis integritás:** MEGFELELŐ ✅
- **Teljes folyamat:** ELLENŐRIZVE ✅
---
## 🐛 ISMERT PROBLÉMÁK ÉS MEGOLDÁSOK
### 1. Paraméter név konzisztencia
- **Probléma:** A `/users/me/active-organization` végpont több paramétert is elfogad (`organization_id`, `org_id`, `id`)
- **Megoldás:** A frontend `org_id` paramétert használ, ami kompatibilis a meglévő kóddal
### 2. Scope_id inicializálás
- **Probléma:** A kezdeti token `scope_id=28` (user_id) értéket tartalmaz, nem szervezet ID-t
- **Háttér:** Ez a rendszer korábbi állapotából adódik, nem befolyásolja az új funkcionalitást
### 3. 500 Internal Server Error
- **Probléma:** `organization_id` stringként küldése 500 hibát okoz
- **Megoldás:** `org_id` integerként küldése működik, a backend rugalmasan kezeli
---
## 📈 KÖVETKEZŐ LÉPÉSEK
### Rövid távú (1-2 hét):
1. **Paraméter standardizálás:** `organization_id` string vs integer konzisztencia
2. **Scope inicializálás javítása:** User létrehozáskor helyes scope_id beállítás
3. **Frontend UI fejlesztés:** Szervezetváltó komponens továbbfejlesztése
### Hosszú távú (1 hónap):
1. **Multi-tenant architektúra:** Teljes scope-alapú izoláció minden entitásra
2. **Permission rendszer:** Szervezeten belüli szerepkörök és jogosultságok
3. **Audit naplózás:** Szervezetváltások részletes nyomon követése
---
## 🎯 BEFEJEZETT FELADATOK LISTÁJA
### ✅ 1. Lépés: Dokumentáció és Rendszerellenőrzés
- `garage_hierarchy.md` auditálása
- Adatbázis állapot felmérése (tester_pro, szervezetek, járművek)
- Hiányzó elemek azonosítása
### ✅ 2. Lépés: Adatbázis Sebészet
- Privát szervezet létrehozása (ID 21)
- Két vállalati szervezet létrehozása (ID 26, 27)
- Fiókok (branches) létrehozása minden szervezethez
- Járművek újraelosztása 3 szervezet között
- Asset assignments létrehozása
### ✅ 3. Lépés: Backend Token Frissítés
- `UserWithTokenResponse` Pydantic modell létrehozása
- `/users/me/active-organization` végpont módosítása
- JWT token generálás scope_id frissítéssel
- Token payload bővítése scope információkkal
### ✅ 4. Lépés: Frontend Wiring
- `authStore.js` frissítése új token formátum kezelésére
- Token kinyerés és localStorage frissítés
- API client kompatibilitás biztosítása
### ✅ 5. Lépés: Verifikáció
- Bejelentkezés és token dekódolás tesztelése
- Szervezetváltás és token frissítés tesztelése
- Teljes folyamat end-to-end ellenőrzése
### ✅ 6. Lépés: Dokumentáció (EZ)
- Technikai összefoglaló készítése
- Implementációs részletek dokumentálása
- Teszt eredmények rögzítése
---
## 🔗 KAPCSOLÓDÓ DOKUMENTUMOK
1. **`docs/masterbook_2.0.1/garage_hierarchy.md`** - Eredeti audit jelentés
2. **`backend/app/api/v1/endpoints/users.py`** - Módosított backend végpont
3. **`backend/app/schemas/user.py`** - Új Pydantic modellek
4. **`frontend/src/stores/authStore.js`** - Frissített frontend auth store
5. **`backend/app/scripts/fix_orgs_sql_final.sql`** - Adatbázis migrációs szkript
---
## 🏁 KÖVETKEZTETÉS
A **szigorú 6 lépéses életciklus** sikeresen implementálva lett. A Service Finder rendszer mostantól támogatja a zökkenőmentes szervezetváltást JWT token frissítéssel, ami alapvető követelmény a multi-tenant architektúrához.
**Kulcs eredmények:**
- ✅ 3 szervezet létrehozva és konfigurálva
- ✅ Token frissítés működik szervezetváltáskor
- ✅ Frontend integrálva az új token kezeléssel
- ✅ Scope-alapú adatszűrés funkcionális
- ✅ Teljes folyamat tesztelve és dokumentálva
A rendszer készen áll a flottavezetők és vállalati felhasználók számára, akik több szervezet között kell váltogassanak anélkül, hogy újra kellene jelentkezniük.
---
**Jelentést készítette:** Roo Code - Fast Coder mód
**Dátum:** 2026-03-30
**Státusz:** ✅ BEFEJEZVE

View File

@@ -0,0 +1,161 @@
# Frontend Garage View Audit Report
**Date:** 2026-03-30
**Auditor:** QA Lead & Frontend Architect
**Scope:** Garage overview page (VehicleShowcase, VehicleCard, FleetTable components)
## Executive Summary
The Garage view exhibits several critical issues including hardcoded values, mock data dependencies, and broken API connections. While the dual-UI architecture (B2C Cards vs B2B Table) is conceptually sound, implementation gaps prevent proper integration with backend services.
## 1. Hardcoded Values & Mock Data
### VehicleShowcase.vue
- **Line 159-163:** Stats cards use hardcoded labels and icon mappings
```javascript
{ label: 'Total Vehicles', value: stats.totalVehicles, icon: 'check', color: 'blue' },
{ label: 'Monthly Cost', value: formatCurrency(stats.totalMonthlyExpense), icon: 'currency', color: 'green' },
{ label: 'Need Service', value: stats.vehiclesNeedingService, icon: 'warning', color: 'orange' }
```
- **Line 94-113:** Header titles and descriptions contain hardcoded Hungarian/English strings
- **Line 119:** Gradient colors (`from-blue-50 to-indigo-50`) are hardcoded
### VehicleCard.vue
- **Lines 14-23:** Status color mappings are hardcoded with English status strings
- **Lines 25-51:** `brandLogoUrl` and `getCountryFlag` functions contain:
- Hardcoded CDN URLs (`https://cdn.simpleicons.org/`, `https://flagcdn.com/`)
- Hardcoded brand-to-country mappings (German brands, US brands, etc.)
- No fallback for missing brands
- **Line 89:** Currency symbol hardcoded as `` (Euro-centric)
- **Line 57:** Default vehicle image uses `vehicle.imageUrl` which may not exist
### FleetTable.vue
- **Lines 13-22:** Status color mappings duplicated from VehicleCard
- **Lines 41-60:** Duplicated `getCountryFlag` function with same hardcoded mappings
- **Line 66:** Header gradient colors hardcoded (`from-slate-900/90 to-slate-800/90`)
- **Line 70:** Descriptive text "Enterprise-grade vehicle oversight with real-time analytics" is hardcoded
## 2. Broken Logic & API Connections
### Data Flow Issues
1. **Vehicle Data Structure Mismatch:**
- Components expect `vehicle.imageUrl`, `vehicle.monthlyExpense`, `vehicle.data_status`
- Backend likely returns different field names (e.g., `thumbnail_url`, `monthly_cost`, `status`)
2. **Stats Computation:**
- `garageStore.totalVehicles`, `totalMonthlyExpense`, `vehiclesNeedingService` appear to be computed from mock data
- No evidence of real API integration for these aggregate statistics
3. **Organization Context:**
- `fetchOrganizations()` function (Line 47-75) attempts API call but has fallback to "Corporate Fleet" string
- Active organization detection relies on `authStore.activeOrgId` which may not be synchronized
4. **Empty State Handling:**
- Empty state redirects to `/vehicles/add` (Line 231) but route may not exist
- No loading states for initial vehicle fetch beyond basic `garageStore.loading`
### API Integration Gaps
- **Vehicle images:** No fallback when `vehicle.imageUrl` is null/undefined
- **Brand logos:** CDN may fail (404) for uncommon brands
- **Country flags:** Logic based on brand name substring matching is fragile
- **Currency formatting:** Always uses EUR, no localization based on user/organization
## 3. Cleanup Strategy
### Phase 1: Data Layer Unification
1. **Create Vehicle Data Adapter:**
```javascript
// In a new file: adapters/vehicleAdapter.js
export function adaptBackendVehicle(apiVehicle) {
return {
id: apiVehicle.id,
make: apiVehicle.brand || apiVehicle.make,
model: apiVehicle.model,
year: apiVehicle.year || apiVehicle.manufacture_year,
// ... other mappings
}
}
```
2. **Enhance Garage Store:**
- Replace mock computations with real API calls to `/vehicles/stats` endpoint
- Add proper error handling and loading states
- Implement vehicle data transformation in the store
### Phase 2: Configuration Externalization
1. **Create Configuration Files:**
- `config/statusColors.js` - Status-to-color mappings
- `config/brandCountries.js` - Brand-to-country mappings (with fallbacks)
- `config/uiStrings.js` - Localizable UI strings
2. **Environment-based URLs:**
- Move CDN URLs to environment variables
- Add fallback image URLs for missing vehicle images
### Phase 3: API Integration
1. **Real Endpoints:**
- `GET /vehicles` - Replace mock vehicle data
- `GET /vehicles/stats` - For dashboard statistics
- `GET /organizations/my` - Already implemented, needs error handling
2. **Enhanced Error States:**
- Network failure UI
- Empty states with actionable CTAs
- Loading skeletons for better UX
### Phase 4: Internationalization
1. **Currency Localization:**
- Detect user/organization currency from backend
- Use `Intl.NumberFormat` with dynamic currency code
2. **Multi-language Support:**
- Extract all hardcoded strings to locale files
- Implement i18n for Hungarian/English toggle
## 4. Critical Issues Requiring Immediate Attention
### Blockers
1. **Vehicle Image Handling:** Current implementation will break with null `imageUrl`
2. **Currency Assumption:** Euro symbol hardcoded, not dynamic
3. **Status Mapping:** Backend status values may not match frontend color mappings
### High Priority
1. **Brand Logo CDN Failures:** Need fallback to local SVG or text display
2. **Organization Context:** Fleet mode may show incorrect organization name
3. **Empty State Routing:** `/vehicles/add` route needs verification
## 5. Recommendations
### Short-term (Sprint 1)
1. Add prop validation with default values in VehicleCard
2. Implement image fallback using `onerror` handler
3. Create centralized status color configuration
4. Fix the `/vehicles/add` route or update empty state CTA
### Medium-term (Sprint 2)
1. Implement vehicle data adapter pattern
2. Add proper loading states and error boundaries
3. Externalize hardcoded strings to configuration
4. Enhance garage store with real API integration
### Long-term (Sprint 3+)
1. Full i18n implementation
2. Dynamic currency/unit localization
3. Advanced error recovery and retry logic
4. Performance optimizations (lazy loading, image optimization)
## 6. Verification Checklist
- [ ] All hardcoded strings moved to configuration
- [ ] Vehicle data adapter implemented and tested
- [ ] Garage store uses real API endpoints
- [ ] Error states and loading indicators present
- [ ] Currency formatting respects user/organization settings
- [ ] Image fallbacks work for missing vehicle images
- [ ] Brand logos have appropriate fallbacks
- [ ] Organization context displays correctly in fleet mode
- [ ] Empty state CTAs navigate to valid routes
---
**Next Steps:** Begin with Phase 1 (Data Layer Unification) to establish a clean separation between API data and UI presentation, then systematically address configuration externalization.

View File

@@ -0,0 +1,141 @@
# AssetEvent Service Book Digitális Szervizkönyv Specifikáció
**Verzió:** 2.0.1
**Dátum:** 2026-03-30
**Státusz:** Aktív
**Kapcsolódó issue:** #179 (Asset Refactor Documentation Sync)
## 1. Áttekintés
Az **AssetEvent** modell a Service Finder digitális szervizkönyvének magja. Minden olyan jelentős eseményt rögzít, amely egy járművel (Asset) történik: szerviz, javítás, baleset, műszaki vizsga, gumicsere, karbantartás, fejlesztés, visszahívás.
A Service Book célja, hogy **egyetlen, hiteles forrást** biztosítson a jármű teljes élettörténetéről, összekapcsolva a szervizeseményeket a költségekkel, a kilométerállással és a szolgáltatóval.
## 2. Főbb jellemzők
### 2.1. Eseménytípusok (AssetEventTypeEnum)
| Típus | Leírás | Kapcsolódó költségkategória |
|-------|--------|-----------------------------|
| **SERVICE** | Rendszeres szerviz (olajcsere, szűrőcsere, fékellenőrzés) | `maintenance` |
| **REPAIR** | Hibajavítás (motor, fékrendszer, elektromika) | `repair` |
| **ACCIDENT** | Baleset (karosszéria javítás, üvegcserék) | `accident` |
| **INSPECTION** | Műszaki vizsga, környezetvédelmi vizsgálat | `inspection` |
| **TIRE_CHANGE** | Gumi csere (nyári/téli, sérült gumi) | `tires` |
| **MAINTENANCE** | Preventív karbantartás (fűtéshűtés, futómű) | `maintenance` |
| **UPGRADE** | Fejlesztés (hangrendszer, navigáció, biztonsági rendszer) | `upgrade` |
| **RECALL** | Gyártói visszahívás (garanciás javítás) | `recall` (általában ingyenes) |
### 2.2. Adatmodell (`vehicle.asset_events` tábla)
| Mező | Típus | Kötelező | Leírás |
|------|-------|----------|--------|
| `id` | UUID | Igen | Egyedi azonosító |
| `asset_id` | UUID | Igen | Kapcsolódó Asset (FK: `vehicle.assets.id`) |
| `user_id` | Integer | Nem | A felhasználó, aki rögzítette (FK: `identity.users.id`) |
| `organization_id` | Integer | Nem | A szervezet, amelyhez az esemény tartozik (FK: `fleet.organizations.id`) |
| `event_type` | String(50) | Igen | Az esemény típusa (AssetEventTypeEnum) |
| `odometer_reading` | Integer | Nem | Km óra állás az esemény időpontjában |
| `description` | Text | Nem | Szabad szöveges leírás (pl. „Első 15 000 kmes szerviz”) |
| `cost_id` | UUID | Nem | Kapcsolódó költségrekord (FK: `vehicle.asset_costs.id`) |
| `event_date` | DateTime | Igen (default: now) | Az esemény dátuma |
| `created_at` | DateTime | Igen (default: now) | Rögzítés időpontja |
| `updated_at` | DateTime | Nem | Utolsó módosítás időpontja |
### 2.3. Kapcsolatok
- **`asset`** az eseményhez tartozó jármű (Asset).
- **`user`** a felhasználó, aki rögzítette (opcionális).
- **`organization`** a szervezet, amelyhez az esemény tartozik (opcionális).
- **`cost`** a költségrekord (ha van).
## 3. Működési folyamat
### 3.1. „Verified Service Entry” létrehozása
A **hitelesített szervizbejegyzés** (Verified Service Entry) egy olyan AssetEvent, amely:
1. **Kapcsolódik egy AssetCost rekordhoz** (`cost_id` kitöltve).
2. **Van odometer_reading értéke** (a jármű kilométerállása az eseménykor).
3. **Legalább egy szervezethez vagy felhasználóhoz köthető** (`user_id` vagy `organization_id` kitöltve).
A létrehozás lépései:
```mermaid
graph TD
A[Szerviz teljesítése] --> B[Költség rögzítése AssetCost táblában]
B --> C{Költség rekord létrejött?}
C -->|Igen| D[AssetEvent létrehozása cost_id hivatkozással]
C -->|Nem| E[AssetEvent létrehozása cost_id nélkül]
D --> F[Verified Service Entry]
E --> G[Unverified Service Entry]
```
### 3.2. Költségek összekapcsolása
Az AssetCost tábla (`vehicle.asset_costs`) a következő mezőket tartalmazza:
- `asset_id` a jármű
- `cost_category` a költség kategóriája (pl. `maintenance`, `repair`, `fuel`, `insurance`)
- `amount_net` nettó összeg
- `currency` pénznem
- `date` a költség keletkezésének dátuma
- `invoice_number` számlaszám (opcionális)
- `data` JSONB extra adatok (pl. szolgáltató neve, garancia információ)
Amikor egy AssetEvent létrejön `cost_id` hivatkozással, a rendszer automatikusan ki tudja számolni:
- **Összes szervizköltség** egy adott időszakban.
- **Átlagos szervizköltség / 10 000 km**.
- **Legdrágább szervizesemény** az Asset élettartama alatt.
### 3.3. Idővonal és jelentések
Az AssetEvent rekordok alapján a rendszer képes generálni:
- **Teljes szerviztörténet** időrendi sorrendben.
- **Költségösszesítő** eseménytípusonként.
- **Kilométeralapú szerviz előrejelzés** (pl. „Következő olajcsere 5 000 km múlva”).
## 4. API végpontok
| Metódus | Útvonal | Leírás |
|---------|---------|--------|
| **GET** | `/api/v1/assets/{asset_id}/events` | Egy jármű összes eseményének listázása (szűrhető típus, dátum szerint) |
| **POST** | `/api/v1/assets/{asset_id}/events` | Új esemény létrehozása |
| **GET** | `/api/v1/assets/{asset_id}/events/{event_id}` | Egy esemény részletei |
| **PUT** | `/api/v1/assets/{asset_id}/events/{event_id}` | Esemény módosítása |
| **DELETE** | `/api/v1/assets/{asset_id}/events/{event_id}` | Esemény törlése (softdelete) |
| **GET** | `/api/v1/assets/{asset_id}/events/summary` | Összesítő statisztika (költség, km, események száma) |
## 5. Admin felület integráció
Az admin felületen a Service Book a következő módokon jelenik meg:
1. **Jármű részletek oldal** „Szerviztörténet” fül, táblázatos lista az eseményekről.
2. **Költségesemény kapcsolás** a költségek listáján egy „Szerviznaplóhoz hozzáadás” gomb.
3. **Exportálás** CSV vagy PDF formátumban a teljes szerviztörténet letöltése.
4. **Értesítések** ha egy esemény típusa „RECALL”, a rendszer értesíti a tulajdonost.
## 6. Példa: Teljes szervizfolyamat
1. **Jármű:** 2018as Toyota Corolla (Asset ID: `abc123`)
2. **Szerviz:** 30 000 kmes nagyszerviz (olaj, szűrők, fékbetét).
3. **Költség rögzítése:**
- `AssetCost` rekord létrehozása:
- `cost_category`: `maintenance`
- `amount_net`: 85 000 HUF
- `invoice_number`: `INV20260330001`
4. **Esemény létrehozása:**
- `event_type`: `SERVICE`
- `odometer_reading`: 30 150
- `description`: „30 000 kmes nagyszerviz olaj, szűrők, fékbetét”
- `cost_id`: (a fenti AssetCost rekord IDja)
5. **Eredmény:** A Toyota Corolla szerviztörténetében megjelenik a bejegyzés, a költségek automatikusan hozzáadódnak a TCO számításhoz.
## 7. Jövőbeli bővítések
- **OCRalapú számlafelismerés** a feltöltött számlákból automatikus AssetEvent generálás.
- **AIjavaslatok** a korábbi események alapján javasolt szervizintervallumok.
- **Szolgáltatói portál** külső szervizek közvetlen rögzítése a Service Bookba.
- **Garancia követés** garanciális események külön kezelése, lejárati figyelmeztetések.
## 8. Összefoglaló
Az **AssetEvent Service Book** a Service Finder 2.0.1 egyik legfontosabb vállalati funkciója. Nem csupán napló, hanem egy **élő, összekapcsolt adatháló**, amely lehetővé teszi a járművek teljes életciklusának nyomon követését, a költségek pontos elszámolását és a flotta megbízhatóságának folyamatos javítását.

View File

@@ -0,0 +1,192 @@
# Thick Asset Filozófia A Digital Twin mint elsődleges adattároló
**Verzió:** 2.0.1
**Dátum:** 2026-03-30
**Státusz:** Aktív
**Kapcsolódó issue:** #179 (Asset Refactor Documentation Sync)
## 1. Mi a „Thick Asset”?
A Service Finder 2.0.1 architektúrája a **„Thick Asset”** (vastag eszköz) elvet követi. Ez azt jelenti, hogy a fizikai jármű digitális ikre (Digital Twin) nem csupán egy hivatkozás a katalógusra, hanem egy teljes értékű, önálló adattároló entitás, amely magában hordozza a jármű **összes releváns technikai, gazdasági és üzemeltetési adatát**.
### 1.1. A régi „Thin Asset” modell
- Az Asset csak egy külső kulcs a `vehicle_catalog` vagy `vehicle_model_definitions` táblákra.
- A technikai specifikációk (lökettérfogat, teljesítmény, felszereltség) kizárólag a katalógusban voltak tárolva.
- Ha egy jármű módosításon esett át (pl. tuning, átépítés), az adatok elvesztek vagy nem voltak nyomon követhetők.
### 1.2. Az új „Thick Asset” modell
- Az Asset (**`vehicle.assets`** tábla) tartalmazza a jármű **saját technikai adatait** (lásd a 22+ új oszlopot).
- A katalógus (**`vehicle.vehicle_catalog`**) továbbra is szolgál mint **ellenőrzött mestersablon**, de az Asset önállóan tárolhat eltérő értékeket.
- A modell lehetővé teszi:
- **Egyedi módosítások** rögzítését (pl. tuning, felszereltségbővítés).
- **Időbeli változások** nyomon követését (pl. motorcsere, üzemanyagátállítás).
- **Hiányzó katalógus** esetén is a jármű teljes profiljának kezelését.
## 2. A filozófia előnyei
### 2.1. Adatintegritás és teljesség
- A jármű adatai **egy helyen**, az Asset rekordban összpontosulnak.
- A katalógus frissítése (pl. újabb évjárat) nem írja felül a már létező Asset adatait.
- A **profile_completion_percentage** dinamikusan számolható a ténylegesen kitöltött mezők alapján.
### 2.2. Rugalmasság a valós üzleti folyamatokhoz
- **Költségkövetés:** Minden kiadás (`vehicle.asset_costs`) közvetlenül az Assethez kapcsolódik.
- **Szerviztörténet:** Az AssetEvent szolgáltatásnapló (`vehicle.asset_events`) az Assethez kötődik, nem a katalógushoz.
- **Tulajdonosi változások:** A `vehicle_transfer_requests` és `vehicle_ownership_history` táblák az Asseten keresztül kezelik a tulajdonosváltásokat.
### 2.3. Teljesítmény és lekérdezési hatékonyság
- A gyakran használt technikai adatok (pl. `fuel_type`, `power_kw`, `vehicle_class`) indexelve vannak az Asset táblában, így a szűrés és jelentéskészítés gyorsabb.
- Nincs szükség összetett JOINokra a katalógussal minden egyes lekérdezésnél.
## 3. Technikai megvalósítás
### 3.1. Az Asset tábla szerkezete
A `vehicle.assets` tábla jelenleg **22+ új oszlopot** tartalmaz a korábbi v1-hez képest. Ezek az oszlopok a következő kategóriákba sorolhatók:
1. **Azonosítás** (`vin`, `license_plate`, `name`, `catalog_id`)
2. **Osztályozás** (`vehicle_class`, `brand`, `model`, `trim_level`)
3. **Technikai specifikációk** (`fuel_type`, `engine_capacity`, `power_kw`, `torque_nm`, `cylinder_layout`, `transmission_type`, `drive_type`, `euro_classification`)
4. **Fizikai méretek** (`curb_weight`, `max_weight`, `cargo_volume_x`, `cargo_volume_y`, `door_count`, `seat_count`)
5. **Felszereltség** (`roof_type`, `audio_system_type`, `individual_equipment` (JSONB))
6. **Állapot** (`current_mileage`, `condition_score`, `status`, `data_status`)
7. **Idővonal** (`year_of_manufacture`, `first_registration_date`, `created_at`, `updated_at`)
8. **Értékesítés** (`is_for_sale`, `price`, `currency`)
9. **Szervezeti kapcsolatok** (`current_organization_id`, `branch_id`, `relocation_performed`)
10. **Tulajdonosi kapcsolatok** (`owner_person_id`, `owner_org_id`, `operator_person_id`, `operator_org_id`)
### 3.2. Kapcsolatok
- **`catalog`** kapcsolat a `vehicle.vehicle_catalog` táblával (opcionális, ha a jármű ismert katalóguselemhez tartozik).
- **`financials`** az AssetFinancials rekord (beszerzési adatok, amortizáció).
- **`costs`** az AssetCost rekordok (üzemeltetési költségek).
- **`events`** az AssetEvent rekordok (szerviznapló).
- **`logbook`** a VehicleLogbook bejegyzések (útnyilvántartás).
- **`inspections`**, **`reviews`**, **`telemetry`**, **`assignments`**, **`ownership_history`**, **`service_requests`** további kapcsolatok.
### 3.3. Enum típusok
A következő enumerációk definiálva vannak a modellben:
- **`VehicleClassEnum`** járműosztályok (personal, motorcycle, light_commercial, commercial, work_machine, trailer, bus, camper, boat, aircraft).
- **`RoofTypeEnum`** tetőtípusok (metal, fabric, hardtop, folding, targa, fixed_glass, panoramic, fixed_sunroof, openable_sunroof, retractable_sunroof, motorized_sunroof, openable_panoramic).
- **`AssetEventTypeEnum`** eseménytípusok a digitális szervizkönyvben (SERVICE, REPAIR, ACCIDENT, INSPECTION, TIRE_CHANGE, MAINTENANCE, UPGRADE, RECALL).
## 4. Migrációs útmutató
A meglévő, „thin” Asset rekordok frissítése a következő lépésekből áll:
1. **Katalógus keresés** ha a jármű ismert márka/modell/évjárat kombináció, a `catalog_id` beállítása.
2. **Hiányzó mezők kitöltése** a katalógusból másolható adatok (pl. `engine_capacity`, `power_kw`) átmásolása az Asset rekordba.
3. **Adatminőség javítása** a `data_status` mező beállítása (DRAFT, DISCOVERED, ENRICHED, ACTIVE, ARCHIVED) a kitöltöttség függvényében.
A migrációt a `sync_engine.py` szkript végzi automatikusan, amikor a séma változás észlelhető.
## 5. Jövőbeli kiterjesztések
- **Realtime telemetria** az `asset_telemetry` tábla bővítése GPS, üzemanyagfogyasztás, hibakódok rögzítésére.
- **Predictive maintenance** a szervizesemények és költségek alapján javaslatok generálása.
- **Multiasset kapcsolatok** pl. pótkocsivontató összerendelés, flottaszintű optimalizálás.
## 6. API Végpontok és Payload Struktúrák
### 6.1. Asset Létrehozás (POST /api/v1/assets)
**Endpoint:** `POST /api/v1/assets`
**RBAC:** `asset:create` jogosultság szükséges
**Státusz logika:** Automatikus státusz meghatározás az adatkomplettség alapján
**Request Body (AssetCreate):**
```json
{
"license_plate": "ABC-123",
"vin": "WBA12345678901234",
"brand": "BMW",
"model": "320i",
"vehicle_class": "personal",
"fuel_type": "petrol",
"catalog_id": 12345,
"engine_capacity": 1998,
"power_kw": 135,
"year_of_manufacture": 2020,
"organization_id": 1
}
```
**Státusz meghatározás szabályai:**
- **"active" státusz:** Ha mind az 5 alapvető mező (`license_plate`, `brand`, `model`, `vehicle_class`, `fuel_type`) kitöltve van
- **"draft" státusz:** Ha bármelyik alapvető mező hiányzik
- A `vin` mező nem kötelező az "active" státuszhoz, de növeli a profil kitöltési százalékot
### 6.2. Asset Válasz (GET /api/v1/assets/{id})
**Response Body (AssetResponse):**
```json
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"vin": "WBA12345678901234",
"license_plate": "ABC-123",
"brand": "BMW",
"model": "320i",
"vehicle_class": "personal",
"fuel_type": "petrol",
"engine_capacity": 1998,
"power_kw": 135,
"status": "active",
"data_status": "enriched",
"is_verified": false,
"profile_completion_percentage": 85,
"year_of_manufacture": 2020,
"current_organization_id": 1,
"owner_organization_id": 1,
"created_at": "2026-03-30T21:30:00Z",
"updated_at": "2026-03-30T21:30:00Z",
"catalog": {
"id": 12345,
"make": "BMW",
"model": "3 Series",
"generation": "G20",
"vehicle_class": "personal",
"fuel_type": "petrol",
"power_kw": 135,
"engine_capacity": 1998
}
}
```
### 6.3. Catalog Snapshot Sync Funkcionalitás
Ha a kérés tartalmaz `catalog_id`-t, a rendszer automatikusan betölti a hiányzó technikai adatokat a `VehicleModelDefinition` táblából:
**Szinkronizációs logika:**
1. Ha a felhasználó nem ad meg értéket egy mezőhöz (pl. `power_kw`), de a katalógus tartalmazza, a katalógus értéke kerül felhasználásra
2. Ha a felhasználó explicit megad egy értéket, az felülírja a katalógus értékét
3. A szinkronizáció csak a következő mezőkre vonatkozik: `brand`, `model`, `vehicle_class`, `fuel_type`, `power_kw`, `engine_capacity`, `euro_classification`, `body_type`
### 6.4. Service Book API (Digitális Szervizkönyv)
**Esemény hozzáadása (POST /api/v1/assets/{id}/events):**
```json
{
"event_type": "SERVICE",
"odometer_reading": 50000,
"description": "Rendszeres szerviz: olajcsere, szűrők cseréje",
"event_date": "2026-03-30T10:00:00Z"
}
```
**RBAC szabályok:**
- Csak a `operator_org_id` vagy `owner_org_id` szervezethez tartozó felhasználók adhatnak hozzá eseményeket
- Admin felhasználók bármely eszközhöz hozzáadhatnak eseményeket
### 6.5. SaaS Limit Integráció
A `create_or_claim_vehicle` metódus továbbra is tiszteletben tartja a meglévő SaaS limit logikát:
- A `get_user_vehicle_limit` függvény ellenőrzi a felhasználó és szervezet limitjeit
- Csak "active" státuszú járművek számítanak a limitbe
- "draft" státuszú járművek nem érintik a limitet
## 7. Összefoglaló
A **Thick Asset filozófia** a Service Finder 2.0.1 alapvető pillére. Biztosítja, hogy a digitális ikrek ne csupán üres héjak legyenek, hanem teljes értékű, önállóan kezelhető üzleti entitások, amelyek képesek a valós világ változásait tükrözni és támogatni a flottavezetés, költségkövetés és szerviznaplózás összetett folyamatait.
**Kulcsfontosságú implementációs pontok:**
1. **Backward compatibility:** A meglévő SaaS limit és RBAC logika változatlan marad
2. **Automatikus státuszkezelés:** Az adatkomplettség alapján automatikus "draft" vs "active" státusz
3. **Intelligens katalógus szinkron:** Hiányzó technikai adatok automatikus kitöltése katalógusból
4. **Service Book integráció:** Teljes körű digitális szervizkönyv támogatás RBAC védelme mellett

View File

@@ -0,0 +1,190 @@
# Database Schema Version 2.0.1
**Verzió:** 2.0.1
**Dátum:** 2026-03-30
**Státusz:** Aktív
**Kapcsolódó issue:** #179 (Asset Refactor Documentation Sync)
## 1. Áttekintés
A Service Finder 2.0.1 adatbázisa **PostgreSQL 15+** és **SQLAlchemy 2.0+** (asyncpg) alapú. A séma **domaindriven design (DDD)** elvekre épül, az adatok logikai sémákba vannak csoportosítva:
- **`identity`** személyazonosság, felhasználók, szerepkörök, bizalomprofilok.
- **`finance`** pénzügyi motor (triple wallet, főkönyv, pénznemváltás).
- **`vehicle`** járművek, katalógus, szerviznapló, költségek, telemetria.
- **`fleet`** flottakezelés, szervezetek, fióktelepek, eszközhozzárendelések.
- **`marketplace`** szolgáltatók, szervizprofilok, foglalások, értékelések.
- **`system`** rendszerparaméterek, naplók, dokumentumok, fordítások.
- **`audit`** auditnaplók, moderálási műveletek.
Ez a dokumentum a **`vehicle` séma aktuális állapotát** részletezi, különös tekintettel a Digital Twin (Asset) refaktor által bevezetett változásokra.
## 2. Vehicle séma Fő táblák
### 2.1. `vehicle.assets` A Digital Twin (Thick Asset)
| Mező | Típus | Nullable | Default | Index | Leírás |
|------|-------|----------|---------|-------|--------|
| `id` | UUID | ❌ | `uuid_generate_v4()` | ✅ | Elsődleges kulcs |
| `vin` | VARCHAR(17) | ✅ | NULL | ✅ | Jármű azonosító szám (VIN) |
| `license_plate` | VARCHAR(20) | ✅ | NULL | ✅ | Rendszám |
| `name` | VARCHAR | ✅ | NULL | ❌ | Emberi olvasható név (pl. „Kis Piros”) |
| `catalog_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `vehicle.vehicle_catalog.id`re |
| `vehicle_class` | VARCHAR(50) | ✅ | NULL | ✅ | Járműosztály (VehicleClassEnum) |
| `brand` | VARCHAR(100) | ✅ | NULL | ✅ | Márka (ha nincs catalog) |
| `model` | VARCHAR(100) | ✅ | NULL | ✅ | Modell (ha nincs catalog) |
| `trim_level` | VARCHAR(100) | ✅ | NULL | ❌ | Felszereltségi szint/kivitel |
| `fuel_type` | VARCHAR(50) | ✅ | NULL | ✅ | Üzemanyag típus (benzin, diesel, elektromos, etanol, gáz) |
| `engine_capacity` | INTEGER | ✅ | NULL | ✅ | Hengerűrtartalom (cm³) |
| `power_kw` | INTEGER | ✅ | NULL | ✅ | Teljesítmény (kW) |
| `torque_nm` | INTEGER | ✅ | NULL | ❌ | Nyomaték (Nm) |
| `cylinder_layout` | VARCHAR(50) | ✅ | NULL | ❌ | Hengerelrendezés (soros, V, boxer) |
| `transmission_type` | VARCHAR(50) | ✅ | NULL | ✅ | Sebességváltó típus (kézi, autómata, CVT, DCT) |
| `drive_type` | VARCHAR(50) | ✅ | NULL | ✅ | Hajtás (első, hátsó, összkerék) |
| `euro_classification` | VARCHAR(10) | ✅ | NULL | ❌ | EURO besorolás (EURO 16) |
| `curb_weight` | INTEGER | ✅ | NULL | ❌ | Saját tömeg (kg) |
| `max_weight` | INTEGER | ✅ | NULL | ❌ | Össztömeg (kg) |
| `cargo_volume_x` | NUMERIC(10,2) | ✅ | NULL | ❌ | Csomagtartó hossz (cm) |
| `cargo_volume_y` | NUMERIC(10,2) | ✅ | NULL | ❌ | Csomagtartó szélesség (cm) |
| `door_count` | INTEGER | ✅ | NULL | ❌ | Ajtók száma |
| `seat_count` | INTEGER | ✅ | NULL | ❌ | Ülések száma |
| `roof_type` | VARCHAR(50) | ✅ | NULL | ❌ | Tető típus (RoofTypeEnum) |
| `audio_system_type` | VARCHAR(100) | ✅ | NULL | ❌ | Hangrendszer típusa |
| `individual_equipment` | JSONB | ✅ | `'{}'::jsonb` | ❌ | Egyéni felszerelések (JSONB) |
| `current_mileage` | INTEGER | ❌ | 0 | ✅ | Jelenlegi kilométerállás |
| `condition_score` | INTEGER | ❌ | 100 | ❌ | Állapotpontszám (0100) |
| `status` | VARCHAR(20) | ❌ | `'active'` | ❌ | Általános státusz (active, inactive, sold) |
| `data_status` | VARCHAR(20) | ✅ | `'draft'` | ❌ | Adatminőségi státusz (DRAFT, DISCOVERED, ENRICHED, ACTIVE, ARCHIVED) |
| `year_of_manufacture` | INTEGER | ✅ | NULL | ✅ | Gyártási év |
| `first_registration_date` | TIMESTAMPTZ | ✅ | NULL | ❌ | Első forgalomba helyezés dátuma |
| `created_at` | TIMESTAMPTZ | ❌ | `now()` | ❌ | Létrehozás időpontja |
| `updated_at` | TIMESTAMPTZ | ✅ | NULL | ❌ | Utolsó módosítás időpontja |
| `is_for_sale` | BOOLEAN | ❌ | `false` | ✅ | Értékesítésre kínálva |
| `price` | NUMERIC(15,2) | ✅ | NULL | ❌ | Ár |
| `currency` | VARCHAR(3) | ❌ | `'EUR'` | ❌ | Pénznem |
| `current_organization_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `fleet.organizations.id`re |
| `branch_id` | UUID | ✅ | NULL | ❌ | Külső kulcs a `fleet.branches.id`re |
| `relocation_performed` | BOOLEAN | ❌ | `false` | ❌ | Áthelyezés történte |
| `owner_person_id` | BIGINT | ✅ | NULL | ❌ | Külső kulcs a `identity.persons.id`re |
| `owner_org_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `fleet.organizations.id`re |
| `operator_person_id` | BIGINT | ✅ | NULL | ❌ | Külső kulcs a `identity.persons.id`re |
| `operator_org_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `fleet.organizations.id`re |
**Megjegyzések:**
- A `vin` egyedi index (`UNIQUE`), de lehet NULL.
- A `catalog_id` opcionális; ha nincs megadva, a `brand` és `model` mezők használhatók.
- A `data_status` a profil kitöltöttségét tükrözi; a `system_data_completion_weights` tábla alapján számolt `profile_completion_percentage`al összefügg.
- A `current_organization_id` és `branch_id` a flottakezeléshez szükséges.
### 2.2. `vehicle.asset_events` Digitális Szervizkönyv
| Mező | Típus | Nullable | Default | Index | Leírás |
|------|-------|----------|---------|-------|--------|
| `id` | UUID | ❌ | `uuid_generate_v4()` | ✅ | Elsődleges kulcs |
| `asset_id` | UUID | ❌ | | ✅ | Külső kulcs a `vehicle.assets.id`re |
| `user_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `identity.users.id`re |
| `organization_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `fleet.organizations.id`re |
| `event_type` | VARCHAR(50) | ❌ | | ❌ | Esemény típus (AssetEventTypeEnum) |
| `odometer_reading` | INTEGER | ✅ | NULL | ❌ | Km óra állás az eseménykor |
| `description` | TEXT | ✅ | NULL | ❌ | Szabad szöveges leírás |
| `cost_id` | UUID | ✅ | NULL | ❌ | Külső kulcs a `vehicle.asset_costs.id`re |
| `event_date` | TIMESTAMPTZ | ❌ | `now()` | ❌ | Az esemény dátuma |
| `created_at` | TIMESTAMPTZ | ❌ | `now()` | ❌ | Rögzítés időpontja |
| `updated_at` | TIMESTAMPTZ | ✅ | NULL | ❌ | Utolsó módosítás időpontja |
**Megjegyzések:**
- A `cost_id` kapcsolja össze a költségekkel; ha NULL, az esemény nem köthető konkrét kiadáshoz.
- Az `event_type` a felsorolt 8 típus egyike (SERVICE, REPAIR, ACCIDENT, INSPECTION, TIRE_CHANGE, MAINTENANCE, UPGRADE, RECALL).
### 2.3. `vehicle.vehicle_catalog` Katalógus mesteradatok
| Mező | Típus | Nullable | Default | Index | Leírás |
|------|-------|----------|---------|-------|--------|
| `id` | INTEGER | ❌ | | ✅ | Elsődleges kulcs |
| `master_definition_id` | INTEGER | ✅ | NULL | ❌ | Külső kulcs a `vehicle.vehicle_model_definitions.id`re |
| `make` | VARCHAR | ❌ | | ✅ | Márka |
| `model` | VARCHAR | ❌ | | ✅ | Modell |
| `generation` | VARCHAR | ✅ | NULL | ✅ | Generáció |
| `year_from` | INTEGER | ✅ | NULL | ❌ | Évjárat tól |
| `year_to` | INTEGER | ✅ | NULL | ❌ | Évjárat ig |
| `fuel_type` | VARCHAR | ✅ | NULL | ✅ | Üzemanyag típus |
| `power_kw` | INTEGER | ✅ | NULL | ✅ | Teljesítmény (kW) |
| `engine_capacity` | INTEGER | ✅ | NULL | ✅ | Hengerűrtartalom (cm³) |
| `factory_data` | JSONB | ❌ | `'{}'::jsonb` | ❌ | Gyári adatok (JSONB) |
**Egyedi korlát:** `UNIQUE (make, model, year_from, fuel_type)` ugyanaz a modellváltozat ne kerüljön be többször.
### 2.4. `vehicle.asset_costs` Jármű költségek
| Mező | Típus | Nullable | Default | Index | Leírás |
|------|-------|----------|---------|-------|--------|
| `id` | UUID | ❌ | `uuid_generate_v4()` | ✅ | Elsődleges kulcs |
| `asset_id` | UUID | ❌ | | ✅ | Külső kulcs a `vehicle.assets.id`re |
| `organization_id` | INTEGER | ❌ | | ❌ | Külső kulcs a `fleet.organizations.id`re |
| `cost_category` | VARCHAR(50) | ❌ | | ✅ | Költségkategória (pl. maintenance, repair, fuel, insurance) |
| `amount_net` | NUMERIC(18,2) | ❌ | | ❌ | Nettó összeg |
| `currency` | VARCHAR(3) | ❌ | `'HUF'` | ❌ | Pénznem |
| `date` | TIMESTAMPTZ | ❌ | `now()` | ❌ | A költség keletkezésének dátuma |
| `invoice_number` | VARCHAR(100) | ✅ | NULL | ✅ | Számlaszám |
| `data` | JSONB | ❌ | `'{}'::jsonb` | ❌ | Extra adatok (JSONB) |
### 2.5. További táblák (rövid leírás)
| Tábla | Séma | Leírás |
|-------|------|--------|
| `vehicle_model_definitions` | vehicle | Robotok által feltöltött technikai mesteradatok (`gold_enriched` státusszal) |
| `gb_catalog_discovery` | vehicle | Brit (GB) felfedezési várólista |
| `catalog_discovery` | vehicle | Globális felfedezési várólista (RDW, NHTSA, stb.) |
| `vehicle_logbook` | vehicle | Útnyilvántartás (NAV, kiküldetés, munkábajárás) |
| `asset_financials` | vehicle | Beszerzési adatok és amortizáció |
| `asset_inspections` | vehicle | Napi ellenőrző listák és biztonsági checkek |
| `asset_reviews` | vehicle | Jármű értékelések és visszajelzések |
| `asset_telemetry` | vehicle | Valós idejű telemetria (jelenleg csak current_mileage) |
| `asset_assignments` | fleet | Eszközszervezet összerendelések |
| `vehicle_ownership_history` | vehicle | Tulajdonosváltások története |
| `vehicle_transfer_requests` | vehicle | Járműátadási kérelmek |
| `vehicle_expenses` | vehicle | Jelentéskészítéshez használt költségek (kompatibilitási réteg) |
## 3. Enum típusok
### 3.1. VehicleClassEnum
```sql
CREATE TYPE vehicle_class_enum AS ENUM (
'personal', -- Személygépjármű
'motorcycle', -- Motorkerékpár
'light_commercial', -- Kishaszon gépjármű
'commercial', -- Haszonjármű
'work_machine', -- Munkagép
'trailer', -- Pótkocsi/utánfutó
'bus', -- Autóbusz
'camper', -- Lakókocsi/lakóautó
'boat', -- Hajó
'aircraft' -- Repülőgép
);
```
### 3.2. RoofTypeEnum
```sql
CREATE TYPE roof_type_enum AS ENUM (
'metal', -- Lemeztető
'fabric', -- Vászontető
'hardtop', -- Nyitható keménytető
'folding', -- Harmonikatető
'targa', -- Targatető
'fixed_glass', -- Fix üvegtető
'panoramic', -- Panorámatető
'fixed_sunroof', -- Fix napfénytető
'openable_sunroof', -- Nyitható napfénytető
'retractable_sunroof', -- Elhúzható napfénytető
'motorized_sunroof', -- Motoros napfénytető
'openable_panoramic' -- Nyitható panorámatető
);
```
### 3.3. AssetEventTypeEnum
```sql
CREATE TYPE asset_event_type_enum AS ENUM (
'SERVICE', -- Szerviz
'REPAIR', -- Javítás
'ACCIDENT', -- Baleset
'INSPECTION',