Workflow

Multi-Currency International Sales

Sell internationally with multiple currencies, localized tax rates, customer-group pricing, and automatic currency conversion for invoicing and payments.

1
Set Up Currencies
2
Localized Pricing
3
Tax per Country
4
Customer Places Order (USD)
5
Convert to Base (EUR)
6
Invoice in Customer Currency
7
Accept Payment (USD)
8
Record in Base Currency

Complete International Sales Workflow

Step 1: Set up exchange rates and localized pricing

import { createServices } from "commercio";

const services = createServices();

// ── Exchange rates ─────────────────────────────────────
// Base currency is EUR
await services.currencyService.createExchangeRate(
  "EUR", "USD", 1.08,
  new Date("2026-01-01"), new Date("2026-12-31")
);
await services.currencyService.createExchangeRate(
  "EUR", "GBP", 0.86,
  new Date("2026-01-01"), new Date("2026-12-31")
);
await services.currencyService.createExchangeRate(
  "EUR", "CHF", 0.97,
  new Date("2026-01-01"), new Date("2026-12-31")
);

// Check supported currencies
const currencies = await services.currencyService.getSupportedCurrencies();
console.log("Supported currencies:", currencies); // ["CHF", "EUR", "GBP", "USD"]

// ── Localized price lists ──────────────────────────────
const eurPrices = await services.pricingService.createPriceList(
  "EU Standard", { currency: "EUR", priority: 1 }
);
const usdPrices = await services.pricingService.createPriceList(
  "US Standard", { currency: "USD", priority: 1 }
);
const gbpPrices = await services.pricingService.createPriceList(
  "UK Standard", { currency: "GBP", priority: 1 }
);

// Set prices per currency (already converted at list level)
await services.pricingService.setPrice(eurPrices.id, laptopId, 129900); // 1299.00 EUR
await services.pricingService.setPrice(usdPrices.id, laptopId, 139900); // 1399.00 USD
await services.pricingService.setPrice(gbpPrices.id, laptopId, 114900); // 1149.00 GBP

// ── Tax rates per country ──────────────────────────────
const vatDE  = await services.taxService.createTaxRate("VAT DE", 19, "DE", { isDefault: true });
const vatUK  = await services.taxService.createTaxRate("VAT UK", 20, "GB", { isDefault: true });
const taxUS  = await services.taxService.createTaxRate("Sales Tax CA", 7.25, "US", { state: "CA" });
const vatCH  = await services.taxService.createTaxRate("VAT CH", 8.1, "CH", { isDefault: true });

Step 2: US customer places an order

// US customer onboarding
const usCustomer = await services.customerService.createCustomer(
  "TechCorp Inc.",
  { street: "500 Market St", city: "San Francisco", postalCode: "94105", country: "US", state: "CA" },
  { email: "orders@techcorp.us", phone: "+1 415 555 0100" },
);

// Get prices in USD for the US customer
const usdLaptopPrice = await services.pricingService.getEffectivePrice(laptopId, {});
// Would return 139900 (from USD price list based on priority/matching)

// Place order with USD prices
const order = await services.orderService.createOrder(usCustomer.id, [
  { productId: laptopId, quantity: 5, unitPrice: 139900 }, // USD
]);

console.log(`Order total: $${(order.totalAmount / 100).toFixed(2)}`); // $6,995.00

Step 3: Convert for internal accounting

// Convert order total from USD to base currency (EUR) for internal records
const conversion = await services.currencyService.convert(
  order.totalAmount, "USD", "EUR"
);

console.log(`Customer pays: $${(order.totalAmount / 100).toFixed(2)} USD`);
console.log(`Internal value: ${(conversion.amount / 100).toFixed(2)} EUR`);
console.log(`Exchange rate: ${conversion.rate}`);

// Also works with inverse rates (no direct USD->EUR needed)
const inverseConversion = await services.currencyService.convertWithInverse(
  order.totalAmount, "USD", "EUR"
);
console.log(`Via inverse: ${(inverseConversion.amount / 100).toFixed(2)} EUR`);

Step 4: Calculate tax & create invoice in customer currency

// Calculate US sales tax (California)
const tax = await services.taxService.calculateTax(taxUS.id, order.totalAmount);
console.log(`Net: $${(tax.netAmount / 100).toFixed(2)}`);
console.log(`Tax (7.25%): $${(tax.taxAmount / 100).toFixed(2)}`);
console.log(`Gross: $${(tax.grossAmount / 100).toFixed(2)}`);

// Create invoice in USD
const dueDate = new Date();
dueDate.setDate(dueDate.getDate() + 30);

const invoice = await services.invoiceService.createInvoice(
  usCustomer.id,
  order.items.map(item => ({
    description: "ThinkPad X1 Carbon",
    productId: item.productId,
    quantity: item.quantity,
    unitPrice: item.unitPrice,
    taxRateId: taxUS.id,
    taxRate: 7.25,
  })),
  dueDate,
  { orderId: order.id, notes: "Currency: USD. California sales tax applied." }
);

await services.invoiceService.sendInvoice(invoice.id);
console.log(`Invoice ${invoice.invoiceNumber} sent (USD)`);

Step 5: Accept payment and record in base currency

// Customer pays in USD via credit card
const payment = await services.paymentService.createPayment(
  order.id, usCustomer.id,
  tax.grossAmount, // pay gross amount including tax
  "CREDIT_CARD",
  { referenceNumber: "STRIPE-pi_3abc123", notes: "Paid in USD" }
);
await services.paymentService.completePayment(payment.id);
await services.invoiceService.recordPayment(invoice.id, tax.grossAmount);

// Convert payment to EUR for accounting
const paymentInEur = await services.currencyService.convert(
  tax.grossAmount, "USD", "EUR"
);

console.log(`Payment received: $${(tax.grossAmount / 100).toFixed(2)} USD`);
console.log(`Booked as: ${(paymentInEur.amount / 100).toFixed(2)} EUR`);

// Audit with currency metadata
await services.auditLogService.log("Payment", payment.id, "CREATE", {
  actor: "payment-gateway",
  newValues: {
    amountUSD: tax.grossAmount,
    amountEUR: paymentInEur.amount,
    exchangeRate: paymentInEur.rate,
  },
  metadata: { gateway: "stripe", currency: "USD" },
});

// ── Compare revenue across currencies ──────────────────
const revenue = await services.reportingService.getRevenueReport();
console.log(`\nTotal revenue (all orders, base currency): ${revenue.totalRevenue} cents`);
console.log(`Total orders: ${revenue.orderCount}`);
console.log(`Average order value: ${revenue.averageOrderValue} cents`);