Plataforma de fichajes
Backend multi-tenant de fichajes y turnos.
Backend empresarial para el tipo de fichajes y turnos que realmente mira una inspección de trabajo. Cada dominio es un módulo, cada módulo es una pila de capas — api → dominio → infraestructura — y la superficie HTTP es solo routing.
Clean architecture
El código está organizado por dominio, no por rol técnico. Cada módulo de primer nivel (auth, companies, schedules, calendars, users, integrations) trae sus propios servicios, schemas y repositorios.
app/
├── api/v1/ # routers y endpoints HTTP
├── domain/ # lógica de negocio
│ ├── auth/ # servicio RBAC, permisos, sesiones
│ ├── companies/ # scope multi-tenant
│ ├── schedules/ # calendarios de trabajo, turnos
│ ├── calendars/ # puente con Google Calendar
│ └── users/ # ciclo de vida de usuario
├── infrastructure/ # sesiones SQLAlchemy, APIs externas
│ ├── database/
│ └── integrations/
└── shared/ # excepciones, utils, primitivas RBAC
Las fronteras se respetan: infrastructure nunca importa de api, api nunca escribe SQL directamente. Testear es simple porque los servicios de dominio reciben repositorios como dependencia.
RBAC con permisos dinámicos
Los permisos no son decoradores hardcodeados — son una tabla. La capa API los resuelve en tiempo de request a través de una dependencia compartida.
# app/api/deps.py
def require_permission(code: str):
def _dep(
user: User = Depends(get_current_user),
rbac: RBACService = Depends(get_rbac_service),
):
if not rbac.user_has(user, code):
raise HTTPException(403, "forbidden")
return user
return _dep
# uso
@router.post("/schedules")
def create_schedule(
payload: ScheduleCreate,
user = Depends(require_permission("schedules.create")),
):
...
Qué lo hace interesante
- Integración Google Calendar — sincronización bidireccional de turnos con calendarios de empleados vía Google API. Tokens OAuth cifrados en reposo con Fernet.
- Modelo de datos tolerante a offline — timestamps normalizados a UTC, resolución de conflictos cuando se edita un turno mientras hay una sincronización en vuelo.
- Generación de informes DOCX — plantillas
docxtplrenderizan informes firmados de asistencia desde los mismos objetos del dominio — sin pipeline de exportación secundario. - Auditoría siempre — cada mutación escribe en una tabla de log dedicada; una inspección que entra por la puerta se lleva el PDF del mes en segundos.
- Tiempo real — canal WebSocket de presencia (clock-ins/clock-outs) al dashboard admin.