feat: Asset Catalog system, PostGIS integration and RobotScout V1

This commit is contained in:
2026-02-11 22:47:38 +00:00
parent a63e6c8fac
commit 09a0430384
53 changed files with 2756 additions and 426 deletions

View File

@@ -6,42 +6,57 @@ from sqlalchemy.sql import func
from app.db.base_class import Base
class AssetCatalog(Base):
"""Globális járműkatalógus (Márka -> Típus -> Generáció -> Motor)."""
__tablename__ = "vehicle_catalog"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True, index=True)
make = Column(String, index=True, nullable=False)
model = Column(String, index=True, nullable=False)
generation = Column(String)
make = Column(String, index=True, nullable=False) # 1. Szint: Audi
model = Column(String, index=True, nullable=False) # 2. Szint: A4
generation = Column(String, index=True) # 3. Szint: B8 (2008-2015)
engine_variant = Column(String) # 4. Szint: 2.0 TDI (150 LE)
year_from = Column(Integer)
year_to = Column(Integer)
vehicle_class = Column(String)
fuel_type = Column(String)
engine_code = Column(String)
factory_data = Column(JSON, server_default=text("'{}'::jsonb"))
factory_data = Column(JSON, server_default=text("'{}'::jsonb")) # Technikai specifikációk
assets = relationship("Asset", back_populates="catalog")
class Asset(Base):
"""Egyedi jármű (Asset) példány - Az ökoszisztéma magja."""
__tablename__ = "assets"
__table_args__ = {"schema": "data"}
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
vin = Column(String(17), unique=True, index=True, nullable=False)
license_plate = Column(String(20), index=True)
name = Column(String)
year_of_manufacture = Column(Integer)
# --- BIZTONSÁGI ÉS JOGOSULTSÁGI IZOLÁCIÓ ---
# A current_organization_id biztosítja a gyors, adatbázis-szintű Scoped RBAC védelmet.
current_organization_id = Column(Integer, ForeignKey("data.organizations.id"), nullable=True)
catalog_id = Column(Integer, ForeignKey("data.vehicle_catalog.id"))
is_verified = Column(Boolean, default=False)
verification_method = Column(String(20)) # 'robot', 'ocr', 'manual'
status = Column(String(20), default="active")
created_at = Column(DateTime(timezone=True), server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
# Kapcsolatok (Digital Twin Modules)
catalog = relationship("AssetCatalog", back_populates="assets")
current_org = relationship("Organization")
financials = relationship("AssetFinancials", back_populates="asset", uselist=False)
telemetry = relationship("AssetTelemetry", back_populates="asset", uselist=False)
assignments = relationship("AssetAssignment", back_populates="asset")
events = relationship("AssetEvent", back_populates="asset")
costs = relationship("AssetCost", back_populates="asset")
reviews = relationship("AssetReview", back_populates="asset")
ownership_history = relationship("VehicleOwnership", back_populates="vehicle")
class AssetFinancials(Base):
__tablename__ = "asset_financials"
@@ -77,9 +92,10 @@ class AssetReview(Base):
created_at = Column(DateTime(timezone=True), server_default=func.now())
asset = relationship("Asset", back_populates="reviews")
user = relationship("User") # <--- JAVÍTÁS: Hozzáadva
user = relationship("User")
class AssetAssignment(Base):
"""Jármű flotta-történetének nyilvántartása."""
__tablename__ = "asset_assignments"
__table_args__ = {"schema": "data"}
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
@@ -90,7 +106,7 @@ class AssetAssignment(Base):
status = Column(String(30), default="active")
asset = relationship("Asset", back_populates="assignments")
organization = relationship("Organization") # <--- KRITIKUS JAVÍTÁS: Ez okozta a login hibát
organization = relationship("Organization")
class AssetEvent(Base):
__tablename__ = "asset_events"
@@ -113,16 +129,13 @@ class AssetCost(Base):
amount_local = Column(Numeric(18, 2), nullable=False)
currency_local = Column(String(3), nullable=False)
amount_eur = Column(Numeric(18, 2), nullable=True)
net_amount_local = Column(Numeric(18, 2))
vat_rate = Column(Numeric(5, 2))
exchange_rate_used = Column(Numeric(18, 6))
date = Column(DateTime(timezone=True), server_default=func.now())
mileage_at_cost = Column(Integer)
data = Column(JSON, server_default=text("'{}'::jsonb"))
asset = relationship("Asset", back_populates="costs")
organization = relationship("Organization") # <--- JAVÍTÁS: Hozzáadva
driver = relationship("User") # <--- JAVÍTÁS: Hozzáadva
organization = relationship("Organization")
driver = relationship("User")
class ExchangeRate(Base):
__tablename__ = "exchange_rates"
@@ -131,5 +144,4 @@ class ExchangeRate(Base):
base_currency = Column(String(3), default="EUR")
target_currency = Column(String(3), unique=True)
rate = Column(Numeric(18, 6), nullable=False)
rate_date = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())