Refactor boot process and error handling; simplify library path setup and enhance number formatting functions. Archivo: parrafos_dinamicos_forma_pago.py

This commit is contained in:
mabejoyb
2026-05-18 12:44:32 -03:00
parent 33cbdd36b8
commit 4af511d016

View File

@@ -9,41 +9,20 @@ import unicodedata
import datetime as dt
from decimal import Decimal, InvalidOperation
def _rb_set_early(name, value):
try:
SetVar(name, value)
except Exception:
pass
# --------------------
# Boot libs (Rocketbot portable)
# --------------------
_rb_set_early("gdoc_textos_status", "BOOTING")
base_dir = os.path.dirname(sys.executable)
libs_dir = os.path.join(base_dir, "py_libs", "py310")
sys.path.insert(0, libs_dir)
try:
base_dir = os.path.dirname(sys.executable)
libs_candidates = [
os.path.join(base_dir, "py_libs", "py310"),
os.path.join(base_dir, "librerias", "py_libs", "py310"),
os.path.join(os.getcwd(), "librerias", "py_libs", "py310"),
]
for libs_dir in libs_candidates:
if os.path.isdir(libs_dir) and libs_dir not in sys.path:
sys.path.insert(0, libs_dir)
for k in list(sys.modules.keys()):
if k == "pyparsing" or k.startswith("pyparsing."):
del sys.modules[k]
for k in list(sys.modules.keys()):
if k == "pyparsing" or k.startswith("pyparsing."):
del sys.modules[k]
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.oauth2 import service_account
except Exception as e:
_rb_set_early("gdoc_textos_status", "ERROR")
_rb_set_early("gdoc_textos_error", "BOOT_IMPORT: " + repr(e))
print("BOOT_IMPORT error:", repr(e))
raise
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.oauth2 import service_account
# -----------------------------------------------------------
@@ -113,13 +92,22 @@ def _normalizar_numero(valor) -> str:
if "," in s:
parts = s.split(',')
if len(parts) == 2 and len(parts[1]) == 3 and parts[0].replace('-', '').isdigit():
return "".join(parts)
if len(parts) > 2 and all(len(p) == 3 for p in parts[1:]):
return "".join(parts)
if len(parts) > 2:
return "".join(parts[:-1]) + "." + parts[-1]
return s.replace(',', '.')
if s.count('.') > 1:
if "." in s:
parts = s.split('.')
return "".join(parts[:-1]) + "." + parts[-1]
if len(parts) == 2 and len(parts[1]) == 3 and parts[0].replace('-', '').isdigit():
return "".join(parts)
if len(parts) > 2 and all(len(p) == 3 for p in parts[1:]):
return "".join(parts)
if len(parts) > 2:
return "".join(parts[:-1]) + "." + parts[-1]
return s
@@ -161,7 +149,7 @@ def numero_decimal_a_palabras_es(valor, max_decimales=2) -> str:
def numero_a_letras_es(valor, max_decimales=2) -> str:
return numero_decimal_a_palabras_es(valor, max_decimales=max_decimales)
def cantidad_a_letras_con_moneda(valor, max_decimales=2, moneda_prefix="DOLARES AMERICANOS") -> str:
def cantidad_a_letras_con_moneda(valor, max_decimales=0, moneda_prefix="DOLARES AMERICANOS") -> str:
s = numero_decimal_a_palabras_es(valor, max_decimales=max_decimales)
if not s or s.strip() == "":
return ""
@@ -258,26 +246,34 @@ def _to_int(v) -> int:
return 0
def _format_money_es(v) -> str:
d = _to_decimal_money(v)
s = f"{d:,.2f}"
return s.replace(",", "X").replace(".", ",").replace("X", ".")
from decimal import ROUND_HALF_UP
d = _to_decimal_money(v).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
s = f"{d:,.0f}"
return s.replace(",", ".")
def _money_amount_display(v) -> str:
from decimal import ROUND_HALF_UP
s = _normalizar_numero(v)
if s == "":
return "0,00"
return "0"
try:
d = Decimal(s)
d = Decimal(s).quantize(Decimal("1"), rounding=ROUND_HALF_UP)
except Exception:
return _format_money_es(v)
s2 = f"{d:,.2f}"
return s2.replace(",", "X").replace(".", ",").replace("X", ".")
s2 = f"{d:,.0f}"
return s2.replace(",", ".")
def _raw_or_money_text(v) -> str:
s = str(v or "").strip()
if s != "" and s != "ERROR_NOT_VAR" and s.lower() != "none":
return s
return _format_money_es(v)
if s == "" or s == "ERROR_NOT_VAR" or s.lower() == "none":
return "0"
return _money_amount_display(v)
def _sanitize_usd_amounts_in_text(text: str) -> str:
s = str(text or "")
def _repl(m):
return f"USD. {_money_amount_display(m.group(1))}"
return re.sub(r"USD\.\s*([0-9][0-9\.,]*)", _repl, s)
def _first_non_empty(*values):
for v in values:
@@ -383,7 +379,7 @@ def _money_text_and_letters(raw_value, raw_letters=""):
txt = _raw_or_money_text(raw_value)
letters = str(raw_letters or "").strip()
if letters == "":
letters = cantidad_a_letras_con_moneda(raw_value, max_decimales=2)
letters = cantidad_a_letras_con_moneda(raw_value, max_decimales=0)
return txt, letters
def _build_cuotas_pre_paragraphs(cuotas_pre, base_label="a", sep_line="--------------------------------------------------------", nl="\n"):
@@ -406,7 +402,7 @@ def _build_cuotas_pre_paragraphs(cuotas_pre, base_label="a", sep_line="---------
amount_txt = _raw_or_money_text(amount_raw)
amount_letras = _first_non_empty(
_safe_dict_get(cuota, "amount_letras", ""),
cantidad_a_letras_con_moneda(amount_raw, max_decimales=2)
cantidad_a_letras_con_moneda(amount_raw, max_decimales=0)
)
frequency = str(_safe_dict_get(cuota, "frequency", "") or "").lower()
fecha_txt = _date_text_long(_safe_dict_get(cuota, "date", ""))
@@ -436,7 +432,7 @@ def _build_cuotas_post_paragraphs(cuotas_post, base_label="a", sep_line="-------
amount_txt = _raw_or_money_text(amount_raw)
amount_letras = _first_non_empty(
_safe_dict_get(cuota, "amount_letras", ""),
cantidad_a_letras_con_moneda(amount_raw, max_decimales=2)
cantidad_a_letras_con_moneda(amount_raw, max_decimales=0)
)
frequency = str(_safe_dict_get(cuota, "frequency", "") or "").lower()
fecha_txt = _date_text_long(_safe_dict_get(cuota, "date", ""))
@@ -460,7 +456,7 @@ def _build_refuerzos_pre_paragraphs(refuerzos_pre, sep_line="-------------------
refuerzo_monto_txt = _money_amount_display(refuerzo_monto_raw)
refuerzo_letras = _first_non_empty(
_safe_dict_get(refuerzo, "amount_letras", ""),
cantidad_a_letras_con_moneda(refuerzo_monto_raw, max_decimales=2)
cantidad_a_letras_con_moneda(refuerzo_monto_raw, max_decimales=0)
)
fecha_txt = _date_text_long(_safe_dict_get(refuerzo, "date", ""))
parts.append(
@@ -479,7 +475,7 @@ def _build_refuerzos_post_paragraphs(refuerzos_post, sep_line="-----------------
refuerzo_monto_txt = _money_amount_display(refuerzo_monto_raw)
refuerzo_letras = _first_non_empty(
_safe_dict_get(refuerzo, "amount_letras", ""),
cantidad_a_letras_con_moneda(refuerzo_monto_raw, max_decimales=2)
cantidad_a_letras_con_moneda(refuerzo_monto_raw, max_decimales=0)
)
fecha_txt = _date_text_long(_safe_dict_get(refuerzo, "date", ""))
parts.append(
@@ -557,6 +553,7 @@ def get_services(credentials_json_path, impersonated_user):
drive = build("drive", "v3", credentials=creds, cache_discovery=False)
return docs, drive, "service_account_impersonated"
# -----------------------------------------------------------
# DRIVE / DOC HELPERS
# -----------------------------------------------------------
@@ -934,10 +931,6 @@ globals().update(locals())
# MAIN
# -----------------------------------------------------------
try:
_sv("gdoc_textos_status", "STARTED")
_sv("gdoc_textos_error", "")
print("parrafos_dinamicos_forma_pago.py STARTED")
NL = "\n"
# usar SOLO current_url
@@ -963,7 +956,7 @@ try:
cred_path = os.path.join(base_dir, cred_path)
if not os.path.exists(cred_path):
raise RuntimeError("No existe JSON de cuenta de servicio: " + cred_path)
raise RuntimeError("No existe credentials.json: " + cred_path)
impersonated_user = _gvs("gdoc_impersonated_user", "")
@@ -1099,7 +1092,7 @@ try:
)
# valor financiado con interés incluído
valor_total_compra_financiado = _to_decimal_money(_gvs("valor_total_compra_financiado", "0"))
valor_total_compra_financiado = _raw_or_money_text(_gvs("valor_total_compra_financiado", ""))
valor_total_letras_financiado = _first_non_empty(
_gvs("valor_total_letras_financiado", ""),
cantidad_a_letras_con_moneda(_gvs("valor_total_compra_financiado", "0"))
@@ -1210,7 +1203,7 @@ try:
saldo_a_pagar_raw = _gvs("saldo_a_pagar", "")
saldo_a_pagar = _raw_or_money_text(saldo_a_pagar_raw)
saldo_letras = cantidad_a_letras_con_moneda(saldo_a_pagar_raw, max_decimales=2)
saldo_letras = cantidad_a_letras_con_moneda(saldo_a_pagar_raw, max_decimales=0)
num_pre_cuotas_fallback = _to_int(_gvs("num_pre_cuotas", "0"))
@@ -1250,7 +1243,7 @@ try:
pre_amount = _raw_or_money_text(pre_amount_raw)
pre_amount_letras = _first_non_empty(
_safe_dict_get(primer_pre, "amount_letras", ""),
cantidad_a_letras_con_moneda(pre_amount_raw, max_decimales=2)
cantidad_a_letras_con_moneda(pre_amount_raw, max_decimales=0)
)
frecuencia_pre = str(_safe_dict_get(primer_pre, "frequency", "") or "").lower()
@@ -1258,7 +1251,7 @@ try:
pos_cuota_monto = _raw_or_money_text(pos_amount_raw)
pos_cuota_letras = _first_non_empty(
_safe_dict_get(primer_pos, "amount_letras", ""),
cantidad_a_letras_con_moneda(pos_amount_raw, max_decimales=2)
cantidad_a_letras_con_moneda(pos_amount_raw, max_decimales=0)
)
frecuencia_pos = str(_safe_dict_get(primer_pos, "frequency", "") or "").lower()
@@ -1789,6 +1782,10 @@ try:
# --------------------
# REEMPLAZAR MARCADORES
# --------------------
_sv("debug_script_version", "v4_sanitize_usd_final")
texto_precio = _sanitize_usd_amounts_in_text(texto_precio)
texto_fp = _sanitize_usd_amounts_in_text(texto_fp)
precio_insert_info = replace_marker_by_index(
docs_service=docs_service,
doc_id=doc_id,
@@ -1833,12 +1830,9 @@ try:
except HttpError as e:
_sv("gdoc_textos_status", "ERROR")
_sv("gdoc_textos_error", "HttpError: " + str(e))
_sv("gdoc_textos_traceback", "HttpError: " + str(e))
raise
except Exception as e:
import traceback
_sv("gdoc_textos_status", "ERROR")
_sv("gdoc_textos_error", str(e))
_sv("gdoc_textos_traceback", traceback.format_exc())
raise