Skip to content

06_movimientos_uuid_fifo.py

Ruta original: docs/proyectos/consumo-interno-fifo/scripts/06_movimientos_uuid_fifo.py

"""
CLI: genera el CSV de movimientos de salida enlazados a su UUID de compra via FIFO on the
fly. Logica compartida con el reporte interactivo V2 del hub en movimientos_uuid_lib.py --
ver ese modulo y decisions/2026-07-movimientos-uuid-fifo.md para el detalle completo.

Uso: python3 scripts/06_movimientos_uuid_fifo.py 2026-01-01 2026-01-31
"""
import sys

from movimientos_uuid_lib import TOLERANCIA, reporte_completo_uuid_fifo


def main(fecha_ini: str, fecha_fin: str):
    print(f"Periodo: {fecha_ini} a {fecha_fin}\n")

    resultado, salidas, mov, chequeo, descuadres = reporte_completo_uuid_fifo(fecha_ini, fecha_fin)

    print(f"Movimientos efectivos del periodo: {len(mov)} totales, {len(salidas)} de salida")
    print(f"Filas de asignacion FIFO: {len(resultado)}")

    folios_usados = resultado["Co_Folio_origen"].dropna().nunique()
    con_uuid = resultado.loc[resultado["con_uuid"], "Co_Folio_origen"].nunique()
    print(f"Folios de compra con UUID resuelto: {con_uuid} de {folios_usados}")

    print(f"\nValidando cobertura (tolerancia {TOLERANCIA})...")
    print(f"  Movimientos con cobertura FIFO != magnitud original: {len(descuadres)} de {len(chequeo)}")

    print("\nMovimientos partidos en 2+ registros por cruce de capa...")
    partidos = resultado[resultado["total_partes_del_movimiento"] > 1]
    n_movimientos_partidos = partidos.groupby(["Pr_Cve_Producto", "Mv_Folio", "Mv_ID"]).ngroups
    print(f"  {n_movimientos_partidos} movimientos partidos (de {len(salidas)} salidas totales) "
          f"-> {len(partidos)} filas resultantes de esos movimientos")
    if n_movimientos_partidos:
        print("\n  Por categoria de movimiento:")
        print(partidos.drop_duplicates(["Pr_Cve_Producto", "Mv_Folio", "Mv_ID"])
              .groupby("categoria_movimiento").size().sort_values(ascending=False).to_string())
        print("\n  Por numero de partes (2, 3, 4...):")
        partes_por_mov = partidos.groupby(["Pr_Cve_Producto", "Mv_Folio", "Mv_ID"])["total_partes_del_movimiento"].first()
        print(partes_por_mov.value_counts().sort_index().to_string())

    out_path = f"output/movimientos_uuid_fifo_{fecha_ini}_a_{fecha_fin}.csv"
    resultado.to_csv(out_path, index=False)
    print(f"\nGuardado: {out_path} ({len(resultado)} filas)")

    return resultado, chequeo, descuadres


if __name__ == "__main__":
    fecha_ini = sys.argv[1] if len(sys.argv) > 1 else "2026-01-01"
    fecha_fin = sys.argv[2] if len(sys.argv) > 2 else "2026-01-31"
    main(fecha_ini, fecha_fin)