Skip to content

Jornadas

Jornadas

Prefijo: /api/jornada
Requiere Auth:
Permiso requerido: jornadas, *

Módulo de jornadas de caja. Cada usuario puede tener una jornada activa que registra apertura, operaciones diarias y cierre.

GET /api/jornada/

Descripción: Lista las jornadas de caja con paginación
Requiere Auth:
Permiso requerido: jornadas, leer

Respuesta exitosa: 200 OK

Response:

[
{
"id": 1,
"usuario": "Juan Pérez",
"apertura": "2025-01-15T06:00:00",
"base_inicial": 500000,
"cierre": "2025-01-15T18:00:00",
"estado": "CERRADA",
"tenant_id": "uuid-tenant"
}
]

cURL:

Terminal window
curl "http://localhost/api/jornada/?skip=0&limit=10" -H "Authorization: Bearer <token>"

Python:

import httpx
resp = httpx.get("http://localhost/api/jornada/", headers={"Authorization": f"Bearer :token"})
jornadas = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/jornada/', {
headers: {'Authorization': `Bearer $:token`}
});
const jornadas = await resp.json();

GET /api/jornada/pendientes-cierre [NUEVO]

Descripción: Jornadas ABIERTAS de días anteriores que quedaron sin cierre de caja. El POS lo consulta a primera hora del día siguiente para avisar al cajero que debe cerrar la jornada anterior con conexión habilitada. El cierre de caja es online obligatorio; si no se hizo el día anterior, al día siguiente el POS muestra un aviso y bloquea nuevas ventas hasta que se realice el cierre.
Caso de uso típico:

  1. El cajero cierra el POS el lunes sin internet (modo offline). La jornada queda ABIERTA en la BD local.
  2. El martes, el POS arranca y llama GET /api/jornada/pendientes-cierre?usuario=Juliana+Leon.
  3. Si la API retorna la jornada del lunes, el POS muestra un modal: “Debe cerrar la jornada del lunes antes de continuar. Conéctese a internet para cerrar.”
  4. El cajero conecta a internet, el POS llama POST /api/jornada/cerrar para cerrar la jornada pendiente.
  5. Una vez cerrada, el POS crea la nueva jornada del martes.

Requiere Auth:
Permiso requerido: jornadas, leer

Parámetros query:

ParámetroTipoObligatorioDescripción
usuariostringNombre del usuario/cajero

Comportamiento:

  • Solo retorna jornadas con estado = "ABIERTA" cuya apertura fue anterior al inicio de hoy (es decir, jornadas de días anteriores que no se cerraron).
  • Si el usuario cerró todas sus jornadas anteriores, retorna un array vacío [].
  • Las jornadas se ordenan por apertura ascendente (la más antigua primero).

Respuesta exitosa: 200 OK

Response (jornadas pendientes):

[
{
"id": 39,
"usuario": "Juliana Leon",
"apertura": "2026-08-24T07:00:00",
"base_inicial": 200000,
"cierre": null,
"estado": "ABIERTA",
"tenant_id": "uuid-tenant"
}
]

Response (sin jornadas pendientes):

[]

Errores:

  • 403 — El usuario autenticado no tiene permiso para acceder a la caja de otro usuario (asistente intentando ver cierre de admin).
  • 404 — No se encontró jornada activa para el usuario (este endpoint retorna 404 solo si require_acceso_caja falla; un array vacío NO es error).

cURL:

Terminal window
curl "http://localhost/api/jornada/pendientes-cierre?usuario=Juliana%20Leon" \
-H "Authorization: Bearer <token>"

Python:

import httpx
resp = httpx.get("http://localhost/api/jornada/pendientes-cierre",
params={"usuario": "Juliana Leon"},
headers={"Authorization": f"Bearer <token}"})
pendientes = resp.json()
if pendientes:
print(f"Hay {len(pendientes)} jornada(s) sin cerrar")

JavaScript:

const resp = await fetch('http://localhost/api/jornada/pendientes-cierre?usuario=Juliana%20Leon', {
headers: {'Authorization': `Bearer $:token`}
});
const pendientes = await resp.json();
if (pendientes.length > 0) {
alert(`Hay ${pendientes.length} jornada(s) sin cerrar`);
}

GET /api/jornada/:jornada_id

Descripción: Obtiene el detalle completo de una jornada por ID. Incluye usuario, fecha/hora de apertura, base inicial, fecha/hora de cierre (si aplica), estado (ABIERTA/CERRADA). Para auditoría, verificación de cuadre o reimpresión.
Requiere Auth:
Permiso requerido: jornadas, leer

Parámetros path:

ParámetroTipoObligatorioDescripción
jornada_idintID de la jornada

Comportamiento / Casos de uso:

  • Admin revisa jornada específica por discrepancia en cierre
  • Verificar si una jornada está ABIERTA o CERRADA
  • Obtener base_inicial para conciliar con caja

Respuesta exitosa: 200 OK

Response:

{
"id": 1,
"usuario": "Juan Pérez",
"apertura": "2025-01-15T06:00:00",
"base_inicial": 500000,
"cierre": "2025-01-15T18:00:00",
"estado": "CERRADA",
"tenant_id": "uuid-tenant"
}

Errores:

CódigoCausaSolución
404Jornada no encontradaVerificar jornada_id
403Sin permiso jornadas, leerSolicitar a admin

cURL:

Terminal window
curl http://localhost/api/jornada/1 -H "Authorization: Bearer <token>"

Python:

import httpx
resp = httpx.get("http://localhost/api/jornada/1", headers={"Authorization": f"Bearer :token"})
jornada = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/jornada/1', {
headers: {'Authorization': `Bearer $:token`}
});
const jornada = await resp.json();

POST /api/jornada/

Descripción: Crea una nueva jornada de caja
Requiere Auth:
Permiso requerido: jornadas, crear

Request:

{
"usuario": "Juan Pérez",
"apertura": "2025-01-15T06:00:00",
"base_inicial": 500000,
"estado": "ABIERTA"
}

Respuesta exitosa: 201 Created

cURL:

Terminal window
curl -X POST http://localhost/api/jornada/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"usuario":"Juan Pérez","apertura":"2025-01-15T06:00:00","base_inicial":500000,"estado":"ABIERTA"}'

Python:

import httpx
resp = httpx.post("http://localhost/api/jornada/",
json={"usuario": "Juan Pérez", "apertura": "2025-01-15T06:00:00", "base_inicial": 500000, "estado": "ABIERTA"},
headers={"Authorization": f"Bearer :token"})
jornada = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/jornada/', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': `Bearer $:token`},
body: JSON.stringify({usuario: 'Juan Pérez', apertura: '2025-01-15T06:00:00', base_inicial: 500000, estado: 'ABIERTA'})
});

PUT /api/jornada/:jornada_id

Descripción: Actualiza una jornada — principalmente para cerrarla (setear cierre timestamp y estado: "CERRADA"). Validación de acceso a caja: solo el usuario dueño de la jornada (o admin) puede cerrarla. Para reapertura usar DELETE + POST nuevo (no recomendado).
Requiere Auth:
Permiso requerido: jornadas, actualizar

Parámetros path:

ParámetroTipoObligatorioDescripción
jornada_idintID de la jornada

Request:

{
"cierre": "2025-01-15T18:00:00",
"estado": "CERRADA"
}

Campos:

CampoTipoObligatorioDescripciónValores
cierredatetimeTimestamp de cierreISO 8601 (ej: 2025-01-15T18:00:00)
estadostringEstado finalCERRADA (único válido para cierre)

Comportamiento / Casos de uso:

  • Cierre manual: admin cierra jornada de cajero que olvidó cerrar
  • Corrección: ajustar hora de cierre si se registró mal
  • Validación: verifica require_acceso_caja — el usuario autenticado debe ser dueño de la jornada o tener rol admin

Respuesta exitosa: 200 OK — retorna JornadaCajaResponse actualizado

Response:

{
"id": 1,
"usuario": "Juan Pérez",
"apertura": "2025-01-15T06:00:00",
"base_inicial": 500000,
"cierre": "2025-01-15T18:00:00",
"estado": "CERRADA",
"tenant_id": "uuid-tenant"
}

Errores:

CódigoCausaSolución
404Jornada no encontradaVerificar jornada_id
403Sin acceso a caja del usuarioSolo dueño o admin
400Estado inválido (no ABIERTA)Solo jornadas ABIERTA se pueden cerrar
409Jornada ya cerradaNo se puede cerrar dos veces

cURL:

Terminal window
curl -X PUT http://localhost/api/jornada/1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"cierre":"2025-01-15T18:00:00","estado":"CERRADA"}'

Python:

import httpx
resp = httpx.put("http://localhost/api/jornada/1",
json={"cierre": "2025-01-15T18:00:00", "estado": "CERRADA"},
headers={"Authorization": f"Bearer :token"})
jornada = resp.json()

JavaScript:

const resp = await fetch('http://localhost/api/jornada/1', {
method: 'PUT',
headers: {'Content-Type': 'application/json', 'Authorization': `Bearer $:token`},
body: JSON.stringify({cierre: '2025-01-15T18:00:00', estado: 'CERRADA'})
});
const jornada = await resp.json();

DELETE /api/jornada/:jornada_id

Descripción: Elimina (hard delete) una jornada de caja. Solo para jornadas de prueba o error de sistema (duplicada, creada por bug). NO usar para anular jornada real — eso rompe la trazabilidad de caja y cuadre. Para corregir: cerrar correctamente y registrar ajuste en egresos/ingresos.
Requiere Auth:
Permiso requerido: jornadas, eliminar

Parámetros path:

ParámetroTipoObligatorioDescripción
jornada_idintID de la jornada

Comportamiento / Casos de uso:

  • Jornada duplicada por bug de frontend (doble click apertura)
  • Jornada de prueba en desarrollo
  • Error de sistema que creó jornada sin base_inicial
  • ADVERTENCIA: Elimina permanentemente. Si la jornada tenía caja asociada, queda huérfana.

Respuesta exitosa: 204 No Content

Errores:

CódigoCausaSolución
404Jornada no encontradaVerificar jornada_id
403Sin permiso jornadas, eliminarSolo superadmin
409Tiene caja asociada (cierre registrado)No eliminar, cerrar correctamente

cURL:

Terminal window
curl -X DELETE http://localhost/api/jornada/1 -H "Authorization: Bearer <token>"

Python:

import httpx
resp = httpx.delete("http://localhost/api/jornada/1", headers={"Authorization": f"Bearer :token"})
assert resp.status_code == 204

JavaScript:

const resp = await fetch('http://localhost/api/jornada/1', {
method: 'DELETE',
headers: {'Authorization': `Bearer $:token`}
});
// 204 = éxito

GET /api/jornada/activa/detalle

Descripción: Obtiene la jornada activa de un usuario
Requiere Auth:
Permiso requerido: jornadas, leer

Parámetros query:

ParámetroTipoObligatorioDescripción
usuariostringNombre del usuario

Respuesta exitosa: 200 OK
Errores: 404 (no hay jornada activa)

cURL:

Terminal window
curl "http://localhost/api/jornada/activa/detalle?usuario=Juan%20P%C3%A9rez" -H "Authorization: Bearer <token>"

GET /api/jornada/activas/usuarios

Descripción: Lista los usuarios con jornada activa
Requiere Auth:
Permiso requerido: jornadas, leer

Respuesta exitosa: 200 OK

Response:

["Juan Pérez", "María López"]

cURL:

Terminal window
curl http://localhost/api/jornada/activas/usuarios -H "Authorization: Bearer <token>"

POST /api/jornada/cerrar [NUEVO]

Descripción: Cierra la jornada activa del usuario (setea estado: "CERRADA" y cierre con timestamp actual).
Requiere Auth:
Permiso requerido: jornadas, actualizar

Request:

{
"usuario": "Juan Pérez"
}

Respuesta exitosa: 200 OK
Errores: 404 (no hay jornada activa para el usuario)

Response:

{
"id": 1,
"usuario": "Juan Pérez",
"apertura": "2026-07-24T06:00:00",
"base_inicial": 500000,
"cierre": "2026-07-24T18:00:00",
"estado": "CERRADA",
"tenant_id": "uuid-tenant"
}

cURL:

Terminal window
curl -X POST http://localhost/api/jornada/cerrar \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <token>" \
-d '{"usuario":"Juan Pérez"}'