Skip to content

Currency Configuration Guide

Overview

TQPro uses a centralized currency configuration that controls which currency is used for display, pricing, supplier API calls, and PDF quotation generation. All TripMaker pages, supplier plugins, and backend services read from this single configuration.

Configuration Properties

Primary Configuration: config/tourlinq-config.xml

The main currency settings are in the <AppProperties> section:

<AppProperties>
    <property name="local.currency" value="AED"/>
    <property name="quotation.currencies" value="AED,USD,EUR"/>
</AppProperties>
Property Description Default Example
local.currency The base/display currency for all pricing, cost summaries, and quotations. All supplier prices are converted to this currency when saved. AED USD, EUR, GBP
quotation.currencies Comma-separated list of currencies available in search dropdowns and quotation currency selectors. AED,USD,EUR AED,USD,EUR,GBP,SAR

Plugin Defaults

Each supplier plugin has its own default currency setting that is used when no currency is explicitly passed in the API call. These should generally match local.currency:

Plugin Config File Property Default
Google Flights config/googleflights-client.xml default.currency AED
Tiqets config/tiqets-client.xml tiqets.default.currency AED
Odoo config/tourlinq-config.xml default.currency 130 (Odoo ID)

Example (config/googleflights-client.xml):

<PluginProperties>
    <property name="default.currency" value="AED"/>
</PluginProperties>

Example (config/tiqets-client.xml):

<PluginProperties>
    <property name="tiqets.default.currency" value="AED"/>
</PluginProperties>

Important: When changing local.currency, also update the plugin defaults to match. Otherwise, search results may come back in a different currency than expected.

How Currency Flows Through the System

1. Configuration API

The POST /tlinq-api/common/currencyConfig endpoint reads the central config and returns:

{
    "localCurrency": "AED",
    "quotationCurrencies": ["AED", "USD", "EUR"]
}

Backend: CommonApi.java reads from ClientConfig properties. Frontend: exchange-rate-service.jsloadCurrencyConfig() caches and returns the config.

2. Search Pages (Flights, Hotels)

  • Currency dropdown is populated dynamically from quotationCurrencies
  • Default selection is localCurrency
  • Selected currency is sent to the supplier API
  • Search results display prices in the supplier's response currency

3. Saving Components (Add Flight, Add Hotel, Add Activity)

When a user adds a search result to their itinerary:

  1. The frontend sends the supplier currency and price to the API
  2. The backend (TripMakerFacade) calls the appropriate convert*Currency() method
  3. ExchangeRateHelper fetches live exchange rates from open.er-api.com (1-hour cache)
  4. The original currency and amount are preserved in currency / originalCost* fields
  5. The converted amount (in local.currency) is stored in the baseCost* field

4. Cost Review & PDF Quotation

  • The getCostBreakdown() response includes localCurrency so the frontend knows which currency to display
  • PDF quotation template uses PdfTemplateRenderer.formatCurrency() which adds the currency symbol/code
  • Supported currency symbols: USD ($), EUR (€), GBP (£), INR (₹), AED/SAR (code displayed as-is)

Frontend Integration

Adding Currency Support to a New Page

To use the centralized currency config in a new TripMaker page:

import { loadCurrencyConfig, populateCurrencySelect } from './exchange-rate-service.js';

// In your initialization function:
const currencyConfig = await loadCurrencyConfig();
const localCurrency = currencyConfig.localCurrency || 'AED';

// Populate a <select> dropdown:
populateCurrencySelect('#my_currency_select', currencyConfig);
$('#my_currency_select').val(localCurrency);

// Format amounts with currency code:
const display = `${localCurrency} ${Number(amount).toFixed(2)}`;

Currency Formatting

For the cost review page, use the fmtCurrency() helper in tripmaker-costs.js which maps common currencies to symbols:

// Returns "$ 100.00" for USD, "AED 100.00" for AED, "€ 100.00" for EUR
fmtCurrency(100, 'USD')

For other pages, display amounts with the currency code prefix (e.g., AED 100.00).

Exchange Rate Conversion (Client-Side)

For pages that need currency conversion (e.g., Groups module):

import { fetchRates, convertToLocal, convertFromLocal } from './exchange-rate-service.js';

// Fetch rates (cached 24h in localStorage)
const rates = await fetchRates('AED');

// Convert using group rate config
const localAmount = convertToLocal(100, 'USD', groupRates, 'AED');

Changing the Local Currency

To change the system's local currency (e.g., from AED to USD):

  1. Update config/tourlinq-config.xml:

    <property name="local.currency" value="USD"/>
    <property name="quotation.currencies" value="USD,AED,EUR"/>
    

  2. Update plugin defaults:

  3. config/googleflights-client.xml: <property name="default.currency" value="USD"/>
  4. config/tiqets-client.xml: <property name="tiqets.default.currency" value="USD"/>

  5. Restart the application server

Note: Changing the local currency does NOT retroactively convert existing stored prices. Previously saved flight, hotel, and activity costs remain in whatever currency they were originally converted to. Only new items will use the updated currency.

Database Storage

TripMaker entities store both the original supplier currency and the converted local amount:

Table Currency Column Original Amount Converted Amount
nts.flight_option currency original_cost_per_person base_cost_per_person
nts.accommodation_option currency original_cost_total base_cost_total
nts.activity currency original_cost_total base_cost_total

The currency column stores the original supplier currency code (e.g., USD), while base_cost_* contains the value converted to local.currency.