API Bolsa de Horas (Hours Bank) v2¶
Documentación de funcionamiento de los endpoints.
📋 Índice¶
- Descripción General
- Endpoints
- GET - Obtener Bolsa de Horas
- POST - Agregar Horas Completadas
- POST - Agregar Horas Pendientes
- PUT - Editar Transacción
- DELETE - Eliminar Transacción
- Errores
- 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_bankyhours_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¶
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¶
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¶
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