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

@@ -1,6 +1,7 @@
# /opt/docker/dev/service_finder/backend/app/models/vehicle/asset.py
from __future__ import annotations
import uuid
import enum
from datetime import datetime
from typing import List, Optional, TYPE_CHECKING
from sqlalchemy import String, Boolean, DateTime, ForeignKey, Numeric, text, Text, UniqueConstraint, BigInteger, Integer, Float
@@ -9,6 +10,7 @@ from sqlalchemy.dialects.postgresql import UUID as PG_UUID, JSONB
from sqlalchemy.sql import func
from app.database import Base
class AssetCatalog(Base):
""" Jármű katalógus mesteradatok (Validált technikai sablonok). """
__tablename__ = "vehicle_catalog"
@@ -33,46 +35,106 @@ class AssetCatalog(Base):
master_definition: Mapped[Optional["VehicleModelDefinition"]] = relationship("VehicleModelDefinition", back_populates="variants")
assets: Mapped[List["Asset"]] = relationship("Asset", back_populates="catalog")
class VehicleClassEnum(str, enum.Enum):
"""Jármű osztályok a 99_Adattarolás.md alapján."""
PERSONAL = "personal" # Személygépjármű
MOTORCYCLE = "motorcycle" # Motorkerékpár
LIGHT_COMMERCIAL = "light_commercial" # Kishaszon gépjármű
COMMERCIAL = "commercial" # Haszonjármű
WORK_MACHINE = "work_machine" # Munkagép
TRAILER = "trailer" # Pótkocsi/utánfutó
BUS = "bus" # Autóbusz
CAMPER = "camper" # Lakókocsi/lakóautó
BOAT = "boat" # Hajó
AIRCRAFT = "aircraft" # Repülőgép
class RoofTypeEnum(str, enum.Enum):
"""Tető típusok a 99_Adattarolás.md alapján."""
METAL = "metal" # Lemeztető
FABRIC = "fabric" # Vászontető
HARDTOP = "hardtop" # Nyitható keménytető
FOLDING = "folding" # Harmonikatető
TARGA = "targa" # Targatető
FIXED_GLASS = "fixed_glass" # Fix üvegtető
PANORAMIC = "panoramic" # Panorámatető
FIXED_SUNROOF = "fixed_sunroof" # Fix napfénytető
OPENABLE_SUNROOF = "openable_sunroof" # Nyitható napfénytető
RETRACTABLE_SUNROOF = "retractable_sunroof" # Elhúzható napfénytető
MOTORIZED_SUNROOF = "motorized_sunroof" # Motoros napfénytető
OPENABLE_PANORAMIC = "openable_panoramic" # Nyitható panorámatető
class Asset(Base):
""" A fizikai eszköz (Digital Twin) - Minden adat itt fut össze. """
__tablename__ = "assets"
__table_args__ = {"schema": "vehicle"}
# === IDENTIFICATION ===
id: Mapped[uuid.UUID] = mapped_column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
vin: Mapped[Optional[str]] = mapped_column(String(17), unique=True, index=True, nullable=True)
license_plate: Mapped[Optional[str]] = mapped_column(String(20), index=True)
name: Mapped[Optional[str]] = mapped_column(String)
# Állapot és életút mérőszámok
catalog_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("vehicle.vehicle_catalog.id"))
# === CLASSIFICATION ===
vehicle_class: Mapped[Optional[str]] = mapped_column(String(50), index=True) # VehicleClassEnum értékek
brand: Mapped[Optional[str]] = mapped_column(String(100), index=True) # Márka (ha nincs catalog)
model: Mapped[Optional[str]] = mapped_column(String(100), index=True) # Modell (ha nincs catalog)
trim_level: Mapped[Optional[str]] = mapped_column(String(100)) # Felszereltségi szint/kivitel
# === TECHNICAL SPECS ===
fuel_type: Mapped[Optional[str]] = mapped_column(String(50), index=True) # benzin, diesel, elektromos, etanol, gáz
engine_capacity: Mapped[Optional[int]] = mapped_column(Integer, index=True) # cm³
power_kw: Mapped[Optional[int]] = mapped_column(Integer, index=True) # kW
torque_nm: Mapped[Optional[int]] = mapped_column(Integer) # Nm
cylinder_layout: Mapped[Optional[str]] = mapped_column(String(50)) # soros, V, boxer, stb.
transmission_type: Mapped[Optional[str]] = mapped_column(String(50), index=True) # kézi, autómata, CVT, DCT
drive_type: Mapped[Optional[str]] = mapped_column(String(50), index=True) # első, hátsó, összkerék
euro_classification: Mapped[Optional[str]] = mapped_column(String(10)) # EURO 1-6
# === PHYSICAL DIMENSIONS ===
curb_weight: Mapped[Optional[int]] = mapped_column(Integer) # saját tömeg (kg)
max_weight: Mapped[Optional[int]] = mapped_column(Integer) # össztömeg (kg)
cargo_volume_x: Mapped[Optional[float]] = mapped_column(Numeric(10, 2)) # csomagtartó hossz (cm)
cargo_volume_y: Mapped[Optional[float]] = mapped_column(Numeric(10, 2)) # csomagtartó szélesség (cm)
door_count: Mapped[Optional[int]] = mapped_column(Integer) # ajtók száma
seat_count: Mapped[Optional[int]] = mapped_column(Integer) # ülések száma
# === EQUIPMENT ===
roof_type: Mapped[Optional[str]] = mapped_column(String(50)) # RoofTypeEnum értékek
audio_system_type: Mapped[Optional[str]] = mapped_column(String(100)) # rádió típusa
individual_equipment: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb")) # JSONB extra felszerelések
# === STATUS ===
current_mileage: Mapped[int] = mapped_column(Integer, default=0, index=True)
condition_score: Mapped[int] = mapped_column(Integer, default=100) # 0-100
status: Mapped[str] = mapped_column(String(20), default="active")
data_status: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, server_default=text("'draft'"))
# === TIMELINE ===
year_of_manufacture: Mapped[Optional[int]] = mapped_column(Integer, index=True)
first_registration_date: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
current_mileage: Mapped[int] = mapped_column(Integer, default=0, index=True)
condition_score: Mapped[int] = mapped_column(Integer, default=100)
# Értékesítési modul
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), onupdate=func.now())
# === SALES MODULE ===
is_for_sale: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
price: Mapped[Optional[float]] = mapped_column(Numeric(15, 2))
currency: Mapped[str] = mapped_column(String(3), default="EUR")
catalog_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("vehicle.vehicle_catalog.id"))
# === ORGANIZATION & LOCATION ===
current_organization_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("fleet.organizations.id"))
# Garage-centric hierarchy
branch_id: Mapped[Optional[uuid.UUID]] = mapped_column(PG_UUID(as_uuid=True), ForeignKey("fleet.branches.id"))
relocation_performed: Mapped[bool] = mapped_column(Boolean, server_default=text('false'), default=False)
# Identity kapcsolatok
# === IDENTITY RELATIONSHIPS ===
owner_person_id: Mapped[Optional[int]] = mapped_column(BigInteger, ForeignKey("identity.persons.id"))
owner_org_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("fleet.organizations.id"))
operator_person_id: Mapped[Optional[int]] = mapped_column(BigInteger, ForeignKey("identity.persons.id"))
operator_org_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("fleet.organizations.id"))
status: Mapped[str] = mapped_column(String(20), default="active")
data_status: Mapped[Optional[str]] = mapped_column(String(20), nullable=True, server_default=text("'draft'"))
individual_equipment: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), onupdate=func.now())
# --- KAPCSOLATOK ---
catalog: Mapped["AssetCatalog"] = relationship("AssetCatalog", back_populates="assets")
financials: Mapped[Optional["AssetFinancials"]] = relationship("AssetFinancials", back_populates="asset", uselist=False)
@@ -119,12 +181,12 @@ class Asset(Base):
if self.license_plate and self.license_plate.strip():
total_score += default_weights['license_plate']
# 2. make (from catalog)
if self.catalog and self.catalog.make:
# 2. make (from catalog or brand field)
if (self.catalog and self.catalog.make) or self.brand:
total_score += default_weights['make']
# 3. model (from catalog)
if self.catalog and self.catalog.model:
# 3. model (from catalog or model field)
if (self.catalog and self.catalog.model) or self.model:
total_score += default_weights['model']
# 4. vin
@@ -137,6 +199,7 @@ class Asset(Base):
return min(total_score, 100)
class AssetFinancials(Base):
""" I. Beszerzés és IV. Értékcsökkenés (Amortizáció). """
__tablename__ = "asset_financials"
@@ -154,6 +217,7 @@ class AssetFinancials(Base):
asset: Mapped["Asset"] = relationship("Asset", back_populates="financials")
class AssetCost(Base):
""" II. Üzemeltetés és TCO kimutatás. """
__tablename__ = "asset_costs"
@@ -172,6 +236,7 @@ class AssetCost(Base):
asset: Mapped["Asset"] = relationship("Asset", back_populates="costs")
organization: Mapped["Organization"] = relationship("Organization")
class VehicleLogbook(Base):
""" Útnyilvántartás (NAV, Kiküldetés, Munkábajárás). """
__tablename__ = "vehicle_logbook"
@@ -193,7 +258,6 @@ class VehicleLogbook(Base):
end_lng: Mapped[Optional[float]] = mapped_column(Numeric(10, 6), nullable=True)
gps_calculated_distance: Mapped[Optional[float]] = mapped_column(Numeric(10, 2), nullable=True)
# OBDII és telemetria
obd_verified: Mapped[bool] = mapped_column(Boolean, default=False)
max_acceleration: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
average_speed: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
@@ -201,6 +265,7 @@ class VehicleLogbook(Base):
asset: Mapped["Asset"] = relationship("Asset", back_populates="logbook")
driver: Mapped["User"] = relationship("User")
class AssetInspection(Base):
""" Napi ellenőrző lista és Biztonsági check. """
__tablename__ = "asset_inspections"
@@ -216,6 +281,7 @@ class AssetInspection(Base):
asset: Mapped["Asset"] = relationship("Asset", back_populates="inspections")
inspector: Mapped["User"] = relationship("User")
class AssetReview(Base):
""" Jármű értékelések és visszajelzések. """
__tablename__ = "asset_reviews"
@@ -231,6 +297,7 @@ class AssetReview(Base):
asset: Mapped["Asset"] = relationship("Asset", back_populates="reviews")
user: Mapped["User"] = relationship("User")
class VehicleOwnership(Base):
""" Tulajdonosváltások története. """
__tablename__ = "vehicle_ownership_history"
@@ -246,6 +313,7 @@ class VehicleOwnership(Base):
# JAVÍTVA: Kapcsolat a User modellhez
user: Mapped["User"] = relationship("User", back_populates="ownership_history")
class AssetTelemetry(Base):
__tablename__ = "asset_telemetry"
__table_args__ = {"schema": "vehicle"}
@@ -254,6 +322,7 @@ class AssetTelemetry(Base):
current_mileage: Mapped[int] = mapped_column(Integer, default=0)
asset: Mapped["Asset"] = relationship("Asset", back_populates="telemetry")
class AssetAssignment(Base):
""" Eszköz-Szervezet összerendelés. """
__tablename__ = "asset_assignments"
@@ -266,14 +335,44 @@ class AssetAssignment(Base):
asset: Mapped["Asset"] = relationship("Asset", back_populates="assignments")
organization: Mapped["Organization"] = relationship("Organization", back_populates="assets")
class AssetEventTypeEnum(str, enum.Enum):
"""Digitális Szervizkönyv eseménytípusok."""
SERVICE = "SERVICE" # Szerviz
REPAIR = "REPAIR" # Javítás
ACCIDENT = "ACCIDENT" # Baleset
INSPECTION = "INSPECTION" # Műszaki vizsga
TIRE_CHANGE = "TIRE_CHANGE" # Gumi csere
MAINTENANCE = "MAINTENANCE" # Karbantartás
UPGRADE = "UPGRADE" # Fejlesztés
RECALL = "RECALL" # Visszahívás
class AssetEvent(Base):
""" Szerviz, baleset és egyéb jelentős események. """
""" Digitális Szervizkönyv - Szerviz, baleset és egyéb jelentős események. """
__tablename__ = "asset_events"
__table_args__ = {"schema": "vehicle"}
id: Mapped[uuid.UUID] = mapped_column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
asset_id: Mapped[uuid.UUID] = mapped_column(PG_UUID(as_uuid=True), ForeignKey("vehicle.assets.id"), nullable=False)
event_type: Mapped[str] = mapped_column(String(50), nullable=False)
user_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"), nullable=True)
organization_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("fleet.organizations.id"), nullable=True)
event_type: Mapped[str] = mapped_column(String(50), nullable=False) # AssetEventTypeEnum értékek
odometer_reading: Mapped[Optional[int]] = mapped_column(Integer) # Km óra állás az eseménykor
description: Mapped[Optional[str]] = mapped_column(Text)
cost_id: Mapped[Optional[uuid.UUID]] = mapped_column(PG_UUID(as_uuid=True), ForeignKey("vehicle.asset_costs.id"), nullable=True)
event_date: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), onupdate=func.now())
# Relationships
asset: Mapped["Asset"] = relationship("Asset", back_populates="events")
user: Mapped[Optional["User"]] = relationship("User")
organization: Mapped[Optional["Organization"]] = relationship("Organization")
cost: Mapped[Optional["AssetCost"]] = relationship("AssetCost")
class ExchangeRate(Base):
__tablename__ = "exchange_rates"
@@ -281,6 +380,7 @@ class ExchangeRate(Base):
id: Mapped[int] = mapped_column(Integer, primary_key=True)
rate: Mapped[float] = mapped_column(Numeric(18, 6), nullable=False)
class CatalogDiscovery(Base):
""" Robot munkaterület a felfedezett modelleknek. """
__tablename__ = "catalog_discovery"
@@ -309,6 +409,7 @@ class CatalogDiscovery(Base):
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
class VehicleExpenses(Base):
""" Jármű költségek a jelentésekhez. """
__tablename__ = "vehicle_expenses"
@@ -347,4 +448,4 @@ class VehicleTransferRequest(Base):
asset: Mapped["Asset"] = relationship("Asset")
requester: Mapped["User"] = relationship("User", foreign_keys=[requester_id])
current_owner: Mapped[Optional["Person"]] = relationship("Person", foreign_keys=[current_owner_id])
proof_document: Mapped[Optional["Document"]] = relationship("Document")
proof_document: Mapped[Optional["Document"]] = relationship("Document")