Overview
The Shifts catalog (Turnos) defines work shifts with their schedules and assigned managers. Shifts are used to categorize scrap records and generate shift-based reports.
Shifts typically follow a 24-hour rotation: Shift A (6:00-14:00), Shift B (14:00-22:00), Shift C (22:00-6:00)
Endpoints
List All Shifts
GET - List All
GET - Get by ID
curl -X GET http://localhost:3001/api/catalogs/turnos \
-H "Authorization: Bearer YOUR_TOKEN"
Create Shift
curl -X POST http://localhost:3001/api/catalogs/turnos \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"nombre": "Turno A - Mañana",
"codigo": "A",
"hora_inicio": 6,
"hora_fin": 14,
"gerente_id": 5,
"activo": 1
}'
Update Shift
curl -X PUT http://localhost:3001/api/catalogs/turnos/1 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"gerente_id": 7}'
Delete Shift (Soft)
curl -X DELETE http://localhost:3001/api/catalogs/turnos/1 \
-H "Authorization: Bearer YOUR_TOKEN"
Data Structure
Shift name (e.g., “Turno A - Mañana”, “Turno B - Tarde”)
Shift code (A, B, C, etc.)
Start hour in 24-hour format (0-23)
End hour in 24-hour format (0-23)
User ID of shift manager/supervisor
Status: 1 = active, 0 = inactive
Response Example
[
{
"id" : 1 ,
"nombre" : "Turno A - Mañana" ,
"codigo" : "A" ,
"hora_inicio" : 6 ,
"hora_fin" : 14 ,
"gerente_id" : 5 ,
"activo" : 1
},
{
"id" : 2 ,
"nombre" : "Turno B - Tarde" ,
"codigo" : "B" ,
"hora_inicio" : 14 ,
"hora_fin" : 22 ,
"gerente_id" : 8 ,
"activo" : 1
},
{
"id" : 3 ,
"nombre" : "Turno C - Noche" ,
"codigo" : "C" ,
"hora_inicio" : 22 ,
"hora_fin" : 6 ,
"gerente_id" : 12 ,
"activo" : 1
}
]
TypeScript Interface
export interface Turno {
id : number ;
nombre : string ;
codigo : string ;
hora_inicio : number ;
hora_fin : number ;
gerente_id ?: number ;
activo : number ;
}
Auto-Detect Current Shift
Automatically determine the current shift based on system time:
const getCurrentShift = ( shifts ) => {
const now = new Date ();
const currentHour = now . getHours ();
for ( const shift of shifts ) {
if ( shift . activo === 0 ) continue ;
// Handle overnight shifts (e.g., C: 22-6)
if ( shift . hora_fin < shift . hora_inicio ) {
if ( currentHour >= shift . hora_inicio || currentHour < shift . hora_fin ) {
return shift ;
}
} else {
if ( currentHour >= shift . hora_inicio && currentHour < shift . hora_fin ) {
return shift ;
}
}
}
return null ;
};
// Usage
const currentShift = getCurrentShift ( turnosCatalog );
if ( currentShift ) {
console . log ( `Current shift: ${ currentShift . codigo } - ${ currentShift . nombre } ` );
}
Shift Reports
Generate shift-specific reports:
const getShiftReport = async ( shiftCode , startDate , endDate ) => {
const response = await fetch (
`http://localhost:3001/api/reports/by-turno?` +
`fecha_inicio= ${ startDate } &fecha_fin= ${ endDate } ` ,
{
headers: { 'Authorization' : `Bearer ${ getToken () } ` }
}
);
const data = await response . json ();
return data . find ( item => item . name === shiftCode );
};
Shift Handover
Generate shift handover summary:
interface ShiftSummary {
shift : string ;
totalScrap : number ;
totalCost : number ;
topFailure : string ;
notes : string [];
}
const generateShiftSummary = async ( shiftCode : string ) : Promise < ShiftSummary > => {
const today = new Date (). toISOString (). split ( 'T' )[ 0 ];
const response = await fetch (
`http://localhost:3001/api/scrap?turno= ${ shiftCode } &desde= ${ today } ` ,
{
headers: { 'Authorization' : `Bearer ${ getToken () } ` }
}
);
const { data } = await response . json ();
return {
shift: shiftCode ,
totalScrap: data . length ,
totalCost: data . reduce (( sum , item ) => sum + item . COSTO , 0 ),
topFailure: getMostCommonFailure ( data ),
notes: data . filter ( item => item . COMENTARIOS ). map ( item => item . COMENTARIOS )
};
};
Permissions
View All authenticated users
Create/Edit admin, calidad roles only
Best Practices
Consistent Codes: Use single-letter codes (A, B, C) for easy data entry and reporting.
Overnight Shifts: For shifts crossing midnight (e.g., 22:00-6:00), ensure hora_fin < hora_inicio is handled correctly in your logic.