feat: Funcion de sistema tenants

This commit is contained in:
2026-02-23 13:01:24 -07:00
parent ceea67eb2b
commit 1ccc39732b
58 changed files with 1889 additions and 315 deletions

View File

@@ -6,7 +6,9 @@ SQLAlchemy 2.0 async setup con PostgreSQL
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from sqlalchemy import String, DateTime, func
from sqlalchemy import String, DateTime, func, text
from sqlalchemy.types import TypeDecorator, CHAR
from sqlalchemy.dialects.postgresql import UUID as PG_UUID
from typing import AsyncGenerator
import uuid
from datetime import datetime
@@ -34,18 +36,46 @@ AsyncSessionLocal = async_sessionmaker(
autoflush=True,
autocommit=False
)
class GUID(TypeDecorator):
"""UUID portable: UUID nativo en Postgres, CHAR(36) en otros dialectos (SQLite para tests)."""
impl = CHAR
cache_ok = True
def load_dialect_impl(self, dialect):
if dialect.name == "postgresql":
return dialect.type_descriptor(PG_UUID(as_uuid=True))
return dialect.type_descriptor(CHAR(36))
def process_bind_param(self, value, dialect):
if value is None:
return None
if dialect.name == "postgresql":
return value
if isinstance(value, uuid.UUID):
return str(value)
return str(uuid.UUID(str(value)))
def process_result_value(self, value, dialect):
if value is None:
return None
if isinstance(value, uuid.UUID):
return value
return uuid.UUID(str(value))
class Base(DeclarativeBase):
"""Base class para todos los modelos SQLAlchemy."""
# Columnas comunes para auditoría
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
id: Mapped[uuid.UUID] = mapped_column(GUID(), primary_key=True, default=uuid.uuid4)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True),
DateTime(timezone=True),
server_default=func.now(),
onupdate=func.now()
onupdate=func.now(),
)
@@ -89,7 +119,7 @@ async def check_database_health() -> bool:
"""
try:
async with AsyncSessionLocal() as session:
await session.execute("SELECT 1")
await session.execute(text("SELECT 1"))
return True
except Exception:
return False