Systems Library / Finance Automation / How to Build a Multi-Currency Invoicing System
Finance Automation invoicing billing

How to Build a Multi-Currency Invoicing System

Generate invoices in multiple currencies with automatic exchange rate updates.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

International clients need invoices in their currency. I built a multi-currency invoicing system that fetches live exchange rates, converts amounts, generates invoices in the client's preferred currency, and tracks everything in your base currency for accounting.

One system handles USD, EUR, GBP, and any other currency your clients use.

What You Need Before Starting

Step 1: Fetch Live Exchange Rates

import requests
from datetime import datetime

def get_exchange_rates(base_currency="USD"):
    response = requests.get(f"https://api.exchangerate-api.com/v4/latest/{base_currency}")
    data = response.json()
    return {"rates": data["rates"], "fetched_at": datetime.now().isoformat()}

def convert_amount(amount, from_currency, to_currency, rates):
    if from_currency == to_currency:
        return amount
    if from_currency != "USD":
        amount_usd = amount / rates.get(from_currency, 1)
    else:
        amount_usd = amount
    return round(amount_usd * rates.get(to_currency, 1), 2)

Step 2: Configure Client Currencies

CLIENT_CURRENCIES = {
    "acme-uk": {"currency": "GBP", "locale": "en_GB", "symbol": "£"},
    "beta-eu": {"currency": "EUR", "locale": "de_DE", "symbol": "€"},
    "gamma-us": {"currency": "USD", "locale": "en_US", "symbol": "$"},
    "delta-jp": {"currency": "JPY", "locale": "ja_JP", "symbol": "¥"}
}

Step 3: Generate Multi-Currency Invoice

def create_multi_currency_invoice(client_id, items_base_currency, base="USD"):
    client_config = CLIENT_CURRENCIES.get(client_id, {"currency": "USD", "symbol": "$"})
    target = client_config["currency"]
    rates = get_exchange_rates(base)

    converted_items = []
    for item in items_base_currency:
        converted_amount = convert_amount(item["amount"], base, target, rates["rates"])
        converted_items.append({
            **item,
            "original_amount": item["amount"],
            "original_currency": base,
            "display_amount": converted_amount,
            "display_currency": target
        })

    total_base = sum(i["amount"] for i in items_base_currency)
    total_display = sum(i["display_amount"] for i in converted_items)

    return {
        "items": converted_items,
        "total_base": total_base,
        "total_display": total_display,
        "currency": target,
        "symbol": client_config["symbol"],
        "rate_used": rates["rates"].get(target, 1),
        "rate_date": rates["fetched_at"]
    }

Step 4: Store with Dual Currency Tracking

import sqlite3

def store_multi_currency_invoice(conn, invoice_data, client_id):
    conn.execute("""
        INSERT INTO invoices (invoice_number, client_id, amount, display_amount,
            base_currency, display_currency, exchange_rate, rate_date)
        VALUES (?,?,?,?,?,?,?,?)
    """, (invoice_data["number"], client_id, invoice_data["total_base"],
          invoice_data["total_display"], "USD", invoice_data["currency"],
          invoice_data["rate_used"], invoice_data["rate_date"]))
    conn.commit()

Step 5: Reconcile in Base Currency

def reconcile_foreign_payment(conn, invoice_number, payment_amount, payment_currency):
    invoice = conn.execute(
        "SELECT amount, display_amount, display_currency FROM invoices WHERE invoice_number=?",
        (invoice_number,)
    ).fetchone()

    rates = get_exchange_rates("USD")
    payment_base = convert_amount(payment_amount, payment_currency, "USD", rates["rates"])
    variance = abs(payment_base - invoice[0])

    return {
        "expected_base": invoice[0],
        "received_base": payment_base,
        "variance": round(variance, 2),
        "within_tolerance": variance < invoice[0] * 0.02
    }

What to Build Next

Add historical rate locking so the rate at invoice creation is stored and used for reconciliation, not the rate at payment time. Currency fluctuation risk management starts with knowing which rate applies to which transaction.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems