All files / libs/tenants/companies/currency-rates/core/src/lib currencyRates.service.ts

54.65% Statements 47/86
33.33% Branches 2/6
66.66% Functions 2/3
54.65% Lines 47/86

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 871x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x                                                 1x 1x                               1x  
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
 
import { type Company } from '@amalia/core/models';
import { dayjs } from '@amalia/ext/dayjs';
import { type CurrencySymbolsEnum } from '@amalia/ext/iso-4217';
 
import { CompanyCurrenciesService } from './companyCurrencies/companyCurrencies.service';
import { CurrenciesService } from './currencies.service';
 
/**
 * Service company currency.
 */
@Injectable()
export class CurrencyRatesService {
  private readonly logger = new Logger(CurrencyRatesService.name);
 
  public constructor(
    private readonly companyCurrenciesService: CompanyCurrenciesService,
    private readonly currencyService: CurrenciesService,
  ) {}
 
  /**
   * Find company currency rate by currency symbol and date
   * @param company company
   * @param currencySymbol currency symbol
   * @param date date
   */
  public async findCurrencyRate(company: Company, currencySymbol: CurrencySymbolsEnum, date?: number): Promise<number> {
    const currencyRateDate = date || dayjs().unix();
 
    // Check if company manages its own currency rates.
    const companyRate = await this.companyCurrenciesService.find(
      company,
      null,
      currencySymbol,
      null,
      null,
      dayjs(currencyRateDate, 'X').format('YYYY-MM-DD'),
    );
 
    // If we found an overwritten currency for this period, return it now.
    if (companyRate.length) {
      return companyRate[0].rate;
    }

    // Else return the default currency.
    let currencyRatesForDate;
    try {
      currencyRatesForDate = await this.currencyService.findCurrencyByDate(company, date);
    } catch {
      // If currency was not found, it will be refreshed next line
    }

    if (!currencyRatesForDate) {
      this.logger.warn('Currency rate not found, we must refresh.');

      await this.currencyService.refreshCurrency(company, dayjs(currencyRateDate, 'X').format('YYYY-MM-DD'));

      // Now we should have it.
      currencyRatesForDate = await this.currencyService.findCurrencyByDate(company, date);
    }

    if (!currencyRatesForDate.rates[currencySymbol]) {
      throw new NotFoundException(`No rate found for ${currencySymbol}`);
    }

    return currencyRatesForDate.rates[currencySymbol];
  }
 
  public async findAllCurrencyRates(company: Company, date: number): Promise<Record<CurrencySymbolsEnum, number>> {
    const currenciesOfPeriod = await this.currencyService.findCurrencyByDate(company, date);

    const companyCurrenciesOfPeriod = await this.companyCurrenciesService.find(company, currenciesOfPeriod.id, null);

    return {
      ...currenciesOfPeriod.rates,
      ...companyCurrenciesOfPeriod.reduce(
        (acc, curr) => {
          acc[curr.symbol] = curr.rate;
          return acc;
        },
        {} as Record<CurrencySymbolsEnum, number>,
      ),
    };
  }
}