Actualizar frontend/src/pages/Cobranza.jsx
This commit is contained in:
@@ -95,6 +95,14 @@ export default function Cobranza() {
|
|||||||
return () => { activo = false; };
|
return () => { activo = false; };
|
||||||
}, [ano, mes, sectorista]);
|
}, [ano, mes, sectorista]);
|
||||||
|
|
||||||
|
// Cargar matrículas POR RETIRAR (para el "Saldo por Retirar" de las tarjetas)
|
||||||
|
const [porRetirar, setPorRetirar] = useState(new Set());
|
||||||
|
useEffect(() => {
|
||||||
|
api.alumnosPorRetirar()
|
||||||
|
.then((r) => setPorRetirar(new Set((r.matriculas || []).map(String))))
|
||||||
|
.catch(() => {});
|
||||||
|
}, [ano, mes]);
|
||||||
|
|
||||||
// Cargar clasificación de sede (sede.json) para los programas visibles
|
// Cargar clasificación de sede (sede.json) para los programas visibles
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!esPrograma) return;
|
if (!esPrograma) return;
|
||||||
@@ -165,6 +173,17 @@ export default function Cobranza() {
|
|||||||
return a.programa;
|
return a.programa;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Saldo por retirar (ANT/MES/TOTAL) de los alumnos marcados POR RETIRAR (según filtros)
|
||||||
|
const retiroKpi = useMemo(() => {
|
||||||
|
let sAnt=0, sMes=0;
|
||||||
|
alumnosFiltrados.forEach((a) => {
|
||||||
|
if (!porRetirar.has(String(a.matricula))) return;
|
||||||
|
sAnt += ((Number(a.cta_ant)||0) - (Number(a.cob_ant)||0));
|
||||||
|
sMes += ((Number(a.cta_cur)||0) - (Number(a.cob_cur)||0));
|
||||||
|
});
|
||||||
|
return { sAnt, sMes, sTot: sAnt + sMes };
|
||||||
|
}, [alumnosFiltrados, porRetirar]);
|
||||||
|
|
||||||
// Exportar el DETALLE DE ALUMNOS (rápido: usa el dataset ya cargado, sin N consultas)
|
// Exportar el DETALLE DE ALUMNOS (rápido: usa el dataset ya cargado, sin N consultas)
|
||||||
async function exportarDetalle() {
|
async function exportarDetalle() {
|
||||||
setExportando(true);
|
setExportando(true);
|
||||||
@@ -262,7 +281,7 @@ export default function Cobranza() {
|
|||||||
{loading ? <Loader text="Calculando cobranza..." /> :
|
{loading ? <Loader text="Calculando cobranza..." /> :
|
||||||
error ? <ErrorBox msg={error} /> :
|
error ? <ErrorBox msg={error} /> :
|
||||||
<>
|
<>
|
||||||
<Tarjetas kpis={kpis} />
|
<Tarjetas kpis={kpis} retiro={retiroKpi} />
|
||||||
|
|
||||||
<div className="table-wrap" style={{marginTop:16, overflowX:"auto"}}>
|
<div className="table-wrap" style={{marginTop:16, overflowX:"auto"}}>
|
||||||
<table className="cob-table" {...cols.tableProps}>
|
<table className="cob-table" {...cols.tableProps}>
|
||||||
@@ -358,7 +377,8 @@ export default function Cobranza() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Tarjetas({ kpis }) {
|
function Tarjetas({ kpis, retiro }) {
|
||||||
|
const rt = retiro || { sAnt:0, sMes:0, sTot:0 };
|
||||||
const alDia = kpis.saldo <= 0.01;
|
const alDia = kpis.saldo <= 0.01;
|
||||||
if (alDia) {
|
if (alDia) {
|
||||||
return (
|
return (
|
||||||
@@ -371,13 +391,13 @@ function Tarjetas({ kpis }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
const cards = [
|
const cards = [
|
||||||
["⚠ MES ANTERIOR","#d97706",kpis.cAnt,kpis.obAnt],
|
["⚠ MES ANTERIOR","#d97706",kpis.cAnt,kpis.obAnt, rt.sAnt],
|
||||||
["📅 MES EN CURSO","#059669",kpis.cMes,kpis.obMes],
|
["📅 MES EN CURSO","#059669",kpis.cMes,kpis.obMes, rt.sMes],
|
||||||
["💰 CARTERA TOTAL","#7c3aed",kpis.cTot,kpis.obTot],
|
["💰 CARTERA TOTAL","#7c3aed",kpis.cTot,kpis.obTot, rt.sTot],
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:14}}>
|
<div style={{display:"grid",gridTemplateColumns:"repeat(3,1fr)",gap:14}}>
|
||||||
{cards.map(([titulo,color,cta,cob]) => {
|
{cards.map(([titulo,color,cta,cob,saldoRetiro]) => {
|
||||||
const ratio = cta>0 ? (cob/cta*100) : 0;
|
const ratio = cta>0 ? (cob/cta*100) : 0;
|
||||||
const c = colorSemaforo(ratio);
|
const c = colorSemaforo(ratio);
|
||||||
const saldo = cta - cob;
|
const saldo = cta - cob;
|
||||||
@@ -388,6 +408,7 @@ function Tarjetas({ kpis }) {
|
|||||||
<Row k="Cta x Cobrar" v={`S/ ${cta.toLocaleString("es-PE",{maximumFractionDigits:0})}`} />
|
<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="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" 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" />
|
||||||
{cta>0 && (
|
{cta>0 && (
|
||||||
<div style={{marginTop:10}}>
|
<div style={{marginTop:10}}>
|
||||||
<div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}>
|
<div style={{display:"flex",justifyContent:"space-between",marginBottom:4}}>
|
||||||
|
|||||||
Reference in New Issue
Block a user