From da70bc461ae8aa1998ddd550fb3595c49befeb5a Mon Sep 17 00:00:00 2001 From: Administrator Date: Tue, 6 Oct 2026 13:31:10 -0500 Subject: [PATCH] Actualizar backend/modules/cobranza/processor.py --- backend/modules/cobranza/processor.py | 56 ++++++++++++++++++++------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/backend/modules/cobranza/processor.py b/backend/modules/cobranza/processor.py index ff5ce4a..c7ded95 100644 --- a/backend/modules/cobranza/processor.py +++ b/backend/modules/cobranza/processor.py @@ -582,19 +582,33 @@ class CobranzaProcessor: if clave_mat in alumnos_tracking: alumnos_tracking[clave_mat]["resta"] += (resta_ant + resta_cur) alumnos_tracking[clave_mat]["cobrado"] += (cobrado_ant + cobrado_curso) + # Si la cuota del mes ya se pagó (está en facturas), registrar su + # N° Cuota y Fecha de Vencimiento aquí también (para que no se pierdan + # al pagar). Solo si el cronograma no las registró antes. + if agrupacion == "PROGRAMA": + _fvcT = self.parse_fecha(fila.get('fch_vencimiento_cuota')) + if _fvcT and (fecha_filtro <= _fvcT < fecha_filtro_siguiente): + if alumnos_tracking[clave_mat].get("fecha_final") is None: + alumnos_tracking[clave_mat]["fecha_final"] = _fvcT.strftime('%d/%m/%Y') + if alumnos_tracking[clave_mat].get("cuota_final") is None: + try: + alumnos_tracking[clave_mat]["cuota_final"] = int(fila.get('num_cuota', -1)) + except Exception: + pass for (mat, llave), track in alumnos_tracking.items(): - saldo_alumno = (track["suma"] - track["resta"]) - track["cobrado"] - if round(saldo_alumno, 2) > 0: - c = track["cuota_final"] - f = track["fecha_final"] - - if c is not None: - if llave not in frecuencias_cuota: frecuencias_cuota[llave] = {} - frecuencias_cuota[llave][c] = frecuencias_cuota[llave].get(c, 0) + 1 - if f is not None: - if llave not in frecuencias_fecha_venc: frecuencias_fecha_venc[llave] = {} - frecuencias_fecha_venc[llave][f] = frecuencias_fecha_venc[llave].get(f, 0) + 1 + # N° Cuota y Fecha de Vencimiento del mes SIEMPRE se registran, haya pagado + # o no (antes solo si saldo>0, por eso desaparecían al pagar). La fecha de + # vencimiento del mes no depende de si el alumno ya canceló. + c = track["cuota_final"] + f = track["fecha_final"] + + if c is not None: + if llave not in frecuencias_cuota: frecuencias_cuota[llave] = {} + frecuencias_cuota[llave][c] = frecuencias_cuota[llave].get(c, 0) + 1 + if f is not None: + if llave not in frecuencias_fecha_venc: frecuencias_fecha_venc[llave] = {} + frecuencias_fecha_venc[llave][f] = frecuencias_fecha_venc[llave].get(f, 0) + 1 # Saldo POR RETIRAR por grupo: suma el saldo de los alumnos marcados POR RETIRAR # (mats_retirar) usando el tracking por (matricula, llave). @@ -831,12 +845,25 @@ class CobranzaProcessor: resta_ant, resta_cur, cobrado_ant, cobrado_curso = self.evaluar_ctaxcob_resta( fila, fecha_filtro, fecha_filtro_siguiente, hoy, stats_resta, tc_correcto ) - + datos_agrupados[mat_factura]["Resta_Ant"] += resta_ant datos_agrupados[mat_factura]["Resta_Cur"] += resta_cur datos_agrupados[mat_factura]["Cob_Ant"] += cobrado_ant datos_agrupados[mat_factura]["Cob_Cur"] += cobrado_curso + # Si la cuota del MES ya se pagó (está en facturas y no en el cronograma), + # igual registrar su N° Cuota y Fecha de Vencimiento del mes (para que NO + # desaparezcan al pagar). Solo si aún no se tenían. + _fvc = self.parse_fecha(fila.get('fch_vencimiento_cuota')) + if _fvc and (fecha_filtro <= _fvc < fecha_filtro_siguiente): + if datos_agrupados[mat_factura].get("Fch_Venc_Mes", "-") in ("-", "", None): + datos_agrupados[mat_factura]["Fch_Venc_Mes"] = _fvc.strftime('%d/%m/%Y') + if datos_agrupados[mat_factura].get("Cuota_Mes", "-") in ("-", "", None): + try: + datos_agrupados[mat_factura]["Cuota_Mes"] = str(int(fila.get('num_cuota', -1))) + except Exception: + pass + datos_limpios = [] for mat, totales in datos_agrupados.items(): cta_cob_ant = totales["Suma_Ant"] - totales["Resta_Ant"] @@ -850,11 +877,10 @@ class CobranzaProcessor: if round(total_cta, 2) <= 0 and round(total_cob, 2) <= 0: continue + # N° Cuota y Fecha de Vencimiento del mes SIEMPRE se muestran, haya pagado + # o no (antes se borraban cuando saldo<=0, por eso desaparecían al pagar). cuota_final = totales["Cuota_Mes"] fecha_final = totales["Fch_Venc_Mes"] - if round(saldo, 2) <= 0: - cuota_final = "-" - fecha_final = "-" datos_limpios.append({ 'MATRICULA': mat, 'ALUMNO': totales["Alumno"],