/// <summary>
        ///     Save a new payment or update an existin one.
        /// </summary>
        /// <param name="payment">item to save</param>
        public void Save(Payment payment)
        {
            if (payment.ChargedAccountId == 0)
            {
                throw new AccountMissingException("charged accout is missing");
            }

            payment.IsCleared = payment.ClearPaymentNow;

            //delete recurring payment if isRecurring is no longer set.
            if (!payment.IsRecurring && payment.RecurringPaymentId != 0)
            {
                recurringDataAccess.DeleteItem(payment.RecurringPayment);
                payment.RecurringPaymentId = 0;
            }

            if (payment.Id == 0)
            {
                data.Add(payment);
            }
            if (dataAccess.SaveItem(payment))
            {
                SettingsHelper.LastDatabaseUpdate = DateTime.Now;
            }
            else
            {
                notificationService.SendBasicNotification(Strings.ErrorTitleSave, Strings.ErrorMessageSave);
            }
        }
        private void Edit(Payment payment)
        {
            paymentRepository.Selected = payment;

            ShowViewModel<ModifyPaymentViewModel>(
                new {isEdit = true, typeString = payment.Type.ToString()});
        }
        public void GetRecurringFromPayment_WeeklyEndlessExpense()
        {
            var startDate = new DateTime(2015, 03, 12);
            var enddate = Convert.ToDateTime("7.8.2016");

            var payment = new Payment
            {
                ChargedAccount = new Account {Id = 3},
                TargetAccount = new Account {Id = 8},
                Category = new Category {Id = 16},
                Date = startDate,
                Amount = 2135,
                IsCleared = false,
                Type = (int) PaymentType.Expense,
                IsRecurring = true
            };

            var recurring = RecurringPaymentHelper.GetRecurringFromPayment(payment, true,
                (int) PaymentRecurrence.Weekly, enddate);

            recurring.ChargedAccount.Id.ShouldBe(3);
            recurring.TargetAccount.Id.ShouldBe(8);
            recurring.StartDate.ShouldBe(startDate);
            recurring.EndDate.ShouldBe(enddate);
            recurring.IsEndless.ShouldBe(true);
            recurring.Amount.ShouldBe(payment.Amount);
            recurring.Category.Id.ShouldBe(payment.Category.Id);
            recurring.Type.ShouldBe((int) PaymentType.Expense);
            recurring.Recurrence.ShouldBe((int) PaymentRecurrence.Weekly);
            recurring.Note.ShouldBe(payment.Note);
        }
        public void CheckRecurringPayments_Daily_CorrectPaymentsCreated()
        {
            //Setup
            var sqliteConnector = new SqliteConnectionCreator(new WindowsSqliteConnectionFactory(), 
                new MvxWindowsCommonFileStore());

            var accountRepo = new AccountRepository(new AccountDataAccess(sqliteConnector));

            var paymentRepo = new PaymentRepository(new PaymentDataAccess(sqliteConnector),
                new RecurringPaymentDataAccess(sqliteConnector),
                accountRepo,
                new CategoryRepository(new CategoryDataAccess(sqliteConnector)));

            var account = new Account
            {
                Name = "test1",
                CurrentBalance = 100
            };

            accountRepo.Save(account);

            var payment = new Payment
            {
                ChargedAccount = account,
                Amount = 10,
                Date = DateTime.Today.AddDays(-1),
                IsRecurring = true
            };

            payment.RecurringPayment =
                RecurringPaymentHelper.
                    GetRecurringFromPayment(payment,
                        true,
                        (int) PaymentRecurrence.Daily,
                        DateTime.Now.AddYears(1));

            paymentRepo.Save(payment);

            //Execution
            new RecurringPaymentManager(paymentRepo, accountRepo).CheckRecurringPayments();

            //Assert
            Assert.AreEqual(90, account.CurrentBalance);
            Assert.AreEqual(90, accountRepo.Data[0].CurrentBalance);

            Assert.AreEqual(2, paymentRepo.Data.Count);

            Assert.IsTrue(paymentRepo.Data[0].IsCleared);
            Assert.IsTrue(paymentRepo.Data[1].IsCleared);

            Assert.IsTrue(paymentRepo.Data[0].IsRecurring);
            Assert.IsTrue(paymentRepo.Data[1].IsRecurring);

            Assert.AreNotEqual(0, paymentRepo.Data[0].RecurringPaymentId);
            Assert.AreNotEqual(0, paymentRepo.Data[1].RecurringPaymentId);

            Assert.IsNotNull(paymentRepo.Data[0].RecurringPayment);
            Assert.IsNotNull(paymentRepo.Data[1].RecurringPayment);
        }
        private Payment GetLastOccurence(Payment payment)
        {
            var transcationList = paymentRepository.Data
                .Where(x => x.RecurringPaymentId == payment.RecurringPaymentId)
                .OrderBy(x => x.Date)
                .ToList();

            return transcationList.LastOrDefault();
        }
        private async void Delete(Payment payment)
        {
            if (!await
                dialogService.ShowConfirmMessage(Strings.DeleteTitle, Strings.DeletePaymentConfirmationMessage))
            {
                return;
            }

            paymentRepository.Delete(payment);
            LoadedCommand.Execute();
        }
 private double HandleTransferAmount(Payment payment, double balance)
 {
     if (AccountRepository.Selected == payment.ChargedAccount)
     {
         balance -= payment.Amount;
     }
     else
     {
         balance += payment.Amount;
     }
     return balance;
 }
        public async Task<bool> CheckForRecurringPayment(Payment payment)
        {
            if (!payment.IsRecurring)
            {
                return false;
            }

            return
                await
                    dialogService.ShowConfirmMessage(Strings.ChangeSubsequentPaymentTitle,
                        Strings.ChangeSubsequentPaymentMessage,
                        Strings.RecurringLabel, Strings.JustThisLabel);
        }
        public void SaveToDatabase_NewPayment_CorrectId()
        {
            var amount = 789;

            var payment = new Payment
            {
                Amount = amount
            };

            new PaymentDataAccess(connectionCreator).SaveItem(payment);

            Assert.IsTrue(payment.Id >= 1);
            Assert.AreEqual(amount, payment.Amount);
        }
        public void SaveToDatabase_ExistingPayment_CorrectId()
        {
            var payment = new Payment();

            var dataAccess = new PaymentDataAccess(connectionCreator);
            dataAccess.SaveItem(payment);

            Assert.AreEqual(0, payment.Amount);

            var id = payment.Id;

            var amount = 789;
            payment.Amount = amount;

            Assert.AreEqual(id, payment.Id);
            Assert.AreEqual(amount, payment.Amount);
        }
        public void DeleteAssociatedPaymentsFromDatabase_Account_DeleteRightPayments()
        {
            var resultList = new List<int>();

            var account1 = new Account
            {
                Id = 3,
                Name = "just an account",
                CurrentBalance = 500
            };
            var account2 = new Account
            {
                Id = 4,
                Name = "just an account",
                CurrentBalance = 900
            };

            var payment = new Payment
            {
                Id = 1,
                ChargedAccount = account1,
                ChargedAccountId = account1.Id
            };

            var paymentRepositorySetup = new Mock<IPaymentRepository>();
            paymentRepositorySetup.SetupAllProperties();
            paymentRepositorySetup.Setup(x => x.Delete(It.IsAny<Payment>()))
                .Callback((Payment trans) => resultList.Add(trans.Id));
            paymentRepositorySetup.Setup(x => x.GetRelatedPayments(It.IsAny<Account>()))
                .Returns(new List<Payment>
                {
                    payment
                });

            var repo = paymentRepositorySetup.Object;
            repo.Data = new ObservableCollection<Payment>();

            new PaymentManager(repo, new Mock<IAccountRepository>().Object, new Mock<IDialogService>().Object)
                .DeleteAssociatedPaymentsFromDatabase(account1);

            Assert.AreEqual(1, resultList.Count);
            Assert.AreEqual(payment.Id, resultList.First());
        }
 /// <summary>
 ///     Creates an recurring Payment based on the Financial payment.
 /// </summary>
 /// <param name="payment">The financial payment the reuccuring shall be based on.</param>
 /// <param name="isEndless">If the recurrence is infinite or not.</param>
 /// <param name="recurrence">How often the payment shall be repeated.</param>
 /// <param name="enddate">Enddate for the recurring payment if it's not endless.</param>
 /// <returns>The new created recurring payment</returns>
 public static RecurringPayment GetRecurringFromPayment(Payment payment,
     bool isEndless,
     int recurrence,
     DateTime enddate = new DateTime())
     => new RecurringPayment
     {
         Id = payment.RecurringPaymentId,
         ChargedAccount = payment.ChargedAccount,
         ChargedAccountId = payment.ChargedAccount.Id,
         TargetAccount = payment.TargetAccount,
         TargetAccountId = payment.TargetAccount?.Id ?? 0,
         StartDate = payment.Date,
         EndDate = enddate,
         IsEndless = isEndless,
         Amount = payment.Amount,
         CategoryId = payment.CategoryId,
         Category = payment.Category,
         Type = payment.Type,
         Recurrence = recurrence,
         Note = payment.Note
     };
        public void SaveWithouthAccount_NoAccount_InvalidDataException()
        {
            var accountRepositorySetup = new Mock<IAccountRepository>();
            accountRepositorySetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Account>());

            var categoryDataAccessSetup = new Mock<IRepository<Category>>();
            categoryDataAccessSetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Category>());

            var repository = new PaymentRepository(new PaymentDataAccessMock(),
                new RecurringPaymentDataAccessMock(),
                accountRepositorySetup.Object,
                categoryDataAccessSetup.Object,
                new Mock<INotificationService>().Object);

            var payment = new Payment
            {
                Amount = 20
            };

            repository.Save(payment);
        }
        /// <summary>
        ///     Checks if the recurring payment is up for a repetition based on the passed Payment
        /// </summary>
        /// <param name="recurringPayment">Recurring payment to check.</param>
        /// <param name="relatedPayment">Payment to compare.</param>
        /// <returns>True or False if the payment have to be repeated.</returns>
        public static bool CheckIfRepeatable(RecurringPayment recurringPayment, Payment relatedPayment)
        {
            if (!relatedPayment.IsCleared)
            {
                return false;
            }

            switch (recurringPayment.Recurrence)
            {
                case (int) PaymentRecurrence.Daily:
                    return DateTime.Today.Date != relatedPayment.Date.Date;

                case (int) PaymentRecurrence.DailyWithoutWeekend:
                    return DateTime.Today.Date != relatedPayment.Date.Date
                           && DateTime.Today.DayOfWeek != DayOfWeek.Saturday
                           && DateTime.Today.DayOfWeek != DayOfWeek.Sunday;

                case (int) PaymentRecurrence.Weekly:
                    var daysWeekly = DateTime.Now - relatedPayment.Date;
                    return daysWeekly.Days >= 7;

                case (int) PaymentRecurrence.Biweekly:
                    var daysBiweekly = DateTime.Now - relatedPayment.Date;
                    return daysBiweekly.Days >= 14;

                case (int) PaymentRecurrence.Monthly:
                    return DateTime.Now.Month != relatedPayment.Date.Month;

                case (int) PaymentRecurrence.Yearly:
                    return (DateTime.Now.Year != relatedPayment.Date.Year
                            && DateTime.Now.Month >= relatedPayment.Date.Month)
                           || DateTime.Now.Year - relatedPayment.Date.Year > 1;

                default:
                    return false;
            }
        }
        public void RemoveRecurringForPayments_RecTrans_PaymentPropertiesProperlyChanged()
        {
            var payment = new Payment
            {
                Id = 2,
                RecurringPaymentId = 3,
                RecurringPayment = new RecurringPayment {Id = 3},
                IsRecurring = true
            };

            var paymentRepositorySetup = new Mock<IPaymentRepository>();
            paymentRepositorySetup.SetupAllProperties();

            var paymentRepository = paymentRepositorySetup.Object;
            paymentRepository.Data = new ObservableCollection<Payment>(new List<Payment> {payment});

            new PaymentManager(paymentRepository,
                new Mock<IAccountRepository>().Object,
                new Mock<IDialogService>().Object).RemoveRecurringForPayments(payment.RecurringPayment);

            payment.IsRecurring.ShouldBeFalse();
            payment.RecurringPaymentId.ShouldBe(0);
        }
        public void ReloadData_UnclearedPayment_Clear()
        {
            var account = new Account {Id = 1, CurrentBalance = 40};
            var payment = new Payment
            {
                ChargedAccount = account,
                ChargedAccountId = 1,
                IsCleared = false,
                Date = DateTime.Today.AddDays(-3)
            };

            var accountRepoSetup = new Mock<IAccountRepository>();
            accountRepoSetup.SetupAllProperties();

            var paymentRepoSetup = new Mock<IPaymentRepository>();
            paymentRepoSetup.SetupAllProperties();
            paymentRepoSetup.Setup(x => x.GetUnclearedPayments())
                .Returns(() => new List<Payment> {payment});

            var categoryRepoSetup = new Mock<IRepository<Category>>();
            categoryRepoSetup.SetupAllProperties();

            var accountRepo = accountRepoSetup.Object;
            var paymentRepository = paymentRepoSetup.Object;

            accountRepo.Data = new ObservableCollection<Account>(new List<Account> {account});

            new RepositoryManager(accountRepo, paymentRepository, categoryRepoSetup.Object,
                new PaymentManager(paymentRepository, accountRepo, new Mock<IDialogService>().Object))
                .ReloadData();

            Assert.IsTrue(payment.IsCleared);
        }
 private void SetDefaultPayment(PaymentType paymentType)
 {
     SelectedPayment = new Payment
     {
         Type = (int) paymentType,
         Date = DateTime.Now,
         // Assign empty category to reset the GUI
         Category = new Category()
     };
 }
        public void Save_TransferPayment_CorrectlySaved()
        {
            var accountRepositorySetup = new Mock<IAccountRepository>();
            accountRepositorySetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Account>());

            var categoryDataAccessSetup = new Mock<IRepository<Category>>();
            categoryDataAccessSetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Category>());

            var paymentDataAccessMock = new PaymentDataAccessMock();
            var repository = new PaymentRepository(new PaymentDataAccessMock(),
                new RecurringPaymentDataAccessMock(),
                accountRepositorySetup.Object,
                categoryDataAccessSetup.Object,
                new Mock<INotificationService>().Object);

            var account = new Account
            {
                Id = 2,
                Name = "TestAccount"
            };

            var targetAccount = new Account
            {
                Id = 3,
                Name = "targetAccount"
            };

            var payment = new Payment
            {
                ChargedAccount = account,
                ChargedAccountId = 2,
                TargetAccount = targetAccount,
                TargetAccountId = 3,
                Amount = 20,
                Type = (int) PaymentType.Transfer
            };

            repository.Save(payment);

            Assert.AreSame(payment, repository.Data[0]);
            Assert.AreEqual((int) PaymentType.Transfer, repository.Data[0].Type);
        }
        private void HandlePaymentAmount(Payment payment,
            Func<double, double> amountFunc,
            Func<Payment, Account> getAccountFunc)
        {
            var account = getAccountFunc(payment);
            if (account == null)
            {
                return;
            }

            account.CurrentBalance += amountFunc(payment.Amount);
            Save(account);
        }
 /// <summary>
 ///     Removes the payment Amount from the charged account of this payment
 /// </summary>
 /// <param name="payment">Payment to remove the account from.</param>
 public void RemovePaymentAmount(Payment payment)
 {
     RemovePaymentAmount(payment, payment.ChargedAccount);
 }
        public void PaymentRepository_Delete()
        {
            var accountRepositorySetup = new Mock<IAccountRepository>();
            accountRepositorySetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Account>());

            var categoryDataAccessSetup = new Mock<IRepository<Category>>();
            categoryDataAccessSetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Category>());

            var paymentDataAccessMock = new PaymentDataAccessMock();
            var repository = new PaymentRepository(new PaymentDataAccessMock(),
                new RecurringPaymentDataAccessMock(),
                accountRepositorySetup.Object,
                categoryDataAccessSetup.Object,
                new Mock<INotificationService>().Object);

            var account = new Account
            {
                Id = 2,
                Name = "TestAccount"
            };

            var payment = new Payment
            {
                ChargedAccount = account,
                ChargedAccountId = 2,
                Amount = 20
            };

            repository.Save(payment);
            Assert.AreSame(payment, repository.Data[0]);

            repository.Delete(payment);

            Assert.IsFalse(repository.Data.Any());
        }
        public void DeletePayment_TransferClearedIsFalse_Deleted()
        {
            var deletedId = 0;

            var account1 = new Account
            {
                Id = 3,
                Name = "just an account",
                CurrentBalance = 500
            };
            var account2 = new Account
            {
                Id = 4,
                Name = "just an account",
                CurrentBalance = 900
            };

            var payment = new Payment
            {
                Id = 10,
                ChargedAccountId = account1.Id,
                ChargedAccount = account1,
                TargetAccountId = account2.Id,
                TargetAccount = account2,
                Amount = 50,
                Type = (int) PaymentType.Transfer,
                IsCleared = false
            };


            var paymentDataAccessMockSetup = new Mock<IDataAccess<Payment>>();
            paymentDataAccessMockSetup.Setup(x => x.DeleteItem(It.IsAny<Payment>()))
                .Callback((Payment trans) => deletedId = trans.Id);
            paymentDataAccessMockSetup.Setup(x => x.SaveItem(It.IsAny<Payment>()));
            paymentDataAccessMockSetup.Setup(x => x.LoadList(null)).Returns(new List<Payment> {payment});

            var recPaymentDataAccessMockSetup = new Mock<IDataAccess<RecurringPayment>>();
            recPaymentDataAccessMockSetup.Setup(x => x.DeleteItem(It.IsAny<RecurringPayment>()));
            recPaymentDataAccessMockSetup.Setup(x => x.LoadList(It.IsAny<Expression<Func<RecurringPayment, bool>>>()))
                .Returns(new List<RecurringPayment>());

            var accountRepositorySetup = new Mock<IAccountRepository>();
            accountRepositorySetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Account> {account1, account2});

            var categoryDataAccessSetup = new Mock<IRepository<Category>>();
            categoryDataAccessSetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Category>());

            new PaymentRepository(paymentDataAccessMockSetup.Object,
                recPaymentDataAccessMockSetup.Object,
                accountRepositorySetup.Object,
                categoryDataAccessSetup.Object,
                new Mock<INotificationService>().Object).Delete(
                    payment);

            Assert.AreEqual(10, deletedId);
            Assert.AreEqual(500, account1.CurrentBalance);
            Assert.AreEqual(900, account2.CurrentBalance);
        }
        public void Save_DifferentPaymentTypes_CorrectlySaved()
        {
            var accountRepositorySetup = new Mock<IAccountRepository>();
            accountRepositorySetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Account>());

            var categoryDataAccessSetup = new Mock<IRepository<Category>>();
            categoryDataAccessSetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Category>());

            var paymentDataAccessMock = new PaymentDataAccessMock();
            var repository = new PaymentRepository(paymentDataAccessMock,
                new RecurringPaymentDataAccessMock(),
                accountRepositorySetup.Object,
                categoryDataAccessSetup.Object,
                new Mock<INotificationService>().Object);

            var account = new Account
            {
                Id = 2,
                Name = "TestAccount"
            };

            var payment = new Payment
            {
                ChargedAccount = account,
                TargetAccount = null,
                Amount = 20,
                Type = (int) PaymentType.Income
            };

            repository.Save(payment);

            Assert.AreSame(payment, paymentDataAccessMock.PaymentTestList[0]);
            Assert.AreEqual((int) PaymentType.Income, paymentDataAccessMock.PaymentTestList[0].Type);
        }
        public void AddItemToDataList_SaveAccount_IsAddedToData()
        {
            var accountRepositorySetup = new Mock<IAccountRepository>();
            accountRepositorySetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Account>());

            var categoryDataAccessSetup = new Mock<IRepository<Category>>();
            categoryDataAccessSetup.SetupGet(x => x.Data).Returns(new ObservableCollection<Category>());

            var repository = new PaymentRepository(new PaymentDataAccessMock(),
                new RecurringPaymentDataAccessMock(),
                accountRepositorySetup.Object,
                categoryDataAccessSetup.Object,
                new Mock<INotificationService>().Object);

            var account = new Account
            {
                Id = 2,
                Name = "TestAccount"
            };

            var payment = new Payment
            {
                ChargedAccount = account,
                Amount = 20,
                Type = (int) PaymentType.Transfer
            };

            repository.Save(payment);
            Assert.IsTrue(repository.Data.Contains(payment));
        }
        /// <summary>
        ///     Adds the payment amount from the selected account
        /// </summary>
        /// <param name="payment">Payment to add the account from.</param>
        public void AddPaymentAmount(Payment payment)
        {
            if (!payment.IsCleared)
            {
                return;
            }

            PrehandleAddIfTransfer(payment);

            Func<double, double> amountFunc = x =>
                payment.Type == (int) PaymentType.Income
                    ? x
                    : -x;

            if (payment.ChargedAccount == null && payment.ChargedAccountId != 0)
            {
                payment.ChargedAccount = data.FirstOrDefault(x => x.Id == payment.ChargedAccountId);
            }

            HandlePaymentAmount(payment, amountFunc, GetChargedAccountFunc(payment.ChargedAccount));
        }
        /// <summary>
        ///     Deletes the passed payment and removes the item from cache
        /// </summary>
        /// <param name="paymentToDelete">Payment to delete.</param>
        public void Delete(Payment paymentToDelete)
        {
            data.Remove(paymentToDelete);
            if (dataAccess.DeleteItem(paymentToDelete))
            {
                SettingsHelper.LastDatabaseUpdate = DateTime.Now;
            }
            else
            {
                notificationService.SendBasicNotification(Strings.ErrorTitleDelete, Strings.ErrorMessageDelete);
            }

            // If this payment was the last one for the linked recurring payment
            // delete the db entry for the recurring payment.
            DeleteRecurringPaymentIfLastAssociated(paymentToDelete);
        }
        /// <summary>
        ///     Removes the payment Amount from the selected account
        /// </summary>
        /// <param name="payment">Payment to remove.</param>
        /// <param name="account">Account to remove the amount from.</param>
        public void RemovePaymentAmount(Payment payment, Account account)
        {
            if (!payment.IsCleared)
            {
                return;
            }

            PrehandleRemoveIfTransfer(payment);

            Func<double, double> amountFunc = x =>
                payment.Type == (int) PaymentType.Income
                    ? -x
                    : x;

            HandlePaymentAmount(payment, amountFunc, GetChargedAccountFunc(account));
        }
        /// <summary>
        ///     Deletes the passed recurring payment
        /// </summary>
        /// <param name="paymentToDelete">Recurring payment to delete.</param>
        public void DeleteRecurring(Payment paymentToDelete)
        {
            var payments = Data.Where(x => x.Id == paymentToDelete.Id).ToList();

            recurringDataAccess.DeleteItem(paymentToDelete.RecurringPayment);

            foreach (var payment in payments)
            {
                payment.RecurringPayment = null;
                payment.IsRecurring = false;
                Save(payment);
            }
        }
 private void PrehandleAddIfTransfer(Payment payment)
 {
     if (payment.Type == (int) PaymentType.Transfer)
     {
         Func<double, double> amountFunc = x => x;
         HandlePaymentAmount(payment, amountFunc, GetTargetAccountFunc());
     }
 }
        private void DeleteRecurringPaymentIfLastAssociated(Payment item)
        {
            if (Data.All(x => x.RecurringPaymentId != item.RecurringPaymentId))
            {
                var recurringList = recurringDataAccess.LoadList(x => x.Id == item.RecurringPaymentId).ToList();

                foreach (var recTrans in recurringList)
                {
                    if (recurringDataAccess.DeleteItem(recTrans))
                    {
                        notificationService.SendBasicNotification(Strings.ErrorTitleDelete, Strings.ErrorMessageDelete);
                    }
                    else
                    {
                        SettingsHelper.LastDatabaseUpdate = DateTime.Now;
                    }
                }
            }
        }