SOP Técnico

La plataforma explicada en cinco minutos

Qué hace, cómo fluye y dónde tocar el código sin perderte. Pensado para que un dev nuevo entienda la operación en un vistazo.

Un solo motor para todos

Slots inteligentes

Muelles sin solapes

Un solo motor para todos

Conductores, transportadoras y admin leen la misma lógica de capacidad y agendas.

Admin, transportadoras y conductores consumen las mismas APIs; cualquier mejora de capacidad aplica a todos.

UI → /api/turnos/disponibilidad → ensureSlotCapacity → Turno creado → /api/admin/muelles

Slots inteligentes

Calculamos ventanas reales por duración de vehículo, no por hora fija.

Las horas visibles se extienden según la duración real del turno y pueden generar slots virtuales.

[Hora base 18:00]
└─ Turno 90 min ⇒ ocupa 18:00–19:30
   Slot virtual 19:00–19:30 para liberar remanente.

Muelles sin solapes

Cada muelle valida inicio y fin exactos antes de asignarse.

Asignar muelle revisa ventana completa (inicio+duración) contra otros turnos del mismo muelle.

[Muelle #3]
Turno A: 10:00–11:00
Turno B: 11:00–12:00 → OK (no solapa)

Flujo en 3 pasos

Cómo se mueve un turno

El mismo flujo aplica para admin, transportadoras y conductores.

Sin jerga rara
1Pide disponibilidad

UI llama a `/api/turnos/disponibilidad` con planta/área/vehículo.

2Validamos cupo

Slot + duración + pausas + grupos; si cabe, el motor lo reserva.

3Asignas muelle

Endpoint `GET /api/admin/muelles` confirma que la ventana esté libre.

Ejemplos rápidos de API

Disponibilidad

POST /api/turnos/disponibilidad

{ plantaId: 1, areaId: 2, fecha: '2025-11-20', tipoVehiculo: 'NAC' }
{ slots: [...], anticipacionHoras: 2, pausas: [...] }

Muelles

GET /api/admin/muelles

?plantaId=1&areaId=2&fecha=2025-11-20&hora=18:00&duracionMin=90
{ items: [{ id, ocupadoPor: { turnoId, hasta } }] }
Guías por rol

Admin

  • Ajusta capacidad y pausas en /admin/parametros.
  • Reprograma turnos y asigna muelles en /admin.
  • Exporta agenda por muelles para validar cupo diario.

Transportadora

  • Crea turnos desde /transportadoras.
  • Consulta disponibilidad antes de agendar.
  • Recibe confirmaciones y estado del muelle asignado.

Conductor

  • Ve tu turno y estado en /panel.
  • Actualiza datos básicos y confirma llegada.
  • Recibe alertas si hay cambios de hora o muelle.
Demos y flujos extendidos

Flujo

Demo

Motor único y efecto dominó

Transportadora solicita slot → ensureSlotCapacity valida cupo → si pasa, se crea turno → Admin asigna muelle → Auditoría registra cambio → Panel conductor refleja estado “confirmado”.
UI de transportadora llama /api/turnos/disponibilidad (planta/área/vehículo).
Si selecciona hora, /api/turnos/crear-manual crea el turno y dispara auditoría.
En Admin, AssignDockModal llama /api/admin/muelles para evitar solape y asigna.
Panel conductor consume /api/turnos/mis-pendientes y muestra el muelle asignado.
Tip: imagina las líneas conectando estos pasos como el mapa de n8n; cada nodo es una API o acción de UI, y las líneas son los datos (planta/área/hora/muelle) moviéndose.

Demo en acción

1

UI

Transportadora abre disponibilidad y elige 18:00

2

API

POST /api/turnos/disponibilidad → slots devueltos

3

API

POST /api/turnos/crear-manual → turno #321

4

UI

Admin asigna muelle 3, conductor ve “confirmado”

Flujo

Demo

Slots inteligentes y virtuales

Slot base 18:00 + duración 90min → ocupa 18:00-19:30 → slot virtual 19:00-19:30 → otro turno puede usar remanente.
slot-utils define intervalos base (ej. cada 60 min).
slot-capacity calcula bloques consumidos según duración del vehículo.
addTurnoEndSlots agrega slot virtual al final si sobra tiempo en la jornada.
Reprogramar usa allowVirtualSlot para horas fuera de la malla cuando hay cupo.
Tip: imagina las líneas conectando estos pasos como el mapa de n8n; cada nodo es una API o acción de UI, y las líneas son los datos (planta/área/hora/muelle) moviéndose.

Demo en acción

1

UI

Admin reprograma a las 18:00 un vehículo de 90 min

2

API

slot-capacity marca 1.5 bloques y extiende a 19:30

3

UI

Agenda muestra barra hasta 19:30 + slot virtual 19:00

4

API

allowVirtualSlot acepta un turno corto a las 19:00

Flujo

Demo

Muelles sin solape y demo de frente

AssignDockModal pide muelles → backend marca ocupadoPor.hasta → UI muestra “ocupado hasta HH:mm” y bloquea botón → al liberar, se refresca en vivo.
GET /api/admin/muelles?fecha&hora&duracionMin usa la ventana real (inicio+duración).
Si solapa, retorna ocupadoPor.turnoId y hasta; la UI deshabilita el botón y muestra tooltip.
Asignar actualiza turno.muelle y la agenda por muelles refleja el cambio con color/estado.
Drivers/panel leen el muelle asignado y el estado cambia a confirmado/en_proceso.
Tip: imagina las líneas conectando estos pasos como el mapa de n8n; cada nodo es una API o acción de UI, y las líneas son los datos (planta/área/hora/muelle) moviéndose.

Demo en acción

1

UI

Admin abre AssignDockModal para turno #88

2

API

GET /api/admin/muelles?hora=10:00&duracionMin=60

3

API

Devuelve muelle 3 ocupado hasta 10:45 → bloqueado

4

UI

Selecciona muelle 5 libre → asignado y reflejado en agenda

Piezas del código

Motor de capacidad

app/api/lib/slot-capacity.ts

Cálculo de cupos (grupos × bloques) y slots virtuales.

Intervalos y pausas

app/api/lib/slot-utils.ts

Define ventanas, extiende horas finales y mide solapes.

Muelles y solapes

app/api/admin/muelles/*

Valida ocupación real con `duracionMin` y hora exacta.

Reprogramar turnos

app/api/admin/turnos/[id]/reprogramar

`allowVirtualSlot` permite horas fuera de la malla si hay cupo.

Seguridad y rutas

app/middleware.ts

Redirige según rol y protege `/admin`, `/transportadoras`, `/panel`.

Base de datos

prisma/schema.prisma

Turnos, muelles, pausas, auditoría y catálogos de vehículos.

Checklist rápido
  • ✔ Ejecuta `prisma migrate` antes de levantar.
  • ✔ Valida `/api/turnos/disponibilidad` y `/api/admin/muelles` si tocas capacidad.
  • ✔ Ajusta `allowedDevOrigins` si usas IP pública en dev.
  • ✔ Revisa `auditoria_turnos` cuando depures estados o reasignaciones.
Guardas clave

Duraciones mandan

Sin duración por vehículo, usamos el intervalo; si es 0, no hay cupo.

Pausas matan slots

Pausas o bloqueos anulan la franja sin importar capacidad.

Muelles requieren ventana libre

Asignamos solo si inicio+duración no pisa otro turno del muelle.

Incumplidos automáticos

`markTurnosIncumplidos` usa el umbral por área (Tiempos de servicio → Umbral incumplido) y cae a `TURNOS_INCUMPLIDO_UMBRAL_MIN` si falta.

Glosario mini

Slot

Bloque de tiempo habilitado en la malla base.

Slot virtual

Bloque extra agregado al final según duración real del turno.

Grupo

Capacidad concurrente de un área (ej. rampas disponibles).

Bloque base

Tamaño mínimo de tiempo (ej. 60 min) configurado por área.

Pausa

Ventana que invalida slots (almuerzos, mantenimiento).

Estados y colores

Pendiente

Esperando llegada. Color ámbar.

Confirmado

Marcado como llegó. Verde suave.

En proceso

Carga/descarga en curso. Azul.

Finalizado

Turno cerrado. Gris.

Cancelado

Se liberó el slot. Rosa.

Incumplido

No llegó a tiempo. Fucsia.

En caso de duda

TL;DR

Si algo falla con cupos o muelles, revisa primero las duraciones configuradas, las pausas del área y la hora exacta del turno. El resto es validar que la API correcta se esté llamando con los parámetros de planta, área y vehículo.

Verifica duraciones y grupos del área; si falta duración, no hay cupo.
Revisa pausas/bloqueos: pueden anular slots aunque haya capacidad.
Consulta `allowedDevOrigins` si la app se sirve por IP externa en dev.
Mira la tabla auditoria_turnos para rastrear estados y reasignaciones.
Prueba las APIs con planta/área/vehículo exactos; un typo en IDs devuelve 0 slots.