feat: implement pivot-currency model, rbac smart tokens & fix circular imports

This commit is contained in:
2026-02-10 10:20:45 +00:00
parent 24d35fe0c1
commit e255fea3a5
117 changed files with 2247 additions and 3542 deletions

View File

@@ -1,133 +1,128 @@
import uuid
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, JSON, Numeric, text
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey, JSON, Numeric, text, Text
from sqlalchemy.orm import relationship
from sqlalchemy.dialects.postgresql import UUID as PG_UUID
from sqlalchemy.sql import func
from app.db.base_class import Base
class AssetCatalog(Base):
"""Központi jármű katalógus (Admin/Bot által tölthető)"""
__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)
year_from = Column(Integer)
year_to = Column(Integer)
vehicle_class = Column(String) # land, sea, air
vehicle_class = Column(String)
fuel_type = Column(String)
engine_code = Column(String)
factory_data = Column(JSON, server_default=text("'{}'::jsonb"))
assets = relationship("Asset", back_populates="catalog")
class Asset(Base):
"""A Jármű Identitás (Digital Twin törzsadatok)"""
__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)
catalog_id = Column(Integer, ForeignKey("data.vehicle_catalog.id"))
# Nemzetközi mutatók
quality_index = Column(Numeric(3, 2), default=1.00)
system_mileage = Column(Integer, default=0)
mileage_unit = Column(String(10), default="km") # Nemzetközi: km, miles, hours
is_verified = Column(Boolean, default=False)
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())
catalog = relationship("AssetCatalog", back_populates="assets")
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"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True)
asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), unique=True)
acquisition_price = Column(Numeric(18, 2))
acquisition_date = Column(DateTime)
financing_type = Column(String)
residual_value_estimate = Column(Numeric(18, 2))
asset = relationship("Asset", back_populates="financials")
class AssetTelemetry(Base):
__tablename__ = "asset_telemetry"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True)
asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), unique=True)
current_mileage = Column(Integer, default=0)
mileage_unit = Column(String(10), default="km")
vqi_score = Column(Numeric(5, 2), default=100.00)
dbs_score = Column(Numeric(5, 2), default=100.00)
asset = relationship("Asset", back_populates="telemetry")
class AssetReview(Base):
__tablename__ = "asset_reviews"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True)
asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False)
user_id = Column(Integer, ForeignKey("data.users.id"), nullable=False)
overall_rating = Column(Integer)
criteria_scores = Column(JSON, server_default=text("'{}'::jsonb"))
comment = Column(Text)
created_at = Column(DateTime(timezone=True), server_default=func.now())
asset = relationship("Asset", back_populates="reviews")
class AssetAssignment(Base):
"""Birtoklás követése (Kié a jármű és mettől meddig)"""
__tablename__ = "asset_assignments"
__table_args__ = {"schema": "data"}
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False)
organization_id = Column(Integer, ForeignKey("data.organizations.id"), nullable=False)
assigned_at = Column(DateTime(timezone=True), server_default=func.now())
released_at = Column(DateTime(timezone=True), nullable=True)
status = Column(String(30), default="active")
notes = Column(String)
asset = relationship("Asset", back_populates="assignments")
organization = relationship("Organization", back_populates="assets")
class AssetEvent(Base):
"""Élettörténeti események (Szerviz, km-óra állások, balesetek)"""
__tablename__ = "asset_events"
__table_args__ = {"schema": "data"}
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False)
event_type = Column(String(50), nullable=False)
event_date = Column(DateTime(timezone=True), server_default=func.now())
event_type = Column(String(50), nullable=False)
recorded_mileage = Column(Integer)
description = Column(String)
data = Column(JSON, server_default=text("'{}'::jsonb"))
asset = relationship("Asset", back_populates="events")
class AssetCost(Base):
"""
Költségkezelő modell: Bruttó/Nettó/ÁFA és deviza támogatás.
"""
__tablename__ = "asset_costs"
__table_args__ = {"schema": "data"}
id = Column(PG_UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
asset_id = Column(PG_UUID(as_uuid=True), ForeignKey("data.assets.id"), nullable=False)
organization_id = Column(Integer, ForeignKey("data.organizations.id"), nullable=False)
cost_type = Column(String(50), nullable=False) # fuel, service, tax, insurance, toll
# Pénzügyi adatok
amount = Column(Numeric(18, 2), nullable=False) # Bruttó összeg
net_amount = Column(Numeric(18, 2)) # Nettó összeg
vat_amount = Column(Numeric(18, 2)) # ÁFA érték
vat_rate = Column(Numeric(5, 2)) # ÁFA kulcs (pl. 27.00)
# Nemzetközi deviza kezelés
currency = Column(String(3), default="HUF") # Riportálási deviza
original_currency = Column(String(3)) # Számla eredeti devizája
exchange_rate_at_cost = Column(Numeric(18, 6)) # Rögzítéskori árfolyam
driver_id = Column(Integer, ForeignKey("data.users.id"), nullable=True)
cost_type = Column(String(50), nullable=False)
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())
description = Column(String)
invoice_id = Column(String)
mileage_at_cost = Column(Integer)
data = Column(JSON, server_default=text("'{}'::jsonb"))
asset = relationship("Asset", back_populates="costs")
class ExchangeRate(Base):
"""Napi árfolyamok tárolása (ECB/MNB adatok alapján)"""
__tablename__ = "exchange_rates"
__table_args__ = {"schema": "data"}
id = Column(Integer, primary_key=True, index=True)
id = Column(Integer, primary_key=True)
base_currency = Column(String(3), default="EUR")
target_currency = Column(String(3), nullable=False)
target_currency = Column(String(3), unique=True)
rate = Column(Numeric(18, 6), nullable=False)
rate_date = Column(DateTime(timezone=False), index=True)
provider = Column(String(50), default="ECB")
updated_at = Column(DateTime(timezone=True), server_default=func.now())
rate_date = Column(DateTime, server_default=func.now())
updated_at = Column(DateTime(timezone=True), onupdate=func.now())