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):
Example (config/tiqets-client.xml):
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:
Backend: CommonApi.java reads from ClientConfig properties.
Frontend: exchange-rate-service.js → loadCurrencyConfig() 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:
- The frontend sends the supplier currency and price to the API
- The backend (
TripMakerFacade) calls the appropriateconvert*Currency()method ExchangeRateHelperfetches live exchange rates fromopen.er-api.com(1-hour cache)- The original currency and amount are preserved in
currency/originalCost*fields - The converted amount (in
local.currency) is stored in thebaseCost*field
4. Cost Review & PDF Quotation¶
- The
getCostBreakdown()response includeslocalCurrencyso 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:
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):
-
Update
config/tourlinq-config.xml: -
Update plugin defaults:
config/googleflights-client.xml:<property name="default.currency" value="USD"/>-
config/tiqets-client.xml:<property name="tiqets.default.currency" value="USD"/> -
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.