Skip to content

03_reconciliacion_recibo_pago.py

Ruta original: docs/proyectos/poliza-explor/scripts/03_reconciliacion_recibo_pago.py

"""
Reconciliacion Recibo_Pago vs poliza contable (origen Pc_Tabla='RECIBO_PAGO').

A diferencia de Cheque, aqui Poliza_Detalle.Pd_Referencia SI trae el folio
correcto (Rp_Folio = Pc_Documento) de forma directa y confiable -- no hizo
falta el workaround de match por monto de 02_reconciliacion_cheque.py.
Se aisla el Cargo (Pd_Tipo=1, cuenta de banco) por Pd_Referencia = Pc_Documento
y se compara contra Rp_Importe.

Una sola poliza consolida varios recibos del mismo dia (hasta 14 documentos
por poliza en el censo de 01_conteo_polizas_por_origen.py) -- por eso el
join agrupa por (Pl_Folio, Pc_Documento), no solo por Pl_Folio.

Validado: enero 2026 100% (69/69 documentos), Q1 2026 99.66% (293/294) --
la unica excepcion (poliza 0000485755, documento 01-0018207) tiene Cargo
$44,379.31 vs Rp_Importe $39,000.00, diferencia $5,379.31 sin explicar
todavia (pendiente si es comision bancaria, tipo de cambio, u otro cargo
combinado en la misma linea).

Uso:
    python3 03_reconciliacion_recibo_pago.py --fecha-ini 2026-01-01 --fecha-fin 2026-02-01
"""
import argparse

from connection_205_trivasadb3 import engine  # default de exploracion -- ver skill trivasa-sql-exploracion

import pandas as pd
from sqlalchemy import text
from helpers_output import console, mostrar_tabla, resumen

QUERY = """
SELECT
    plc.Pl_Folio, plc.Pc_Documento AS RECIBO_FOLIO, MAX(rp.Rp_Importe) AS RP_IMPORTE,
    SUM(CASE WHEN pd.Pd_Tipo = 1 THEN pd.Pd_Importe ELSE 0 END) AS CARGO
FROM Poliza pl
JOIN Poliza_Control plc ON plc.Pl_Folio = pl.Pl_Folio AND plc.Pc_Tabla = 'RECIBO_PAGO'
JOIN Recibo_Pago rp ON rp.Rp_Folio = plc.Pc_Documento
LEFT JOIN Poliza_Detalle pd ON pd.Pl_Folio = plc.Pl_Folio AND pd.Pd_Referencia = plc.Pc_Documento
WHERE pl.Pl_Fecha >= :fecha_ini AND pl.Pl_Fecha < :fecha_fin
  AND pl.Es_Cve_Estado <> 'CA'
GROUP BY plc.Pl_Folio, plc.Pc_Documento
"""


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--fecha-ini", required=True)
    ap.add_argument("--fecha-fin", required=True)
    args = ap.parse_args()

    df = pd.read_sql(
        text(QUERY), engine,
        params={"fecha_ini": args.fecha_ini, "fecha_fin": args.fecha_fin},
    )
    df["DIFERENCIA"] = (df["CARGO"] - df["RP_IMPORTE"]).abs()
    df["CUADRA"] = df["DIFERENCIA"] <= 1

    out = f"03_reconciliacion_recibo_pago_{args.fecha_ini}_{args.fecha_fin}.csv"
    df.to_csv(out, index=False)

    n, c = len(df), int(df["CUADRA"].sum())
    resumen(documentos=n, cuadran=c, pct=f"{100 * c / n:.2f}%")

    no_cuadra = df[~df["CUADRA"]]
    if len(no_cuadra):
        console.print(f"\n[bold red]No cuadran:[/bold red] {len(no_cuadra)}")
        mostrar_tabla(no_cuadra, "Excepciones", max_filas=30)
    else:
        console.print("\n[green]100% de los documentos de Recibo_Pago cuadran.[/green]")

    console.print(f"\n[green]Guardado: {out}[/green]")


if __name__ == "__main__":
    main()