Skip to content

Currency Exchange

Converts supplier prices to market currency when creating offers. Rates are fetched daily from the European Central Bank via Frankfurter API.

The OfferObserver automatically converts land_base_price when:

  1. Offer has a supplier_tour_rate_id (linked to a supplier rate)
  2. Service rate price currency differs from market’s default_currency_code
  3. An exchange rate exists for the currency pair

The source currency is resolved from supplier_service_rate_prices (the actual records that compose the land price), with a fallback to the supplier’s currency.

No conversion occurs if currencies match. Throws an error if currencies differ but no exchange rate exists.

Rates sync daily via scheduler. Manual sync:

Terminal window
# Sync today's rates (base: EUR)
php artisan currency:sync-rates
# Sync specific date
php artisan currency:sync-rates --date=2025-01-15
# Different base currency
php artisan currency:sync-rates --base=USD

Source: backend/app/Console/Commands/SyncExchangeRatesCommand.php

ModelPurpose
CurrencyExchangeRateStores rates with inverse calculation support
CurrencyReference currencies (EUR, USD, GBP, etc.)
SupplierServiceRatePriceStores service price + currency per room type

SupplierObserver: When a supplier’s currency_id changes, cascades the update to all related SupplierTourRateRoomPrice records.

OfferObserver: Converts land_base_price from service rate price currency to market currency during offer creation.

Exchange rates use worksome/exchange package configured in config/exchange.php.

Required: Active currencies must exist in currencies table before syncing.

  • Suppliers - Supplier currency assignment
  • Offers - Offer pricing calculation
  • Source: backend/app/Services/CurrencyExchangeService.php