Skip to main content

Overview

The amount-to-words conversion utilities transform numeric monetary values into their Spanish written equivalents. This is a legal requirement for Venezuelan invoices, where amounts must be displayed both numerically and written out in words. Two functions are available:
  • monto_a_letras() - Primary function with currency-aware formatting (USD/Bolívares)
  • monto_a_letras_b() - Alternative function with digit-by-digit decimal conversion

monto_a_letras() Function

Purpose

Converts monetary amounts to Spanish words with proper currency handling for dollars and bolívares, including appropriate decimal terminology (centavos vs céntimos).

Function Signature

def monto_a_letras(monto, moneda="dolares")
Source: main.py:51-71

Parameters

monto
float | str | int
required
The monetary amount to convert. Can be:
  • Float with decimals: 1234.56
  • Integer: 1000
  • String representation: "1234.56"
The amount is converted to float and split into integer and decimal parts.
moneda
string
default:"dolares"
The currency type, affecting decimal terminology and suffix:
  • "dolares" - Uses “centavos” for decimals, no currency suffix
  • "bolivares" - Uses “céntimos” for decimals, adds “bolívares” suffix when no decimals
Case-insensitive comparison (converted to lowercase).

Return Value

result
string | None
Returns the amount written in Spanish words. Returns None if conversion fails due to invalid input.Format patterns:
  • Dollars with decimals: "[integer words] con [decimal words] centavos"
  • Dollars without decimals: "[integer words]"
  • Bolívares with decimals: "[integer words] con [decimal words] céntimos"
  • Bolívares without decimals: "[integer words] bolívares"

Currency Handling

# With decimals
monto_a_letras(1234.56, "dolares")
# Returns: "mil doscientos treinta y cuatro con cincuenta y seis centavos"

# Without decimals
monto_a_letras(1000.00, "dolares")
# Returns: "mil"

# Rounds to 2 decimal places
monto_a_letras(99.999, "dolares")
# Returns: "cien" (rounded to 100.00, decimals become 0)
For dollars, the currency name is not included in the output string. This allows flexibility in invoice templates.

Decimal Handling

The function implements precise decimal rounding:
entero = int(monto)
decimals = int(round((monto - entero) * 100))
1

Extract Integer Part

Converts the float to an integer, truncating decimals: int(1234.56)1234
2

Calculate Decimal Cents

Subtracts integer, multiplies by 100, and rounds: (1234.56 - 1234) * 10056
3

Check Decimal Threshold

If decimals > 0, includes decimal words with “con [decimals] centavos/céntimos”
Original AmountInteger PartDecimal PartBehavior
1234.56123456Includes “con cincuenta y seis”
1234.0012340No decimal words
1234.00412340Rounds down, no decimals
1234.9951234100Rounds to 100 céntimos/centavos
0.99099”cero con noventa y nueve”

Examples

# Typical USD invoice amount (main.py:184)
monto_usd = 1250.00
monto_a_letras(monto_usd)
# Output: "mil doscientos cincuenta"

# With cents
monto_a_letras(1250.75, "dolares")
# Output: "mil doscientos cincuenta con setenta y cinco centavos"

# Small amount
monto_a_letras(0.99, "dolares")
# Output: "cero con noventa y nueve centavos"

monto_a_letras_b() Function

Purpose

Alternative conversion function that uses digit-by-digit pronunciation for decimal parts, producing more literal translations (e.g., “punto cinco seis” instead of “cincuenta y seis”).

Function Signature

def monto_a_letras_b(monto)
Source: main.py:36-49

Parameters

monto
float | str | int
required
The amount to convert. Accepts same types as monto_a_letras() but without currency parameter.

Return Value

result
string | None
Returns the amount in Spanish with digit-by-digit decimal pronunciation:
  • With decimals: "[integer words] punto [digit words]"
  • Without decimals: "[integer words]"
  • On error: None

Decimal Conversion Approach

Unlike monto_a_letras(), this function converts each decimal digit individually:
if '.' in monto_str:
    partes = monto_str.split('.')
    entero = int(partes[0])
    decimal_str = partes[1]
    entero_letras = num2words(entero, lang='es')
    decimal_letras = " ".join(num2words(int(d), lang='es') for d in decimal_str)
    return f"{entero_letras} punto {decimal_letras}"
This function uses string splitting on the decimal point, which means the number of decimal places affects the output. 1234.5 produces different output than 1234.50.

Comparison: monto_a_letras() vs monto_a_letras_b()

Amountmonto_a_letras() (USD)monto_a_letras_b()
1234.56mil doscientos treinta y cuatro con cincuenta y seis centavosmil doscientos treinta y cuatro punto cinco seis
1234.5mil doscientos treinta y cuatro con cincuenta centavosmil doscientos treinta y cuatro punto cinco
1234.50mil doscientos treinta y cuatro con cincuenta centavosmil doscientos treinta y cuatro punto cinco cero
1000milmil
0.99cero con noventa y nueve centavoscero punto nueve nueve
When to use monto_a_letras_b():
  • Invoice systems that prefer literal decimal pronunciation
  • Used for Bolívares amounts in the invoice “MontoEnLetras” field (main.py:149)
  • Simpler output without currency-specific logic

Examples

# Standard usage
monto_a_letras_b(1234.56)
# Output: "mil doscientos treinta y cuatro punto cinco seis"

# Integer amount
monto_a_letras_b(5000)
# Output: "cinco mil"

# Many decimal places
monto_a_letras_b(99.9999)
# Output: "noventa y nueve punto nueve nueve nueve nueve"

# Small decimal
monto_a_letras_b(0.5)
# Output: "cero punto cinco"

Spanish Language Conversion

Both functions use the num2words library with Spanish language support:
from num2words import num2words
num2words(1234, lang='es')
# Returns: "mil doscientos treinta y cuatro"

Number Translation Examples

NumberSpanish WordsNotes
0cero
1uno
15quince
56cincuenta y seis
100cien
101ciento uno”ciento” for 101-199
1000mil
1234mil doscientos treinta y cuatro
1000000un millón
The num2words library handles all Spanish grammar rules including gender agreement, conjunctions (“y”), and special cases like “cien” vs “ciento”.

Integration in Invoice Processing

Both functions are used in the transformar_fila() pipeline:
# Bolívares amount with digit-by-digit decimals (main.py:149)
"MontoEnLetras": monto_a_letras_b(monto_bs)

# USD amount with currency-aware formatting (main.py:184)
"MontoEnLetras": monto_a_letras(monto_usd)

Invoice JSON Output

{
  "Totales": {
    "TotalAPagar": "45625.50",
    "MontoEnLetras": "cuarenta y cinco mil seiscientos veinticinco punto cinco cero"
  },
  "TotalesOtraMoneda": {
    "Moneda": "USD",
    "TotalAPagar": "1250",
    "MontoEnLetras": "mil doscientos cincuenta"
  }
}

Error Handling

Both functions include try-except blocks for robust error handling:

Invalid Input Types

Non-numeric strings, None values, or objects that can’t be converted to float return None

Conversion Failures

If num2words fails or string operations error out, returns None gracefully

Unknown Currency

monto_a_letras() returns "Moneda no reconocida." for unsupported currency types

Null Safety

Both functions handle None, empty strings, and invalid numeric formats without crashing

Best Practices

  • Use monto_a_letras() when you need proper currency terminology and natural decimal reading
  • Use monto_a_letras_b() when you need literal decimal digit pronunciation
  • For multi-currency invoices, use monto_a_letras() with the appropriate currency parameter
  • Always round amounts to 2 decimal places before conversion for consistent results
  • Be aware that monto_a_letras() automatically rounds decimals to cents
  • monto_a_letras_b() preserves trailing zeros in the string representation
  • Only use “dolares” or “bolivares” (lowercase preferred) with monto_a_letras()
  • Implement fallback logic if the currency might be unsupported
  • Consider adding validation before calling the function
  • Always check for None return values before using the result
  • Log conversion failures for debugging invoice processing issues
  • Provide fallback text (e.g., “[Monto inválido]”) in invoice templates

Dependencies

num2words

Python library for converting numbers to words in multiple languages.
pip install num2words
Version: Compatible with num2words >= 0.5.12Documentation: https://github.com/savoirfairelinux/num2words
The num2words library supports 40+ languages. This implementation specifically uses lang='es' for Spanish (Spain and Latin America) conventions.

Build docs developers (and LLMs) love