static void Main(string[] args)
        {
            try
            {
                IEnumerable <IFeesCalculationRule>     feesCalculationInstances     = GetInstancesOfFeesCalculationRules.GetRulesInstances();
                IEnumerable <IDiscountCalculationRule> discountCalculationInstances = GetInstancesOfDiscountCalculationRules.GetRulesInstances();

                //get all transactions
                var transactions = TransactionRepository
                                   .GetAllTransactions()
                                   .OrderByDescending(x => x.date)
                                   .ThenBy(x => x.merchantName)
                                   .ToList();

                // get list of discounts for merchants
                Dictionary <string, decimal> discountsForMerchants = DiscountsForMerchants.GetDiscounts();

                while (transactions.Any())
                {
                    var firstTransaction = transactions.First();

                    //get transactions by merchant's name and month
                    var filteredTransactionsByFirstTransaction =
                        TransactionRepository.GetFilteredTransactionsByDateAndMerchant(firstTransaction.merchantName, firstTransaction.date);

                    //get fee model
                    var feeModel = CalculateFees.CalculateFee(
                        filteredTransactionsByFirstTransaction,
                        feesCalculationInstances,
                        discountCalculationInstances,
                        discountsForMerchants);

                    feeModel.merchantName = firstTransaction.merchantName;
                    feeModel.date         = firstTransaction.date;

                    var feeWithDiscount = feeModel.feesAmount - feeModel.discountAmount + feeModel.additionalFeesAmount;

                    Console.WriteLine($"{feeModel.date.ToString("yyyy-MM"),10}" +
                                      $"{feeModel.merchantName,15}" +
                                      $"{string.Format("{0:0.00}", feeWithDiscount).Replace(',', '.'),10}");

                    // remove processed transactions from list
                    transactions = transactions.Except(filteredTransactionsByFirstTransaction).ToList();
                }
                Console.ReadLine();
            }
            catch (InvalidFileException)
            {
                Console.WriteLine("Error reading from file...");
                Console.ReadLine();
            }
            catch (Exception)
            {
                Console.WriteLine("Error...");
                Console.ReadLine();
            }
        }
        public void ValidateFeeCalculation()
        {
            var dispatcher = new Dispachers.MessageDispatcher();
            var order      = new Order()
            {
                TicketCount = 4, Subtotal = 50.0M
            };
            var message = new CalculateFees()
            {
                Order = order
            };

            var feeManager = new BasicFeeManager(dispatcher);

            dispatcher.Subscribe <CalculateFees>(feeManager);

            dispatcher.Publish(message);

            Assert.AreEqual(5.0M, order.Fees);
        }
        public void CalculateFeeTest_WithDiscount()
        {
            //Arange
            var merchantName = "TELIA";
            List <TransactionModel> transactions = new List <TransactionModel>()
            {
                new TransactionModel()
                {
                    date = new System.DateTime(2018, 10, 02), merchantName = merchantName, transactionAmount = 300
                },
                new TransactionModel()
                {
                    date = new System.DateTime(2018, 10, 03), merchantName = merchantName, transactionAmount = 150
                }
            };

            //Act
            var feeModel = CalculateFees.CalculateFee(transactions, feesCalculationInstances, discountCalculationInstances, discountsForMerchants);

            //Assert
            Assert.AreEqual(feeModel.feesAmount, 4.5m);
            Assert.AreEqual(feeModel.additionalFeesAmount, 29m);
            Assert.AreEqual(feeModel.discountAmount, 0.45m);
        }