Actualizar frontend/src/pages/Cobranza.jsx
This commit is contained in:
@@ -339,8 +339,8 @@ export default function Cobranza() {
|
||||
// al menos un grupo expandido, o siempre en PROGRAMA.
|
||||
const conColsExtra = esPrograma || (expandidas.size > 0);
|
||||
const headers = !conColsExtra
|
||||
? ["GRUPO","CTA X COB. MES ANT.","COB. MES ANT.","% ANT","CTA X COB EN CURSO","COB. EN CURSO","% MES","CTA X COB TOTAL","COB. TOTAL","% TOTAL","SALDO","SALDO POR RETIRAR","OPC."]
|
||||
: [(esPrograma?"PROGRAMA":"GRUPO"),"FREC.","N° CUOTA","VENCIMIENTO","CTA X COB. MES ANT.","COB. MES ANT.","% ANT","CTA X COB EN CURSO","COB. EN CURSO","% MES","CTA X COB TOTAL","COB. TOTAL","% TOTAL","SALDO","SALDO POR RETIRAR","OPC."];
|
||||
? ["GRUPO","CTA X COB. MES ANT.","COB. MES ANT.","% ANT","CTA X COB EN CURSO","COB. EN CURSO","% MES","CTA X COB TOTAL","COB. TOTAL","% TOTAL","SALDO","RETIROS","DIFERENCIA","OPC."]
|
||||
: [(esPrograma?"PROGRAMA":"GRUPO"),"FREC.","N° CUOTA","VENCIMIENTO","CTA X COB. MES ANT.","COB. MES ANT.","% ANT","CTA X COB EN CURSO","COB. EN CURSO","% MES","CTA X COB TOTAL","COB. TOTAL","% TOTAL","SALDO","RETIROS","DIFERENCIA","OPC."];
|
||||
|
||||
// Anchos para columnas redimensionables (1ª columna más ancha, resto estándar)
|
||||
const anchosCob = headers.map((h, i) => i === 0 ? (conColsExtra ? 280 : 200) : (h === "FREC." || h.startsWith("%") || h === "OPC." ? 80 : 120));
|
||||
@@ -598,7 +598,7 @@ export default function Cobranza() {
|
||||
<tbody>
|
||||
{datos.map((fRaw, ri) => {
|
||||
const f = filaLayout(fRaw); // layout normalizado (15 o 12 cols)
|
||||
const nCols = headers.length - 1; // sin OPC
|
||||
const nCols = headers.length - 2; // sin RETIROS (calculada) ni OPC
|
||||
const sedeKey = String(f[0]).toUpperCase();
|
||||
const abiertaSede = !esPrograma && expandidas.has(sedeKey);
|
||||
// Hijos a mostrar al expandir: en SEDE los programas de la sede;
|
||||
@@ -609,7 +609,14 @@ export default function Cobranza() {
|
||||
const av = !String(fila[LAY.ant[2]]||"").trim() || ["-","—"].includes(String(fila[LAY.ant[2]]).trim());
|
||||
const mv = !String(fila[LAY.mes[2]]||"").trim() || ["-","—"].includes(String(fila[LAY.mes[2]]).trim());
|
||||
const tv = !String(fila[LAY.tot[2]]||"").trim() || ["-","—"].includes(String(fila[LAY.tot[2]]).trim());
|
||||
return fila.slice(0, nCols).map((v, ci) => {
|
||||
// RETIROS (calculada) = SALDO − SALDO POR RETIRAR de la propia fila.
|
||||
const retiros = toMonto(fila[LAY.saldo]) - toMonto(fila[LAY.saldoRet]);
|
||||
const celdaRetiros = (
|
||||
<td key="retiros" style={{textAlign:"center",whiteSpace:"nowrap",color:"#7c3aed",fontWeight:700, backgroundColor: bg}}>
|
||||
{"S/ " + retiros.toLocaleString("es-PE",{maximumFractionDigits:0})}
|
||||
</td>
|
||||
);
|
||||
const celdas = fila.slice(0, nCols).map((v, ci) => {
|
||||
const isPct = LAY.ant[2]===ci || LAY.mes[2]===ci || LAY.tot[2]===ci;
|
||||
let val = v;
|
||||
if ((ci===LAY.ant[0]||ci===LAY.ant[1]||ci===LAY.ant[2]) && av) val = "—";
|
||||
@@ -642,6 +649,7 @@ export default function Cobranza() {
|
||||
</td>
|
||||
);
|
||||
});
|
||||
return [...celdas, celdaRetiros];
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -688,6 +696,7 @@ export default function Cobranza() {
|
||||
if (ci===LAY.tot[2]) return ratio(T.oTot,T.cTot);
|
||||
if (ci===LAY.saldo) return money(T.saldo);
|
||||
if (ci===LAY.saldoRet) return money(T.saldoRet);
|
||||
if (ci===LAY.saldoRet+1) return money(T.saldo - T.saldoRet); // RETIROS (calculada)
|
||||
return "";
|
||||
};
|
||||
return (
|
||||
@@ -703,10 +712,12 @@ export default function Cobranza() {
|
||||
boxShadow:`inset -1px 0 0 0 #cbd5e1${ci===FIJAS_MAIN-1?", 3px 0 5px -2px rgba(0,0,0,0.18)":""}, inset 0 1px 0 0 #cbd5e1` }
|
||||
: { position:"sticky", bottom:0, zIndex:9, backgroundColor:"#eff6ff",
|
||||
boxShadow:"inset 0 1px 0 0 #cbd5e1" };
|
||||
const esRetiros = ci===LAY.saldoRet+1;
|
||||
return (
|
||||
<td key={ci} className={ci===0?"col-name":""}
|
||||
style={{textAlign: ci===0?"left":"center",whiteSpace:"nowrap",
|
||||
color: ci===LAY.saldoRet ? "#dc2626" : undefined, ...st}}>
|
||||
color: ci===LAY.saldoRet ? "#dc2626" : (esRetiros ? "#7c3aed" : undefined),
|
||||
fontWeight: esRetiros ? 700 : undefined, ...st}}>
|
||||
{isPct ? <MiniBar valStr={val} /> : val}
|
||||
</td>
|
||||
);
|
||||
@@ -841,8 +852,8 @@ function Tarjetas({ kpis, retiro, loading }) {
|
||||
<Row k="Cta x Cobrar" v={`S/ ${cta.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
|
||||
<Row k="Cobrado" v={`S/ ${cob.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
|
||||
<Row k="Saldo" v={`S/ ${saldo.toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color={saldo>0?"#dc2626":"#10b981"} />
|
||||
<Row k="Saldo por Retirar" v={`S/ ${(saldoRetiro||0).toLocaleString("es-PE",{maximumFractionDigits:0})}`} color="#dc2626" />
|
||||
<Row k="Retiros" v={`S/ ${(saldo-(saldoRetiro||0)).toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color="#7c3aed" />
|
||||
<Row k="Retiros" v={`S/ ${(saldoRetiro||0).toLocaleString("es-PE",{maximumFractionDigits:0})}`} color="#dc2626" />
|
||||
<Row k="Diferencia" v={`S/ ${(saldo-(saldoRetiro||0)).toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color="#7c3aed" />
|
||||
{cta>0 && (
|
||||
<div style={{marginTop:10}}>
|
||||
<div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}>
|
||||
@@ -892,8 +903,8 @@ function TarjetasResumen({ r, retiro }) {
|
||||
<Row k="Cta x Cobrar" v={`S/ ${cta.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
|
||||
<Row k="Cobrado" v={`S/ ${cob.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
|
||||
<Row k="Saldo" v={`S/ ${saldo.toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color={saldo>0?"#dc2626":"#10b981"} />
|
||||
<Row k="Saldo por Retirar" v={`S/ ${(saldoRetiro||0).toLocaleString("es-PE",{maximumFractionDigits:0})}`} color="#dc2626" />
|
||||
<Row k="Retiros" v={`S/ ${(saldo-(saldoRetiro||0)).toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color="#7c3aed" />
|
||||
<Row k="Retiros" v={`S/ ${(saldoRetiro||0).toLocaleString("es-PE",{maximumFractionDigits:0})}`} color="#dc2626" />
|
||||
<Row k="Diferencia" v={`S/ ${(saldo-(saldoRetiro||0)).toLocaleString("es-PE",{maximumFractionDigits:0})}`} bold color="#7c3aed" />
|
||||
{cta>0 && (
|
||||
<div style={{marginTop:8}}>
|
||||
<div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}>
|
||||
@@ -1136,7 +1147,7 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
};
|
||||
useEffect(() => { cargarPorRetirar(); }, [ano, mes]);
|
||||
|
||||
const COLS = ["PROGRAMA","ALUMNO","N° CUOTA","F. VENC.","CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO","INFO"];
|
||||
const COLS = ["PROGRAMA","ALUMNO","N° CUOTA","F. VENC.","CTA ANT.","COB ANT.","% ANT","CTA MES","COB MES","% MES","CTA TOT","COB TOT","% TOT","SALDO","DIFERENCIA","INFO"];
|
||||
|
||||
// Alumno seleccionado para el pop-up de INFO (estado + observaciones)
|
||||
const [infoAlumno, setInfoAlumno] = useState(null);
|
||||
@@ -1256,7 +1267,7 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
Ver solo por retirar
|
||||
</label>
|
||||
</div>
|
||||
<div className="table-wrap" style={{overflow:"auto", maxHeight:"60vh"}}>
|
||||
<div className="table-wrap" style={{overflow:"auto", maxHeight:"52vh"}}>
|
||||
<table className="cob-table" {...cols.tableProps}>
|
||||
<cols.ColGroup />
|
||||
<thead><tr>{COLS.map((c,i)=>{
|
||||
@@ -1264,7 +1275,7 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
const stH = fija
|
||||
? stickyCol(i,{esHeader:true,bg:"#334155"})
|
||||
: { position:"sticky", top:0, zIndex:12, backgroundColor:"#334155" };
|
||||
const ordenable = i !== 14;
|
||||
const ordenable = i !== 14 && i !== 15; // RETIROS (14, calculada) e INFO (15) no ordenables
|
||||
return <th key={c} onClick={()=>clickOrden(i)}
|
||||
style={{...stH, position:stH.position||"relative", cursor: ordenable?"pointer":"default", userSelect:"none"}}>
|
||||
{c}{ordenable && _flecha(ordCol===i, ordDir)}<cols.Resizer index={i} /></th>;
|
||||
@@ -1282,6 +1293,9 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
const totVacio = !String(f[12]||"").trim() || ["-","—"].includes(String(f[12]).trim());
|
||||
const programa = f[14] || "-"; // programa del alumno (extra del backend)
|
||||
const retira = porRetirar.has(String(f[0])); // alumno POR RETIRAR
|
||||
// RETIROS (calculada) = SALDO − SALDO POR RETIRAR. Si el alumno está POR
|
||||
// RETIRAR, todo su saldo es "por retirar" ⇒ RETIROS = 0; si no, = su saldo.
|
||||
const retirosFila = retira ? 0 : saldo;
|
||||
return (
|
||||
<tr key={i} className={deuda?"row-deuda":""}
|
||||
style={retira ? { textDecoration:"line-through", textDecorationColor:"#dc2626",
|
||||
@@ -1315,6 +1329,10 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
{/* RETIROS (calculada) = SALDO − SALDO POR RETIRAR */}
|
||||
<td style={{textAlign:"center",whiteSpace:"nowrap",color:"#7c3aed",fontWeight:700}}>
|
||||
{"S/ " + retirosFila.toLocaleString("es-PE",{maximumFractionDigits:0})}
|
||||
</td>
|
||||
{/* Botón INFO por alumno (estado + observaciones) */}
|
||||
<td style={{textAlign:"center"}}>
|
||||
<button
|
||||
@@ -1337,6 +1355,10 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
if (alumnos.length===0) return null;
|
||||
const sum = (j)=>alumnos.reduce((s,f)=>s+toMonto(f[j]),0);
|
||||
const t = {4:sum(4),5:sum(5),7:sum(7),8:sum(8),10:sum(10),11:sum(11),13:sum(13)};
|
||||
// RETIROS total (calculada) = SALDO total − SALDO POR RETIRAR total.
|
||||
// SALDO POR RETIRAR = saldo de los alumnos marcados POR RETIRAR.
|
||||
const saldoPorRetirarTot = alumnos.reduce((s,f)=> s + (porRetirar.has(String(f[0])) ? toMonto(f[13]) : 0), 0);
|
||||
const retirosTot = t[13] - saldoPorRetirarTot;
|
||||
const r = (cob,cta)=>cta>0?`${Math.round(cob/cta*100)}%`:"";
|
||||
const celda = (j)=>{
|
||||
if (j===0) return "TOTAL GENERAL";
|
||||
@@ -1369,6 +1391,10 @@ function ModalEstadoCuenta({ grupo, ano, mes, sectorista, agrupacion, progFiltro
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
{/* RETIROS total (calculada) */}
|
||||
<td style={{position:"sticky",bottom:0,zIndex:8,backgroundColor:"#eff6ff",padding:"11px 8px",textAlign:"center",whiteSpace:"nowrap",color:"#7c3aed",fontWeight:700,boxShadow:"inset 0 1px 0 0 #cbd5e1"}}>
|
||||
{"S/ " + retirosTot.toLocaleString("es-PE",{maximumFractionDigits:0})}
|
||||
</td>
|
||||
<td style={{position:"sticky",bottom:0,zIndex:8,backgroundColor:"#eff6ff",boxShadow:"inset 0 1px 0 0 #cbd5e1"}}></td>
|
||||
</tr>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user