Files
scripts_zubabot/parrafos_dinamicos_forma_pago.py

1845 lines
124 KiB
Python

from __future__ import annotations
import os
import sys
import json
import re
import ast
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")
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]
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
# -----------------------------------------------------------
# NÚMEROS A LETRAS
# -----------------------------------------------------------
import re as _re_module
_UNIDADES = ["CERO","UNO","DOS","TRES","CUATRO","CINCO","SEIS","SIETE","OCHO","NUEVE"]
_ESPECIALES = {
10:"DIEZ",11:"ONCE",12:"DOCE",13:"TRECE",14:"CATORCE",15:"QUINCE",
16:"DIECISEIS",17:"DIECISIETE",18:"DIECIOCHO",19:"DIECINUEVE"
}
_DECENAS = ["","DIEZ","VEINTE","TREINTA","CUARENTA","CINCUENTA","SESENTA","SETENTA","OCHENTA","NOVENTA"]
_CENTENAS = ["","CIENTO","DOSCIENTOS","TRESCIENTOS","CUATROCIENTOS","QUINIENTOS","SEISCIENTOS","SETECIENTOS","OCHOCIENTOS","NOVECIENTOS"]
MESES_ESPANOL = [
"", "Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"
]
def _hasta_999(n: int) -> str:
if n < 10:
return _UNIDADES[n]
if 10 <= n < 20:
return _ESPECIALES[n]
if 20 <= n < 30:
if n == 20:
return "VEINTE"
return "VEINTI" + _UNIDADES[n - 20]
if n < 100:
d, u = divmod(n, 10)
return _DECENAS[d] if u == 0 else (_DECENAS[d] + " Y " + _UNIDADES[u])
if n == 100:
return "CIEN"
if n < 1000:
c, r = divmod(n, 100)
return _CENTENAS[c] if r == 0 else (_CENTENAS[c] + " " + _hasta_999(r))
return str(n)
def numero_a_palabras_es(n: int) -> str:
if n < 0:
return "MENOS " + numero_a_palabras_es(-n)
if n < 1000:
return _hasta_999(n)
if n < 1_000_000:
miles, resto = divmod(n, 1000)
pref = "MIL" if miles == 1 else (_hasta_999(miles) + " MIL")
return pref if resto == 0 else (pref + " " + _hasta_999(resto))
if n < 1_000_000_000:
millones, resto = divmod(n, 1_000_000)
pref = "UN MILLON" if millones == 1 else (numero_a_palabras_es(millones) + " MILLONES")
return pref if resto == 0 else (pref + " " + numero_a_palabras_es(resto))
return str(n)
def _normalizar_numero(valor) -> str:
s = str(valor).strip()
s = _re_module.sub(r"[^0-9,\.\-]", "", s)
if s == "" or s.lower() == "false" or s.lower() == "none":
return ""
if "," in s and "." in s:
if s.rfind(",") > s.rfind('.'):
return s.replace('.', '').replace(',', '.')
else:
return s.replace(',', '')
if "," in s:
parts = s.split(',')
if len(parts) > 2:
return "".join(parts[:-1]) + "." + parts[-1]
return s.replace(',', '.')
if s.count('.') > 1:
parts = s.split('.')
return "".join(parts[:-1]) + "." + parts[-1]
return s
def numero_decimal_a_palabras_es(valor, max_decimales=2) -> str:
import decimal as _decimal
s = _normalizar_numero(valor)
if s == "":
return ""
try:
d = _decimal.Decimal(s)
except Exception:
return str(valor)
max_decimales = int(max_decimales)
if max_decimales <= 0:
d = d.quantize(_decimal.Decimal("1"), rounding=_decimal.ROUND_HALF_UP)
else:
q = _decimal.Decimal("1." + ("0" * max_decimales))
d = d.quantize(q, rounding=_decimal.ROUND_HALF_UP)
sign = "MENOS " if d < 0 else ""
d_abs = abs(d)
ent = int(d_abs)
if max_decimales <= 0:
return (sign + numero_a_palabras_es(ent)).strip()
dec_str = format(d_abs, "f").split('.')[1]
dec = int(dec_str) if dec_str else 0
if dec == 0:
return (sign + numero_a_palabras_es(ent)).strip()
return (sign + numero_a_palabras_es(ent) + " PUNTO " + numero_a_palabras_es(dec)).strip()
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:
s = numero_decimal_a_palabras_es(valor, max_decimales=max_decimales)
if not s or s.strip() == "":
return ""
return f"{moneda_prefix} {s.strip()}"
# -----------------------------------------------------------
# ROCKETBOT VAR HELPERS
# -----------------------------------------------------------
def _missing(v) -> bool:
if v is None:
return True
if isinstance(v, str):
s = v.strip()
return s == "" or s == "ERROR_NOT_VAR"
return False
def _gv(name, default=None):
try:
v = GetVar(name)
except Exception:
return default
return default if _missing(v) else v
def _gvs(name, default="") -> str:
v = _gv(name, default)
if v is None:
return default
s = str(v).strip()
return default if (s == "" or s == "ERROR_NOT_VAR") else s
def _sv(name, value):
try:
SetVar(name, value)
except Exception:
pass
# -----------------------------------------------------------
# HELPERS GENERALES
# -----------------------------------------------------------
def _norm_alnum(s: str) -> str:
if s is None:
return ""
s = unicodedata.normalize("NFKD", str(s)).lower()
out = []
for ch in s:
if unicodedata.category(ch) == "Mn":
continue
if ch.isalnum():
out.append(ch)
return "".join(out)
def _safe_preview(v, max_len=600) -> str:
try:
s = repr(v)
except Exception:
s = str(v)
return s[:max_len]
def _to_decimal_money(v) -> Decimal:
if v is None:
return Decimal("0")
s0 = str(v).strip()
if s0 == "" or s0 == "ERROR_NOT_VAR" or s0.lower() in ("none", "false"):
return Decimal("0")
s = s0.replace(" ", "")
if "," in s and "." in s:
s = s.replace(".", "").replace(",", ".")
elif "," in s and "." not in s:
s = s.replace(",", ".")
s = re.sub(r"[^0-9\.\-]", "", s)
if s in ("", "-", ".", "-."):
return Decimal("0")
try:
return Decimal(s)
except InvalidOperation:
return Decimal("0")
def _to_int(v) -> int:
if v is None:
return 0
s = str(v).strip()
if s == "" or s == "ERROR_NOT_VAR":
return 0
s2 = re.sub(r"[^0-9\-]", "", s)
try:
return int(s2) if s2 not in ("", "-") else 0
except Exception:
return 0
def _format_money_es(v) -> str:
d = _to_decimal_money(v)
s = f"{d:,.2f}"
return s.replace(",", "X").replace(".", ",").replace("X", ".")
def _money_amount_display(v) -> str:
s = _normalizar_numero(v)
if s == "":
return "0,00"
try:
d = Decimal(s)
except Exception:
return _format_money_es(v)
s2 = f"{d:,.2f}"
return s2.replace(",", "X").replace(".", ",").replace("X", ".")
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)
def _first_non_empty(*values):
for v in values:
if str(v or "").strip() != "":
return v
return ""
def _first_non_missing_var(*names):
for name in names:
v = _gv(name, None)
if not _missing(v):
return v
return []
def _as_list(v):
if isinstance(v, list):
return v
if v is None:
return []
s = str(v).strip()
if s == "" or s == "ERROR_NOT_VAR" or s.lower() in ("false", "none"):
return []
try:
parsed = json.loads(s)
except Exception:
try:
parsed = ast.literal_eval(s)
except Exception:
return []
return parsed if isinstance(parsed, list) else []
def _as_list_of_dicts(v):
raw_list = _as_list(v)
out = []
for item in raw_list:
if isinstance(item, dict):
out.append(item)
continue
if isinstance(item, str):
s = item.strip()
if not s:
continue
try:
parsed = json.loads(s)
except Exception:
try:
parsed = ast.literal_eval(s)
except Exception:
parsed = None
if isinstance(parsed, dict):
out.append(parsed)
return out
def _safe_dict_get(item, key, default=""):
if isinstance(item, dict):
return item.get(key, default)
return default
def _sum_qty(items):
total = 0
for item in items:
total += _to_int(_safe_dict_get(item, "qty", 0))
return total
def _derive_date_parts(fecha_raw):
"""
Parse a raw date string and return (day, month_name_spanish, year).
Accepts common formats like YYYY-MM-DD, YYYY/MM/DD, DD/MM/YYYY, DD-MM-YYYY.
Returns empty strings if parsing fails.
"""
s = str(fecha_raw or "").strip()
if not s or s == "ERROR_NOT_VAR":
return "", "", ""
s = s.split("T")[0].strip()
for fmt in ("%Y-%m-%d", "%Y/%m/%d", "%d/%m/%Y", "%d-%m-%Y"):
try:
dt_obj = dt.datetime.strptime(s, fmt)
return str(dt_obj.day), MESES_ESPANOL[dt_obj.month], str(dt_obj.year)
except Exception:
pass
return "", "", ""
def _date_text_long(fecha_raw):
"""
Return a human-friendly long Spanish date text for a raw date.
Example: '2026-04-18' -> '18 de Abril del 2026'. If parsing fails,
returns the original raw value as string.
"""
day, mes, anio = _derive_date_parts(fecha_raw)
if day and mes and anio:
return f"{day} de {mes} del {anio}"
return str(fecha_raw or "").strip()
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)
return txt, letters
def _build_cuotas_pre_paragraphs(cuotas_pre, base_label="a", sep_line="--------------------------------------------------------", nl="\n"):
"""
Build dynamic paragraphs for pre-entrega cuotas.
Each cuota becomes a separate line with the format:
{base_label}.{index}- ETAPA PRE ENTREGA: {qty} cuota/s ... con fecha de primer vencimiento el {fecha} en adelante.
The function is resilient: it uses `amount_letras` if provided in the cuota,
otherwise falls back to `cantidad_a_letras_con_moneda`.
"""
if not cuotas_pre:
return ""
parts = []
for idx, cuota in enumerate(cuotas_pre, start=1):
qty = _to_int(_safe_dict_get(cuota, "qty", 0))
amount_raw = _safe_dict_get(cuota, "amount", "")
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)
)
frequency = str(_safe_dict_get(cuota, "frequency", "") or "").lower()
fecha_txt = _date_text_long(_safe_dict_get(cuota, "date", ""))
freq_part = f" {frequency}/es" if frequency else ""
parts.append(
f"{base_label}.{idx}- ETAPA PRE ENTREGA: {qty} cuota/s{freq_part} de USD. {amount_txt} ({amount_letras}) "
f"con fecha de primer vencimiento el {fecha_txt} en adelante."
+ sep_line + nl
)
return "".join(parts)
def _build_cuotas_post_paragraphs(cuotas_post, base_label="a", sep_line="--------------------------------------------------------", nl="\n"):
"""
Build dynamic paragraphs for post-entrega cuotas (same shape as pre).
Uses the same fallback rules as the pre builder and supports an arbitrary
number of cuotas.
"""
if not cuotas_post:
return ""
parts = []
for idx, cuota in enumerate(cuotas_post, start=1):
qty = _to_int(_safe_dict_get(cuota, "qty", 0))
amount_raw = _safe_dict_get(cuota, "amount", "")
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)
)
frequency = str(_safe_dict_get(cuota, "frequency", "") or "").lower()
fecha_txt = _date_text_long(_safe_dict_get(cuota, "date", ""))
freq_part = f" {frequency}/es" if frequency else ""
parts.append(
f"{base_label}.{idx}- ETAPA POS ENTREGA: {qty} cuota/s{freq_part} de USD. {amount_txt} ({amount_letras}) "
f"con fecha de primer vencimiento el {fecha_txt} en adelante."
+ sep_line + nl
)
return "".join(parts)
def _build_refuerzos_pre_paragraphs(refuerzos_pre, sep_line="-------------------------------------------------------------", nl="\n"):
if not refuerzos_pre:
return ""
parts = []
for i, refuerzo in enumerate(refuerzos_pre, start=1):
refuerzo_monto_raw = _safe_dict_get(refuerzo, "amount", "")
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)
)
fecha_txt = _date_text_long(_safe_dict_get(refuerzo, "date", ""))
parts.append(
f"REFUERZO PRE {i}: Un pago de USD. {refuerzo_monto_txt} ({refuerzo_letras}) con fecha de vencimiento el {fecha_txt}."
+ sep_line + nl
)
return "".join(parts)
def _build_refuerzos_post_paragraphs(refuerzos_post, sep_line="-------------------------------------------------------------", nl="\n"):
if not refuerzos_post:
return ""
parts = []
for i, refuerzo in enumerate(refuerzos_post, start=1):
refuerzo_monto_raw = _safe_dict_get(refuerzo, "amount", "")
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)
)
fecha_txt = _date_text_long(_safe_dict_get(refuerzo, "date", ""))
parts.append(
f"REFUERZO POST {i}: Un pago de USD. {refuerzo_monto_txt} ({refuerzo_letras}) con fecha de vencimiento el {fecha_txt}."
+ sep_line + nl
)
return "".join(parts)
# -----------------------------------------------------------
# GOOGLE AUTH
# -----------------------------------------------------------
def _resolve_google_scopes():
default_scopes = [
"https://www.googleapis.com/auth/documents",
"https://www.googleapis.com/auth/drive",
]
try:
raw = scopes_api_google
except NameError:
raw = _gv("scopes_api_google", None)
if _missing(raw):
return default_scopes
if isinstance(raw, (list, tuple, set)):
scopes = [str(x).strip() for x in raw if str(x).strip()]
return scopes or default_scopes
s = str(raw).strip()
if not s:
return default_scopes
try:
parsed = json.loads(s)
except Exception:
try:
parsed = ast.literal_eval(s)
except Exception:
parsed = None
if isinstance(parsed, (list, tuple, set)):
scopes = [str(x).strip() for x in parsed if str(x).strip()]
return scopes or default_scopes
if "," in s:
scopes = [x.strip().strip("'\"") for x in s.split(",") if x.strip()]
return scopes or default_scopes
return [s.strip("'\"")]
SCOPES = _resolve_google_scopes()
def _load_json(path):
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
def get_services(credentials_json_path, impersonated_user):
info = _load_json(credentials_json_path)
if not isinstance(info, dict) or info.get("type") != "service_account":
raise RuntimeError("gdoc_sa_json debe apuntar a un JSON de cuenta de servicio.")
impersonated_user = (impersonated_user or "").strip()
if not impersonated_user:
raise RuntimeError("Falta la variable gdoc_impersonated_user.")
creds = service_account.Credentials.from_service_account_file(
credentials_json_path,
scopes=SCOPES,
subject=impersonated_user,
)
docs = build("docs", "v1", credentials=creds, cache_discovery=False)
drive = build("drive", "v3", credentials=creds, cache_discovery=False)
return docs, drive, "service_account_impersonated"
# -----------------------------------------------------------
# DRIVE / DOC HELPERS
# -----------------------------------------------------------
def extract_doc_id_from_url(url):
m = re.search(r"/document/d/([a-zA-Z0-9_-]+)", url or "")
return m.group(1) if m else ""
def ensure_docs_api_compatible(drive_service, file_id: str):
meta = drive_service.files().get(
fileId=file_id,
fields="id,name,mimeType,shortcutDetails",
supportsAllDrives=True
).execute()
if meta.get("mimeType") == "application/vnd.google-apps.shortcut":
target = (meta.get("shortcutDetails") or {}).get("targetId", "")
if not target:
raise RuntimeError("Es shortcut pero no trae targetId.")
file_id = target
meta = drive_service.files().get(
fileId=file_id,
fields="id,name,mimeType",
supportsAllDrives=True
).execute()
if meta.get("mimeType") != "application/vnd.google-apps.document":
new_name = (meta.get("name") or "Documento") + " (Google Docs)"
converted = drive_service.files().copy(
fileId=file_id,
body={"name": new_name, "mimeType": "application/vnd.google-apps.document"},
fields="id,name,mimeType",
supportsAllDrives=True
).execute()
return converted["id"], converted, True
return file_id, meta, False
def docs_get(docs_service, doc_id: str):
return docs_service.documents().get(documentId=doc_id).execute()
def _walk_tabs(tabs):
if not tabs:
return
for t in tabs:
yield t
for x in _walk_tabs(t.get("childTabs") or []):
yield x
def _get_tab_body_content(doc, tab_id):
tabs = doc.get("tabs")
if not tabs:
return (doc.get("body") or {}).get("content", [])
for t in _walk_tabs(tabs):
tid = ((t.get("tabProperties") or {}).get("tabId")) or ""
if tid == (tab_id or ""):
dtab = t.get("documentTab") or {}
return (dtab.get("body") or {}).get("content", [])
return []
def _paragraph_text(paragraph: dict) -> str:
parts = []
for pe in (paragraph.get("elements") or []):
tr = (pe.get("textRun") or {})
txt = tr.get("content")
if txt:
parts.append(txt)
return "".join(parts)
def collect_paragraphs(doc: dict):
out = []
def walk_content(content_list, tab_id=None):
for el in content_list or []:
if not isinstance(el, dict):
continue
p = el.get("paragraph")
if p:
text = _paragraph_text(p)
out.append({
"tabId": tab_id or "",
"startIndex": int(el.get("startIndex", 0)),
"endIndex": int(el.get("endIndex", 0)),
"text": text,
"norm_alnum": _norm_alnum(text),
})
continue
t = el.get("table")
if t:
for row in t.get("tableRows", []):
for cell in row.get("tableCells", []):
walk_content(cell.get("content", []), tab_id=tab_id)
continue
toc = el.get("tableOfContents")
if toc:
walk_content(toc.get("content", []), tab_id=tab_id)
continue
walk_content((doc.get("body") or {}).get("content", []), tab_id=None)
for t in _walk_tabs(doc.get("tabs") or []):
tab_id = ((t.get("tabProperties") or {}).get("tabId")) or ""
dtab = t.get("documentTab") or {}
walk_content((dtab.get("body") or {}).get("content", []), tab_id=tab_id)
out.sort(key=lambda x: (x["tabId"], x["startIndex"]))
return out
# -----------------------------------------------------------
# BODY MARKER SEARCH BY INDEX
# -----------------------------------------------------------
def _iter_text_chars_from_body(doc, tab_id):
content = _get_tab_body_content(doc, tab_id)
def walk(content_list):
for el in content_list or []:
if not isinstance(el, dict):
continue
p = el.get("paragraph")
if p:
for pe in p.get("elements", []):
tr = pe.get("textRun")
if not tr:
continue
txt = tr.get("content", "")
st = pe.get("startIndex")
if st is None or txt is None:
continue
rel = 0
for ch in txt:
yield (int(st) + rel, ch)
rel += _utf16_len(ch)
continue
t = el.get("table")
if t:
for row in t.get("tableRows", []):
for cell in row.get("tableCells", []):
yield from walk(cell.get("content", []))
continue
toc = el.get("tableOfContents")
if toc:
yield from walk(toc.get("content", []))
continue
yield from walk(content)
def find_marker_in_body(doc, marker: str, restrict_tab_id=None, min_doc_index=None, max_doc_index=None):
target = _norm_alnum(marker)
if not target:
return None
tabs = doc.get("tabs")
tab_ids = [None]
if tabs:
tab_ids = []
for t in _walk_tabs(tabs):
tid = ((t.get("tabProperties") or {}).get("tabId")) or ""
tab_ids.append(tid)
if restrict_tab_id is not None:
tab_ids = [restrict_tab_id]
for tab_id in tab_ids:
norm_chars = []
norm_to_docidx = []
for doc_i, ch in _iter_text_chars_from_body(doc, tab_id):
if min_doc_index is not None and int(doc_i) < int(min_doc_index):
continue
if max_doc_index is not None and int(doc_i) >= int(max_doc_index):
continue
if ch.isalnum():
norm_chars.append(ch.lower())
norm_to_docidx.append(int(doc_i))
norm_text = "".join(norm_chars)
pos = norm_text.find(target)
if pos != -1:
start_doc = norm_to_docidx[pos]
end_doc = norm_to_docidx[pos + len(target) - 1] + 1
return {
"tabId": tab_id,
"start": int(start_doc),
"end": int(end_doc),
"mode": "fuzzy_alnum"
}
return None
# -----------------------------------------------------------
# BATCH UPDATE HELPERS
# -----------------------------------------------------------
def _loc(index, tab_id=None):
d = {"index": int(index)}
if tab_id:
d["tabId"] = tab_id
return d
def _range(start, end, tab_id=None):
d = {"startIndex": int(start), "endIndex": int(end)}
if tab_id:
d["tabId"] = tab_id
return d
def _batch_update(docs_service, doc_id, reqs):
docs_service.documents().batchUpdate(
documentId=doc_id,
body={"requests": reqs}
).execute()
def _utf16_len(text: str) -> int:
if text is None:
return 0
return len(str(text).encode("utf-16-le")) // 2
_UPPER_WORD_RE = re.compile(r"(?<![A-ZÁÉÍÓÚÜÑ])([A-ZÁÉÍÓÚÜÑ]{2,})(?![A-ZÁÉÍÓÚÜÑ])")
_NUMBER_RE = re.compile(r"(?<!\w)(\d+(?:[.,]\d+)*)(?!\w)")
_BULLET_RE = re.compile(r"(?:(?<=^)|(?<=\n)|(?<=\s))(([A-Za-zÁÉÍÓÚÜÑáéíóúüñ])\.\s*\d+(?:[.,]\d+)*)")
_DATE_RE = re.compile(r"(?<!\d)(\d{1,2}\s+de\s+[A-Za-zÁÉÍÓÚÜÑáéíóúüñ]+\s+del\s+\d{4})(?!\d)", re.IGNORECASE)
_EXCEPTION_WORD_RE = re.compile(r"(?<![A-ZÁÉÍÓÚÜÑ])CONTRATO(?![A-ZÁÉÍÓÚÜÑ])")
def _match_to_doc_range(insert_start: int, text: str, start_pos: int, end_pos: int):
start_offset = _utf16_len(text[:start_pos])
end_offset = _utf16_len(text[:end_pos])
return int(insert_start) + start_offset, int(insert_start) + end_offset
def _collect_bold_requests(insert_info):
text = str((insert_info or {}).get("text") or "")
start = int((insert_info or {}).get("start") or 0)
tab_id = (insert_info or {}).get("tabId")
reqs = []
match_count = 0
for rgx in (_UPPER_WORD_RE, _NUMBER_RE, _BULLET_RE, _DATE_RE):
for m in rgx.finditer(text):
token = m.group(1)
if token.upper() == "CONTRATO":
continue
r0, r1 = _match_to_doc_range(start, text, m.start(1), m.end(1))
if r1 <= r0:
continue
reqs.append({
"updateTextStyle": {
"range": _range(r0, r1, tab_id),
"textStyle": {"bold": True},
"fields": "bold",
}
})
match_count += 1
return reqs, match_count
def _collect_no_bold_contrato_requests(insert_info):
text = str((insert_info or {}).get("text") or "")
start = int((insert_info or {}).get("start") or 0)
tab_id = (insert_info or {}).get("tabId")
reqs = []
match_count = 0
for m in _EXCEPTION_WORD_RE.finditer(text):
r0, r1 = _match_to_doc_range(start, text, m.start(0), m.end(0))
if r1 <= r0:
continue
reqs.append({
"updateTextStyle": {
"range": _range(r0, r1, tab_id),
"textStyle": {"bold": False},
"fields": "bold",
}
})
match_count += 1
return reqs, match_count
def apply_bold_rules_to_inserted_text(docs_service, doc_id, insert_info, debug_prefix):
try:
bold_reqs, bold_matches = _collect_bold_requests(insert_info)
contrato_reqs, contrato_matches = _collect_no_bold_contrato_requests(insert_info)
all_reqs = bold_reqs + contrato_reqs
_sv(f"{debug_prefix}_bold_match_count", str(bold_matches))
_sv(f"{debug_prefix}_contrato_count", str(contrato_matches))
_sv(f"{debug_prefix}_style_request_count", str(len(all_reqs)))
if all_reqs:
_batch_update(docs_service, doc_id, all_reqs)
_sv(f"{debug_prefix}_bold_status", "OK")
except Exception as e:
_sv(f"{debug_prefix}_bold_status", "ERROR")
_sv(f"{debug_prefix}_bold_error", str(e))
raise
def replace_marker_by_index(
docs_service,
doc_id: str,
marker: str,
replacement_text: str,
debug_prefix: str,
restrict_tab_id=None,
min_doc_index=None,
max_doc_index=None
):
doc = docs_get(docs_service, doc_id)
hit = None
hit_scope = "global"
if restrict_tab_id is not None or min_doc_index is not None or max_doc_index is not None:
hit = find_marker_in_body(
doc=doc,
marker=marker,
restrict_tab_id=restrict_tab_id,
min_doc_index=min_doc_index,
max_doc_index=max_doc_index
)
if hit:
hit_scope = "restricted"
if not hit:
hit = find_marker_in_body(doc=doc, marker=marker)
if not hit:
_sv(f"{debug_prefix}_found", "0")
_sv(f"{debug_prefix}_marker", marker)
_sv(f"{debug_prefix}_restrict_tabId", "" if restrict_tab_id is None else str(restrict_tab_id))
_sv(f"{debug_prefix}_restrict_min", "" if min_doc_index is None else str(min_doc_index))
_sv(f"{debug_prefix}_restrict_max", "" if max_doc_index is None else str(max_doc_index))
raise RuntimeError(f"No encontré el marcador en el BODY del documento: '{marker}'")
tab_id = hit.get("tabId")
start = int(hit["start"])
end = int(hit["end"])
_sv(f"{debug_prefix}_found", "1")
_sv(f"{debug_prefix}_marker", marker)
_sv(f"{debug_prefix}_tabId", "" if tab_id is None else str(tab_id))
_sv(f"{debug_prefix}_start", str(start))
_sv(f"{debug_prefix}_end", str(end))
_sv(f"{debug_prefix}_mode", hit.get("mode", ""))
_sv(f"{debug_prefix}_scope", hit_scope)
_sv(f"{debug_prefix}_replacement_len", str(len(replacement_text or "")))
reqs = [
{"deleteContentRange": {"range": _range(start, end, tab_id)}},
{"insertText": {"location": _loc(start, tab_id), "text": replacement_text}},
]
_batch_update(docs_service, doc_id, reqs)
return {
"tabId": tab_id,
"start": start,
"end": start + _utf16_len(replacement_text or ""),
"text": replacement_text or "",
}
# Rocketbot quirk FIX
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
url_doc = _gvs("current_url", "")
if url_doc == "":
raise RuntimeError("Falta current_url con la URL exacta del documento a procesar.")
_sv("debug_current_url_var", url_doc)
_sv("debug_gdoc_url_var", _gvs("gdoc_url", ""))
_sv("gdoc_url_used", url_doc)
raw_id = extract_doc_id_from_url(url_doc)
if not raw_id:
raise RuntimeError("No pude extraer documentId de la URL.")
_sv("gdoc_original_id", raw_id)
cred_path = _gvs("gdoc_sa_json", "")
if cred_path == "":
raise RuntimeError("Falta la variable gdoc_sa_json.")
if not os.path.isabs(cred_path):
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)
impersonated_user = _gvs("gdoc_impersonated_user", "")
docs_service, drive_service, auth_mode = get_services(cred_path, impersonated_user)
_sv("gdoc_impersonated_user_used", impersonated_user)
_sv("gdoc_auth_mode", auth_mode)
doc_id, meta_file, converted = ensure_docs_api_compatible(drive_service, raw_id)
_sv("gdoc_id", doc_id)
_sv("gdoc_converted", "1" if converted else "0")
_sv("gdoc_url_final", f"https://docs.google.com/document/d/{doc_id}/edit")
_sv("gdoc_name", meta_file.get("name", ""))
doc_before = docs_get(docs_service, doc_id)
_sv("gdoc_revision_before", doc_before.get("revisionId", ""))
# --------------------
# UBICAR SECCIONES
# --------------------
paragraphs = collect_paragraphs(doc_before)
_sv("gdoc_paragraphs_count", str(len(paragraphs)))
key_seg = _norm_alnum("SEGUNDA")
key_prec = _norm_alnum("PRECIO")
key_ter = _norm_alnum("TERCERO")
key_pago = _norm_alnum("PAGO")
key_cuarta = _norm_alnum("CUARTA")
segunda_title = None
tercero_title = None
cuarta_title = None
for p in paragraphs:
n = p["norm_alnum"]
if segunda_title is None and (key_seg in n and key_prec in n):
segunda_title = p
if tercero_title is None and (key_ter in n and key_pago in n):
tercero_title = p
if cuarta_title is None and n.startswith(key_cuarta):
cuarta_title = p
precio_tab = None
precio_min = None
precio_max = None
if segunda_title:
precio_tab = segunda_title.get("tabId") or ""
precio_min = int(segunda_title.get("startIndex", 0))
if tercero_title and ((tercero_title.get("tabId") or "") == precio_tab):
precio_max = int(tercero_title.get("startIndex", 0))
fp_tab = None
fp_min = None
fp_max = None
if tercero_title:
fp_tab = tercero_title.get("tabId") or ""
fp_min = int(tercero_title.get("startIndex", 0))
if cuarta_title and ((cuarta_title.get("tabId") or "") == fp_tab):
fp_max = int(cuarta_title.get("startIndex", 0))
_sv("gdoc_precio_scope_tab", "" if precio_tab is None else str(precio_tab))
_sv("gdoc_precio_scope_min", "" if precio_min is None else str(precio_min))
_sv("gdoc_precio_scope_max", "" if precio_max is None else str(precio_max))
_sv("gdoc_fp_scope_tab", "" if fp_tab is None else str(fp_tab))
_sv("gdoc_fp_scope_min", "" if fp_min is None else str(fp_min))
_sv("gdoc_fp_scope_max", "" if fp_max is None else str(fp_max))
# --------------------
# MARCADORES
# --------------------
marker_precio = _gvs("gdoc_marker_precio", "RB_MARKER_PRECIO_2026")
marker_forma_pago = _gvs("gdoc_marker_forma_pago", "RB_MARKER_FORMA_PAGO_2026")
if marker_precio == "":
raise RuntimeError("La variable gdoc_marker_precio está vacía.")
if marker_forma_pago == "":
raise RuntimeError("La variable gdoc_marker_forma_pago está vacía.")
_sv("gdoc_marker_precio_used", marker_precio)
_sv("gdoc_marker_forma_pago_used", marker_forma_pago)
# --------------------
# VARIABLES NECESARIAS ANTES DE TEXTO PRECIO
# --------------------
plan_pagos_raw = _first_non_empty(
_gvs("plan_de_pagos", ""),
_gvs("plan_pagos", "")
)
plan_pagos = _norm_alnum(plan_pagos_raw)
num_pre_cuotas_fallback = _to_int(_gvs("num_pre_cuotas", "0"))
cant_cuotas_pos_fallback = _to_int(_gvs("cant_cuotas_pos", "0"))
pos_num_cuota_fallback = _to_int(_gvs("pos_num_cuota", "0"))
raw_refuerzos_pre = _first_non_missing_var("refuerzos_pre", "refuerzo_pre")
raw_refuerzos_post = _first_non_missing_var("refuerzos_post", "refuerzo_post")
raw_cuotas_post = _gv("cuotas_post", [])
raw_cuotas_pre = _gv("cuotas_pre", [])
refuerzos_pre = _as_list_of_dicts(raw_refuerzos_pre)
refuerzos_post = _as_list_of_dicts(raw_refuerzos_post)
cuotas_post = _as_list_of_dicts(raw_cuotas_post)
cuotas_pre = _as_list_of_dicts(raw_cuotas_pre)
num_pre_cuotas_calc = _sum_qty(cuotas_pre)
pos_num_cuota_calc = _sum_qty(cuotas_post)
num_pre_cuotas = num_pre_cuotas_calc if num_pre_cuotas_calc > 0 else num_pre_cuotas_fallback
pos_num_cuota = pos_num_cuota_calc if pos_num_cuota_calc > 0 else pos_num_cuota_fallback
meses_financiado = num_pre_cuotas + pos_num_cuota
letra_meses_financiado = numero_a_letras_es(int(meses_financiado))
# --------------------
# TEXTO PRECIO
# --------------------
adicional_piso = _to_decimal_money(_gvs("adicional_piso", "0"))
precio_departamento = _raw_or_money_text(_gvs("precio_departamento", ""))
precio_letras = _first_non_empty(
_gvs("precio_letras", ""),
cantidad_a_letras_con_moneda(_gvs("precio_departamento", "0"))
)
adicional_piso_txt = _raw_or_money_text(_gvs("adicional_piso", ""))
adicional_piso_letras = _first_non_empty(
_gvs("adicional_piso_letras", ""),
cantidad_a_letras_con_moneda(_gvs("adicional_piso", "0"))
)
valor_total_compra = _raw_or_money_text(_gvs("valor_total_compra", ""))
valor_total_letras = _first_non_empty(
_gvs("valor_total_letras", ""),
cantidad_a_letras_con_moneda(_gvs("valor_total_compra", "0"))
)
# valor financiado con interés incluído
valor_total_compra_financiado = _to_decimal_money(_gvs("valor_total_compra_financiado", "0"))
valor_total_letras_financiado = _first_non_empty(
_gvs("valor_total_letras_financiado", ""),
cantidad_a_letras_con_moneda(_gvs("valor_total_compra_financiado", "0"))
)
# ======================== #
# ======================== #
#--- CONTADO -----
if adicional_piso > 0 and plan_pagos == 'contado':
texto_precio = (
f"USD. {precio_departamento} ({precio_letras}) más ADICIONAL por piso de USD. {adicional_piso_txt} ({adicional_piso_letras}). "
f"Valor total de la compra USD. {valor_total_compra} ({valor_total_letras})."
+ "-------------------------------------------------------------------------------------------------------------" + NL +
"Los precios de venta incluyen el impuesto al valor agregado correspondiente a la operación de venta de la unidad, calculado a la tasa vigente."
+ "----------------------------------------------------------" + NL
)
elif adicional_piso == 0 and plan_pagos == 'contado':
texto_precio = (
f"USD. {precio_departamento} ({precio_letras})."
+ "------------------------------------------------" + NL +
"Los precios de venta incluyen el impuesto al valor agregado correspondiente a la operación de venta de la unidad, calculado a la tasa vigente."
+ "-----------------------------------" + NL
)
# ======================== #
# ======================== #
#--- FINANCIADO -----
if adicional_piso > 0 and plan_pagos == 'financiado':
texto_precio = (
f"USD. {precio_departamento} ({precio_letras}) más ADICIONAL por piso de USD. {adicional_piso_txt} ({adicional_piso_letras}). "
f"Valor total de la compra USD. {valor_total_compra} ({valor_total_letras})."
+ "-------------------------------------------------------------------------------------------------------------" + NL +
f"VALOR FINANCIADO: El precio total de la compraventa con la financiación a {meses_financiado} meses ({letra_meses_financiado}) asciende a un USD. {valor_total_compra_financiado} ({valor_total_letras_financiado})."
+ "-------------------------------------------" + NL +
"Los precios de venta incluyen el impuesto al valor agregado correspondiente a la operación de venta de la unidad, calculado a la tasa vigente. "
"Cualquier aumento en este impuesto u otro impuesto existente o que se cree en el futuro, estará a cargo exclusivo de EL(LOS) COMPRADOR(ES). "
"Asimismo, y no obstante lo pactado en las restantes cláusulas de este contrato, queda establecido que cualquier importe emergente del presente contrato que tuviera que ser abonado por EL(LOS) COMPRADOR(ES), tal como intereses punitorios, costos o cualquier otro tipo de compensación o gasto y que estuviere alcanzado en cada caso por el impuesto al valor agregado, dicho impuesto será a cargo exclusivo de EL(LOS) COMPRADOR(ES)."
+ "-----------------------------------" + NL
)
elif adicional_piso == 0 and plan_pagos == 'financiado':
texto_precio = (
f"USD. {precio_departamento} ({precio_letras})."
+ "-------------------------------------------------------------------------------------------------------------" + NL +
f"VALOR FINANCIADO: El precio total de la compraventa con la financiación a {meses_financiado} meses ({letra_meses_financiado}) asciende a un USD. {valor_total_compra_financiado} ({valor_total_letras_financiado})."
+ "-------------------------------------------" + NL +
"Los precios de venta incluyen el impuesto al valor agregado correspondiente a la operación de venta de la unidad, calculado a la tasa vigente. "
"Cualquier aumento en este impuesto u otro impuesto existente o que se cree en el futuro, estará a cargo exclusivo de EL(LOS) COMPRADOR(ES). "
"Asimismo, y no obstante lo pactado en las restantes cláusulas de este contrato, queda establecido que cualquier importe emergente del presente contrato que tuviera que ser abonado por EL(LOS) COMPRADOR(ES), tal como intereses punitorios, costos o cualquier otro tipo de compensación o gasto y que estuviere alcanzado en cada caso por el impuesto al valor agregado, dicho impuesto será a cargo exclusivo de EL(LOS) COMPRADOR(ES)."
+ "-----------------------------------" + NL
)
# ======================== #
# ======================== #
#--- DURANTE OBRA -----
if adicional_piso > 0 and plan_pagos == 'duranteobra':
texto_precio = (
f"USD. {precio_departamento} ({precio_letras}) más ADICIONAL por piso de USD. {adicional_piso_txt} ({adicional_piso_letras}). "
f"Valor total de la compra USD. {valor_total_compra} ({valor_total_letras})."
+ "-------------------------------------------" + NL +
"Los precios de venta incluyen el impuesto al valor agregado correspondiente a la operación de venta de la unidad, calculado a la tasa vigente. "
"Cualquier aumento en este impuesto u otro impuesto existente o que se cree en el futuro, estará a cargo exclusivo de EL(LOS) COMPRADOR(ES). "
"Asimismo, y no obstante lo pactado en las restantes cláusulas de este contrato, queda establecido que cualquier importe emergente del presente contrato que tuviera que ser abonado por EL(LOS) COMPRADOR(ES), tal como intereses punitorios, costos o cualquier otro tipo de compensación o gasto y que estuviere alcanzado en cada caso por el impuesto al valor agregado, dicho impuesto será a cargo exclusivo de EL(LOS) COMPRADOR(ES)."
+ "-----------------------------------" + NL
)
elif adicional_piso == 0 and plan_pagos == 'duranteobra':
texto_precio = (
f"USD. {precio_departamento} ({precio_letras})."
+ "------------------------------------------------" + NL +
"Los precios de venta incluyen el impuesto al valor agregado correspondiente a la operación de venta de la unidad, calculado a la tasa vigente. "
"Cualquier aumento en este impuesto u otro impuesto existente o que se cree en el futuro, estará a cargo exclusivo de EL(LOS) COMPRADOR(ES). "
"Asimismo, y no obstante lo pactado en las restantes cláusulas de este contrato, queda establecido que cualquier importe emergente del presente contrato que tuviera que ser abonado por EL(LOS) COMPRADOR(ES), tal como intereses punitorios, costos o cualquier otro tipo de compensación o gasto y que estuviere alcanzado en cada caso por el impuesto al valor agregado, dicho impuesto será a cargo exclusivo de EL(LOS) COMPRADOR(ES)."
+ "-----------------------------------" + NL
)
# --------------------
# TEXTO FORMA DE PAGO
# --------------------
pago_sena_raw = _gvs("pago_sena", "0")
pago_inicial_raw = _gvs("pago_inicial", "0")
cant_cuotas_raw = _gvs("cant_cuotas", "0")
pago_sena = _to_decimal_money(pago_sena_raw)
pago_inicial = _to_decimal_money(pago_inicial_raw)
cant_cuotas_pre = _to_int(cant_cuotas_raw)
pago_sena_txt, pago_sena_letras = _money_text_and_letters(
pago_sena_raw,
_gvs("pago_sena_letras", "")
)
pago_inicial_txt, pago_inicial_letras = _money_text_and_letters(
pago_inicial_raw,
_gvs("pago_inicial_letras", "")
)
saldo_day = _gvs("day_contrato", "")
saldo_mes = _gvs("mes_contrato", "")
saldo_anio = _gvs("anio_contrato", "")
nombre_comprador = _gvs("nombre_comprador", "")
plan_pagos_raw = _first_non_empty(
_gvs("plan_de_pagos", ""),
_gvs("plan_pagos", "")
)
plan_pagos = _norm_alnum(plan_pagos_raw)
_sv("debug_plan_pagos_raw", plan_pagos_raw)
_sv("debug_plan_pagos_norm", plan_pagos)
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)
num_pre_cuotas_fallback = _to_int(_gvs("num_pre_cuotas", "0"))
cant_cuotas_pos_fallback = _to_int(_gvs("cant_cuotas_pos", "0"))
pos_num_cuota_fallback = _to_int(_gvs("pos_num_cuota", "0"))
# Legacy + nuevos arreglos
raw_refuerzos_pre = _first_non_missing_var("refuerzos_pre", "refuerzo_pre")
raw_refuerzos_post = _first_non_missing_var("refuerzos_post", "refuerzo_post")
raw_cuotas_post = _gv("cuotas_post", [])
raw_cuotas_pre = _gv("cuotas_pre", [])
_sv("debug_refuerzos_pre_raw_type", type(raw_refuerzos_pre).__name__)
_sv("debug_refuerzos_post_raw_type", type(raw_refuerzos_post).__name__)
_sv("debug_cuotas_post_raw_type", type(raw_cuotas_post).__name__)
_sv("debug_cuotas_pre_raw_type", type(raw_cuotas_pre).__name__)
_sv("debug_refuerzos_pre_raw_preview", _safe_preview(raw_refuerzos_pre))
_sv("debug_refuerzos_post_raw_preview", _safe_preview(raw_refuerzos_post))
_sv("debug_cuotas_post_raw_preview", _safe_preview(raw_cuotas_post))
_sv("debug_cuotas_pre_raw_preview", _safe_preview(raw_cuotas_pre))
refuerzos_pre = _as_list_of_dicts(raw_refuerzos_pre)
refuerzos_post = _as_list_of_dicts(raw_refuerzos_post)
cuotas_post = _as_list_of_dicts(raw_cuotas_post)
cuotas_pre = _as_list_of_dicts(raw_cuotas_pre)
_sv("debug_refuerzos_pre_parsed_len", str(len(refuerzos_pre)))
_sv("debug_refuerzos_post_parsed_len", str(len(refuerzos_post)))
_sv("debug_cuotas_post_parsed_len", str(len(cuotas_post)))
_sv("debug_cuotas_pre_parsed_len", str(len(cuotas_pre)))
primer_pre = cuotas_pre[0] if cuotas_pre else {}
primer_pos = cuotas_post[0] if cuotas_post else {}
pre_amount_raw = _safe_dict_get(primer_pre, "amount", "")
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)
)
frecuencia_pre = str(_safe_dict_get(primer_pre, "frequency", "") or "").lower()
pos_amount_raw = _safe_dict_get(primer_pos, "amount", "")
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)
)
frecuencia_pos = str(_safe_dict_get(primer_pos, "frequency", "") or "").lower()
num_pre_cuotas_calc = _sum_qty(cuotas_pre)
pos_num_cuota_calc = _sum_qty(cuotas_post)
num_pre_cuotas = num_pre_cuotas_calc if num_pre_cuotas_calc > 0 else num_pre_cuotas_fallback
pos_num_cuota = pos_num_cuota_calc if pos_num_cuota_calc > 0 else pos_num_cuota_fallback
cant_cuotas_pre = cant_cuotas_pre if cant_cuotas_pre > 0 else num_pre_cuotas
cant_cuotas_pos = pos_num_cuota if pos_num_cuota > 0 else cant_cuotas_pos_fallback
fecha_fallback = _first_non_empty(
_gvs("pre_date", ""),
_gvs("fecha_contrato", ""),
_safe_dict_get(primer_pre, "date", ""),
_safe_dict_get(primer_pos, "date", "")
)
if not saldo_day or not saldo_mes or not saldo_anio:
fb_day, fb_mes, fb_anio = _derive_date_parts(fecha_fallback)
saldo_day = saldo_day or fb_day
saldo_mes = saldo_mes or fb_mes
saldo_anio = saldo_anio or fb_anio
_sv("debug_fecha_fallback_usada", fecha_fallback)
_sv("debug_saldo_day_final", saldo_day)
_sv("debug_saldo_mes_final", saldo_mes)
_sv("debug_saldo_anio_final", saldo_anio)
_sv("debug_pago_sena_raw", pago_sena_raw)
_sv("debug_pago_sena_num", str(pago_sena))
_sv("debug_pago_inicial_raw", pago_inicial_raw)
_sv("debug_pago_inicial_num", str(pago_inicial))
_sv("debug_cant_cuotas_raw", cant_cuotas_raw)
_sv("debug_cant_cuotas_pre_final", str(cant_cuotas_pre))
_sv("debug_cant_cuotas_pos_final", str(cant_cuotas_pos))
_sv("debug_num_pre_cuotas_final", str(num_pre_cuotas))
_sv("debug_pos_num_cuota_final", str(pos_num_cuota))
_sv("debug_refuerzos_total_final", str(len(refuerzos_pre) + len(refuerzos_post)))
_sv("debug_saldo_a_pagar_letras", saldo_letras)
has_sena = pago_sena > 0
has_inicial = pago_inicial > 0
has_pre = len(cuotas_pre) > 0 or num_pre_cuotas > 0
has_pos = len(cuotas_post) > 0 or pos_num_cuota > 0
# bloques de párrafos dinámicos
#
# Nota: aquí se construyen las cuatro variables que almacenan los párrafos
# dinámicos usados posteriormente en `texto_fp` u otros textos:
# - pre_paragraphs_a, pre_paragraphs_b
# - post_paragraphs_a, post_paragraphs_b
#
# Estas variables deben inicializarse sólo en esta sección y no ser
# sobreescritas más abajo. Si se necesita reutilizarlas, se debe leer
# su valor (no reasignarlo) para preservar la consistencia del texto.
if len(cuotas_pre) > 0:
pre_paragraphs_a = _build_cuotas_pre_paragraphs(cuotas_pre, base_label="a", nl=NL)
else:
freq_part = f" {frecuencia_pre}/es" if frecuencia_pre else ""
# Preferir la fecha indicada en la primera cuota (`primer_pre['date']`) si existe;
# si no, caer atrás en los valores `saldo_day/mes/anio`.
primer_pre_fecha_txt = _date_text_long(_safe_dict_get(primer_pre, "date", "")) if primer_pre else ""
fallback_fecha_txt = f"{saldo_day} de {saldo_mes} del {saldo_anio}" if (saldo_day or saldo_mes or saldo_anio) else ""
fecha_txt = primer_pre_fecha_txt or fallback_fecha_txt
pre_paragraphs_a = (
f"a- ETAPA PRE ENTREGA: {num_pre_cuotas} cuota/s{freq_part} de USD. {pre_amount} ({pre_amount_letras}) "
f"con fecha de primer vencimiento el {fecha_txt} en adelante."
+ "--------------------------------------------------------" + NL
if has_pre else ""
)
if len(cuotas_post) > 0:
post_paragraphs_a = _build_cuotas_post_paragraphs(cuotas_post, base_label="a", nl=NL)
post_paragraphs_b = _build_cuotas_post_paragraphs(cuotas_post, base_label="b", nl=NL)
else:
freq_part = f" {frecuencia_pos}/es" if frecuencia_pos else ""
# Preferir la fecha indicada en la primera cuota post (`primer_pos['date']`) si existe;
# si no, usar `saldo_day/mes/anio`.
primer_pos_fecha_txt = _date_text_long(_safe_dict_get(primer_pos, "date", "")) if primer_pos else ""
fallback_pos_fecha_txt = f"{saldo_day} de {saldo_mes} del {saldo_anio}" if (saldo_day or saldo_mes or saldo_anio) else ""
fecha_pos_txt = primer_pos_fecha_txt or fallback_pos_fecha_txt
base_text_post = (
f"ETAPA POS ENTREGA: {pos_num_cuota} cuota/s{freq_part} de USD. {pos_cuota_monto} ({pos_cuota_letras}) "
f"con fecha de primer vencimiento el {fecha_pos_txt} en adelante."
)
post_paragraphs_a = (
f"a- {base_text_post}" + "--------------------------------------------------------" + NL
if has_pos else ""
)
post_paragraphs_b = (
f"b- {base_text_post}" + "--------------------------------------------------------" + NL
if has_pos else ""
)
if len(cuotas_pre) > 0:
pre_paragraphs_b = _build_cuotas_pre_paragraphs(cuotas_pre, base_label="b", nl=NL)
else:
# Cuando no hay lista detallada, generamos la variante 'b' a partir de
# la 'a' reemplazando el primer prefijo "a-" por "b-". Esto evita
# duplicar la lógica de construcción de texto y mantiene consistencia.
pre_paragraphs_b = pre_paragraphs_a.replace("a-", "b-", 1) if pre_paragraphs_a else ""
refuerzos_text = (
_build_refuerzos_pre_paragraphs(refuerzos_pre, nl=NL)
+ _build_refuerzos_post_paragraphs(refuerzos_post, nl=NL)
)
texto_fp = ""
debug_case = ""
# --------------------
# CONTADO
# --------------------
if plan_pagos == 'contado':
debug_case = "PLAN_PAGO_CONTADO"
if has_sena and has_inicial and has_pre:
debug_case = "SENA_MAS_INICIAL_MAS_SALDO"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
"3.3 PAGO DEL SALDO: El saldo será cancelado de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
elif has_sena and (not has_inicial) and has_pre:
debug_case = "SENA_MAS_SALDO"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-------------------------------------" + NL +
"3.2 PAGO DEL SALDO: El saldo será cancelado de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
elif (not has_sena) and has_inicial and has_pre:
debug_case = "INICIAL_MAS_SALDO"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
"3.2 PAGO DEL SALDO: El saldo será cancelado de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
else:
debug_case = "PAGO_CONTADO"
texto_fp = (
f"3.1 PAGO CONTADO: Un pago único de USD. {valor_total_compra} ({valor_total_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "----------------------------" + NL
)
# --------------------
# FINANCIADO
# --------------------
def inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos):
if refuerzos_text:
texto_fp = texto_fp + refuerzos_text + clausula_proteccion_datos
else:
texto_fp = texto_fp + clausula_proteccion_datos
return texto_fp
if plan_pagos == 'financiado':
debug_case = "PLAN_PAGO_FINANCIADO"
if has_pre and has_pos:
if has_sena and has_inicial:
debug_case = "SENA_INICIAL_MAS_PRE_Y_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.3 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.4 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_sena and (not has_inicial):
debug_case = "SENA_MAS_PRE_Y_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif (not has_sena) and has_inicial:
debug_case = "INICIAL_MAS_PRE_Y_POS"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
else:
debug_case = "PRE_Y_POS_SIN_SENA_NI_INICIAL"
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.2 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_pre:
if has_sena and has_inicial:
debug_case = "SENA_MAS_INICIAL_MAS_CUOTA_PRE"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.3 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.4 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_sena and (not has_inicial):
debug_case = "SENA_MAS_CUOTA_PRE"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif (not has_sena) and has_inicial:
debug_case = "INICIAL_MAS_CUOTA_PRE"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
else:
debug_case = "CUOTA_PRE_SIN_SENA_NI_INICIAL"
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.2 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_pos:
if has_sena and has_inicial:
debug_case = "SENA_INICIAL_MAS_CUOTA_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.3 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.4 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_sena and (not has_inicial):
debug_case = "SENA_MAS_CUOTA_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif (not has_sena) and has_inicial:
debug_case = "INICIAL_MAS_CUOTA_POS"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
else:
debug_case = "CUOTA_POS_SIN_SENA_NI_INICIAL"
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.2 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
# ==================
# DURANTE OBRA
# ==================
if plan_pagos == 'duranteobra':
debug_case = "PLAN_PAGO_DURANTE_OBRA"
if has_pre and has_pos:
if has_sena and has_inicial:
debug_case = "SENA_INICIAL_MAS_PRE_Y_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.3 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.4 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_sena and (not has_inicial):
debug_case = "SENA_MAS_PRE_Y_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif (not has_sena) and has_inicial:
debug_case = "INICIAL_MAS_PRE_Y_POS"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
else:
debug_case = "PRE_Y_POS_SIN_SENA_NI_INICIAL"
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a +
post_paragraphs_b
)
clausula_proteccion_datos = (
f'3.2 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_pre:
if has_sena and has_inicial:
debug_case = "SENA_MAS_INICIAL_MAS_CUOTA_PRE"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.3 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.4 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_sena and (not has_inicial):
debug_case = "SENA_MAS_CUOTA_PRE"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif (not has_sena) and has_inicial:
debug_case = "INICIAL_MAS_CUOTA_PRE"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
else:
debug_case = "CUOTA_PRE_SIN_SENA_NI_INICIAL"
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
pre_paragraphs_a
)
clausula_proteccion_datos = (
f'3.2 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_pos:
if has_sena and has_inicial:
debug_case = "SENA_INICIAL_MAS_CUOTA_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.3 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.4 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif has_sena and (not has_inicial):
debug_case = "SENA_MAS_CUOTA_POS"
texto_fp = (
f"3.1 PAGO DE SEÑA: El Sr./Sra {nombre_comprador}, ha realizado la entrega de USD. {pago_sena_txt} ({pago_sena_letras}) como seña de trato."
+ "-----------------------------------------------------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
elif (not has_sena) and has_inicial:
debug_case = "INICIAL_MAS_CUOTA_POS"
texto_fp = (
f"3.1 PAGO INICIAL: Un pago inicial de USD. {pago_inicial_txt} ({pago_inicial_letras}) al momento de la firma del CONTRATO, sirviendo el presente de suficiente recibo y formal carta de pago, reemplazando cualquier documento emitido antes de este acto."
+ "--------------------------------------" + NL +
f"3.2 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.3 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
else:
debug_case = "CUOTA_POS_SIN_SENA_NI_INICIAL"
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras}) este suscribe en GARANTÍA a favor del VENDEDOR un pagaré, el cual forma parte integrante de este instrumento y el mismo será devuelto a EL COMPRADOR una vez sea cubierto el pago total de lo adeudado, será de la siguiente manera, durante la etapa de construcción de la obra:"
+ NL +
post_paragraphs_a
)
clausula_proteccion_datos = (
f'3.2 Conforme a los términos de la Ley 6534/2020 "De protección de datos personales crediticios", EL(LOS) COMPRADOR(ES) autorizan a ZUBA SAECA a tratar, recabar, procesar, proveer, almacenar y/o difundir, cualquier tipo de información referente a los datos personales (nacionalidad, cédula de identidad, RUC, domicilio, estado civil, lugar de trabajo, teléfono particular, laboral y móvil); información societaria (RUC, datos de su constitución y modificaciones, personería jurídica, socios y beneficiarios finales); así como antecedentes civiles, penales, actividad comercial, información crediticia (positiva o negativa), situación patrimonial, solvencia económica, nivel de endeudamiento y datos del cumplimiento de mis (nuestras) obligaciones comerciales e impositivas, de cualquier empresa y/o entidad, pública o privada, nacional o extranjera dedicada a la gestión de bases de datos personales o crediticios, como ser INFORMCONF, INFOMERCIO, BICSA, Central de Informaciones del Banco Central del Paraguay, Central de Riesgo Bancard; haciendo extensiva esta autorización a dichas empresas, y/o cualquier otra empresa y/o Institución dedicada al tratamiento y almacenamiento de datos que pudiera existir en el país o en el extranjero en el futuro. Quedan igualmente autorizados a proporcionar los mismos datos mencionados en la nota de consentimiento informado a terceros interesados, sean entidades del sector financiero o no financiero, en el marco de acuerdos comerciales en curso con dichas entidades, como contratos de cesión, venta o pignoración de cartera de créditos. Los datos personales y crediticios servirán en estos casos para a aprobación o rechazo de la cesión, venta o pignoración del crédito de EL(LOS) COMPRADOR(ES).'
)
texto_fp = inclusion_clausula_proteccion_datos(texto_fp, refuerzos_text, clausula_proteccion_datos)
_sv("debug_texto_fp_case", debug_case)
_sv("debug_texto_fp_len", str(len(texto_fp)))
if texto_fp.strip() == "":
_sv("debug_texto_fp_vacio", "1")
_sv("debug_has_sena", str(has_sena))
_sv("debug_has_inicial", str(has_inicial))
_sv("debug_has_pre", str(has_pre))
_sv("debug_has_pos", str(has_pos))
_sv("debug_saldo_a_pagar", saldo_a_pagar)
_sv("debug_pre_amount", pre_amount)
_sv("debug_pos_cuota_monto", pos_cuota_monto)
texto_fp = (
f"3.1 PAGO DEL SALDO: El saldo restante de USD. {saldo_a_pagar} ({saldo_letras})."
+ "--------------------------------------------------------" + NL
)
# --------------------
# REEMPLAZAR MARCADORES
# --------------------
precio_insert_info = replace_marker_by_index(
docs_service=docs_service,
doc_id=doc_id,
marker=marker_precio,
replacement_text=texto_precio,
debug_prefix="gdoc_precio",
restrict_tab_id=precio_tab,
min_doc_index=precio_min,
max_doc_index=precio_max,
)
apply_bold_rules_to_inserted_text(
docs_service=docs_service,
doc_id=doc_id,
insert_info=precio_insert_info,
debug_prefix="gdoc_precio",
)
forma_pago_insert_info = replace_marker_by_index(
docs_service=docs_service,
doc_id=doc_id,
marker=marker_forma_pago,
replacement_text=texto_fp,
debug_prefix="gdoc_forma_pago",
restrict_tab_id=fp_tab,
min_doc_index=fp_min,
max_doc_index=fp_max,
)
apply_bold_rules_to_inserted_text(
docs_service=docs_service,
doc_id=doc_id,
insert_info=forma_pago_insert_info,
debug_prefix="gdoc_forma_pago",
)
doc_after = docs_get(docs_service, doc_id)
_sv("gdoc_revision_after", doc_after.get("revisionId", ""))
_sv("gdoc_replace_mode", "BODY_marker_by_index_with_current_url")
_sv("gdoc_textos_status", "OK")
_sv("gdoc_textos_error", "")
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