diff --git a/frontend/src/pages/Cobranza.jsx b/frontend/src/pages/Cobranza.jsx index 742498a..d7b5d40 100644 --- a/frontend/src/pages/Cobranza.jsx +++ b/frontend/src/pages/Cobranza.jsx @@ -155,9 +155,8 @@ export default function Cobranza() { }, [alumnos, esPrograma, sede, frec]); function grupoDe(a) { - if (agrupacion === "SEDE") return a.sede; - if (agrupacion === "ASESOR") return ""; // el sectorista ya filtra; no hay sub-grupo por alumno - return a.programa; // PROGRAMA + // El programa detallado del alumno, en TODOS los filtros (Sede, Asesor, Programa). + return a.programa; } // Exportar el DETALLE DE ALUMNOS (rápido: usa el dataset ya cargado, sin N consultas) @@ -169,10 +168,7 @@ export default function Cobranza() { const toDate = (v) => { if (!v || v === "-") return ""; - const s = String(v).trim().replace(/\//g,"-"); - const p = s.split("-"); - if (p.length === 3 && p[2].length === 4) return new Date(+p[2], +p[1]-1, +p[0]); - return String(v); + return String(v).trim(); }; const pct = (cob, cta) => cta > 0 ? cob/cta : null; @@ -210,7 +206,6 @@ export default function Cobranza() { const st = cellStyle(c); if ([5,6,8,9,11,12,14].includes(c)) ws[ref] = { v:Number(v)||0, t:"n", z:moneyFmt, ...(st?{s:st}:{}) }; else if ([7,10,13].includes(c)) ws[ref] = (v===null) ? { v:"-", t:"s", ...(st?{s:st}:{}) } : { v:Number(v), t:"n", z:pctFmt, ...(st?{s:st}:{}) }; - else if (c===4 && v instanceof Date) ws[ref] = { v, t:"d", z:dateFmt }; else ws[ref] = { v: v ?? "", t:"s" }; }); }); @@ -560,7 +555,11 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, onClose }) return () => { activo = false; }; }, [grupo, ano, mes, sectorista, agrupacion]); - const COLS = ["MATRÍCULA","ALUMNO","N° CUOTA","F. VENC.","CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO"]; + const COLS = ["PROGRAMA","ALUMNO","N° CUOTA","F. VENC.","CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO"]; + + // Columnas redimensionables (igual que la tabla principal): PROGRAMA y ALUMNO más anchas + const anchosDet = COLS.map((h, i) => i === 0 ? 240 : (i === 1 ? 220 : (h.startsWith("%") ? 80 : 110))); + const cols = useColumnasAjustables(anchosDet); // Resumen para las 3 tarjetas (siempre visibles) — suma del detalle de alumnos const resumen = useMemo(() => { @@ -574,6 +573,17 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, onClose }) return { cAnt,obAnt,cMes,obMes,cTot,obTot }; }, [filas]); + // Conteo de alumnos: total, ya pagaron (saldo 0) y por pagar (saldo > 0) + const conteo = useMemo(() => { + let total=0, pagaron=0, deben=0; + filas.forEach((f) => { + if (String(f[0]).toUpperCase() === "TOTAL") return; + total++; + if (toMonto(f[13]) > 0.01) deben++; else pagaron++; + }); + return { total, pagaron, deben }; + }, [filas]); + return ( {loading ? : @@ -582,9 +592,28 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, onClose })
-
- - {COLS.map((c)=>)} + {/* Etiquetas de conteo de alumnos */} +
+ + 👥 Total: {conteo.total} alumno{conteo.total!==1?"s":""} + + + ✅ Pagaron: {conteo.pagaron} + + + ⏳ Por pagar: {conteo.deben} + +
+
+
{c}
+ + {COLS.map((c,i)=>)} {filas.filter((f)=>String(f[0]).toUpperCase()!=="TOTAL").map((f, i) => { const saldo = toMonto(f[13]); @@ -593,10 +622,12 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, onClose }) const antVacio = !String(f[6]||"").trim() || ["-","—"].includes(String(f[6]).trim()); const mesVacio = !String(f[9]||"").trim() || ["-","—"].includes(String(f[9]).trim()); const totVacio = !String(f[12]||"").trim() || ["-","—"].includes(String(f[12]).trim()); + const programa = f[14] || "-"; // programa del alumno (extra del backend) return ( - {f.map((v, j) => { - let val = v; + {f.slice(0, 14).map((v, j) => { + // Columna 0: mostrar PROGRAMA en vez de la matrícula + let val = (j===0) ? programa : v; if ((j===4||j===5||j===6) && antVacio) val = "—"; if ((j===7||j===8||j===9) && mesVacio) val = "—"; if ((j===10||j===11||j===12) && totVacio) val = "—"; @@ -606,11 +637,15 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, onClose }) if ([4,5,6].includes(j)) cart = "cart-ant"; else if ([7,8,9].includes(j)) cart = "cart-mes"; else if ([10,11,12].includes(j)) cart = "cart-tot"; - const clss = ((j===1?"col-name":"") + (cart?` ${cart}`:"")).trim(); + const clss = (((j===0||j===1)?"col-name":"") + (cart?` ${cart}`:"")).trim(); + const esTexto = (j===0||j===1); return (
{c}
{isPct ? (val==="—"?:) : fmtMoneda(val)}