Beispiel #1
0
        public async Task AddExpense_WhenAddingDuplicatedExpenseWithoutComment_ShouldThrowAnExceptionWithTheCorrectErrorCode()
        {
            // Arrange
            var dtoExpense1 = new DTOExpense()
            {
                Amount = (decimal)1457.23, Category = "Restaurant", Comment = "A comment", Currency = "USD", PurchasedOn = this.currentTime.AddDays(-1), UserId = anthonyUser.Id
            };

            await this.expensesService.AddExpense(dtoExpense1);

            var dtoExpense2 = new DTOExpense()
            {
                Amount = (decimal)1457.23, Category = "Restaurant", Comment = "", Currency = "USD", PurchasedOn = this.currentTime.AddDays(-1), UserId = anthonyUser.Id
            };

            // Act
            Func <Task> addExpense = () => this.expensesService.AddExpense(dtoExpense2);

            // Assert
            ExpenseValidationException ex = await Assert.ThrowsAsync <ExpenseValidationException>(addExpense);

            var errorCodes = ex.GetErrorCodes();

            errorCodes.Should().HaveCount(2);
            errorCodes.Should().Contain(ExpenseErrorCode.DuplicatedExpense);
            errorCodes.Should().Contain(ExpenseErrorCode.CommentIsMandatory);
        }
Beispiel #2
0
 public Expenses(DTOExpense dtoExpense)
     : this()
 {
     // TODO use a mapper
     this.UserId      = dtoExpense.UserId;
     this.PurchasedOn = dtoExpense.PurchasedOn;
     this.Currency    = dtoExpense.Currency;
     this.Comment     = dtoExpense.Comment;
     this.Category    = (ExpenseCategory)Enum.Parse(typeof(ExpenseCategory), dtoExpense.Category);
     this.Amount      = dtoExpense.Amount;
 }
Beispiel #3
0
        public async Task <DTOExpense> AddExpense(DTOExpense dtoExpense)
        {
            using (LuccaContext context = this.serviceProvider.GetService <LuccaContext>())
            {
                this.ThrowIfExpenseInvalid(context, dtoExpense);

                var expenseToAdd = new Expenses(dtoExpense);
                context.Expenses.Add(expenseToAdd);

                await context.SaveChangesAsync();

                return(expenseToAdd.ToDTOExpense(context));
            }
        }
Beispiel #4
0
        public async Task AddExpense_WhenWellConfigured_ShouldNotThrowAnException()
        {
            // Arrange
            var dtoExpense = new DTOExpense()
            {
                Amount = (decimal)1457.23, Category = "Restaurant", Comment = "A comment", Currency = "USD", PurchasedOn = this.currentTime.AddDays(-1), UserId = anthonyUser.Id
            };

            // Act
            await this.expensesService.AddExpense(dtoExpense);

            // Assert
            var expenses = await this.expensesService.GetExpenses(new ExpensesQuery());

            expenses.Should().HaveCount(1);
        }
Beispiel #5
0
        private void ThrowIfExpenseInvalid(LuccaContext context, DTOExpense expense)
        {
            var errors = new Dictionary <ExpenseErrorCode, string>();

            if (expense.PurchasedOn > this.timeService.GetCurrentUtcTime())
            {
                errors.Add(ExpenseErrorCode.PurchaseInFuture, $"Expense cannot be recorded for this date {expense.PurchasedOn}");
            }
            else if (DateTime.UtcNow - expense.PurchasedOn > TimeSpan.FromDays(90))
            {
                errors.Add(ExpenseErrorCode.PurchaseMoreThan3MonthOld, $"The expense is older than 90 days: {expense.PurchasedOn}");
            }

            if (string.IsNullOrEmpty(expense.Comment))
            {
                errors.Add(ExpenseErrorCode.CommentIsMandatory, $"The expense comment is mandatory");
            }

            var user = context.UserInfo.Where(user => user.Id == expense.UserId).FirstOrDefault();

            if (user == null)
            {
                errors.Add(ExpenseErrorCode.UserNotFound, $"The user {expense.UserId} cannot be found");
            }
            else
            {
                var userExpenses = context.Expenses.Where(exp => exp.UserId == expense.UserId);
                if (userExpenses.Any(exp => exp.PurchasedOn == expense.PurchasedOn && exp.Amount == expense.Amount))
                {
                    errors.Add(ExpenseErrorCode.DuplicatedExpense, $"The expense purchased on {expense.PurchasedOn} with an amount of {expense.Amount} seems already recorded.");
                }

                if (expense.Currency != user.Currency)
                {
                    errors.Add(ExpenseErrorCode.ExpenseCurrencyDifferentThanUserCurrency, $"The expense currency {expense.Currency} should be the same than the user currency {user.Currency}");
                }
            }

            if (errors.Any())
            {
                throw new ExpenseValidationException(errors);
            }
        }
Beispiel #6
0
        public async Task AddExpense_WhenPurchaseMoreThan3MonthAgo_ShouldThrowAnExceptionWithTheCorrectErrorCode()
        {
            // Arrange
            var dtoExpense = new DTOExpense()
            {
                Amount = (decimal)10.23, Category = "Restaurant", Comment = "A comment", Currency = "USD", PurchasedOn = this.currentTime.AddDays(-100), UserId = anthonyUser.Id
            };

            // Act
            Func <Task> addExpense = () => this.expensesService.AddExpense(dtoExpense);

            // Assert
            ExpenseValidationException ex = await Assert.ThrowsAsync <ExpenseValidationException>(addExpense);

            var errorCodes = ex.GetErrorCodes();

            errorCodes.Should().HaveCount(1);
            errorCodes.First().Should().Be(ExpenseErrorCode.PurchaseMoreThan3MonthOld);
        }
Beispiel #7
0
        public async Task <ActionResult <DTOExpense> > PostExpenses(DTOExpense expense)
        {
            var expenseAdded = await this.expensesService.AddExpense(expense);

            return(expenseAdded);
        }