public void TestIntialise()
        {
            this.mockRuleService = new Mock<ITransactionRuleService>(MockBehavior.Strict);
            this.mockReconciliationConsistency = new Mock<IReconciliationConsistency>();
            this.bucketRepo = new BucketBucketRepoAlwaysFind();
            this.testDataBudgets = BudgetModelTestData.CreateCollectionWith1And2();
            this.testDataBudgetContext = new BudgetCurrencyContext(this.testDataBudgets, this.testDataBudgets.CurrentActiveBudget);
            this.testDataStatement = new StatementModelBuilder()
                .TestData5()
                .AppendTransaction(new Transaction
                {
                    Account = StatementModelTestData.ChequeAccount,
                    Amount = -23.56M,
                    BudgetBucket = StatementModelTestData.RegoBucket,
                    Date = ReconcileDate.Date.AddDays(-1),
                    TransactionType = new NamedTransaction("Foo"),
                    Description = "Last transaction"
                })
                .Build();
            this.testDataToDoList = new List<ToDoTask>();
            this.subject = new ReconciliationManager(this.mockRuleService.Object, this.mockReconciliationConsistency.Object, new FakeLogger());

            this.testDataLedgerBook = LedgerBookTestData.TestData5(() => new LedgerBookTestHarness(new Mock<IReconciliationBuilder>().Object));

            this.mockReconciliationConsistency.Setup(m => m.EnsureConsistency(It.IsAny<LedgerBook>())).Returns(new Mock<IDisposable>().Object);
        }
Beispiel #2
0
        public void TestIntialise()
        {
            this.mockRuleService = new Mock <ITransactionRuleService>(MockBehavior.Strict);
            this.mockReconciliationConsistency = new Mock <IReconciliationConsistency>();
            this.bucketRepo            = new BucketBucketRepoAlwaysFind();
            this.testDataBudgets       = BudgetModelTestData.CreateCollectionWith1And2();
            this.testDataBudgetContext = new BudgetCurrencyContext(this.testDataBudgets, this.testDataBudgets.CurrentActiveBudget);
            this.testDataStatement     = new StatementModelBuilder()
                                         .TestData5()
                                         .AppendTransaction(new Transaction
            {
                Account         = StatementModelTestData.ChequeAccount,
                Amount          = -23.56M,
                BudgetBucket    = StatementModelTestData.RegoBucket,
                Date            = ReconcileDate.Date.AddDays(-1),
                TransactionType = new NamedTransaction("Foo"),
                Description     = "Last transaction"
            })
                                         .Build();
            this.testDataToDoList = new List <ToDoTask>();
            this.subject          = new ReconciliationCreationManager(this.mockRuleService.Object, this.mockReconciliationConsistency.Object, new FakeLogger());

            this.testDataLedgerBook = LedgerBookTestData.TestData5(() => new LedgerBookTestHarness(new Mock <IReconciliationBuilder>().Object));

            this.mockReconciliationConsistency.Setup(m => m.EnsureConsistency(It.IsAny <LedgerBook>())).Returns(new Mock <IDisposable>().Object);
        }
        private int SearchForOtherNonLedgerBookOverspentBuckets(
            StatementModel statement,
            GlobalFilterCriteria filter,
            IBudgetCurrencyContext budget,
            IDictionary <BudgetBucket, decimal> overspendingSummary)
        {
            var warnings = 0;
            List <Transaction> transactions = statement.Transactions.Where(t => t.Date < filter.BeginDate?.Date.AddMonths(1)).ToList();

            foreach (var expense in budget.Model.Expenses.Where(e => e.Bucket is BillToPayExpenseBucket))
            {
                if (overspendingSummary.ContainsKey(expense.Bucket))
                {
                    continue;
                }

                var bucketBalance = expense.Amount +
                                    transactions.Where(t => t.BudgetBucket == expense.Bucket).Sum(t => t.Amount);
                overspendingSummary.Add(expense.Bucket, bucketBalance);
                if (bucketBalance < -Tolerance)
                {
                    warnings++;
                }
            }

            return(warnings);
        }
Beispiel #4
0
        public LedgerEntryLine MonthEndReconciliation(
            LedgerBook ledgerBook,
            DateTime reconciliationDate,
            IBudgetCurrencyContext budgetContext,
            StatementModel statement,
            bool ignoreWarnings,
            params BankBalance[] balances)
        {
            var reconResult = this.reconciliationManager.MonthEndReconciliation(ledgerBook, reconciliationDate,
                                                                                budgetContext, statement, ignoreWarnings, balances);

            ReconciliationToDoList.Clear();
            reconResult.Tasks.ToList().ForEach(ReconciliationToDoList.Add);
            return(reconResult.Reconciliation);
        }
Beispiel #5
0
 public static void Output(this IBudgetCurrencyContext instance)
 {
     Debug.WriteLine(string.Empty);
     Debug.WriteLine($"Budget Currency Context: {instance.FileName} Budget Name: {instance.Model.Name} Effective From: {instance.Model.EffectiveFrom:d} Effective Until: {instance.EffectiveUntil:d}");
     if (instance.BudgetActive)
     {
         Debug.WriteLine("Budget is ACTIVE.");
     }
     else if (instance.BudgetArchived)
     {
         Debug.WriteLine("Budget is ARCHIVED.");
     }
     else if (instance.BudgetInFuture)
     {
         Debug.WriteLine("Budget is FUTURE.");
     }
     instance.Model.Output(false);
 }
Beispiel #6
0
        private void ActOnTestData5(StatementModel statementModelTestData = null, bool ignoreWarnings = false)
        {
            this.testDataLedgerBook    = LedgerBookTestData.TestData5(() => new LedgerBookTestHarness(new Mock <IReconciliationBuilder>().Object));
            this.testDataBudgets       = new BudgetCollection(new[] { BudgetModelTestData.CreateTestData5() });
            this.testDataBudgetContext = new BudgetCurrencyContext(this.testDataBudgets, this.testDataBudgets.CurrentActiveBudget);
            this.testDataStatement     = statementModelTestData ?? StatementModelTestData.TestData5();

            Console.WriteLine("********************** BEFORE RUNNING RECONCILIATION *******************************");
            this.testDataStatement.Output(ReconcileDate.AddMonths(-1));
            this.testDataLedgerBook.Output(true);

            Act(bankBalances: new[] { new BankBalance(StatementModelTestData.ChequeAccount, 1850.5M), new BankBalance(StatementModelTestData.SavingsAccount, 1200M) },
                ignoreWarnings: ignoreWarnings);

            Console.WriteLine();
            Console.WriteLine("********************** AFTER RUNNING RECONCILIATION *******************************");
            this.testDataLedgerBook.Output(true);
        }
        public void TestInitialise()
        {
            this.bucketRepo       = new BucketBucketRepoAlwaysFind();
            this.subject          = new RemainingSurplusWidget();
            this.criteriaTestData = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2015, 10, 20),
                EndDate   = new DateTime(2015, 11, 19)
            };

            StatementModelTestDataForThisTest.AccountTypeRepo  = new InMemoryAccountTypeRepository();
            StatementModelTestDataForThisTest.BudgetBucketRepo = this.bucketRepo;
            this.statementTestData = StatementModelTestDataForThisTest.TestDataGenerated();

            BudgetModel budgetModel = BudgetModelTestData.CreateTestData1();

            this.budgetTestData = new BudgetCurrencyContext(new BudgetCollection(budgetModel), budgetModel);

            this.ledgerBookTestData = new LedgerBookBuilder
            {
                StorageKey = "RemainingSurplusWidgetTest.xml",
                Modified   = new DateTime(2015, 11, 23),
                Name       = "Smith Budget 2015"
            }
            .IncludeLedger(LedgerBookTestData.PhoneLedger, 130M)
            .IncludeLedger(LedgerBookTestData.CarMtcLedger, 90M)
            .IncludeLedger(LedgerBookTestData.PowerLedger)
            .AppendReconciliation(
                new DateTime(2015, 10, 20),
                new BankBalance(LedgerBookTestData.ChequeAccount, 4502.75M))
            .WithReconciliationEntries(
                entryBuilder =>
            {
                entryBuilder.WithLedger(LedgerBookTestData.PhoneLedger).HasNoTransactions();
                entryBuilder.WithLedger(LedgerBookTestData.CarMtcLedger).HasNoTransactions();
                entryBuilder.WithLedger(LedgerBookTestData.PowerLedger)
                .AppendTransactions(txnBuilder => { txnBuilder.WithCredit(3000M, "Oct Savings", new DateTime(2015, 10, 20), "automatchref12"); });
            })
            .Build();

            this.ledgerCalculation = new LedgerCalculation(new FakeLogger());
        }
        public void TestInitialise()
        {
            this.bucketRepo = new BucketBucketRepoAlwaysFind();
            this.subject = new RemainingSurplusWidget();
            this.criteriaTestData = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2015, 10, 20),
                EndDate = new DateTime(2015, 11, 19)
            };

            StatementModelTestDataForThisTest.AccountTypeRepo = new InMemoryAccountTypeRepository();
            StatementModelTestDataForThisTest.BudgetBucketRepo = this.bucketRepo;
            this.statementTestData = StatementModelTestDataForThisTest.TestDataGenerated();

            BudgetModel budgetModel = BudgetModelTestData.CreateTestData1();
            this.budgetTestData = new BudgetCurrencyContext(new BudgetCollection(budgetModel), budgetModel);

            this.ledgerBookTestData = new LedgerBookBuilder
            {
                StorageKey = "RemainingSurplusWidgetTest.xml",
                Modified = new DateTime(2015, 11, 23),
                Name = "Smith Budget 2015"
            }
                .IncludeLedger(LedgerBookTestData.PhoneLedger, 130M)
                .IncludeLedger(LedgerBookTestData.CarMtcLedger, 90M)
                .IncludeLedger(LedgerBookTestData.PowerLedger)
                .AppendReconciliation(
                    new DateTime(2015, 10, 20),
                    new BankBalance(LedgerBookTestData.ChequeAccount, 4502.75M))
                .WithReconciliationEntries(
                    entryBuilder =>
                    {
                        entryBuilder.WithLedger(LedgerBookTestData.PhoneLedger).HasNoTransactions();
                        entryBuilder.WithLedger(LedgerBookTestData.CarMtcLedger).HasNoTransactions();
                        entryBuilder.WithLedger(LedgerBookTestData.PowerLedger)
                            .AppendTransactions(txnBuilder => { txnBuilder.WithCredit(3000M, "Oct Savings", new DateTime(2015, 10, 20), "automatchref12"); });
                    })
                .Build();

            this.ledgerCalculation = new LedgerCalculation(new FakeLogger());
        }
        public void TestInitialise()
        {
            this.subject = new BudgetBucketMonitorWidget();
            this.subject.BucketCode = StatementModelTestData.PhoneBucket.Code;

            this.bucketRepo = new BucketBucketRepoAlwaysFind();
            this.criteriaTestData = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2015, 10, 20),
                EndDate = new DateTime(2015, 11, 19)
            };

            CreateStatementTestData();

            BudgetModel budgetModel = BudgetModelTestData.CreateTestData5();
            this.budgetTestData = new BudgetCurrencyContext(new BudgetCollection(budgetModel), budgetModel);

            CreateLedgerBookTestData();

            this.ledgerCalculation = new LedgerCalculation(new FakeLogger());
        }
Beispiel #10
0
        public void TestInitialise()
        {
            this.subject            = new BudgetBucketMonitorWidget();
            this.subject.BucketCode = StatementModelTestData.PhoneBucket.Code;

            this.bucketRepo       = new BucketBucketRepoAlwaysFind();
            this.criteriaTestData = new GlobalFilterCriteria
            {
                BeginDate = new DateTime(2015, 10, 20),
                EndDate   = new DateTime(2015, 11, 19)
            };

            CreateStatementTestData();

            BudgetModel budgetModel = BudgetModelTestData.CreateTestData5();

            this.budgetTestData = new BudgetCurrencyContext(new BudgetCollection(budgetModel), budgetModel);

            CreateLedgerBookTestData();

            this.ledgerCalculation = new LedgerCalculation(new FakeLogger());
        }
Beispiel #11
0
 public BudgetReadyMessage(IBudgetCurrencyContext activeBudget, BudgetCollection budgets = null)
 {
     ActiveBudget = activeBudget;
     Budgets      = budgets;
 }
        private int SearchForOtherNonLedgerBookOverspentBuckets(
            StatementModel statement,
            GlobalFilterCriteria filter,
            IBudgetCurrencyContext budget,
            IDictionary<BudgetBucket, decimal> overspendingSummary)
        {
            var warnings = 0;
            List<Transaction> transactions = statement.Transactions.Where(t => t.Date < filter.BeginDate?.Date.AddMonths(1)).ToList();
            foreach (var expense in budget.Model.Expenses.Where(e => e.Bucket is BillToPayExpenseBucket))
            {
                if (overspendingSummary.ContainsKey(expense.Bucket))
                {
                    continue;
                }

                var bucketBalance = expense.Amount +
                                    transactions.Where(t => t.BudgetBucket == expense.Bucket).Sum(t => t.Amount);
                overspendingSummary.Add(expense.Bucket, bucketBalance);
                if (bucketBalance < -Tolerance)
                {
                    warnings++;
                }
            }

            return warnings;
        }
        public ReconciliationResult MonthEndReconciliation(
            LedgerBook ledgerBook,
            DateTime reconciliationDate,
            IBudgetCurrencyContext budgetContext,
            StatementModel statement,
            bool ignoreWarnings,
            params BankBalance[] currentBankBalances)
        {
            if (ledgerBook == null)
            {
                throw new ArgumentNullException(nameof(ledgerBook));
            }

            if (currentBankBalances == null)
            {
                throw new ArgumentNullException(nameof(currentBankBalances));
            }

            if (budgetContext == null)
            {
                throw new ArgumentNullException(nameof(budgetContext));
            }

            if (statement == null)
            {
                throw new ArgumentNullException(nameof(statement));
            }

            if (!budgetContext.BudgetActive)
            {
                throw new ArgumentException("Reconciling against an inactive budget is invalid.");
            }

            var stopWatch = Stopwatch.StartNew();

            this.logger.LogInfo(l => l.Format("Starting Ledger Book reconciliation {0}", DateTime.Now));

            if (!ignoreWarnings)
            {
                this.validationMessages = new Collection <string>();
            }
            try
            {
                PreReconciliationValidation(ledgerBook, reconciliationDate, statement);
            }
            catch (ValidationWarningException ex)
            {
                if (ShouldValidationExceptionBeRethrown(ignoreWarnings, ex))
                {
                    throw;
                }
            }

            ReconciliationResult recon;

            using (this.reconciliationConsistency.EnsureConsistency(ledgerBook))
            {
                recon = ledgerBook.Reconcile(reconciliationDate, budgetContext.Model, statement, currentBankBalances);
            }

            // Create new single use matching rules - if needed to ensure transfers are assigned a bucket easily without user intervention.
            foreach (var task in recon.Tasks)
            {
                this.logger.LogInfo(
                    l => l.Format("TASK: {0} SystemGenerated:{1}", task.Description, task.SystemGenerated));
                var transferTask = task as TransferTask;
                if (transferTask != null && transferTask.SystemGenerated && transferTask.Reference.IsSomething())
                {
                    this.logger.LogInfo(
                        l =>
                        l.Format(
                            "TRANSFER-TASK detected- creating new single use rule. SystemGenerated:{1} Reference:{2}",
                            task.Description, task.SystemGenerated, transferTask.Reference));
                    this.transactionRuleService.CreateNewSingleUseRule(transferTask.BucketCode, null,
                                                                       new[] { transferTask.Reference }, null, null, true);
                }
            }

            stopWatch.Stop();
            this.logger.LogInfo(l => l.Format("Finished Ledger Book reconciliation {0}. It took {1:F0}ms", DateTime.Now, stopWatch.ElapsedMilliseconds));
            this.validationMessages = null;
            return(recon);
        }
 public LedgerEntryLine MonthEndReconciliation(
     LedgerBook ledgerBook,
     DateTime reconciliationDate,
     IBudgetCurrencyContext budgetContext,
     StatementModel statement,
     bool ignoreWarnings,
     params BankBalance[] balances)
 {
     var reconResult = this.reconciliationManager.MonthEndReconciliation(ledgerBook, reconciliationDate,
         budgetContext, statement, ignoreWarnings, balances);
     ReconciliationToDoList.Clear();
     reconResult.Tasks.ToList().ForEach(ReconciliationToDoList.Add);
     return reconResult.Reconciliation;
 }
 public BudgetReadyMessage(IBudgetCurrencyContext activeBudget, BudgetCollection budgets = null)
 {
     ActiveBudget = activeBudget;
     Budgets = budgets;
 }
        public ReconciliationResult MonthEndReconciliation(
            LedgerBook ledgerBook,
            DateTime reconciliationDate,
            IBudgetCurrencyContext budgetContext,
            StatementModel statement,
            bool ignoreWarnings,
            params BankBalance[] currentBankBalances)
        {
            if (ledgerBook == null)
            {
                throw new ArgumentNullException(nameof(ledgerBook));
            }

            if (currentBankBalances == null)
            {
                throw new ArgumentNullException(nameof(currentBankBalances));
            }

            if (budgetContext == null)
            {
                throw new ArgumentNullException(nameof(budgetContext));
            }

            if (statement == null)
            {
                throw new ArgumentNullException(nameof(statement));
            }

            if (!budgetContext.BudgetActive)
            {
                throw new ArgumentException("Reconciling against an inactive budget is invalid.");
            }

            var stopWatch = Stopwatch.StartNew();
            this.logger.LogInfo(l => l.Format("Starting Ledger Book reconciliation {0}", DateTime.Now));

            if (!ignoreWarnings) this.validationMessages = new Collection<string>();
            try
            {
                PreReconciliationValidation(ledgerBook, reconciliationDate, statement);
            }
            catch (ValidationWarningException ex)
            {
                if (ShouldValidationExceptionBeRethrown(ignoreWarnings, ex)) throw;
            }

            ReconciliationResult recon;
            using (this.reconciliationConsistency.EnsureConsistency(ledgerBook))
            {
                recon = ledgerBook.Reconcile(reconciliationDate, budgetContext.Model, statement, currentBankBalances);
            }

            // Create new single use matching rules - if needed to ensure transfers are assigned a bucket easily without user intervention.
            foreach (var task in recon.Tasks)
            {
                this.logger.LogInfo(
                    l => l.Format("TASK: {0} SystemGenerated:{1}", task.Description, task.SystemGenerated));
                var transferTask = task as TransferTask;
                if (transferTask != null && transferTask.SystemGenerated && transferTask.Reference.IsSomething())
                {
                    this.logger.LogInfo(
                        l =>
                            l.Format(
                                "TRANSFER-TASK detected- creating new single use rule. SystemGenerated:{1} Reference:{2}",
                                task.Description, task.SystemGenerated, transferTask.Reference));
                    this.transactionRuleService.CreateNewSingleUseRule(transferTask.BucketCode, null,
                        new[] { transferTask.Reference }, null, null, true);
                }
            }

            stopWatch.Stop();
            this.logger.LogInfo(l => l.Format("Finished Ledger Book reconciliation {0}. It took {1:F0}ms", DateTime.Now, stopWatch.ElapsedMilliseconds));
            this.validationMessages = null;
            return recon;
        }
        private void ActOnTestData5(StatementModel statementModelTestData = null, bool ignoreWarnings = false)
        {
            this.testDataLedgerBook = LedgerBookTestData.TestData5(() => new LedgerBookTestHarness(new Mock<IReconciliationBuilder>().Object));
            this.testDataBudgets = new BudgetCollection(new[] { BudgetModelTestData.CreateTestData5() });
            this.testDataBudgetContext = new BudgetCurrencyContext(this.testDataBudgets, this.testDataBudgets.CurrentActiveBudget);
            this.testDataStatement = statementModelTestData ?? StatementModelTestData.TestData5();

            Console.WriteLine("********************** BEFORE RUNNING RECONCILIATION *******************************");
            this.testDataStatement.Output(ReconcileDate.AddMonths(-1));
            this.testDataLedgerBook.Output(true);

            Act(bankBalances: new[] { new BankBalance(StatementModelTestData.ChequeAccount, 1850.5M), new BankBalance(StatementModelTestData.SavingsAccount, 1200M) },
                ignoreWarnings: ignoreWarnings);

            Console.WriteLine();
            Console.WriteLine("********************** AFTER RUNNING RECONCILIATION *******************************");
            this.testDataLedgerBook.Output(true);
        }