Skip to content

08_baseline_existencias.py

Ruta original: docs/proyectos/consumo-interno-fifo/scripts/08_baseline_existencias.py

"""
Extiende el baseline de 07_baseline_rpmv008co.py agregando, por producto,
existencia_inicial y existencia_final del periodo -- Metodo C (el mismo de
movimientos_lib.existencia_a_fecha_metodo_c, reimplementado aqui sin la
columna Mv_Cantidad_Control_2 porque el baseline nativo solo necesita
Control_1).

existencia_inicial = existencia al dia anterior a fecha_ini
existencia_final   = existencia al ultimo dia del periodo (fecha_fin)

Uso:
    python3 08_baseline_existencias.py --fecha-ini 2026-03-01 --fecha-fin 2026-03-31 \
        --baseline output/baseline_rpmv008co_2026-03-01_2026-03-31.csv
"""
import argparse
import sys

import pandas as pd
from rich.console import Console

sys.path.append(".")
import connection_205_trivasadb3 as c

console = Console()
PR_CVE_LEN = 10


def existencia_a_fecha_metodo_c(fecha: str) -> pd.DataFrame:
    """Metodo C, validado 100% contra 3 exports reales de MPRO. fecha inclusive."""
    df = c.q(f"""
        SELECT Producto.Pr_Cve_Producto,
               SUM(Movimiento.Mv_Cantidad_Control_1) AS Mv_Cantidad_Control_1
        FROM Movimiento
        INNER JOIN Producto ON Movimiento.Pr_Cve_Producto = Producto.Pr_Cve_Producto
        INNER JOIN Sucursal ON Movimiento.Sc_Cve_Sucursal = Sucursal.Sc_Cve_Sucursal
        WHERE Sucursal.Em_Cve_Empresa = '0001' AND Movimiento.Mv_Fecha <= '{fecha}'
        GROUP BY Producto.Pr_Cve_Producto
        HAVING (SUM(Movimiento.Mv_Cantidad_Control_1) <> 0)
    """)
    df["Pr_Cve_Producto"] = df["Pr_Cve_Producto"].astype(str).str.strip().str.zfill(PR_CVE_LEN)
    return df.groupby("Pr_Cve_Producto", as_index=False)["Mv_Cantidad_Control_1"].sum()


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--fecha-ini", required=True)
    ap.add_argument("--fecha-fin", required=True)
    ap.add_argument("--baseline", required=True, help="CSV de 07_baseline_rpmv008co.py a extender")
    args = ap.parse_args()

    base = pd.read_csv(args.baseline, dtype={"Pr_Cve_Producto": str})
    base["Pr_Cve_Producto"] = base["Pr_Cve_Producto"].str.strip().str.zfill(PR_CVE_LEN)

    fecha_inicial_existencia = (pd.Timestamp(args.fecha_ini) - pd.Timedelta(days=1)).strftime("%Y-%m-%d")

    console.print(f"Consultando existencia inicial ({fecha_inicial_existencia})...")
    ini = existencia_a_fecha_metodo_c(fecha_inicial_existencia).rename(
        columns={"Mv_Cantidad_Control_1": "existencia_inicial"}
    )
    console.print(f"Consultando existencia final ({args.fecha_fin})...")
    fin = existencia_a_fecha_metodo_c(args.fecha_fin).rename(
        columns={"Mv_Cantidad_Control_1": "existencia_final"}
    )

    out = base.merge(ini, on="Pr_Cve_Producto", how="left").merge(fin, on="Pr_Cve_Producto", how="left")
    out["existencia_inicial"] = out["existencia_inicial"].fillna(0)
    out["existencia_final"] = out["existencia_final"].fillna(0)

    out_path = args.baseline.replace(".csv", "_con_existencias.csv")
    out.to_csv(out_path, index=False)

    productos = out["Pr_Cve_Producto"].nunique()
    console.print(f"[bold]Baseline con existencias[/bold] {args.fecha_ini} a {args.fecha_fin}")
    console.print(f"Filas: {len(out):,} | Productos distintos: {productos:,}")
    console.print(f"Guardado en: {out_path}")


if __name__ == "__main__":
    main()