4.1 ๐ฏ Overview del mรณdulo
Mรณdulo mรกs complejo desde el punto de vista de ingestiรณn. Procesa 6 archivos Excel del ERP por mes, aplica un pipeline de clasificaciรณn 3-tier y alimenta 3 dashboards independientes (Gastos, Tesorerรญa, Finanzas) que comparten la misma base de datos.
caja_sincronizaciones.AI = 23)4.2 ๐งฉ Los 3 submรณdulos del hub
/gastos/
Pipeline de clasificaciรณn 3-tier que convierte 6 archivos Excel en gastos clasificados por rubro ร concepto ร provincia.
/tesoreria/
Flujo de caja, formas de cobro/pago, origen de cobros, cheques en cartera y alertas (5 pestaรฑas).
/finanzas/
IVA, percepciones, centros de costo, top proveedores y cruce de rentabilidad con ventas (3 pestaรฑas).
Mapa funcional
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ /reportes/caja/ โ Hub (landing)
โ index.php โ cards + KPIs globales
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โ
โ via header sticky con sub-tabs
โโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
/gastos/ /tesoreria/ /finanzas/
index.php index.php index.php
(Tabulator รกrbol) (5 pestaรฑas) (3 pestaรฑas)
โ โ โ
โ api/data.php โ api/flujo ยท cobros โ api/iva ยท perc ยท cc
โ โ ยท origen ยท cajas โ ยท proveedores
โ โ ยท alertas โ ยท cruce_ventas
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ BASE DE DATOS COMPARTIDA (Schema v2) โ
โ caja_sincronizaciones ยท caja_gastos ยท caja_raw_* (10 tablas) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ โฒ
โ โ
โโโโโโโโโโโ sync compartido (alimenta a TODOS) โโโโโ
/caja/sync.php (individual)
/caja/sync_bulk.php (masivo multi-mes)
4.3 โ๏ธ Pipeline de clasificaciรณn 3-tier
Para cada fila de EgresosDetalle filtrada por operaciรณn de gasto
(compras / gastos - caja o gastos - liquidaciones):
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ EgresosDetalle (gasto detectado) โ
โ Extrae nยบ ME de col "Observaciones" via regex: โ
โ /ME\s+0*(\d+)-0*(\d+)/i โ (serie, numero, empresa) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ NIVEL 1: GastosTipificados (PRIMARIA) โ
โ ยฟExiste (serie, numero, empresa) en gastosMap? โ
โ โโโ Sร โ emite 1 fila por cada lรญnea GT del comprobante โ
โ โ rubro_id = GT.rubro_id โ
โ โ rubro = GT.rubro โ
โ โ concepto_libre = GT.concepto โ
โ โโโ NO โ continรบa al nivel 2 โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ NIVEL 2: MovimientoDetalle + ConceptosDeGastos (FALLBACK) โ
โ ยฟExiste (serie, numero, empresa) en movDetMap? โ
โ โโโ Sร โ tomar mdEntry.concepto_id โ
โ โ โโโ existe en conceptosMap โ usar c.rubro_id, c.rubro โ
โ โ โโโ no existe โ rubro = mdEntry.concepto (libre) โ
โ โโโ NO โ continรบa al nivel 3 โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ NIVEL 3: SIN CLASIFICAR (รบltimo recurso) โ
โ rubro = 'SIN CLASIFICAR' โ
โ concepto_libre = obs.substring(0, 200) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Mapeo de provincia (paso paralelo)
// JavaScript en sync.php / sync_bulk.php
const cajero = cajaMap[`${empresa}-${cajaNro}`];
const provincia = CAJERO_PROV[cajero?.toLowerCase()?.trim()] || 'OTRAS';
// CAJERO_PROV es un objeto hardcoded:
const CAJERO_PROV = {
'lar-cajero1': 'LA RIOJA',
'sgo-cajero2': 'SANTIAGO DEL ESTERO',
'cat-cajero3': 'CATAMARCA',
// โฆ
};
sync.php y sync_bulk.php.
Cada cajero nuevo requiere editar 2 archivos. Propuesta en ยง11: tabla DB
caja_cajero_provincia editable desde UI.
๐ฅ Bug histรณrico (FIXED v2.0.2)
El parser parseMovDetalleMap buscaba 'ME' en la
columna 6 (Tipo = letra del comprobante A/B/C/P/E) cuando
debe buscarlo en la columna 5 (Comprobante).
Impacto en los datos cargados con versiones anteriores:
- 2024: 1.676 MEs reales no se procesaron (de 5.208 filas).
- 2025: 3.850 MEs reales no se procesaron (de 12.162 filas).
Toda la clasificaciรณn dependรญa 100% de GastosTipificados; lo que no estaba ahรญ caรญa directamente como SIN CLASIFICAR. Re-sincronizar los meses afectados para que el nivel 2 funcione correctamente.
Mรฉtricas en log del bulk
GT: 185 | MD: 0 | SIN CLASIF: 0 | Sin ME: 37 | Otros meses: 2336 | Total: 278
GT: clasificadas por nivel 1 (GastosTipificados)MD: clasificadas por nivel 2 (MovimientoDetalle + Conceptos)SIN CLASIF: nivel 3 (rubro = 'SIN CLASIFICAR')Sin ME: filas de EgresosDetalle sin nยบ ME extraรญbleOtros meses: filas de archivos compartidos filtradas por fechaTotal: filas finalmente insertadas encaja_gastos
4.4 ๐๏ธ Schema v2 detallado
Vista global de las 10 tablas
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ caja_sincronizaciones โ control
โ PK id ยท UK (mes, anio) โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ
โ 1
โ
โโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ N โ N โ N
โผ โผ โผ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ caja_gastos โ โ caja_raw_* (6 tab.) โ โ caja_audit_log โ
โ (derivada) โ โ - egresos_caja โ โ (eventos sync) โ
โ โ โ - egresos_detalle โ โโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโ โ - gastos_tipificados โ
โ - movimiento_detalle โ โโโโโโโโโโโโโโโโโโโโ
โ - movimiento_resumidoโ โ caja_cajeros โ
โ - conceptos โ โ (denormalizaciรณn)โ
โ (catรกlogo persist) โ โ rebuilt post-syncโ
โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
Helpers PHP en api/_schema.php
caja_ensure_schema(PDO $pdo)
// Crea las 10 tablas con CREATE IF NOT EXISTS
// Aplica ALTER TABLE defensivos en try/catch para migraciones idempotentes
caja_rebuild_cajeros(PDO $pdo)
// Reconstruye caja_cajeros desde caja_gastos JOIN caja_raw_egresos_caja
// Llamado al finalizar cada sync (save.php finalizar=true)
caja_audit_log(PDO $pdo, ?int $syncId, string $evento, ?string $tabla, ?int $filas, ?string $msg)
// INSERT en caja_audit_log
// try/catch silencioso: si falla no rompe el sync
Tipos de tablas y su rol
| Tabla | Rol | Truncate en sync? | Particionada por |
|---|---|---|---|
caja_sincronizaciones | Control | No (idempotente) | โ |
caja_gastos | Derivada para dashboard | No (por sync_id) | sync_id |
caja_raw_egresos_caja | Snapshot Excel | No (desde v2) | sync_id |
caja_raw_egresos_detalle | Snapshot Excel | No | sync_id |
caja_raw_gastos_tipificados | Snapshot Excel | No | sync_id |
caja_raw_movimiento_detalle | Snapshot Excel | No | sync_id |
caja_raw_movimiento_resumido | Snapshot Excel | No | sync_id |
caja_raw_conceptos | โ Catรกlogo persistente | Sรณlo si se sube nuevo | โ |
caja_cajeros | Denormalizaciรณn | No (rebuilt post-sync) | โ |
caja_audit_log | Auditorรญa | No (append-only) | โ |
4.5 ๐ค Sync individual (sync.php ยท 37 KB)
Flujo
Usuario Browser (sync.php) Server (api/*.php)
โ โ โ
โ click "Cargar mes" โ โ
โโโโโโโโโโโโโโโโโโโโโโโโบโ โ
โ โ Dropzone 6 archivos: โ
โ drag 6 Excel โโโโโโโโบโ ยท EgresosCaja โ
โ โ ยท ConceptosDeGastos โ
โ โ ยท EgresosDetalle โ
โ โ ยท GastosTipificados โ
โ โ ยท MovimientoDetalle โ
โ โ ยท MovimientoResumido (opt) โ
โ โ โ
โ click "Procesar" โ โ
โโโโโโโโโโโโโโโโโโโโโโโโบโ โ
โ โ SheetJS parsea los 6 (browser)โ
โ โ โ arrays JS en memoria โ
โ โ โ
โ โ POST api/init.php โ
โ โ {mes, anio} โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ
โ โ โ caja_ensure_schema()
โ โ โ INSERT caja_sincronizaciones
โ โ โ โ sync_id
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ โ
โ โ โโโโโ POST save_raw.php ร 6 โโโโโ
โ โ โ {tabla, sync_id, rows: 300} โ
โ โ โ INSERT a la tabla raw โ
โ โ โ โ
โ โ โ Pipeline 3-tier en cliente: โ
โ โ โ 1. Detectar gastos โ
โ โ โ 2. Match GT por (s,n,e) โ
โ โ โ 3. Fallback MD+Conceptos โ
โ โ โ 4. SIN CLASIFICAR โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โ โ POST save.php ร N (caja_gastos)โ
โ โ {sync_id, rows: 300} โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ
โ โ โ
โ โ POST save.php {finalizar:1} โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ
โ โ โ caja_rebuild_cajeros()
โ โ โ caja_audit_log()
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค UPDATE estado='completado'
โ โ โ
โ โ
"Sync OK" โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโค โ
4.6 ๐ฆ Sync bulk multi-mes (sync_bulk.php ยท 57 KB)
UI mรกs sofisticada: detecta automรกticamente los meses contenidos en cada Excel y los procesa secuencialmente.
Algoritmo
- Usuario sube 1 archivo por tipo (cada uno puede contener varios meses).
- SheetJS parsea todos.
- JS escanea las fechas y detecta los meses รบnicos.
- Genera una "cola" de meses a procesar.
- Por cada mes: filtra las filas de cada Excel que pertenecen a ese mes, ejecuta el pipeline 3-tier, persiste con un
sync_iddedicado. - Al final: cada mes queda self-contained en la BD (eliminar uno no afecta los demรกs).
sync_id
del primer item del bulk โ si eliminabas ese perรญodo se perdรญa la raw histรณrica
de los demรกs. Fix: cada item del bulk filtra por fecha y persiste solo sus
filas linkeadas a su propio sync_id.
Variables globales del JS del bulk
// Estado global (antes era const local โ bug v2.0.1)
let cajaRowsGlobal = null; // EgresosCaja parseado
let detalleRowsGlobal = null; // EgresosDetalle
let tipificadosRowsGlobal = null;
let movDetalleRowsGlobal = null;
let movResumidoRowsGlobal = null;
let conceptosRowsGlobal = null;
let conceptosMap = {}; // Map para nivel 2
let CAJERO_PROV = { ... }; // โ ๏ธ Duplicado con sync.php
4.7 ๐ฆ Submรณdulo Tesorerรญa (5 pestaรฑas)
KPIs ejecutivos (siempre visibles)
| KPI | Cรกlculo | Fuente |
|---|---|---|
| Ingresos | SUM(total_ingresos) | caja_raw_egresos_caja |
| Egresos | SUM(total_egresos) | idem |
| Flujo Neto | Ingresos โ Egresos | calculado |
| Ratio Ing/Egr | Ingresos / Egresos (semรกforo) | calculado |
| Saldo Final | total_saldo_final del รบltimo mes/mes filtrado | caja_raw_egresos_caja |
Pestaรฑa 1 ยท ๐ฐ Flujo de Caja
Endpoint: api/flujo.php?anio=N
- Bar chart Ingresos (verde) vs Egresos (rojo) por mes + lรญnea Flujo Neto.
- Stacked bar Saldo Final = Efectivo + Cheques de terceros, por mes.
- Tabla detallada Categorรญas ร Meses con secciones
โ INGRESOSyโ EGRESOS.
Pestaรฑa 2 ยท ๐ณ Cobros & Pagos
Endpoint: api/cobros.php?anio=N
- Donut Cobros por forma (Efectivo / Cheques / Transferencias / Venta cheques).
- Stacked bar Contado vs Cta Cte por mes.
- Donut Pagos por forma (vista anual).
- Tabla Top 20 cuentas acreedoras con forma de pago dominante (sub-query).
Pestaรฑa 3 ยท ๐ฏ Origen de Cobros
Endpoint: api/origen.php?anio=N
- Donut distribuciรณn anual por origen con % en leyenda.
- Stacked bar estado de pago (PAGADO / PENDIENTE / PARCIAL).
- Tabla Top 25 cuentas que mรกs cobran.
Pestaรฑa 4 ยท ๐ฆ Cajas & Cheques (Mayo 2026)
Endpoint: api/cajas.php?anio=N
- Bar + lรญnea: promedio mensual y mรกximo de cheques en cartera.
- Lรญnea apilada 90 dรญas: saldo diario consolidado (efectivo + cheques).
- Tabla Top 30 cajeros con eficiencia (neto coloreado).
- Tabla saldo por caja fรญsica.
Pestaรฑa 5 ยท โ ๏ธ Alertas (Mayo 2026)
Endpoint: api/alertas.php?anio=N
- Anticipos: entregados vs rendidos vs pendiente acumulado.
- Runway defensivo (sin ingresos) vs estresado (-70% ingresos).
- Anulados por mes (cantidad + monto).
- Diferencia de cotizaciรณn (exposiciรณn USD).
Niveles de alerta del runway
| Meses runway | Nivel | Color |
|---|---|---|
| < 1 | ๐จ Crรญtico | rojo |
| 1 โ 3 | ๐ถ Naranja | rojo |
| 3 โ 6 | โ ๏ธ Amarillo | azul |
| โฅ 6 | โ Verde | verde |
4.8 ๐ Submรณdulo Finanzas (3 pestaรฑas)
Pestaรฑa 1 ยท ๐ Impuestos
Endpoints: api/iva.php ยท api/percepciones.php
- IVA Crรฉdito: viene de
caja_raw_movimiento_resumido. Discrimina por tasa (21%, 27%, 10.5%, otras). - IVA Dรฉbito: aproximado como
subtotalNeto ร 0.21desde tablaventas. - Saldo = Dรฉbito โ Crรฉdito. Positivo = a pagar, negativo = a favor.
- Percepciones:
per_ibrutos + per_3337 + per_5329 + perc_municdesdecaja_raw_gastos_tipificados.
Pestaรฑa 2 ยท ๐ข Costos & Proveedores
Endpoints: api/centros_costo.php ยท api/proveedores.php
- Centros de Costo: bar horizontal Top 10 + stacked Top 6 ร meses.
- Top Proveedores: total facturado, neto gravado, comprobantes, รบltima compra, plazo promedio, forma de pago dominante.
- Mรฉtricas de concentraciรณn:
top10_pct,top20_pct.
Pestaรฑa 3 ยท ๐ Rentabilidad
Endpoint: api/cruce_ventas.php?anio=N
Ventas netas = SUM(subtotalNeto) FROM ventas
Ventas reales = SUM(subtotalNeto WHERE dsArticulo IS NOT NULL)
Costo mercaderรญa = SUM(preciocomprant * cantidadesTotal)
Peso (ton) = SUM(cantidadesTotal * peso) / 1000
Margen bruto = Ventas reales โ Costo mercaderรญa
Margen limpio = Margen bruto โ Gastos de Caja totales
% Margen limpio = Margen limpio / Ventas reales
Costo logรญstico = SUM(monto WHERE rubro LIKE %COMBUSTIBLE/FLETE/TRANSPORTE/...)
Costo admin = SUM(monto WHERE rubro LIKE %SUELDO/SERVICIO/ALQUILER/...)
$/Tonelada = Costo logรญstico / Peso (ton)
Admin/Venta = Costo admin / Ventas netas (%)
Heurรญsticas de clasificaciรณn de rubros
$rubrosLogisticos = ['COMBUSTIBLE','FLETE','TRANSPORTE','LUBRICANTE','PEAJE','GOMERIA','REPUESTO'];
$rubrosAdmin = ['SALARIO','SUELDO','HONORARIO','SERVICIO','TELEFONIA','INTERNET','ALQUILER','SEGURO','BANCO','IMPUESTO'];
// Se hace UPPER(rubro) LIKE '%KEY%' por cada palabra
4.9 ๐ธ Submรณdulo Gastos (el dashboard original)
Endpoint: api/data.php?anio=N&mes=M&prov=P&rubro=R
Dashboard
- Tabulator
dataTree: รกrbol RUBRO โธ CONCEPTO con expansiรณn y suma. - Chart.js: bar chart por mes con stacked rubros.
- Filtros: aรฑo, mes (botonera), provincia (LA RIOJA / SGO / CAT / OTRAS), rubro.
- KPI: gasto total, # comprobantes, # cajeros activos, promedio diario.
Queries clave
-- Agregado RUBRO ร CONCEPTO ร MES (Mayo 2024 - Diciembre 2025 actual)
SELECT
rubro,
concepto_libre AS concepto,
mes,
SUM(monto) AS monto,
COUNT(*) AS lineas
FROM caja_gastos
WHERE anio = ?
AND ($mes = 0 OR mes = $mes)
AND ($prov = '' OR provincia = $prov)
GROUP BY rubro, concepto, mes
ORDER BY rubro, concepto, mes;
4.10 ๐ Bugs histรณricos resueltos (changelog)
| Versiรณn | Fecha | Bug | Impacto |
|---|---|---|---|
v2.0.2 | 2026-05-21 | parseMovDetalleMap: leรญa col 6 en vez de col 5 para detectar MEs. | 5.526 MEs perdidos en 2024+2025 caรญan como SIN CLASIFICAR. |
v2.0.1 | 2026-05-21 | Bulk sync: archivos compartidos GT/MD/MR quedaban con el sync_id del primer item. | Eliminar un perรญodo borraba data raw histรณrica de otros. |
v2.0.1 | 2026-05-21 | Scope bug: cajaRows era const local a importarTodo(). |
procesarMes() no podรญa acceder โ filas de EgresosCaja no se persistรญan. |
v2.0.0 | 2026-05-21 | caja_raw_egresos_caja era catรกlogo (TRUNCATE per sync). | Tesorerรญa sรณlo mostraba el รบltimo mes sincronizado. Migraciรณn automรกtica. |
4.11 โ ๏ธ Hallazgos especรญficos del mรณdulo
| ID | Hallazgo | Lรญnea/archivo | Prioridad |
|---|---|---|---|
CAJ-01 |
dashboard.jsx (22 KB) legado React quedรณ en producciรณn. |
caja/dashboard.jsx |
Alto |
CAJ-02 |
reset_db.php sin auth โ cualquiera puede DROPear las 10 tablas. |
reset_db.php:1-3 (session_start comentado) |
Crรญtico |
CAJ-03 |
SQL interpolation: "DELETE FROM $t WHERE sync_id=$sid" dentro de loop. |
reset_db.php:46-48 |
Alto |
CAJ-04 |
CAJERO_PROV duplicado en sync.php y sync_bulk.php (mapa JS hardcoded). |
~150 (sync) ยท ~310 (bulk) | Medio |
CAJ-05 |
Pipeline 3-tier corre en cliente (JS): bug histรณrico v2.0.2 muestra fragilidad. | sync*.php |
Medio |
CAJ-06 |
Heurรญsticas de "rubros logรญsticos/admin" como arrays hardcoded en PHP. | finanzas/api/cruce_ventas.php |
Medio |
CAJ-07 |
Cajeros sin matchear caen como provincia='OTRAS'. No hay alerta proactiva. |
sync.php |
Bajo |
CAJ-08 |
IVA Dรฉbito aproximado al 21% genรฉrico โ no discrimina por tipo de comprobante. | finanzas/api/iva.php |
Medio |
CAJ-09 |
Sin FK declaradas โ eliminar manualmente con delete_period depende del cรณdigo. |
api/_schema.php |
Medio |
CAJ-10 |
Catรกlogo articulos_raw_tipos_mercaderia y unidades_medida vacรญos en BD. |
BD | Bajo |
4.12 ๐ Propuestas especรญficas del mรณdulo
P-CAJ-1 ยท Tabla DB para CAJERO_PROV
CREATE TABLE caja_cajero_provincia (
cajero VARCHAR(100) PRIMARY KEY,
provincia VARCHAR(50) NOT NULL,
activo TINYINT(1) DEFAULT 1,
notas TEXT,
creado_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
-- UI admin: /reportes/caja/admin/cajero_provincia.php
-- Pipeline lee de DB en vez de JS hardcoded
P-CAJ-2 ยท Mover pipeline 3-tier al backend
Actualmente el pipeline corre en JS (frontend). Esto:
- Fragilidad: el bug histรณrico de col 5 vs 6 estuvo aรฑos sin detectarse.
- Difรญcil testear unitariamente.
- Pesa el browser (parsear 6 Excel grandes consume RAM).
Propuesta: upload de archivos crudos โ save_raw.php los persiste tal cual โ cron job nocturno reconstruye caja_gastos en PHP con tests unitarios. Esfuerzo: 1 semana.
P-CAJ-3 ยท Tabla DB para reglas de clasificaciรณn de rubros
CREATE TABLE caja_rubro_categoria (
id INT PK AI,
pattern VARCHAR(100) NOT NULL, -- ej: "%COMBUSTIBLE%"
categoria ENUM('logistico','administrativo','operativo','otro'),
prioridad TINYINT DEFAULT 0,
activo TINYINT(1) DEFAULT 1
);
-- Reemplaza los arrays hardcoded en cruce_ventas.php
-- UI admin para editar sin tocar cรณdigo
P-CAJ-4 ยท FK CASCADE para reset_db.php mรกs simple
ALTER TABLE caja_gastos ADD FOREIGN KEY (sync_id) REFERENCES caja_sincronizaciones(id) ON DELETE CASCADE;
ALTER TABLE caja_raw_egresos_caja ADD FOREIGN KEY (sync_id) REFERENCES caja_sincronizaciones(id) ON DELETE CASCADE;
-- ... etc para las 6 raw
-- Luego reset_db.php delete_period queda en 1 lรญnea:
DELETE FROM caja_sincronizaciones WHERE id = ?;
-- (las raw + gastos se borran solas)
P-CAJ-5 ยท IVA dรฉbito discriminado por tasa
Hoy: dรฉbito = ventas * 0.21 (genรฉrico).
Propuesta: usar tipoIvaArticulo de la tabla ventas (existe pero no se usa) para discriminar tasas. Si no existe, crearla.
P-CAJ-6 ยท Alertas proactivas en sync
- Al finalizar sync, verificar que el % de SIN CLASIFICAR < 5%. Si no, mostrar warning en UI.
- Verificar que cajeros nuevos sin provincia matched > 0 โ email + UI badge.
- Verificar que
SUM(monto)del mes estรก en rango ยฑ50% del promedio histรณrico โ alerta de anomalรญa.
P-CAJ-7 ยท Eliminar dashboard.jsx
30 segundos. Backup si querรฉs (dashboard.jsx.bak.2026-05-21) y eliminarlo del doc root.
P-CAJ-8 ยท Vista materializada para Tesorerรญa
Los KPIs ejecutivos se recalculan en cada hit a /tesoreria/. Con cron diario:
CREATE TABLE caja_tesoreria_mensual_mv (
anio SMALLINT,
mes TINYINT,
ingresos DECIMAL(15,2),
egresos DECIMAL(15,2),
saldo_final DECIMAL(15,2),
dias_caja INT,
updated_at TIMESTAMP,
PRIMARY KEY (anio, mes)
);
-- Refresh cron diario 03:30:
INSERT INTO caja_tesoreria_mensual_mv ...
ON DUPLICATE KEY UPDATE ...;