using Nop.Core; using Nop.Core.Domain.Directory; using Nop.Data; using Nop.Services.Stores; namespace Nop.Services.Directory; /// /// Currency service /// public partial class CurrencyService : ICurrencyService { #region Fields protected readonly CurrencySettings _currencySettings; protected readonly IExchangeRatePluginManager _exchangeRatePluginManager; protected readonly IRepository _currencyRepository; protected readonly IStoreMappingService _storeMappingService; #endregion #region Ctor public CurrencyService(CurrencySettings currencySettings, IExchangeRatePluginManager exchangeRatePluginManager, IRepository currencyRepository, IStoreMappingService storeMappingService) { _currencySettings = currencySettings; _exchangeRatePluginManager = exchangeRatePluginManager; _currencyRepository = currencyRepository; _storeMappingService = storeMappingService; } #endregion #region Methods #region Currency /// /// Deletes currency /// /// Currency /// A task that represents the asynchronous operation public virtual async Task DeleteCurrencyAsync(Currency currency) { await _currencyRepository.DeleteAsync(currency); } /// /// Gets a currency /// /// Currency identifier /// /// A task that represents the asynchronous operation /// The task result contains the currency /// public virtual async Task GetCurrencyByIdAsync(int currencyId) { return await _currencyRepository.GetByIdAsync(currencyId, cache => default); } /// /// Gets a currency by code /// /// Currency code /// /// A task that represents the asynchronous operation /// The task result contains the currency /// public virtual async Task GetCurrencyByCodeAsync(string currencyCode) { if (string.IsNullOrEmpty(currencyCode)) return null; return (await GetAllCurrenciesAsync(true)) .FirstOrDefault(c => c.CurrencyCode.ToLowerInvariant() == currencyCode.ToLowerInvariant()); } /// /// Gets all currencies /// /// A value indicating whether to show hidden records /// Load records allowed only in a specified store; pass 0 to load all records /// /// A task that represents the asynchronous operation /// The task result contains the currencies /// public virtual async Task> GetAllCurrenciesAsync(bool showHidden = false, int storeId = 0) { var currencies = await _currencyRepository.GetAllAsync(query => { if (!showHidden) query = query.Where(c => c.Published); query = query.OrderBy(c => c.DisplayOrder).ThenBy(c => c.Id); return query; }, cache => cache.PrepareKeyForDefaultCache(NopDirectoryDefaults.CurrenciesAllCacheKey, showHidden)); //store mapping if (storeId > 0) currencies = await currencies .WhereAwait(async c => await _storeMappingService.AuthorizeAsync(c, storeId)) .ToListAsync(); return currencies; } /// /// Inserts a currency /// /// Currency /// A task that represents the asynchronous operation public virtual async Task InsertCurrencyAsync(Currency currency) { await _currencyRepository.InsertAsync(currency); } /// /// Updates the currency /// /// Currency /// A task that represents the asynchronous operation public virtual async Task UpdateCurrencyAsync(Currency currency) { await _currencyRepository.UpdateAsync(currency); } #endregion #region Conversions /// /// Gets live rates regarding the passed currency /// /// Currency code; pass null to use primary exchange rate currency /// /// A task that represents the asynchronous operation /// The task result contains the exchange rates /// public virtual async Task> GetCurrencyLiveRatesAsync(string currencyCode = null) { var exchangeRateProvider = await _exchangeRatePluginManager.LoadPrimaryPluginAsync() ?? throw new Exception("Active exchange rate provider cannot be loaded"); currencyCode ??= (await GetCurrencyByIdAsync(_currencySettings.PrimaryExchangeRateCurrencyId))?.CurrencyCode ?? throw new NopException("Primary exchange rate currency is not set"); return await exchangeRateProvider.GetCurrencyLiveRatesAsync(currencyCode); } /// /// Converts currency /// /// Amount /// Currency exchange rate /// Converted value public virtual decimal ConvertCurrency(decimal amount, decimal exchangeRate) { if (amount != decimal.Zero && exchangeRate != decimal.Zero) return amount * exchangeRate; return decimal.Zero; } /// /// Converts to primary store currency /// /// Amount /// Source currency code /// /// A task that represents the asynchronous operation /// The task result contains the converted value /// public virtual async Task ConvertToPrimaryStoreCurrencyAsync(decimal amount, Currency sourceCurrencyCode) { ArgumentNullException.ThrowIfNull(sourceCurrencyCode); var primaryStoreCurrency = await GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId); var result = await ConvertCurrencyAsync(amount, sourceCurrencyCode, primaryStoreCurrency); return result; } /// /// Converts from primary store currency /// /// Amount /// Target currency code /// /// A task that represents the asynchronous operation /// The task result contains the converted value /// public virtual async Task ConvertFromPrimaryStoreCurrencyAsync(decimal amount, Currency targetCurrencyCode) { var primaryStoreCurrency = await GetCurrencyByIdAsync(_currencySettings.PrimaryStoreCurrencyId); var result = await ConvertCurrencyAsync(amount, primaryStoreCurrency, targetCurrencyCode); return result; } /// /// Converts currency /// /// Amount /// Source currency code /// Target currency code /// /// A task that represents the asynchronous operation /// The task result contains the converted value /// public virtual async Task ConvertCurrencyAsync(decimal amount, Currency sourceCurrencyCode, Currency targetCurrencyCode) { ArgumentNullException.ThrowIfNull(sourceCurrencyCode); ArgumentNullException.ThrowIfNull(targetCurrencyCode); var result = amount; if (result == decimal.Zero || sourceCurrencyCode.Id == targetCurrencyCode.Id) return result; result = await ConvertToPrimaryExchangeRateCurrencyAsync(result, sourceCurrencyCode); result = await ConvertFromPrimaryExchangeRateCurrencyAsync(result, targetCurrencyCode); return result; } /// /// Converts to primary exchange rate currency /// /// Amount /// Source currency code /// /// A task that represents the asynchronous operation /// The task result contains the converted value /// public virtual async Task ConvertToPrimaryExchangeRateCurrencyAsync(decimal amount, Currency sourceCurrencyCode) { ArgumentNullException.ThrowIfNull(sourceCurrencyCode); var primaryExchangeRateCurrency = await GetCurrencyByIdAsync(_currencySettings.PrimaryExchangeRateCurrencyId) ?? throw new Exception("Primary exchange rate currency cannot be loaded"); var result = amount; if (result == decimal.Zero || sourceCurrencyCode.Id == primaryExchangeRateCurrency.Id) return result; var exchangeRate = sourceCurrencyCode.Rate; if (exchangeRate == decimal.Zero) throw new NopException($"Exchange rate not found for currency [{sourceCurrencyCode.Name}]"); result /= exchangeRate; return result; } /// /// Converts from primary exchange rate currency /// /// Amount /// Target currency code /// /// A task that represents the asynchronous operation /// The task result contains the converted value /// public virtual async Task ConvertFromPrimaryExchangeRateCurrencyAsync(decimal amount, Currency targetCurrencyCode) { ArgumentNullException.ThrowIfNull(targetCurrencyCode); var primaryExchangeRateCurrency = await GetCurrencyByIdAsync(_currencySettings.PrimaryExchangeRateCurrencyId) ?? throw new Exception("Primary exchange rate currency cannot be loaded"); var result = amount; if (result == decimal.Zero || targetCurrencyCode.Id == primaryExchangeRateCurrency.Id) return result; var exchangeRate = targetCurrencyCode.Rate; if (exchangeRate == decimal.Zero) throw new NopException($"Exchange rate not found for currency [{targetCurrencyCode.Name}]"); result *= exchangeRate; return result; } #endregion #endregion }