2026.03.29 20:00 Gitea_manager javítás előtt
This commit is contained in:
@@ -97,7 +97,12 @@ class ServiceReview(Base):
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
service_id: Mapped[int] = mapped_column(Integer, ForeignKey("marketplace.service_profiles.id", ondelete="CASCADE"), nullable=False)
|
||||
user_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id", ondelete="SET NULL"), nullable=False)
|
||||
transaction_id: Mapped[uuid.UUID] = mapped_column(PG_UUID(as_uuid=True), nullable=False, index=True)
|
||||
transaction_id: Mapped[uuid.UUID] = mapped_column(
|
||||
PG_UUID(as_uuid=True),
|
||||
ForeignKey("audit.financial_ledger.transaction_id", ondelete="RESTRICT"),
|
||||
nullable=False,
|
||||
index=True
|
||||
)
|
||||
|
||||
# Rating dimensions (1-10)
|
||||
price_rating: Mapped[int] = mapped_column(Integer, nullable=False) # 1-10
|
||||
@@ -113,4 +118,5 @@ class ServiceReview(Base):
|
||||
|
||||
# Relationships
|
||||
service: Mapped["ServiceProfile"] = relationship("ServiceProfile", back_populates="reviews")
|
||||
user: Mapped["User"] = relationship("User", back_populates="service_reviews")
|
||||
user: Mapped["User"] = relationship("User", back_populates="service_reviews")
|
||||
financial_transaction: Mapped["FinancialLedger"] = relationship("FinancialLedger", foreign_keys=[transaction_id])
|
||||
@@ -1,175 +0,0 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/marketplace/service.py
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Any, List, Optional
|
||||
from sqlalchemy import Integer, String, Boolean, DateTime, ForeignKey, text, Text, Float, Index, Numeric, BigInteger
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
from sqlalchemy.dialects.postgresql import UUID as PG_UUID, JSONB
|
||||
from geoalchemy2 import Geometry
|
||||
from sqlalchemy.sql import func
|
||||
|
||||
# MB 2.0: Központi aszinkron adatbázis motorból húzzuk be a Base-t
|
||||
from app.database import Base
|
||||
|
||||
class ServiceProfile(Base):
|
||||
""" Szerviz szolgáltató adatai (v1.3.1). """
|
||||
__tablename__ = "service_profiles"
|
||||
__table_args__ = (
|
||||
Index('idx_service_fingerprint', 'fingerprint', unique=True),
|
||||
{"schema": "marketplace"}
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
organization_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("fleet.organizations.id"), unique=True)
|
||||
parent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("marketplace.service_profiles.id"))
|
||||
|
||||
fingerprint: Mapped[str] = mapped_column(String(255), index=True, nullable=False)
|
||||
location: Mapped[Any] = mapped_column(Geometry(geometry_type='POINT', srid=4326, spatial_index=False), index=True)
|
||||
|
||||
status: Mapped[str] = mapped_column(String(20), server_default=text("'ghost'"), index=True)
|
||||
last_audit_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
google_place_id: Mapped[Optional[str]] = mapped_column(String(100), unique=True)
|
||||
rating: Mapped[Optional[float]] = mapped_column(Float)
|
||||
user_ratings_total: Mapped[Optional[int]] = mapped_column(Integer)
|
||||
|
||||
# Aggregated verified review ratings (Social 3)
|
||||
rating_verified_count: Mapped[Optional[int]] = mapped_column(Integer, server_default=text("0"))
|
||||
rating_price_avg: Mapped[Optional[float]] = mapped_column(Float)
|
||||
rating_quality_avg: Mapped[Optional[float]] = mapped_column(Float)
|
||||
rating_time_avg: Mapped[Optional[float]] = mapped_column(Float)
|
||||
rating_communication_avg: Mapped[Optional[float]] = mapped_column(Float)
|
||||
rating_overall: Mapped[Optional[float]] = mapped_column(Float)
|
||||
last_review_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
||||
|
||||
vibe_analysis: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
social_links: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
specialization_tags: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
|
||||
trust_score: Mapped[int] = mapped_column(Integer, default=30)
|
||||
is_verified: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
verification_log: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
|
||||
opening_hours: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
contact_phone: Mapped[Optional[str]] = mapped_column(String)
|
||||
contact_email: Mapped[Optional[str]] = mapped_column(String)
|
||||
website: Mapped[Optional[str]] = mapped_column(String)
|
||||
bio: Mapped[Optional[str]] = mapped_column(Text)
|
||||
|
||||
# Kapcsolatok
|
||||
organization: Mapped["Organization"] = relationship("Organization", back_populates="service_profile")
|
||||
expertises: Mapped[List["ServiceExpertise"]] = relationship("ServiceExpertise", back_populates="service")
|
||||
reviews: Mapped[List["ServiceReview"]] = relationship("ServiceReview", back_populates="service")
|
||||
|
||||
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())
|
||||
|
||||
class ExpertiseTag(Base):
|
||||
"""
|
||||
Szakmai címkék mesterlistája (MB 2.0).
|
||||
Ez a tábla vezérli a robotok keresését és a Gamification pontozást is.
|
||||
"""
|
||||
__tablename__ = "expertise_tags"
|
||||
__table_args__ = {"schema": "marketplace"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
|
||||
# Egyedi azonosító kulcs (pl. 'ENGINE_REBUILD')
|
||||
key: Mapped[str] = mapped_column(String(50), unique=True, index=True)
|
||||
|
||||
# Megjelenítendő nevek
|
||||
name_hu: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
name_en: Mapped[Optional[str]] = mapped_column(String(100))
|
||||
|
||||
# Főcsoport (pl. 'MECHANICS', 'ELECTRICAL', 'EMERGENCY')
|
||||
category: Mapped[Optional[str]] = mapped_column(String(30), index=True)
|
||||
|
||||
# --- 🎮 GAMIFICATION ÉS DISCOVERY ---
|
||||
|
||||
# Hivatalos címke (True) vagy júzer/robot által javasolt (False)
|
||||
is_official: Mapped[bool] = mapped_column(Boolean, default=True, server_default=text("true"))
|
||||
|
||||
# Ha júzer javasolta, itt tároljuk, ki volt az (XP jóváíráshoz)
|
||||
suggested_by_id: Mapped[Optional[int]] = mapped_column(BigInteger, ForeignKey("identity.persons.id"))
|
||||
|
||||
# ÁLLÍTHATÓ PONTÉRTÉK: Az adatbázisból jön, így bármikor módosítható.
|
||||
# Ritka szakmáknál magasabb, gyakoriaknál alacsonyabb érték állítható be.
|
||||
discovery_points: Mapped[int] = mapped_column(Integer, default=10, server_default=text("10"))
|
||||
|
||||
# Robot kulcsszavak (JSONB): ["fék", "betét", "tárcsa", "fékfolyadék"]
|
||||
# A Scout robot ez alapján azonosítja be a szervizt a weboldala alapján.
|
||||
search_keywords: Mapped[Any] = mapped_column(JSONB, server_default=text("'[]'::jsonb"))
|
||||
|
||||
# Népszerűségi mutató (hányszor lett felhasználva a rendszerben)
|
||||
usage_count: Mapped[int] = mapped_column(Integer, default=0, server_default=text("0"))
|
||||
|
||||
# UI ikon azonosító (pl. 'wrench', 'tire-flat', 'car-electric')
|
||||
icon: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
|
||||
# Leírás a szakmáról (Adminisztratív célokra)
|
||||
description: Mapped[Optional[str]] = mapped_column(Text)
|
||||
|
||||
# Időbélyegek
|
||||
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 ---
|
||||
services: Mapped[List["ServiceExpertise"]] = relationship("ServiceExpertise", back_populates="tag")
|
||||
# Visszamutatás a beküldőre (ha van)
|
||||
suggested_by: Mapped[Optional["Person"]] = relationship("Person")
|
||||
|
||||
class ServiceExpertise(Base):
|
||||
"""
|
||||
KAPCSOLÓTÁBLA: Ez köti össze a szervizt a szakmáival.
|
||||
Itt tároljuk, hogy az adott szerviznél mennyire validált egy szakma.
|
||||
"""
|
||||
__tablename__ = "service_expertises"
|
||||
__table_args__ = {"schema": "marketplace"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
service_id: Mapped[int] = mapped_column(Integer, ForeignKey("marketplace.service_profiles.id", ondelete="CASCADE"))
|
||||
expertise_id: Mapped[int] = mapped_column(Integer, ForeignKey("marketplace.expertise_tags.id", ondelete="CASCADE"))
|
||||
|
||||
# Mennyire biztos ez a tudás? (0: robot találta, 1: júzer mondta, 2: igazolt szakma)
|
||||
confidence_level: Mapped[int] = mapped_column(Integer, default=0, server_default=text("0"))
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=text("now()"))
|
||||
|
||||
# Kapcsolatok visszafelé
|
||||
service = relationship("ServiceProfile", back_populates="expertises")
|
||||
tag = relationship("ExpertiseTag", back_populates="services")
|
||||
|
||||
class ServiceStaging(Base):
|
||||
""" Hunter (robot) adatok tárolója. """
|
||||
__tablename__ = "service_staging"
|
||||
__table_args__ = (
|
||||
Index('idx_staging_fingerprint', 'fingerprint', unique=True),
|
||||
{"schema": "marketplace"}
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
|
||||
name: Mapped[str] = mapped_column(String, index=True, nullable=False)
|
||||
postal_code: Mapped[Optional[str]] = mapped_column(String(10), index=True)
|
||||
city: Mapped[Optional[str]] = mapped_column(String(100), index=True)
|
||||
full_address: Mapped[Optional[str]] = mapped_column(String)
|
||||
fingerprint: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
raw_data: Mapped[Any] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
|
||||
# Additional contact and identification fields
|
||||
contact_phone: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
|
||||
website: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
||||
external_id: Mapped[Optional[str]] = mapped_column(String(100), nullable=True, index=True)
|
||||
|
||||
status: Mapped[str] = mapped_column(String(20), server_default=text("'pending'"), index=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
class DiscoveryParameter(Base):
|
||||
""" Robot vezérlési paraméterek adminból. """
|
||||
__tablename__ = "discovery_parameters"
|
||||
__table_args__ = {"schema": "marketplace"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
city: Mapped[str] = mapped_column(String(100))
|
||||
keyword: Mapped[str] = mapped_column(String(100))
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
last_run_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
||||
@@ -1,73 +0,0 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/models/marketplace/staged_data.py
|
||||
from datetime import datetime
|
||||
from typing import Optional, Any
|
||||
from sqlalchemy import String, Integer, DateTime, text, Boolean, Float
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlalchemy.sql import func
|
||||
from app.db.base_class import Base
|
||||
|
||||
class StagedVehicleData(Base):
|
||||
""" Robot 2.1 (Researcher) nyers adatgyűjtője. """
|
||||
__tablename__ = "staged_vehicle_data"
|
||||
__table_args__ = {"schema": "system"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
source_url: Mapped[Optional[str]] = mapped_column(String)
|
||||
raw_data: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
|
||||
status: Mapped[str] = mapped_column(String(20), default="PENDING", index=True)
|
||||
error_log: Mapped[Optional[str]] = mapped_column(String)
|
||||
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
class ServiceStaging(Base):
|
||||
""" Robot 1.3 (Scout) által talált nyers szerviz adatok és a Robot 5 (Auditor) naplója. """
|
||||
__tablename__ = "service_staging"
|
||||
__table_args__ = {"schema": "marketplace"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
name: Mapped[str] = mapped_column(String(255), index=True)
|
||||
source: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
external_id: Mapped[Optional[str]] = mapped_column(String(100), index=True)
|
||||
fingerprint: Mapped[str] = mapped_column(String(64), unique=True, index=True)
|
||||
|
||||
# Elérhetőségek
|
||||
city: Mapped[str] = mapped_column(String(100), index=True)
|
||||
postal_code: Mapped[Optional[str]] = mapped_column(String(10))
|
||||
full_address: Mapped[Optional[str]] = mapped_column(String(500))
|
||||
contact_phone: Mapped[Optional[str]] = mapped_column(String(50))
|
||||
website: Mapped[Optional[str]] = mapped_column(String(255))
|
||||
contact_email: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
|
||||
|
||||
# Beküldés és Bizalom
|
||||
description: Mapped[Optional[str]] = mapped_column(Text)
|
||||
submitted_by: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.users.id"))
|
||||
trust_score: Mapped[int] = mapped_column(Integer, default=0, server_default=text("0"))
|
||||
|
||||
# Nyers adatok és Státusz
|
||||
raw_data: Mapped[dict] = mapped_column(JSONB, server_default=text("'{}'::jsonb"))
|
||||
status: Mapped[str] = mapped_column(String(20), default="pending", index=True)
|
||||
|
||||
# --- Robot 5 (Auditor) technikai mezők ---
|
||||
# Ezek kellenek a munka naplózásához
|
||||
rejection_reason: Mapped[Optional[str]] = mapped_column(String(500))
|
||||
published_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
||||
service_profile_id: Mapped[Optional[int]] = mapped_column(Integer)
|
||||
organization_id: Mapped[Optional[int]] = mapped_column(Integer)
|
||||
audit_trail: Mapped[Optional[dict]] = mapped_column(JSONB)
|
||||
|
||||
# Időbélyegek
|
||||
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())
|
||||
|
||||
class DiscoveryParameter(Base):
|
||||
""" Felderítési paraméterek (Városok, ahol a Scout keres). """
|
||||
__tablename__ = "discovery_parameters"
|
||||
__table_args__ = {"schema": "marketplace"}
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
city: Mapped[str] = mapped_column(String(100), unique=True, index=True)
|
||||
keyword: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
last_run_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
||||
@@ -106,7 +106,7 @@ class FinancialLedger(Base):
|
||||
gross_amount: Mapped[Optional[float]] = mapped_column(Numeric(18, 4))
|
||||
net_amount: Mapped[Optional[float]] = mapped_column(Numeric(18, 4))
|
||||
transaction_id: Mapped[uuid.UUID] = mapped_column(
|
||||
PG_UUID(as_uuid=True), default=uuid.uuid4, nullable=False, index=True
|
||||
PG_UUID(as_uuid=True), default=uuid.uuid4, nullable=False, unique=True, index=True
|
||||
)
|
||||
status: Mapped[LedgerStatus] = mapped_column(
|
||||
PG_ENUM(LedgerStatus, name="ledger_status", schema="audit"),
|
||||
|
||||
@@ -38,8 +38,8 @@ class SystemParameter(Base):
|
||||
updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), onupdate=func.now(), server_default=func.now())
|
||||
|
||||
class InternalNotification(Base):
|
||||
"""
|
||||
Belső értesítési központ.
|
||||
"""
|
||||
Belső értesítési központ.
|
||||
Ezek az üzenetek várják a felhasználót belépéskor.
|
||||
"""
|
||||
__tablename__ = "internal_notifications"
|
||||
@@ -53,11 +53,33 @@ class InternalNotification(Base):
|
||||
category: Mapped[str] = mapped_column(String(50), server_default="info")
|
||||
priority: Mapped[str] = mapped_column(String(20), server_default="medium")
|
||||
|
||||
is_read: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
||||
read_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
data: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)
|
||||
|
||||
is_read: Mapped[bool] = mapped_column(Boolean, default=False, index=True)
|
||||
|
||||
class SystemDataCompletionWeight(Base):
|
||||
"""Adatkitöltési súlyok rendszerszintű konfigurációja - mely mezők mennyire fontosak a profil teljességéhez."""
|
||||
__tablename__ = "system_data_completion_weights"
|
||||
__table_args__ = (
|
||||
UniqueConstraint('entity_type', 'field_name', name='uix_entity_field'),
|
||||
{"schema": "system"}
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
entity_type: Mapped[str] = mapped_column(String(50), nullable=False, index=True) # pl: "vehicle", "person", "organization"
|
||||
field_name: Mapped[str] = mapped_column(String(100), nullable=False, index=True) # pl: "vin", "license_plate", "email"
|
||||
weight_percent: Mapped[int] = mapped_column(Integer, nullable=False) # 0-100%
|
||||
is_mandatory: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=True)
|
||||
|
||||
description: Mapped[Optional[str]] = mapped_column(Text)
|
||||
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())
|
||||
|
||||
# Shadow column that exists in database (should be removed in future migration)
|
||||
is_read: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
|
||||
|
||||
|
||||
class SystemServiceStaging(Base):
|
||||
|
||||
@@ -64,6 +64,7 @@ class Asset(Base):
|
||||
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())
|
||||
@@ -87,6 +88,51 @@ class Asset(Base):
|
||||
"""Always False for now, as verification is not yet implemented."""
|
||||
return False
|
||||
|
||||
@property
|
||||
def profile_completion_percentage(self) -> int:
|
||||
"""
|
||||
Calculate profile completion percentage based on available data.
|
||||
Uses dynamic weights from system.system_data_completion_weights table.
|
||||
Default weights (if not configured):
|
||||
- license_plate: 20%
|
||||
- make: 15% (from catalog)
|
||||
- model: 15% (from catalog)
|
||||
- vin: 30%
|
||||
- year_of_manufacture: 20%
|
||||
"""
|
||||
# Default weights (fallback if dynamic weights not available)
|
||||
default_weights = {
|
||||
'license_plate': 20,
|
||||
'make': 15,
|
||||
'model': 15,
|
||||
'vin': 30,
|
||||
'year_of_manufacture': 20
|
||||
}
|
||||
|
||||
total_score = 0
|
||||
|
||||
# 1. license_plate
|
||||
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:
|
||||
total_score += default_weights['make']
|
||||
|
||||
# 3. model (from catalog)
|
||||
if self.catalog and self.catalog.model:
|
||||
total_score += default_weights['model']
|
||||
|
||||
# 4. vin
|
||||
if self.vin and self.vin.strip():
|
||||
total_score += default_weights['vin']
|
||||
|
||||
# 5. year_of_manufacture
|
||||
if self.year_of_manufacture:
|
||||
total_score += default_weights['year_of_manufacture']
|
||||
|
||||
return min(total_score, 100)
|
||||
|
||||
class AssetFinancials(Base):
|
||||
""" I. Beszerzés és IV. Értékcsökkenés (Amortizáció). """
|
||||
__tablename__ = "asset_financials"
|
||||
@@ -273,4 +319,27 @@ class VehicleExpenses(Base):
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
# Relationship
|
||||
asset: Mapped["Asset"] = relationship("Asset")
|
||||
asset: Mapped["Asset"] = relationship("Asset")
|
||||
|
||||
|
||||
class VehicleTransferRequest(Base):
|
||||
"""Járműátadási kérelem - asset átruházás másik tulajdonosnak vagy szervezetnek."""
|
||||
__tablename__ = "vehicle_transfer_requests"
|
||||
__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, index=True)
|
||||
requester_id: Mapped[int] = mapped_column(Integer, ForeignKey("identity.users.id"), nullable=False, index=True)
|
||||
current_owner_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("identity.persons.id"), nullable=True, index=True)
|
||||
status: Mapped[str] = mapped_column(String(20), default="pending", index=True)
|
||||
proof_document_id: Mapped[Optional[uuid.UUID]] = mapped_column(PG_UUID(as_uuid=True), ForeignKey("system.documents.id"), nullable=True)
|
||||
|
||||
requested_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
|
||||
processed_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True))
|
||||
notes: Mapped[Optional[str]] = mapped_column(Text)
|
||||
|
||||
# Relationships
|
||||
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")
|
||||
Reference in New Issue
Block a user