La comparación abs(a - b) < 0.01 no era fiable por la coma flotante: el mismo céntimo se aceptaba o rechazaba según el importe (431.41 contra 431.40 se rechazaba y 624.39 contra 624.38 se aceptaba). pipeline_utils.importes_coinciden redondea la diferencia a 2 decimales, lo que muestra un comprobante, y admite hasta 1 céntimo. Se usa en la validación de precios y en la comparación del valor referencial. Con datos reales de SAP (49 líneas) ningún resultado cambió. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
55 lines
2.2 KiB
Python
55 lines
2.2 KiB
Python
"""Utilidades compartidas por los módulos del pipeline."""
|
|
|
|
import os
|
|
import logging
|
|
import tomllib
|
|
|
|
logger = logging.getLogger("pipeline")
|
|
|
|
|
|
def ruta_carpeta(subcarpeta: str) -> str:
|
|
"""Retorna la ruta absoluta de ``subcarpeta`` relativa a la raíz del proyecto."""
|
|
return os.path.join(os.path.dirname(__file__), subcarpeta)
|
|
|
|
|
|
def log(msg: str, level: int = 1, last: bool = False, severity: int = logging.INFO) -> None:
|
|
"""
|
|
Registra ``msg`` con la indentación de árbol usada en el log del pipeline.
|
|
|
|
Args:
|
|
msg: Mensaje a registrar.
|
|
level: Nivel de indentación del árbol (1-4).
|
|
last: True si es el último hijo de su rama (``└──`` en vez de ``├──``).
|
|
severity: Nivel de ``logging`` (``logging.WARNING``, ``logging.ERROR``…).
|
|
Por defecto ``logging.INFO``.
|
|
"""
|
|
branch = " └── " if last else " ├── "
|
|
pfx = {1: branch, 2: f" │ {branch}", 3: f" │ │ {branch}", 4: f" │ │ │ {branch}"}.get(level, branch)
|
|
logger.log(severity, f"{pfx}{msg}")
|
|
|
|
|
|
def version_del_proyecto() -> str:
|
|
"""Versión de ``pyproject.toml`` (por ejemplo ``1.2.0``), o ``desconocida`` si no se puede leer."""
|
|
try:
|
|
with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "pyproject.toml"), "rb") as f:
|
|
return tomllib.load(f)["project"]["version"]
|
|
except (OSError, KeyError, tomllib.TOMLDecodeError):
|
|
return "desconocida"
|
|
|
|
|
|
# Diferencia máxima, en soles, entre el importe de la factura y el de SAP para darlos por iguales.
|
|
TOLERANCIA_IMPORTE = 0.01
|
|
|
|
|
|
def importes_coinciden(a: float, b: float) -> bool:
|
|
"""
|
|
True si dos importes son iguales **a nivel de céntimos**, que es lo que muestra un comprobante.
|
|
|
|
La diferencia se redondea a 2 decimales y se admite hasta ``TOLERANCIA_IMPORTE`` (1 céntimo).
|
|
Comparar la diferencia sin redondear (``abs(a - b) < 0.01``) no es fiable: con coma flotante,
|
|
431.41 - 431.40 da 0.01000000000004775 (se rechazaba) y 624.39 - 624.38 da 0.00999999999999091
|
|
(se aceptaba), de modo que el mismo céntimo pasaba o no según el importe.
|
|
"""
|
|
return round(abs(a - b), 2) <= TOLERANCIA_IMPORTE
|
|
|