Esempio n. 1
0
        public async Task <List <TransactionsDTO> > GetTransactionsBySKUinEuro(string SKU)
        {
            //I'm understanding that this method will be called after getting rates and transactions.
            //That's the reason why I'm reading first from DB, to avoid make 2 requests to the URL that provides data.
            try
            {
                //Get rates, first from DB, if there is not data, go to URL
                var rates = _ratesRepository.FindAll().Select(x => DTOMapper.Rate_To_RateDTO(x)).ToList();
                if (!rates.Any())
                {
                    rates = await GetRates();
                }

                var euroRates = GetToEuroRates(rates.ToList());

                //Get Transactions filtering by SKU, first from DB, if there is not data, go to URL
                var transactions = _transactionsRepository.FindAll(x => x.SKU == SKU).Select(x => DTOMapper.Transaction_To_TransactionDTO(x)).ToList();
                if (!transactions.Any())
                {
                    transactions = await GetTransactions();

                    transactions = transactions.ToList().Where(x => x.SKU == SKU).ToList() ?? new List <TransactionsDTO>();
                }

                if (!transactions.Any())
                {
                    //TODO: Add constants or resources file to avoid hardcoded strings
                    LoggerHelper.LogError("There are not transactions for the required SKU");
                }
                else
                {
                    foreach (var trans in transactions.Where(x => x.Currency != "EUR"))
                    {
                        var rate = euroRates.FirstOrDefault(x => x.From == trans.Currency);
                        if (rate != null)
                        {
                            trans.Amount   = RounderHelper.RoundToBankersRounding(trans.Amount * rate.Rate);
                            trans.Currency = "EUR";
                        }
                    }
                }

                return(transactions.ToList());
            }
            catch (Exception ex)
            {
                LoggerHelper.LogError(ex.ToString());
                return(new List <TransactionsDTO>());
            }
        }
        public async Task <JsonResult> Get(string SKU)
        {
            var transactionsInEuro = await TransactionsWorker.GetTransactionsBySKUinEuro(SKU);

            List <object> result = new List <object>();

            if (transactionsInEuro.Any())
            {
                result.Add(transactionsInEuro);
                result.Add(new
                {
                    SKU          = SKU,
                    Total_Amount = RounderHelper.RoundToBankersRounding(transactionsInEuro.Sum(x => x.Amount))
                });
            }
            else
            {
                result.Add(new { Message = "There are not transactions for the requested SKU!" });
            }

            return(new JsonResult(result));
        }
Esempio n. 3
0
        private List <RatesDTO> GetToEuroRates(List <RatesDTO> lRates)
        {
            List <RatesDTO> conversedRates = new List <RatesDTO>();

            try
            {
                List <string> currencies = new List <string>();

                //Add to a list the different currencies
                currencies.AddRange(lRates.Select(x => x.From).Distinct());
                currencies.AddRange(lRates.Select(x => x.To).Distinct());
                currencies = currencies.Where(x => x != "EUR").Distinct().ToList();

                //Find direct conversions that we already have
                foreach (var currency in currencies)
                {
                    conversedRates.AddRange(lRates.Where(x => x.From == currency && x.To == "EUR"));
                }

                //Add to a new list the pending currencies which still doesn't have a conversion to EUR
                var pendingCurrencies = currencies.Except(conversedRates.Select(x => x.From)).ToList();

                //Simple (and dirty) control to avoid possible infinite loop if can't find conversions
                var maxRetry = 10;
                var counter  = 0;

                while (pendingCurrencies.Any() && counter < maxRetry)
                {
                    counter++;

                    foreach (var currency in pendingCurrencies)
                    {
                        //find a indirect conversion
                        var      currencyConversions = lRates.Where(x => x.From == currency).ToList();
                        var      indirectConversion  = new RatesDTO();
                        RatesDTO usedRate            = null;

                        foreach (var item in currencyConversions)
                        {
                            if ((indirectConversion = conversedRates.FirstOrDefault(x => x.From == item.To)) != null)
                            {
                                usedRate = item;
                                break;
                            }
                        }

                        //Use the indirect conversion to calculate the EUR conversion
                        if (usedRate != null)
                        {
                            conversedRates.Add(new RatesDTO
                            {
                                From = currency,
                                To   = "EUR",
                                Rate = RounderHelper.RoundToBankersRounding(usedRate.Rate * indirectConversion.Rate)
                            });

                            pendingCurrencies = pendingCurrencies.Except(conversedRates.Select(x => x.From)).ToList();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LoggerHelper.LogError(ex.ToString());
            }

            return(conversedRates);
        }