private static Entities.Budget BudgetFromElement(
            XElement element,
            Dictionary <string, Entities.Account> accountsByName)
        {
            string name   = GetRequiredAttribute(element, "name").Value;
            string period = GetRequiredAttribute(element, "period").Value;

            var budget = new Entities.Budget
            {
                Name         = name,
                Period       = (BudgetPeriod)Enum.Parse(typeof(BudgetPeriod), period),
                Transactions = element
                               .Elements(XName.Get("BudgetTransaction"))
                               .Select(e => BudgetTransactionFromElement(e, accountsByName)).ToList()
            };

            if (budget.Transactions.Count(t => t.IsInitial) != 1)
            {
                throw new ArgumentException("Budget element must have exactly one initial transaction", nameof(element));
            }
            if (budget.Transactions.Count(t => t.IsSurplus) != 1)
            {
                throw new ArgumentException("Budget element must have exactly one surplus transaction", nameof(element));
            }

            return(budget);
        }
예제 #2
0
        public void Create(Budget budget)
        {
            if (budget == null)
            {
                throw new ArgumentNullException(nameof(budget));
            }

            if (budget.InitialTransaction == null)
            {
                throw new ArgumentException("InitialTransaction cannot be null", nameof(budget));
            }

            if (budget.SurplusTransaction == null)
            {
                throw new ArgumentException("SurplusTransaction cannot be null", nameof(budget));
            }

            using (var transaction = m_dbContext.Database.BeginTransaction())
            {
                var budgetEntity = new Entities.Budget
                {
                    Name   = budget.Name,
                    Period = budget.Period
                };
                m_dbContext.Budgets.Add(budgetEntity);
                m_dbContext.SaveChanges();

                Entities.BudgetTransaction initialTransactionEntity = ToEntity(budgetEntity, budget.InitialTransaction);
                initialTransactionEntity.IsInitial = true;
                m_dbContext.BudgetTransactions.Add(initialTransactionEntity);

                List <Entities.BudgetTransaction> transactionEntities =
                    budget.Transactions
                    .Select(t => ToEntity(budgetEntity, t))
                    .ToList();
                m_dbContext.BudgetTransactions.AddRange(transactionEntities);

                Entities.BudgetTransaction surplusTransactionEntity = ToEntity(budgetEntity, budget.SurplusTransaction);
                surplusTransactionEntity.IsSurplus = true;
                m_dbContext.BudgetTransactions.Add(surplusTransactionEntity);

                m_dbContext.SaveChanges();

                transaction.Commit();

                // Update IDs
                budget.BudgetId = budgetEntity.BudgetId;
                budget.InitialTransaction.BudgetTransactionId = initialTransactionEntity.BudgetTransactionId;
                for (int transactionIndex = 0; transactionIndex < budget.Transactions.Count(); ++transactionIndex)
                {
                    budget.Transactions.ElementAt(transactionIndex).BudgetTransactionId =
                        transactionEntities[transactionIndex].BudgetTransactionId;
                }
                budget.SurplusTransaction.BudgetTransactionId = surplusTransactionEntity.BudgetTransactionId;
            }
        }
        private static XElement ElementFromBudget(Entities.Budget budget)
        {
            var element = new XElement(XName.Get("Budget"),
                                       new XAttribute(XName.Get("name"), budget.Name),
                                       new XAttribute(XName.Get("period"), budget.Period),
                                       budget.Transactions.Select(ElementFromBudgetTransaction)
                                       );

            return(element);
        }
예제 #4
0
        public void Delete(int budgetId)
        {
            Entities.Budget budgetEntity =
                m_dbContext.Budgets.SingleOrDefault(b => b.BudgetId == budgetId);

            if (budgetEntity == null)
            {
                throw new ArgumentException($"No Budget exists with BudgetId {budgetId}", nameof(budgetId));
            }

            m_dbContext.Budgets.Remove(budgetEntity);
            m_dbContext.SaveChanges();
        }
예제 #5
0
        public void Update(Budget budget)
        {
            Entities.Budget budgetEntity = m_dbContext.Budgets
                                           .Include(b => b.Transactions)
                                           .Single(b => b.BudgetId == budget.BudgetId);
            budgetEntity.Name   = budget.Name;
            budgetEntity.Period = (BudgetPeriod)budget.Period;

            Entities.BudgetTransaction initialTransactionEntity = budgetEntity.Transactions.Single(t => t.IsInitial);
            UpdateTransactionEntity(budget.InitialTransaction, initialTransactionEntity);

            List <Entities.BudgetTransaction> transactionEntities =
                budgetEntity.Transactions
                .Where(t => !t.IsInitial && !t.IsSurplus)
                .ToList();
            var transactionIds = new HashSet <int>(
                budget.Transactions
                .Select(t => t.BudgetTransactionId)
                );

            foreach (Entities.BudgetTransaction transactionEntity in transactionEntities)
            {
                if (transactionIds.Contains(transactionEntity.BudgetTransactionId))
                {
                    // update existing transaction
                    BudgetTransaction transaction = budget.Transactions
                                                    .Single(t => t.BudgetTransactionId == transactionEntity.BudgetTransactionId);
                    UpdateTransactionEntity(transaction, transactionEntity);
                }
                else
                {
                    // remove missing transaction
                    budgetEntity.Transactions.Remove(transactionEntity);
                }
            }

            // add new transactions
            var transactionEntityIds = new HashSet <int>(transactionEntities.Select(t => t.BudgetTransactionId));
            IEnumerable <BudgetTransaction> transactionsWithNoEntity =
                budget.Transactions.Where(t => !transactionEntityIds.ToList().Contains(t.BudgetTransactionId));

            foreach (BudgetTransaction transactionWithNoEntity in transactionsWithNoEntity)
            {
                budgetEntity.Transactions.Add(ToEntity(budgetEntity, transactionWithNoEntity));
            }

            Entities.BudgetTransaction surplusTransactionEntity = budgetEntity.Transactions.Single(t => t.IsSurplus);
            UpdateTransactionEntity(budget.SurplusTransaction, surplusTransactionEntity);

            m_dbContext.SaveChanges();
        }
예제 #6
0
        private static Entities.BudgetTransaction ToEntity(Entities.Budget budgetEntity, BudgetTransaction budgetTransaction)
        {
            var transactionEntity = new Entities.BudgetTransaction
            {
                Budget          = budgetEntity,
                CreditAccountId = budgetTransaction.CreditAccount.AccountId,
                DebitAccountId  = budgetTransaction.DebitAccount.AccountId,
                Amount          = budgetTransaction.Amount,
                IsInitial       = false,
                IsSurplus       = false
            };

            return(transactionEntity);
        }
예제 #7
0
        public Budget Get(int budgetId)
        {
            Entities.Budget budgetEntity =
                m_dbContext.Budgets
                .Include(b => b.Transactions)
                .ThenInclude(t => t.CreditAccount)
                .Include(b => b.Transactions)
                .ThenInclude(t => t.DebitAccount)
                .SingleOrDefault(b => b.BudgetId == budgetId);

            if (budgetEntity == null)
            {
                throw new ArgumentException($"No Budget exists with BudgetId {budgetId}", nameof(budgetId));
            }

            return(FromEntity(budgetEntity));
        }
예제 #8
0
        private static Budget FromEntity(Entities.Budget budgetEntity)
        {
            Entities.BudgetTransaction initialTransactionEntity =
                budgetEntity.Transactions.Single(t => t.IsInitial);
            IEnumerable <Entities.BudgetTransaction> transactionEntities =
                budgetEntity.Transactions.Where(t => !t.IsInitial && !t.IsSurplus);

            Entities.BudgetTransaction surplusTransactionEntity =
                budgetEntity.Transactions.Single(t => t.IsSurplus);

            var budget = new Budget
            {
                BudgetId           = budgetEntity.BudgetId,
                Name               = budgetEntity.Name,
                Period             = (BudgetPeriod)budgetEntity.Period,
                InitialTransaction = FromEntity(initialTransactionEntity),
                Transactions       = transactionEntities.Select(FromEntity).ToList(),
                SurplusTransaction = FromEntity(surplusTransactionEntity),
            };

            return(budget);
        }
        public void TestBudgetEditViewModelOK()
        {
            ILoggerFactory loggerFactory = new LoggerFactory();

            using (var sqliteMemoryWrapper = new SqliteMemoryWrapper())
            {
                var currencyFactory = new CurrencyFactory();
                Entities.Currency usdCurrencyEntity = currencyFactory.Create(CurrencyPrefab.Usd, true);
                currencyFactory.Add(sqliteMemoryWrapper.DbContext, usdCurrencyEntity);

                var accountFactory = new AccountFactory();
                Entities.Account incomeAccountEntity =
                    accountFactory.Create(AccountPrefab.Income, usdCurrencyEntity);
                Entities.Account checkingAccountEntity =
                    accountFactory.Create(AccountPrefab.Checking, usdCurrencyEntity);
                Entities.Account savingsAccountEntity =
                    accountFactory.Create(AccountPrefab.Savings, usdCurrencyEntity);
                Entities.Account rentPrepaymentAccountEntity =
                    accountFactory.Create(AccountPrefab.RentPrepayment, usdCurrencyEntity);
                Entities.Account rentExpenseAccountEntity =
                    accountFactory.Create(AccountPrefab.RentExpense, usdCurrencyEntity);
                Entities.Account groceriesPrepaymentAccountEntity =
                    accountFactory.Create(AccountPrefab.GroceriesPrepayment, usdCurrencyEntity);
                Entities.Account groceriesExpenseAccountEntity =
                    accountFactory.Create(AccountPrefab.GroceriesExpense, usdCurrencyEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, incomeAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, checkingAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, savingsAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, rentPrepaymentAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, rentExpenseAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, groceriesPrepaymentAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, groceriesExpenseAccountEntity);

                var checkingToRentPrepaymentRelationship = new Entities.AccountRelationship
                {
                    SourceAccount      = checkingAccountEntity,
                    DestinationAccount = rentPrepaymentAccountEntity,
                    Type = AccountRelationshipType.PhysicalToLogical
                };
                var checkingToGroceriesPrepaymentRelationship = new Entities.AccountRelationship
                {
                    SourceAccount      = checkingAccountEntity,
                    DestinationAccount = groceriesPrepaymentAccountEntity,
                    Type = AccountRelationshipType.PhysicalToLogical
                };
                var rentPrepaymentToExpenseRelationship = new Entities.AccountRelationship
                {
                    SourceAccount      = rentPrepaymentAccountEntity,
                    DestinationAccount = rentExpenseAccountEntity,
                    Type = AccountRelationshipType.PrepaymentToExpense
                };
                var groceriesPrepaymentToExpenseRelationship = new Entities.AccountRelationship
                {
                    SourceAccount      = groceriesPrepaymentAccountEntity,
                    DestinationAccount = groceriesExpenseAccountEntity,
                    Type = AccountRelationshipType.PrepaymentToExpense
                };

                sqliteMemoryWrapper.DbContext.AccountRelationships.Add(checkingToRentPrepaymentRelationship);
                sqliteMemoryWrapper.DbContext.AccountRelationships.Add(checkingToGroceriesPrepaymentRelationship);
                sqliteMemoryWrapper.DbContext.AccountRelationships.Add(rentPrepaymentToExpenseRelationship);
                sqliteMemoryWrapper.DbContext.AccountRelationships.Add(groceriesPrepaymentToExpenseRelationship);
                sqliteMemoryWrapper.DbContext.SaveChanges();

                var budget = new Entities.Budget
                {
                    Name   = "Budget",
                    Period = BudgetPeriod.Fortnightly
                };
                sqliteMemoryWrapper.DbContext.Budgets.Add(budget);
                sqliteMemoryWrapper.DbContext.SaveChanges();

                var initialTransaction = new Entities.BudgetTransaction
                {
                    CreditAccount = incomeAccountEntity,
                    DebitAccount  = checkingAccountEntity,
                    Amount        = 200m,
                    IsInitial     = true,
                    Budget        = budget
                };
                var rentTransaction = new Entities.BudgetTransaction
                {
                    CreditAccount = checkingAccountEntity,
                    DebitAccount  = rentPrepaymentAccountEntity,
                    Amount        = 100m,
                    Budget        = budget
                };
                var groceriesTransaction = new Entities.BudgetTransaction
                {
                    CreditAccount = checkingAccountEntity,
                    DebitAccount  = groceriesPrepaymentAccountEntity,
                    Amount        = 50m,
                    Budget        = budget
                };
                var surplusTransaction = new Entities.BudgetTransaction
                {
                    CreditAccount = checkingAccountEntity,
                    DebitAccount  = groceriesPrepaymentAccountEntity,
                    IsSurplus     = true,
                    Budget        = budget
                };
                sqliteMemoryWrapper.DbContext.BudgetTransactions.Add(initialTransaction);
                sqliteMemoryWrapper.DbContext.BudgetTransactions.Add(rentTransaction);
                sqliteMemoryWrapper.DbContext.BudgetTransactions.Add(groceriesTransaction);
                sqliteMemoryWrapper.DbContext.BudgetTransactions.Add(surplusTransaction);
                sqliteMemoryWrapper.DbContext.SaveChanges();

                var accountService = new AccountService(
                    loggerFactory,
                    sqliteMemoryWrapper.DbContext);

                var budgetService = new BudgetService(
                    loggerFactory,
                    sqliteMemoryWrapper.DbContext);

                var mockTransactionItemViewModelFactory = new Mock <IBudgetTransactionItemViewModelFactory>();
                mockTransactionItemViewModelFactory
                .Setup(f => f.Create(
                           It.IsAny <ObservableCollection <IAccountLinkViewModel> >(),
                           It.IsAny <BudgetTransaction>(),
                           It.IsAny <BudgetTransactionType>()))
                .Returns(
                    (ObservableCollection <IAccountLinkViewModel> accountLinks,
                     BudgetTransaction budgetTransaction,
                     BudgetTransactionType type) =>
                {
                    return(new BudgetTransactionItemViewModel(
                               loggerFactory,
                               accountLinks,
                               budgetTransaction,
                               type));
                });

                var mockTransactionListViewModelFactory = new Mock <IBudgetTransactionListViewModelFactory>();
                mockTransactionListViewModelFactory
                .Setup(f => f.Create(It.IsAny <int>()))
                .Returns((int budgetId) =>
                {
                    return(new BudgetTransactionListViewModel(
                               loggerFactory,
                               accountService,
                               budgetService,
                               new Concrete.StubAccountLinkViewModelFactory(),
                               mockTransactionItemViewModelFactory.Object,
                               new Mock <IDeleteConfirmationViewService>().Object,
                               budgetId
                               ));
                });

                var viewModel = new BudgetEditViewModel(
                    loggerFactory,
                    budgetService,
                    mockTransactionListViewModelFactory.Object,
                    budget.BudgetId
                    );

                viewModel.Name           = "My First Budget";
                viewModel.SelectedPeriod = BudgetPeriod.Monthly;
                viewModel.OKCommand.Execute(this);

                List <Budget> budgets = budgetService.GetAll().ToList();

                Assert.AreEqual(1, budgets.Count);
                Assert.AreEqual(viewModel.Name, budgets[0].Name);
                Assert.AreEqual(viewModel.SelectedPeriod, budgets[0].Period);
                Assert.AreEqual(initialTransaction.CreditAccountId, budgets[0].InitialTransaction.CreditAccount.AccountId);
                Assert.AreEqual(initialTransaction.DebitAccountId, budgets[0].InitialTransaction.DebitAccount.AccountId);
                Assert.AreEqual(initialTransaction.Amount, budgets[0].InitialTransaction.Amount);
                Assert.AreEqual(surplusTransaction.CreditAccountId, budgets[0].SurplusTransaction.CreditAccount.AccountId);
                Assert.AreEqual(surplusTransaction.DebitAccountId, budgets[0].SurplusTransaction.DebitAccount.AccountId);
                Assert.AreEqual(surplusTransaction.Amount, budgets[0].SurplusTransaction.Amount);
                Assert.AreEqual(2, budgets[0].Transactions.Count());
            }
        }
예제 #10
0
        public void TestReloadBudget()
        {
            const string   path          = "TestData/BudgetReload.xml";
            ILoggerFactory loggerFactory = new LoggerFactory();

            var currencyFactory = new CurrencyFactory();

            Entities.Currency usdCurrencyEntity = currencyFactory.Create(CurrencyPrefab.Usd, true);

            var accountFactory = new AccountFactory();

            Entities.Account incomeAccountEntity =
                accountFactory.Create(AccountPrefab.Income, usdCurrencyEntity);
            Entities.Account checkingAccountEntity =
                accountFactory.Create(AccountPrefab.Checking, usdCurrencyEntity);
            Entities.Account rentPrepaymentAccountEntity =
                accountFactory.Create(AccountPrefab.RentPrepayment, usdCurrencyEntity);
            Entities.Account savingsAccountEntity =
                accountFactory.Create(AccountPrefab.Savings, usdCurrencyEntity);

            var accountRelationship = new Entities.AccountRelationship
            {
                SourceAccount      = checkingAccountEntity,
                DestinationAccount = rentPrepaymentAccountEntity,
                Type = AccountRelationshipType.PhysicalToLogical
            };
            var budget = new Entities.Budget
            {
                Name         = "The Budget",
                Period       = BudgetPeriod.Fortnightly,
                Transactions = new List <Entities.BudgetTransaction>
                {
                    new Entities.BudgetTransaction
                    {
                        CreditAccount = incomeAccountEntity,
                        DebitAccount  = checkingAccountEntity,
                        Amount        = 100m,
                        IsInitial     = true
                    },
                    new Entities.BudgetTransaction
                    {
                        CreditAccount = checkingAccountEntity,
                        DebitAccount  = rentPrepaymentAccountEntity,
                        Amount        = 80m,
                    },
                    new Entities.BudgetTransaction
                    {
                        CreditAccount = checkingAccountEntity,
                        DebitAccount  = savingsAccountEntity,
                        Amount        = 100m,
                        IsSurplus     = true
                    }
                }
            };

            using (var sqliteMemoryWrapper = new SqliteMemoryWrapper())
            {
                currencyFactory.Add(sqliteMemoryWrapper.DbContext, usdCurrencyEntity);

                accountFactory.Add(sqliteMemoryWrapper.DbContext, incomeAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, checkingAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, rentPrepaymentAccountEntity);
                accountFactory.Add(sqliteMemoryWrapper.DbContext, savingsAccountEntity);

                sqliteMemoryWrapper.DbContext.AccountRelationships.Add(accountRelationship);
                sqliteMemoryWrapper.DbContext.SaveChanges();

                sqliteMemoryWrapper.DbContext.Budgets.Add(budget);
                sqliteMemoryWrapper.DbContext.SaveChanges();

                var service = new DatabaseSerializationXmlService(loggerFactory, sqliteMemoryWrapper.DbContext);
                service.Save(path);
            }

            using (var sqliteMemoryWrapper = new SqliteMemoryWrapper())
            {
                var service = new DatabaseSerializationXmlService(loggerFactory, sqliteMemoryWrapper.DbContext);
                service.Load(path);

                List <Entities.Account>             accounts             = sqliteMemoryWrapper.DbContext.Accounts.ToList();
                List <Entities.AccountRelationship> accountRelationships = sqliteMemoryWrapper.DbContext.AccountRelationships.ToList();
                List <Entities.Budget>            budgets            = sqliteMemoryWrapper.DbContext.Budgets.ToList();
                List <Entities.BudgetTransaction> budgetTransactions = sqliteMemoryWrapper.DbContext.BudgetTransactions.ToList();
                List <Entities.Currency>          currencies         = sqliteMemoryWrapper.DbContext.Currencies.ToList();
                List <Entities.Transaction>       transactions       = sqliteMemoryWrapper.DbContext.Transactions.ToList();

                Assert.AreEqual(4, accounts.Count);
                Assert.AreEqual(1, accountRelationships.Count);
                Assert.AreEqual(1, budgets.Count);
                Assert.AreEqual(3, budgetTransactions.Count);
                Assert.AreEqual(1, currencies.Count);
                Assert.AreEqual(0, transactions.Count);

                Assert.AreEqual(budget.Name, budgets[0].Name);
                Assert.AreEqual(budget.Period, budgets[0].Period);

                Entities.BudgetTransaction initialTransaction = budgetTransactions.First(bt => bt.IsInitial && !bt.IsSurplus);
                Entities.BudgetTransaction regularTransaction = budgetTransactions.First(bt => !bt.IsInitial && !bt.IsSurplus);
                Entities.BudgetTransaction surplusTransaction = budgetTransactions.First(bt => !bt.IsInitial && bt.IsSurplus);
                Assert.AreEqual(budget.Transactions[0].DebitAccount.Name, initialTransaction.DebitAccount.Name);
                Assert.AreEqual(budget.Transactions[0].CreditAccount.Name, initialTransaction.CreditAccount.Name);
                Assert.AreEqual(budget.Transactions[0].Amount, initialTransaction.Amount);
                Assert.AreEqual(budget.Transactions[0].IsInitial, initialTransaction.IsInitial);
                Assert.AreEqual(budget.Transactions[0].IsSurplus, initialTransaction.IsSurplus);
                Assert.AreEqual(budget.Transactions[1].DebitAccount.Name, regularTransaction.DebitAccount.Name);
                Assert.AreEqual(budget.Transactions[1].CreditAccount.Name, regularTransaction.CreditAccount.Name);
                Assert.AreEqual(budget.Transactions[1].Amount, regularTransaction.Amount);
                Assert.AreEqual(budget.Transactions[1].IsInitial, regularTransaction.IsInitial);
                Assert.AreEqual(budget.Transactions[1].IsSurplus, regularTransaction.IsSurplus);
                Assert.AreEqual(budget.Transactions[2].DebitAccount.Name, surplusTransaction.DebitAccount.Name);
                Assert.AreEqual(budget.Transactions[2].CreditAccount.Name, surplusTransaction.CreditAccount.Name);
                Assert.AreEqual(budget.Transactions[2].Amount, surplusTransaction.Amount);
                Assert.AreEqual(budget.Transactions[2].IsInitial, surplusTransaction.IsInitial);
                Assert.AreEqual(budget.Transactions[2].IsSurplus, surplusTransaction.IsSurplus);
            }
        }