Saltar a contenido

API Bolsa de Horas (Hours Bank) v2

Documentación de funcionamiento de los endpoints.


📋 Índice

  1. Descripción General
  2. Endpoints
  3. GET - Obtener Bolsa de Horas
  4. POST - Agregar Horas Completadas
  5. POST - Agregar Horas Pendientes
  6. PUT - Editar Transacción
  7. DELETE - Eliminar Transacción
  8. Errores
  9. Notas Importantes

Descripción General

La Bolsa de Horas gestiona horas realizadas y pendientes de cada empleado, separadas por curso escolar. Incluye histórico de transacciones.

Mejoras en v2 respecto a v1:

  • Transacción DB: Todas las operaciones usan transacción para garantizar consistencia.
  • Lock de fila: Evita race conditions en operaciones concurrentes.
  • Sin tablas redundantes: Solo usa hours_bank y hours_transactions.
  • Validación de empleado: Verifica que el empleado exista antes de operar.
  • Decimales correctos: Parsea DECIMAL de Sequelize correctamente.

Endpoints

Método Endpoint Descripción
GET /api/v2/hours-bank/:employeeId Obtiene la bolsa de horas
POST /api/v2/hours-bank/:employeeId/completed Agrega horas completadas (realizadas)
POST /api/v2/hours-bank/:employeeId/pending Agrega horas pendientes
PUT /api/v2/hours-bank/transactions/:transactionId Edita una transacción existente
DELETE /api/v2/hours-bank/transactions/:transactionId Elimina una transacción

GET - Obtener Bolsa de Horas

GET /api/v2/hours-bank/:employeeId

Parámetros

Parámetro Tipo Ubicación Requerido Descripción
employeeId number Path ID del empleado
schoolCourseId number Query ID del curso escolar (usa actual si no se envía)

Response 200 OK

{
  "message": "ok",
  "data": {
    "employeeId": 123,
    "schoolCourseId": 5,
    "totals": {
      "pendingHours": "1h 30m",
      "completedHours": "2h",
      "pendingDecimal": 1.5,
      "completedDecimal": 2
    },
    "tracking": {
      "transactions": [...],
      "byType": { "completed": [...], "pending": [...] }
    }
  }
}

POST - Agregar Horas Completadas

POST /api/v2/hours-bank/:employeeId/completed

Agrega horas realizadas. Si hay pendientes, primero las compensa.

Body

Campo Tipo Requerido Descripción
time string Tiempo en formato "2h", "30m", "2h 30m"
reason string Motivo de la transacción
date string Fecha ISO (usa actual si no se envía)
schoolCourseId number ID del curso (usa actual si no se envía)

Ejemplo Request

{
  "time": "2h 30m",
  "reason": "Claustro General - 14 de octubre"
}

Response 200 OK

{
  "message": "Completed hours registered successfully",
  "data": {
    "employeeId": 123,
    "schoolCourseId": 5,
    "totals": {
      "pendingHours": "0h",
      "completedHours": "1h 30m",
      "pendingDecimal": 0,
      "completedDecimal": 1.5
    },
    "details": {
      "hoursRegistered": "2h 30m",
      "hoursSubtractedFromPending": "1h",
      "hoursAddedToCompleted": "1h 30m"
    },
    "transactionId": 45
  }
}

POST - Agregar Horas Pendientes

POST /api/v2/hours-bank/:employeeId/pending

Agrega horas pendientes. Si hay realizadas, primero las compensa.

Body

Campo Tipo Requerido Descripción
time string Tiempo en formato "2h", "30m", "2h 30m"
reason string Motivo de la transacción
date string Fecha ISO (usa actual si no se envía)
schoolCourseId number ID del curso (usa actual si no se envía)

Ejemplo Request

{
  "time": "30m",
  "reason": "Sale antes por motivos personales"
}

Response 200 OK

{
  "message": "Pending hours registered successfully",
  "data": {
    "employeeId": 123,
    "schoolCourseId": 5,
    "totals": {
      "pendingHours": "30m",
      "completedHours": "0h",
      "pendingDecimal": 0.5,
      "completedDecimal": 0
    },
    "details": {
      "hoursRegistered": "30m",
      "hoursSubtractedFromCompleted": "0h",
      "hoursAddedToPending": "30m"
    },
    "transactionId": 46
  }
}

PUT - Editar Transacción

PUT /api/v2/hours-bank/transactions/:transactionId

Edita una transacción existente. Revierte la transacción original y crea una nueva con las horas actualizadas, aplicando la misma lógica de compensación.

Parámetros

Parámetro Tipo Ubicación Requerido Descripción
transactionId number Path ID de la transacción a editar

Body

Campo Tipo Requerido Descripción
time string Nuevo tiempo en formato "2h", "30m", "2h 30m"
reason string Nuevo motivo (mantiene el original si no se envía)

Ejemplo Request

{
  "time": "1h 30m",
  "reason": "Corrección de horas registradas"
}

Response 200 OK

{
  "message": "Transaction edited successfully",
  "data": {
    "employeeId": 123,
    "schoolCourseId": 5,
    "totals": {
      "pendingHours": "0h",
      "completedHours": "1h 30m",
      "pendingDecimal": 0,
      "completedDecimal": 1.5
    },
    "details": {
      "previousHours": "2h",
      "newHours": "1h 30m",
      "transactionType": "COMPLETED"
    },
    "oldTransactionId": 45,
    "newTransactionId": 47
  }
}

DELETE - Eliminar Transacción

DELETE /api/v2/hours-bank/transactions/:transactionId

Elimina una transacción (soft delete) y revierte sus efectos en los totales.

Parámetros

Parámetro Tipo Ubicación Requerido Descripción
transactionId number Path ID de la transacción a eliminar

Response 200 OK

{
  "message": "Transaction deleted successfully",
  "data": {
    "employeeId": 123,
    "schoolCourseId": 5,
    "totals": {
      "pendingHours": "0h",
      "completedHours": "0h",
      "pendingDecimal": 0,
      "completedDecimal": 0
    },
    "deletedTransaction": {
      "id": 45,
      "type": "COMPLETED",
      "totalHours": "2h"
    }
  }
}

Errores

Código Mensaje Descripción
400 Employee ID is required Falta el ID del empleado
400 Transaction ID is required Falta el ID de la transacción
400 Time is required Falta el tiempo
400 INVALID_TIME_FORMAT Formato de tiempo inválido
400 INVALID_MINUTES Minutos >= 60
400 INVALID_HOURS Horas <= 0
401 Unauthorized Token inválido o expirado
404 Employee not found Empleado no existe
404 No school course found No existe curso escolar
404 Transaction not found Transacción no existe o inactiva
404 Hours bank not found Banco de horas no encontrado

Notas Importantes

Lógica de Compensación (Balanza)

Al agregar horas completadas (realizadas): 1. Si hay pendientes → primero resta de pendientes 2. El resto → suma a realizadas

Al agregar horas pendientes: 1. Si hay realizadas → primero resta de realizadas 2. El resto → suma a pendientes

Ejemplo de Compensación

Estado inicial: pendientes=1h, realizadas=0h

Se agregan 2h completadas: - Resta 1h de pendientes → pendientes=0h - Suma 1h restante a realizadas → realizadas=1h

Resultado: pendientes=0h, realizadas=1h

Formato de Tiempo

  • Entrada: "2h", "30m", "2h 30m"
  • Almacenamiento: decimal (1.5 = 1h 30m)
  • Respuesta: incluye ambos formatos

Última actualización: 2025-12-05