Spaces:
Sleeping
Sleeping
File size: 3,871 Bytes
67aa1ca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | """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"
)
|