Ir al contenido

Turnos de caja

ShiftManager administra turnos de trabajo como horarios recurrentes: un nombre, una hora de inicio y de término (HH:mm) y los días de la semana en que aplican. No es un registro de sesión de caja con dinero: la apertura y el cierre con montos viven en CashFlowManager, y el estado abierto/cerrado de una caja en CashRegisterManager.

Extiende BaseDocument (provee _id, _rev, createdAt, updatedAt, version).

CampoTipoDescripción
type'shift'Discriminador del documento.
companyIdstringIdentificador de compañía (aislamiento multi-tenant).
namestringNombre del turno (p. ej. Mañana, Noche).
startTimestringHora de inicio en formato HH:mm (24h).
endTimestringHora de término en formato HH:mm (24h).
daysOfWeek('Mon' | 'Tue' | 'Wed' | 'Thu' | 'Fri' | 'Sat' | 'Sun')[]Días en que aplica el turno.
isActivebooleanSi el turno está vigente. Por defecto true al crear.
metadata.syncStatus'pending' | 'synced' | 'error'Estado de sincronización del documento.

El manager se apoya en BaseManager (caché y reactividad), conservando una API con validación de horario y errores explícitos.

create tiene dos firmas. La clásica recibe los campos sueltos; la nueva recibe el objeto de datos. Ambas validan startTime y endTime.

// Firma clásica
await shiftManager.create(
'Mañana', // name
'08:00', // startTime (HH:mm)
'16:00', // endTime (HH:mm)
['Mon', 'Tue', 'Wed', 'Thu', 'Fri'], // daysOfWeek
true // isActive? (default true)
);
// Firma por objeto
await shiftManager.create({
name: 'Noche',
startTime: '16:00',
endTime: '23:59',
daysOfWeek: ['Fri', 'Sat'],
isActive: true,
companyId: 'company-123',
});
await shiftManager.getById(id); // ShiftDocument | null
await shiftManager.getAll(); // ShiftDocument[]
await shiftManager.getActive(); // find({ isActive: true })
await shiftManager.getDeleted(); // soft-deleted
// Lanza SHIFT_NOT_FOUND si el id no existe; valida HH:mm si vienen los campos
await shiftManager.update(id, { endTime: '17:00' });
await shiftManager.deactivate(id); // update(id, { isActive: false })
await shiftManager.activate(id); // update(id, { isActive: true })
await shiftManager.delete(id); // soft delete (por defecto)
await shiftManager.delete(id, true); // hard delete; lanza SHIFT_INVALID si no existe

ShiftManager reexpone las utilidades reactivas de BaseManager:

shiftManager.getAll$(); // Observable<ShiftDocument[]>
shiftManager.listenToChanges((doc) => {/* ... */}); // Subscription
shiftManager.invalidateCache();
shiftManager.dispose();
CódigoCuándo
SHIFT_INVALID_TIMEstartTime/endTime no cumplen HH:mm.
SHIFT_NOT_FOUNDupdate sobre un id inexistente.
SHIFT_INVALIDHard delete de un documento inexistente o sin _rev.

El turno establece la franja horaria de operación; el dinero se controla en otras dos entidades:

  1. Caja registradora (CashRegisterManager): cada caja tiene status: 'open' | 'closed', currentBalance, currency, lastOpenedAt / lastClosedAt y un cash_flow_id apuntando al flujo de efectivo activo.

  2. Flujo de efectivo (CashFlowManager): la apertura con monto inicial (openingAmount / opening_amount) y el cierre con monto final (closingAmount) ocurren aquí, junto con los movimientos de ingreso y egreso.

Es decir, un operador “abre su turno” en la práctica abriendo un flujo de efectivo en una caja durante la franja horaria que define el ShiftDocument.

Como todos los documentos del SDK, los turnos viven en la base de datos prefijada por compañía (company_<id>_...) y llevan companyId explícito. Ver Finanzas para el panorama del módulo.