Files
scripts_zubabot/numeros_a_letras.py

121 lines
4.2 KiB
Python

def main():
import re
import decimal
_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"]
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.sub(r"[^0-9,\.\-]", "", s)
if s == "" or s.lower() == "false":
return ""
# Si tiene , y . => el último separador es el decimal
if "," in s and "." in s:
if s.rfind(",") > s.rfind("."):
# 1.234,56 -> 1234.56
return s.replace(".", "").replace(",", ".")
else:
# 1,234.56 -> 1234.56
return s.replace(",", "")
# Solo coma: coma decimal (y comas previas como miles)
if "," in s:
parts = s.split(",")
if len(parts) > 2:
return "".join(parts[:-1]) + "." + parts[-1]
return s.replace(",", ".")
# Solo punto: si hay varios puntos, los anteriores son miles
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:
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] # conserva ceros por quantize
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()
# ---- Rocketbot ----
saldo_a_pagar = GetVar("monto_saldo") # sin llaves
saldo_a_pagar_letras = numero_decimal_a_palabras_es(saldo_a_pagar, max_decimales=2)
# sufijo requerido
if saldo_a_pagar_letras.strip() != "":
saldo_a_pagar_letras = "DOLARES AMERICANOS " + saldo_a_pagar_letras.strip()
SetVar("saldo_a_pagar_letras", saldo_a_pagar_letras)
# IMPORTANTE: llamar la función
main()