public void SetUp() { var expenseItem = new ExpenseLineItem(1, "Somu", 234); _items.Add(expenseItem); _expenseCalculatorFactory = new ExpenseCalculatorFactory(_items); }
public void SetUp() { var expenseItem1 = new ExpenseLineItem(1, "Somu", 234); var expenseItem2 = new ExpenseLineItem(2, "Somu1", 455); var expenseItem3 = new ExpenseLineItem(1, "Somu", 343); _items.Add(expenseItem1); _items.Add(expenseItem2); _items.Add(expenseItem3); _moqExpenseCalculatorFactory = new Mock <IExpenseCalculatorFactory>(); _moqExpenseCalculatorFactory.Setup(x => x.CreateExpenseCalculator()).Returns(new ExpenseCalculator(_items)); }
public ExpenseRepaymentCollection Post([FromBody] IEnumerable <User> users) { if (users == null || !users.Any() || users.All(u => !u.Expenses.Any())) { // empty result passed ThrowResponseException(HttpStatusCode.BadRequest, "Empty list of users entered"); } if (users.SelectMany(u => u.Expenses).Any(exp => exp < 0)) { // one or more expenses has a negative amount ThrowResponseException(HttpStatusCode.BadRequest, "One or more Expense line items have a negative expense amount"); } ExpenseRepaymentCollection result = new ExpenseRepaymentCollection(); // Flatten list into 1 expense line item per name, with their total expenditure var totalExpenses = users.GroupBy(u => u.Name) .Select(x => new ExpenseLineItem() { Name = x.Key, ExpenseAmount = x.SelectMany(y => y.Expenses).Sum() } ).ToList(); decimal totalExpenditure = 0; try { totalExpenditure = totalExpenses.Sum(e => e.ExpenseAmount); } catch (OverflowException) { ThrowResponseException(HttpStatusCode.BadRequest, "Expenses entered are total greater than maximum precision"); } if (totalExpenditure == 0) { return(result); } decimal equalShares = totalExpenditure / totalExpenses.Count; if (totalExpenses.All(e => e.EqualWithinOneCent(equalShares))) { // All users have already paid equally, no repayments need to be done return(result); } //Because we only ever need to look at the front of the line, a stack is more efficient Stack <ExpenseLineItem> paidMoreThanEqual = new Stack <ExpenseLineItem>(totalExpenses.Where(e => e.ExpenseAmount > equalShares)); Stack <ExpenseLineItem> paidLessThanEqual = new Stack <ExpenseLineItem>(totalExpenses.Where(e => e.ExpenseAmount < equalShares)); List <ExpenseRepayment> repayments = new List <ExpenseRepayment>(); while (paidMoreThanEqual.Any() && paidLessThanEqual.Any()) { ExpenseLineItem currentUnderpayer = paidLessThanEqual.Peek(); ExpenseLineItem currentOverpayer = paidMoreThanEqual.Peek(); decimal amountToPay = Math.Min(currentOverpayer.ExpenseAmount - equalShares, equalShares - currentUnderpayer.ExpenseAmount); repayments.Add(new ExpenseRepayment() { PayFrom = currentUnderpayer.Name, PayTo = currentOverpayer.Name, Amout = amountToPay }); currentOverpayer.ExpenseAmount -= amountToPay; currentUnderpayer.ExpenseAmount += amountToPay; if (currentUnderpayer.EqualWithinOneCent(equalShares)) { paidLessThanEqual.Pop(); } if (currentOverpayer.EqualWithinOneCent(equalShares)) { paidMoreThanEqual.Pop(); } } result.Repayments = repayments.ToArray(); result.Status = (byte)(result.Repayments.Any() ? 1 : 0); return(result); }
private static void InsertExpensive() { var item = new ExpenseLineItem { Amount = 3000, Description = "Expensive Item" }; var expense = new Expense { Description = "Expensive Description", Title = "Expensive Title" }; expense.AddLineItem(item); using (var uow = new UnitOfWork()) { var repository = uow.GetRepository<ExpenseRepository>(); repository.Save(expense); uow.Commit(); } }
private static void InsertWithItems() { var item1 = new ExpenseLineItem { Amount = 10, Description = "Item 1" }; var item2 = new ExpenseLineItem { Amount = 300, Description = "Item 2" }; var expense = new Expense { Description = "Expense", Title = "Title" }; expense.AddLineItem(item1); expense.AddLineItem(item2); using (var uow = new UnitOfWork()) { var repository = uow.GetRepository<ExpenseRepository>(); repository.Save(expense); uow.Commit(); } }