public LedgerTransaction CreateLedgerTransaction(LedgerBook ledgerBook, LedgerEntryLine reconciliation, LedgerEntry ledgerEntry, decimal amount, string narrative) { if (reconciliation == null) { throw new ArgumentNullException(nameof(reconciliation)); } if (ledgerEntry == null) { throw new ArgumentNullException(nameof(ledgerEntry)); } if (narrative == null) { throw new ArgumentNullException(nameof(narrative)); } LedgerTransaction newTransaction = new CreditLedgerTransaction(); newTransaction.WithAmount(amount).WithNarrative(narrative); newTransaction.Date = reconciliation.Date; // ledgerEntry.AddTransactionForPersistenceOnly(newTransaction); List <LedgerTransaction> replacementTxns = ledgerEntry.Transactions.ToList(); replacementTxns.Add(newTransaction); ledgerEntry.SetTransactionsForReconciliation(replacementTxns); ledgerEntry.RecalculateClosingBalance(ledgerBook); return(newTransaction); }
/// <summary> /// This is effectively stage 2 of the Reconciliation process. /// Called by <see cref="ReconciliationBuilder.CreateNewMonthlyReconciliation" />. It builds the contents of the new /// ledger line based on budget and statement input. /// </summary> /// <param name="budget">The current applicable budget</param> /// <param name="statement">The current period statement.</param> /// <param name="startDateIncl"> /// The date of the previous ledger line. This is used to include transactions from the /// Statement starting from this date and including this date. /// </param> private void AddNew( BudgetModel budget, StatementModel statement, DateTime startDateIncl) { if (!this.newReconciliationLine.IsNew) { throw new InvalidOperationException("Cannot add a new entry to an existing Ledger Line, only new Ledger Lines can have new entries added."); } var reconciliationDate = this.newReconciliationLine.Date; // Date filter must include the start date, which goes back to and includes the previous ledger date up to the date of this ledger line, but excludes this ledger date. // For example if this is a reconciliation for the 20/Feb then the start date is 20/Jan and the finish date is 20/Feb. So transactions pulled from statement are between // 20/Jan (inclusive) and 19/Feb (inclusive) but not including anything for the 20th of Feb. List <Transaction> filteredStatementTransactions = statement?.AllTransactions.Where(t => t.Date >= startDateIncl && t.Date < reconciliationDate).ToList() ?? new List <Transaction>(); IEnumerable <LedgerEntry> previousLedgerBalances = CompileLedgersAndBalances(LedgerBook); var entries = new List <LedgerEntry>(); foreach (var previousLedgerEntry in previousLedgerBalances) { LedgerBucket ledgerBucket; var openingBalance = previousLedgerEntry.Balance; var currentLedger = LedgerBook.Ledgers.Single(l => l.BudgetBucket == previousLedgerEntry.LedgerBucket.BudgetBucket); if (previousLedgerEntry.LedgerBucket.StoredInAccount != currentLedger.StoredInAccount) { // Check to see if a ledger has been moved into a new default account since last reconciliation. ledgerBucket = currentLedger; } else { ledgerBucket = previousLedgerEntry.LedgerBucket; } var newEntry = new LedgerEntry(true) { Balance = openingBalance, LedgerBucket = ledgerBucket }; // Start by adding the budgeted amount to a list of transactions. List <LedgerTransaction> transactions = IncludeBudgetedAmount(budget, ledgerBucket, reconciliationDate); // Append all other transactions for this bucket, if any, to the transaction list. transactions.AddRange(IncludeStatementTransactions(newEntry, filteredStatementTransactions)); AutoMatchTransactionsAlreadyInPreviousPeriod(filteredStatementTransactions, previousLedgerEntry, transactions); newEntry.SetTransactionsForReconciliation(transactions); entries.Add(newEntry); } this.newReconciliationLine.SetNewLedgerEntries(entries); foreach (var behaviour in ReconciliationBehaviourFactory.ListAllBehaviours()) { behaviour.Initialise(filteredStatementTransactions, this.newReconciliationLine, this.toDoList, this.logger, statement); behaviour.ApplyBehaviour(); } // At this point each ledger balance is still set to the opening balance, it hasn't ben updated yet. This should always be done last. foreach (var ledger in this.newReconciliationLine.Entries) { ledger.Balance += ledger.Transactions.Sum(t => t.Amount); } }