feat: add backend FastAPI structure and Supabase schema
This commit is contained in:
21
server/app/domain/__init__.py
Normal file
21
server/app/domain/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from app.domain.entities.ruta import (
|
||||
Coordenada,
|
||||
EstadoCamion,
|
||||
ETAResult,
|
||||
NotificationPreferences,
|
||||
PuntoRuta,
|
||||
Ruta,
|
||||
TruckStatus,
|
||||
TipoNotificacion,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Coordenada",
|
||||
"EstadoCamion",
|
||||
"ETAResult",
|
||||
"NotificationPreferences",
|
||||
"PuntoRuta",
|
||||
"Ruta",
|
||||
"TruckStatus",
|
||||
"TipoNotificacion",
|
||||
]
|
||||
21
server/app/domain/entities/__init__.py
Normal file
21
server/app/domain/entities/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from app.domain.entities.ruta import (
|
||||
Coordenada,
|
||||
EstadoCamion,
|
||||
ETAResult,
|
||||
NotificationPreferences,
|
||||
PuntoRuta,
|
||||
Ruta,
|
||||
TruckStatus,
|
||||
TipoNotificacion,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"Coordenada",
|
||||
"EstadoCamion",
|
||||
"ETAResult",
|
||||
"NotificationPreferences",
|
||||
"PuntoRuta",
|
||||
"Ruta",
|
||||
"TruckStatus",
|
||||
"TipoNotificacion",
|
||||
]
|
||||
77
server/app/domain/entities/ruta.py
Normal file
77
server/app/domain/entities/ruta.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
Entidades del dominio — sin dependencias externas.
|
||||
Alineadas con el esquema de Persona A.
|
||||
"""
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class EstadoCamion(str, Enum):
|
||||
EN_RUTA = "EN_RUTA"
|
||||
APROXIMANDOSE = "APROXIMANDOSE"
|
||||
COMPLETADO = "COMPLETADO"
|
||||
AVERIADA = "AVERIADA" # truck_status: AVERIADA
|
||||
RETRASADA = "RETRASADA" # truck_status: RETRASADA
|
||||
|
||||
|
||||
class TipoNotificacion(str, Enum):
|
||||
RUTA_INICIADA = "ruta_iniciada"
|
||||
APROXIMANDOSE = "aproximandose"
|
||||
COMPLETADO = "completado"
|
||||
FALLA_MECANICA = "falla_mecanica"
|
||||
RUTA_TARDE = "ruta_tarde"
|
||||
|
||||
|
||||
@dataclass
|
||||
class Coordenada:
|
||||
lat: float
|
||||
lng: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class PuntoRuta:
|
||||
orden: int # == current_position_id en truck_status
|
||||
nombre: str
|
||||
coordenada: Coordenada
|
||||
tiempo_estimado_min: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class Ruta:
|
||||
id: str # ej. "RUTA-01"
|
||||
nombre: str
|
||||
puntos: list[PuntoRuta] = field(default_factory=list)
|
||||
turno: str = "mañana"
|
||||
|
||||
|
||||
@dataclass
|
||||
class TruckStatus:
|
||||
"""Espejo directo de la tabla truck_status de Persona A."""
|
||||
route_id: str
|
||||
current_position_id: int
|
||||
last_update: datetime
|
||||
status: EstadoCamion
|
||||
|
||||
|
||||
@dataclass
|
||||
class NotificationPreferences:
|
||||
"""Preferencias del usuario — leídas antes de cada notificación."""
|
||||
user_id: int
|
||||
notify_proximity: bool = True
|
||||
notify_breakdown: bool = True
|
||||
notify_delay: bool = True
|
||||
notify_route_start: bool = True
|
||||
|
||||
|
||||
@dataclass
|
||||
class ETAResult:
|
||||
"""Lo que ve el ciudadano — sin coordenadas, sin índice de waypoint."""
|
||||
address_id: int
|
||||
route_id: str
|
||||
status: str
|
||||
eta_minutos: Optional[int]
|
||||
ventana_inicio: Optional[str] # ej. "7:20 pm"
|
||||
ventana_fin: Optional[str] # ej. "7:35 pm"
|
||||
mensaje: str
|
||||
3
server/app/domain/interfaces/__init__.py
Normal file
3
server/app/domain/interfaces/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from app.domain.interfaces.i_ruta_repository import IRutaRepository
|
||||
|
||||
__all__ = ["IRutaRepository"]
|
||||
32
server/app/domain/interfaces/i_ruta_repository.py
Normal file
32
server/app/domain/interfaces/i_ruta_repository.py
Normal file
@@ -0,0 +1,32 @@
|
||||
"""
|
||||
Interfaces del dominio.
|
||||
El dominio define QUÉ necesita, no CÓMO se implementa.
|
||||
La capa de Datos implementa estas interfaces.
|
||||
"""
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional
|
||||
|
||||
from app.domain.entities.ruta import EstadoRuta, Ruta
|
||||
|
||||
|
||||
class IRutaRepository(ABC):
|
||||
|
||||
@abstractmethod
|
||||
def obtener_ruta(self, ruta_id: str) -> Optional[Ruta]:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def obtener_estado(self, ruta_id: str) -> Optional[EstadoRuta]:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def guardar_estado(self, estado: EstadoRuta) -> None:
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def obtener_ruta_por_zona(self, zona_id: str) -> Optional[Ruta]:
|
||||
"""
|
||||
Devuelve la ruta asignada a una zona.
|
||||
Cumple la restricción de 'túnel': el domicilio solo ve su ruta.
|
||||
"""
|
||||
...
|
||||
Reference in New Issue
Block a user