coder16
updated claudio
67aa1ca
Raw
History Blame Contribute Delete
3.87 kB
"""Tipos compartidos, enumeraciones y objetos de valor embebidos.
Estos componentes se reutilizan tanto en los modelos de dominio
(:mod:`app.models`) como en los esquemas de la API (:mod:`app.schemas`),
manteniendo el sistema genérico y fácil de extender.
"""
from __future__ import annotations
from datetime import datetime, timezone
from enum import Enum
from typing import Annotated
from pydantic import BaseModel, BeforeValidator, ConfigDict, EmailStr, Field
# ---------------------------------------------------------------------------
# Identificadores
# ---------------------------------------------------------------------------
# El ``_id`` de MongoDB (ObjectId) se serializa siempre como cadena.
PyObjectId = Annotated[str, BeforeValidator(str)]
# Patrón de hora en formato 24h "HH:MM".
_HORA_PATTERN = r"^([01]\d|2[0-3]):[0-5]\d$"
def utcnow() -> datetime:
"""Devuelve la fecha y hora actual en UTC (con zona horaria)."""
return datetime.now(timezone.utc)
# ---------------------------------------------------------------------------
# Enumeraciones
# ---------------------------------------------------------------------------
class TipoItem(str, Enum):
"""Tipo de item ofertado por un negocio."""
menu = "menu"
servicio = "servicio"
producto = "producto"
class DiaSemana(str, Enum):
"""Días de la semana para los horarios de atención."""
lunes = "lunes"
martes = "martes"
miercoles = "miercoles"
jueves = "jueves"
viernes = "viernes"
sabado = "sabado"
domingo = "domingo"
# ---------------------------------------------------------------------------
# Objetos de valor embebidos
# ---------------------------------------------------------------------------
class Telefono(BaseModel):
"""Número de teléfono de un negocio."""
tipo: str = Field(default="principal", max_length=40)
numero: str = Field(min_length=1, max_length=40)
class Correo(BaseModel):
"""Correo electrónico de contacto de un negocio."""
tipo: str = Field(default="principal", max_length=40)
correo: EmailStr
class RedSocial(BaseModel):
"""Enlace a una red social del negocio."""
tipo: str = Field(min_length=1, max_length=40)
url: str = Field(min_length=1, max_length=2048)
class Direccion(BaseModel):
"""Dirección física del negocio."""
direccion: str = Field(min_length=1, max_length=512)
referencias: str | None = Field(default=None, max_length=512)
class Ubicacion(BaseModel):
"""Coordenadas geográficas del negocio."""
latitud: float = Field(ge=-90, le=90)
longitud: float = Field(ge=-180, le=180)
class Horario(BaseModel):
"""Horario de atención para un día concreto."""
dia: DiaSemana
apertura: str = Field(pattern=_HORA_PATTERN)
cierre: str = Field(pattern=_HORA_PATTERN)
class Imagen(BaseModel):
"""Imagen asociada a un negocio."""
url: str = Field(min_length=1, max_length=2048)
principal: bool = False
class ImagenItem(BaseModel):
"""Imagen asociada a un item."""
url: str = Field(min_length=1, max_length=2048)
# ---------------------------------------------------------------------------
# Modelo base de documentos
# ---------------------------------------------------------------------------
class MongoModel(BaseModel):
"""Base para los modelos que representan documentos de MongoDB.
Mapea el ``_id`` de Mongo al campo ``id`` y lo expone como cadena.
"""
model_config = ConfigDict(
populate_by_name=True,
use_enum_values=True,
arbitrary_types_allowed=True,
json_schema_extra={"description": "Documento almacenado en MongoDB."},
)
# Lee el ``_id`` de Mongo y lo expone como ``id`` (cadena) en la salida.
id: PyObjectId | None = Field(
default=None, alias="_id", serialization_alias="id"
)