Appearance
Cambio de Fecha de Caja Activa
Módulo: Tesorería Tipo: Process Estado: Planificado Fecha: 2026-05-12
Descripción
Permite modificar la fecha_apertura de una caja activa (abierta). Como todos los movimientos registrados en la caja heredan la fecha de la caja al momento de su inserción, el cambio de fecha se propaga automáticamente a todos los movimientos existentes de esa caja en una sola operación atómica.
Contexto de Negocio
- Una caja se considera activa mientras
fecha_cierre IS NULL - Al registrar un movimiento, su
fechase asigna igual acaja.fecha_apertura(en el momento del insert) - Cambiar la fecha de la caja sin actualizar los movimientos dejaría los registros inconsistentes
- Los asientos contables se generan recién al cierre de la caja — no hay riesgo de inconsistencia contable mientras la caja esté abierta
Reglas de Negocio
RN-TES-CF-001: La caja debe estar activa
Condición: Solo se puede cambiar la fecha de una caja que esté abierta (fecha_cierre IS NULL).
Error: Si la caja está cerrada, rechazar con:
"No se puede modificar la fecha: la caja ya fue cerrada"RN-TES-CF-002: La nueva fecha debe pertenecer al período de tesorería actual
Condición: La fecha ingresada debe coincidir en mes y año con el período de tesorería vigente (tabla periodo, código TESORERIA).
Error:
"La fecha de la caja no pertenece al período de tesorería actual"RN-TES-CF-003: La nueva fecha debe pertenecer a un ejercicio contable abierto (si el módulo está activo)
Condición: Si el módulo de Contabilidad está activo, la fecha debe caer dentro del rango (desde/hasta) de al menos un ejercicio contable con estado abierto.
Error:
"La fecha de la caja debe pertenecer a un ejercicio abierto"RN-TES-CF-004: Propagación atómica a movimientos
Condición: El cambio de fecha debe actualizar en una sola transacción:
caja.fecha_apertura→ nueva fechamovimi.fechaWHEREnrocaj = {id}→ nueva fecha
Si cualquiera de los dos updates falla, se revierte la transacción completa.
RN-TES-CF-005: Los vencimientos bancarios no se modifican
Condición: iteban.vencimiento almacena el vencimiento del movimiento bancario al momento de su carga. Este campo no se modifica al cambiar la fecha de la caja — es un dato de conciliación bancaria, no una fecha operativa de caja.
RN-TES-CF-006: Registro de auditoría
Condición: Todo cambio de fecha debe registrar en auditoría: id de caja, fecha anterior, fecha nueva, usuario y timestamp de la operación.
Casos de Uso
UC-TES-CF-001: Cambio de fecha exitoso
Actor: Usuario de tesorería con caja activa
Precondiciones:
- Caja abierta (
fecha_cierre IS NULL) - Nueva fecha en el período de tesorería actual
- Si Contabilidad activo: nueva fecha en ejercicio contable abierto
Flujo principal:
- Usuario accede a la planilla de caja activa
- Usuario selecciona la acción "Cambiar Fecha"
- Sistema muestra confirmación: "Cambiar la fecha afectará TODOS los movimientos de esta planilla. ¿Deseás continuar?"
- Usuario confirma e ingresa la nueva fecha
- Sistema valida: caja abierta (RN-TES-CF-001), período (RN-TES-CF-002), ejercicio (RN-TES-CF-003)
- Sistema inicia transacción atómica
- Sistema actualiza
caja.fecha_apertura - Sistema actualiza
movimi.fechapara todos los movimientos de esa caja - Sistema confirma transacción
- Sistema registra auditoría (RN-TES-CF-006)
- Sistema refresca la vista de planilla con la nueva fecha
Postcondiciones:
caja.fecha_apertura= nueva fecha- Todos los
movimi.fechaWHEREnrocaj = id= nueva fecha iteban.vencimientosin cambios (RN-TES-CF-005)- Cambio auditado
UC-TES-CF-002: Rechazo por caja cerrada
Actor: Usuario de tesorería
Precondiciones: Caja con fecha_cierre NOT NULL
Flujo:
- Usuario intenta cambiar la fecha
- Sistema detecta
fecha_cierre IS NOT NULL(RN-TES-CF-001) - Sistema rechaza con mensaje de error
- No se realizan cambios
UC-TES-CF-003: Rechazo por fecha fuera del período
Actor: Usuario de tesorería con caja activa
Flujo:
- Usuario ingresa una fecha que no corresponde al mes/año del período de tesorería actual
- Sistema valida período (RN-TES-CF-002)
- Sistema rechaza con mensaje de error
- No se realizan cambios
Backend
Endpoint
PATCH /mod-tesoreria/cajas/{id}/fechaBody:
json
{
"fecha": "2026-05-15"
}Respuesta exitosa (200):
json
{
"id": 42,
"fecha_apertura": "2026-05-15",
"movimientos_actualizados": 7
}Errores:
400 Bad Request— fecha fuera de período o ejercicio422 Unprocessable Entity— caja cerrada404 Not Found— caja no existe
Capas afectadas
| Capa | Archivo | Cambio |
|---|---|---|
| Routes | Routes/Tesoreria/CajaRoutes.php | Nuevo PATCH /{id}/fecha |
| Controller | controller/modulo-tesoreria/CajaController.php | Método cambiarFecha() |
| Service | service/Tesoreria/CajaService.php | Método cambiarFechaApertura() + helper privado validateFechaApertura() |
| Model | models/modulo-tesoreria/MovimientoCaja.php | Método updateFechaByNrocaj(int $nrocaj, string $fecha): int |
Reutilización de validación
La lógica de validación de período/ejercicio que existe en CajaService::insert() se extrae a un método privado validateFechaApertura(string $fecha): void y se reutiliza tanto en insert() como en cambiarFechaApertura().
Transacción atómica
php
// Solo la conexión 'principal' necesita transacción
// (tanto caja como movimi viven en el mismo schema)
// La conexión 'oficial' se usa solo para leer período/ejercicio (read-only)
$this->connections->beginTransaction('principal');
try {
$this->caja->update($id, ['fecha_apertura' => $fecha]);
$movimientoCaja->updateFechaByNrocaj($id, $fecha);
$this->connections->commit();
} catch (Exception $e) {
$this->connections->rollBack();
throw $e;
}Selección de conexión (CantCajas)
php
// La instancia $this->caja ya tiene la conexión correcta según CantCajas:
// CantCajas = 1 → usa 'oficial'
// CantCajas > 1 → usa 'principal'
// MovimientoCaja debe instanciarse con la misma conexión que $this->cajaTests
Tests/Unit/Tesoreria/CajaServiceCambiarFechaTest.php— validaciones unitariasTests/Integration/Tesoreria/CajaCambiarFechaIntegrationTest.php— transacción atómica real (extiendeBaseMovimientoCajaIntegrationTestCase)
Frontend
El frontend de la planilla de caja activa es legacy PHP/jQuery (
movimientos.php+movimientos.js).
Cambios requeridos
| Archivo | Cambio |
|---|---|
view/mod-tesoreria/movimientos.php | Agregar botón "Cambiar Fecha" en la cabecera de planilla |
js/view/mod-tesoreria/movimientos.js | Handler cambiarFecha() con modal de confirmación + input de fecha + llamada al endpoint |
php/backend/mod-tesoreria/cajas.php | Extender proxy PATCH para rutear /fecha además de /close |
Flujo de interacción
- Usuario hace clic en "Cambiar Fecha"
- Modal de confirmación: "Cambiar la fecha afectará TODOS los movimientos de esta planilla. ¿Deseás continuar?"
- Al confirmar: input de fecha (tipo
date, pre-cargado con fecha actual de la caja) - Al aceptar:
PATCH /mod-tesoreria/cajas/{id}/fechacon la nueva fecha - Si éxito: refrescar vista de planilla (actualizar cabecera + tabla de movimientos)
- Si error: mostrar mensaje del backend
Patrón existente a seguir
El confirmationModal() de movimientos.js (línea ~438) es el precedente directo. El proxy PHP cajas.php actualmente solo rutea PATCH hacia /close; necesita detectar y reenviar la nueva ruta /fecha.
Consideraciones Técnicas
iteban.vencimientofuera de alcance: el vencimiento bancario se fija al momento de la carga del movimiento bancario y no es una fecha operativa de caja — no se modifica.- Multi-tenant:
cajaymovimiviven en el schemaprincipalde la sucursal/caja. La transacción opera exclusivamente sobre ese schema. - Sin impacto contable: los asientos contables se generan al cierre de la caja, no durante su operación — no hay riesgo de inconsistencia contable.
Criterios de Aceptación
- [ ] AC-TES-CF-001: Si la caja está cerrada, el endpoint retorna error y no modifica nada
- [ ] AC-TES-CF-002: Si la fecha no pertenece al período de tesorería actual, el endpoint retorna error
- [ ] AC-TES-CF-003: Si Contabilidad está activo y la fecha no cae en un ejercicio abierto, el endpoint retorna error
- [ ] AC-TES-CF-004: Al cambiar la fecha,
caja.fecha_aperturay todos losmovimi.fechade esa caja se actualizan en la misma transacción - [ ] AC-TES-CF-005: Si la transacción falla a mitad, ambas tablas quedan sin cambios (rollback completo)
- [ ] AC-TES-CF-006:
iteban.vencimientono se modifica bajo ninguna circunstancia - [ ] AC-TES-CF-007: La operación queda registrada en auditoría con fecha anterior, fecha nueva y usuario
- [ ] AC-TES-CF-008: El frontend muestra confirmación explícita antes de ejecutar el cambio
- [ ] AC-TES-CF-009: El endpoint respeta la selección de conexión según
CantCajas(1 →oficial, >1 →principal)
Referencias
- Planilla de caja activa:
view/mod-tesoreria/movimientos.php - CajaService:
service/Tesoreria/CajaService.php - MovimientoCajaService:
service/Tesoreria/MovimientoCajaService.php - Patrón de transacción: ver
CajaService::close()— precedente debeginTransaction('principal', 'oficial') - Multi-schema: Implementación Multi-Schema para Tesorería