Exemple #1
0
        public IEnumerable <Debt> GetDebts(IEnumerable <Action> actions)
        {
            if (actions?.Any() != true)
            {
                return(Enumerable.Empty <Debt>());
            }

            var debtAggregator = new DebtAggregator();

            foreach (var action in actions.OrderBy(a => a.Date))
            {
                var totalAmountPaid = action.Sponsors.Sum(s => s.Amount);
                var payersDict      = action.Goods
                                      .SelectMany(good => good.Consumers)
                                      .ToLookup(consumer => consumer.Participant)
                                      .ToDictionary(p => p.Key, p => p.Sum(consumer => consumer.Amount));

                foreach (var sponsor in action.Sponsors)
                {
                    var sponsorRate = sponsor.Amount / totalAmountPaid;

                    foreach (var pair in payersDict.Where(pair => pair.Key != sponsor.Participant))
                    {
                        var consumer        = pair.Key;
                        var amount          = pair.Value;
                        var debtAmount      = Math.Round(amount * sponsorRate, 2);
                        var debtTransaction = new DebtTransaction(debtAmount, action.Description, action.Date);
                        debtAggregator.AddTransaction(sponsor.Participant, consumer, debtTransaction);
                    }
                }
            }
            return(debtAggregator.GetDebts().Where(totalDebt => totalDebt.Amount != 0));
        }
        public void AddTransaction(string creditor, string debtor, DebtTransaction transaction)
        {
            if ((transaction?.Amount ?? 0m) < 0m)
            {
                throw new ArgumentException($"Cannot add transaction: amount must be > 0 but was {transaction?.Amount}.");
            }
            if (creditor.IsNullOrWhiteSpace() || debtor.IsNullOrWhiteSpace())
            {
                throw new ArgumentException($"Cannot add transaction: creditor = [{creditor}], debtor = [{debtor}].");
            }
            if ((transaction?.Amount ?? 0m) == 0m)
            {
                return;
            }

            var key = new DebtAggregatorKey(creditor, debtor);

            if (!debts.ContainsKey(key))
            {
                debts.Add(key, new Debt {
                    Creditor = creditor, Debtor = debtor
                });
            }

            var debt = debts[key];

            if (key.Creditor == debt.Creditor)
            {
                debt.Transactions.Add(transaction);
            }
            else
            {
                debt.Transactions.Add(transaction.Reverse());
                if (debt.Amount < 0)
                {
                    debts[key] = debt.Reverse();
                }
                else if (debt.Amount == 0)
                {
                    debts.Remove(key);
                }
            }
        }