import { Injectable } from '@angular/core'; import { CurrencyResources } from '@core/resources/currency.resources'; import { CurrencyState } from '@core/states/currency.state'; import currencyFormatting from '@core/static-assets/currency-formatting'; import { ClientSettingsService } from '@features/client-settings/client-settings.service'; import { ArrayHelpersService, MoneyService } from '@yourcause/common'; import { CurrencyFormatting, CurrencyFormattingObj, CurrencyRadioOptions, ExchangeRate, MaskingService } from '@yourcause/common/masking'; import { AttachYCState, BaseYCService } from '@yourcause/common/state'; import { SpinnerService } from './spinner.service'; export const Set_Value_Key_Prefix = 'SET_VALUE_'; @AttachYCState(CurrencyState) @Injectable({ providedIn: 'root' }) export class CurrencyService extends BaseYCService { constructor ( private currencyResources: CurrencyResources, private spinnerService: SpinnerService, private clientSettingsService: ClientSettingsService, private moneyService: MoneyService, private maskingService: MaskingService, private arrayHelper: ArrayHelpersService ) { super(); } get exchangeRateMap () { return this.get('exchangeRateMap'); } get precisionMap () { return this.get('precisionMap'); } get formattingData () { return this.get('formattingData'); } fixNumberOfDecimals ( amount: number, currency = this.clientSettingsService.defaultCurrency ): string { return parseFloat( '' + (Math.round(amount * 100) / 100) ).toFixed( this.precisionMap[currency] ); } formatMoney ( amount: number, currency = this.clientSettingsService.defaultCurrency, showCurrencyAtEnd = false ) { const formatted = this.moneyService.formatMoney( amount, currency as any, this.formattingData[currency] ); return showCurrencyAtEnd ? `${formatted} ${currency}` : formatted; } setPrecisionMap () { if (Object.keys(this.precisionMap).length === 0) { const map: { [x: string]: number; } = {}; Object.keys(this.formattingData).map((key) => { const item = (this.formattingData)[key]; map[key] = item.precision; }); this.set('precisionMap', map); } } setCurrencyFormatting () { if (!this.formattingData) { const { formattingInfo } = currencyFormatting as CurrencyFormatting; const formatted: Record = {}; Object.keys(formattingInfo).forEach((key) => { formatted[key.toUpperCase()] = formattingInfo[key]; }); this.set('formattingData', formatted); this.setPrecisionMap(); } } getCurrencyFormattingData ( currencyCode: string ) { return this.formattingData[currencyCode] || this.formattingData['USD']; } getCurrencyValueForFormGroup ( amount = 0, currency = this.clientSettingsService.defaultCurrency ) { return this.maskingService.maskNumberDecimal( this.fixNumberOfDecimals(amount, currency), this.formattingData[currency] ); } async setExchangeRateMap (base: string) { if (!this.exchangeRateMap[base]) { this.spinnerService.startSpinner(); const rates = await this.currencyResources.getExchangeRates(base); this.spinnerService.stopSpinner(); this.set('exchangeRateMap', { ...this.exchangeRateMap, [base]: rates }); } } async getExchangeRate ( base: string, convertTo: string ): Promise { await this.setExchangeRateMap(base); const rates = this.exchangeRateMap[base]; const found = rates.find((item) => { return item.code === convertTo; }); return found; } /** * Get Currency Options for Component * * @param selectedCurrency: currently selected currency * @param useCustomCurrency: custom currency setting * @param customCurrency: custom currency selected in config * @returns the currency options from the component */ getCurrencyOptionsForComponent ( selectedCurrency: string, useCustomCurrency: CurrencyRadioOptions, customCurrency: string ) { let _currencies = this.clientSettingsService.selectedCurrencies; if (useCustomCurrency === CurrencyRadioOptions.USE_ONE_CURRENCY && customCurrency) { _currencies = [{ displayName: '', code: customCurrency, default: true }]; } if (_currencies.length === 0) { _currencies = [{ displayName: 'US Dollar', code: 'USD', default: true }]; } if (selectedCurrency) { // Make sure selected currency is in list. If not, add it. const mapped = _currencies.map((curr) => { return curr.code; }); if (!mapped.includes(selectedCurrency)) { const found = this.clientSettingsService.currencies.find((curr) => { return curr.code === selectedCurrency; }); if (found) { const selectedCurrencyObj = { displayName: found.displayName, code: found.code, default: true }; _currencies.push(selectedCurrencyObj); } } } return this.arrayHelper.sort(_currencies.map((curr) => { return { label: curr.code, value: curr.code }; }), 'label'); } }