landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
LandveX Admin Backend — Database Base Model
|
||||
SQLAlchemy declarative base and mixins
|
||||
"""
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Dict
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy import Column, DateTime, String, event
|
||||
from sqlalchemy.dialects.postgresql import UUID, JSONB
|
||||
from sqlalchemy.orm import DeclarativeBase, declared_attr
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
"""Base class for all database models."""
|
||||
|
||||
# Generate tablename automatically from class name
|
||||
@declared_attr.directive
|
||||
def __tablename__(cls) -> str:
|
||||
return cls.__name__.lower() + "s"
|
||||
|
||||
# Common columns for all tables
|
||||
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid4)
|
||||
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
|
||||
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert model instance to dictionary."""
|
||||
result = {}
|
||||
for column in self.__table__.columns:
|
||||
value = getattr(self, column.name)
|
||||
if value is not None:
|
||||
if isinstance(value, datetime):
|
||||
result[column.name] = value.isoformat()
|
||||
else:
|
||||
result[column.name] = value
|
||||
return result
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<{self.__class__.__name__}(id={self.id})>"
|
||||
|
||||
|
||||
class AuditMixin:
|
||||
"""Mixin to add audit fields to models."""
|
||||
|
||||
created_by = Column(String(255), nullable=True)
|
||||
updated_by = Column(String(255), nullable=True)
|
||||
deleted_at = Column(DateTime(timezone=True), nullable=True)
|
||||
deleted_by = Column(String(255), nullable=True)
|
||||
is_deleted = Column(String(1), default="N") # Soft delete flag
|
||||
|
||||
@property
|
||||
def is_active(self) -> bool:
|
||||
"""Check if record is active (not soft-deleted)."""
|
||||
return self.is_deleted == "N" and self.deleted_at is None
|
||||
|
||||
|
||||
class MetadataMixin:
|
||||
"""Mixin to add JSON metadata field to models."""
|
||||
|
||||
metadata_json = Column("metadata", JSONB, default=dict)
|
||||
|
||||
def get_metadata(self) -> Dict[str, Any]:
|
||||
"""Get metadata as dictionary."""
|
||||
return self.metadata_json or {}
|
||||
|
||||
def set_metadata(self, key: str, value: Any) -> None:
|
||||
"""Set a metadata value."""
|
||||
if self.metadata_json is None:
|
||||
self.metadata_json = {}
|
||||
self.metadata_json[key] = value
|
||||
Reference in New Issue
Block a user