public void UsingTestData1_FirstLineShouldHaveBankBalance2950() { LedgerBook result = ArrangeAndAct(); LedgerEntryLine subject = result.Reconciliations.First(); Assert.AreEqual(2950, subject.TotalBankBalance); }
private void SetReconciliation(IReadOnlyDictionary <LedgerBucket, SpecificLedgerEntryTestDataBuilder> ledgers, string remarks) { var recon = new LedgerEntryLine(this.tempReconDate, this.tempBankBalances) { Remarks = remarks }; LedgerEntryLine previousRecon = Reconciliations.OrderByDescending(r => r.Date).FirstOrDefault(); var entries = new List <LedgerEntry>(); foreach (LedgerBucket ledgerBucket in this.ledgerBuckets) { decimal openingBalance; if (previousRecon == null) { openingBalance = this.openingBalances[ledgerBucket]; } else { LedgerEntry previousEntry = previousRecon.Entries.Single(e => e.LedgerBucket == ledgerBucket); openingBalance = previousEntry.Balance; } var entry = new LedgerEntry { LedgerBucket = ledgerBucket, Balance = openingBalance }; entry.SetTransactionsForTesting(ledgers[ledgerBucket].Transactions.ToList()); entries.Add(entry); } recon.SetEntriesForTesting(entries); this.reconciliations.Add(recon); }
private void OnShellDialogResponseReceived(ShellDialogResponseMessage message) { if (!message.IsItForMe(this.dialogCorrelationId)) { return; } if (message.Response == ShellDialogButton.Ok) { if (ShowAddingNewTransactionPanel) { OnAddNewTransactionCommandExecuted(); } Save(); this.entryLine = null; LedgerEntry = null; } if (message.Response == ShellDialogButton.Cancel) { this.isAddDirty = false; this.entryLine = null; LedgerEntry = null; } EventHandler <LedgerTransactionEventArgs> handler = Complete; handler?.Invoke(this, new LedgerTransactionEventArgs(this.wasChanged)); Reset(); this.wasChanged = false; }
private decimal RetrieveOpeningBalance() { var book = this.ledgerService.LedgerBook; bool found = false; IEnumerable <LedgerEntryLine> remainingRecons = book.Reconciliations.SkipWhile(r => { // Find the recon that directly precedes this current one. if (found) { return(false); // Found recon line on previous pass, now return. } found = r.Entries.Contains(LedgerEntry); return(true); // Keep skipping... }).Take(1); LedgerEntryLine previousLine = remainingRecons.FirstOrDefault(); if (previousLine == null) { return(0M); } var previousEntry = previousLine.Entries.FirstOrDefault(l => l.LedgerBucket == LedgerEntry.LedgerBucket); return(previousEntry?.Balance ?? 0M); }
public void UsingTestData1_FirstLineShouldHaveSurplusOf2712() { LedgerBook result = ArrangeAndAct(); LedgerEntryLine subject = result.Reconciliations.First(); Assert.AreEqual(2712.97M, subject.CalculatedSurplus); }
public void UsingTestData1_FirstLineShouldHaveDate20130815() { LedgerBook result = ArrangeAndAct(); LedgerEntryLine subject = result.Reconciliations.First(); Assert.AreEqual(new DateTime(2013, 08, 15), subject.Date); }
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); }
public void UsingTestData1_FirstLineShouldHave3Entries() { LedgerBook result = ArrangeAndAct(); LedgerEntryLine subject = result.Reconciliations.First(); Assert.AreEqual(3, subject.Entries.Count()); }
public static IEnumerable <LedgerTransaction> FindAutoMatchingTransactions([CanBeNull] LedgerEntryLine recon, bool includeMatchedTransactions = false) { if (recon == null) { return(new List <LedgerTransaction>()); } return(recon.Entries.SelectMany(e => FindAutoMatchingTransactions(e, includeMatchedTransactions))); }
public void ShouldMapLineBankBalance() { LedgerBook result = ArrangeAndAct(); LedgerEntryLine subject = result.Reconciliations.First(); Assert.AreEqual(TestData.Reconciliations.First().BankBalance, subject.TotalBankBalance); Assert.AreNotEqual(0, subject.TotalBankBalance); }
public BankBalanceViewModel([CanBeNull] LedgerEntryLine line, [NotNull] BankBalance balance) : base(balance.Account, balance.Balance) { if (balance == null) { throw new ArgumentNullException(nameof(balance)); } this.line = line; }
public void CancelBalanceAdjustment(LedgerEntryLine entryLine, Guid transactionId) { if (entryLine == null) { throw new ArgumentNullException(nameof(entryLine)); } entryLine.CancelBalanceAdjustment(transactionId); }
private static LedgerEntryLine CreateLine(DateTime date, IEnumerable <BankBalance> bankBalances, string remarks) { var line = new LedgerEntryLine(date, bankBalances) { Remarks = remarks }; return(line); }
/// <summary> /// Transfer funds from one ledger bucket to another. This is only possible if the current ledger reconciliation is /// unlocked. /// This is usually used during reconciliation. /// </summary> /// <param name="ledgerBook">The parent ledger book.</param> /// <param name="reconciliation"> /// The reconciliation line that this transfer will be created in. A transfer can only occur /// between two ledgers in the same reconciliation. /// </param> /// <param name="transferDetails">The details of the requested transfer.</param> public void TransferFunds(LedgerBook ledgerBook, LedgerEntryLine reconciliation, TransferFundsCommand transferDetails) { if (reconciliation == null) { throw new ArgumentNullException(nameof(reconciliation), "There are no reconciliations. Transfer funds can only be used on the most recent reconciliation."); } this.reconciliationManager.TransferFunds(ledgerBook, transferDetails, reconciliation); }
public void ShouldMapLineBalanceAdjustments() { TestData = LedgerBookDtoTestData.TestData2(); LedgerBook result = ArrangeAndAct(); LedgerEntryLine subject = result.Reconciliations.First(); Assert.AreEqual(TestData.Reconciliations.First().BankBalanceAdjustments.Sum(a => a.Amount), subject.TotalBalanceAdjustments); Assert.AreNotEqual(0, subject.BankBalanceAdjustments.Count()); }
public void Initialise(params object[] anyParameters) { foreach (var argument in anyParameters) { NewReconLine = NewReconLine ?? argument as LedgerEntryLine; } if (NewReconLine == null) { throw new ArgumentNullException(nameof(NewReconLine)); } }
public static void Output(this LedgerEntryLine line, Dictionary <BudgetBucket, int> ledgerOrder, bool outputTransactions = false, bool outputHeader = false) { if (outputHeader) { OutputReconciliationHeader(); } Debug.Write($"{line.Date:d} "); foreach (var entry in line.Entries.OrderBy(e => e.LedgerBucket.BudgetBucket)) { Debug.Write($"{entry.NetAmount.ToString("N").PadRight(8)} {entry.LedgerBucket.StoredInAccount.Name.Truncate(1)} {entry.Balance.ToString("N").PadRight(9)}"); } Debug.Write(line.CalculatedSurplus.ToString("N").PadRight(9)); var balanceCount = 0; foreach (var bankBalance in line.BankBalances) { if (++balanceCount > 2) { break; } // Only two bank balances are shown in the test output at this stage. var balanceText = string.Format("{0} {1} ", bankBalance.Account.Name.Truncate(1), bankBalance.Balance.ToString("N")); Debug.Write(balanceText.PadLeft(13).TruncateLeft(13)); } Debug.Write(line.TotalBalanceAdjustments.ToString("N").PadLeft(9).TruncateLeft(9)); Debug.Write(line.LedgerBalance.ToString("N").PadLeft(13).TruncateLeft(13)); Debug.WriteLine(string.Empty); if (outputTransactions) { foreach (var entry in line.Entries.OrderBy(e => e.LedgerBucket.BudgetBucket)) { var tab = new string(' ', 11 + 18 * ledgerOrder[entry.LedgerBucket.BudgetBucket]); foreach (var transaction in entry.Transactions) { Debug.WriteLine( "{0} {1} {2} {3} {4} {5}", tab, entry.LedgerBucket.BudgetBucket.Code.PadRight(6), transaction.Amount >= 0 ? (transaction.Amount.ToString("N") + "Cr").PadLeft(8) : (transaction.Amount.ToString("N") + "Dr").PadLeft(16), transaction.Narrative.Truncate(15), transaction.Id, transaction.AutoMatchingReference); } } Debug.WriteLine("================================================================================================================================="); } }
public void Show(LedgerEntryLine line, bool isNew) { LedgerEntryLine = line; Remarks = LedgerEntryLine.Remarks; IsReadOnly = !isNew; this.dialogCorrelationId = Guid.NewGuid(); var dialogRequest = new ShellDialogRequestMessage(BudgetAnalyserFeature.LedgerBook, this, ShellDialogType.Ok) { Title = "Ledger Entry Remarks", CorrelationId = this.dialogCorrelationId }; MessengerInstance.Send(dialogRequest); }
public void UpdateRemarks(LedgerEntryLine entryLine, string remarks) { if (entryLine == null) { throw new ArgumentNullException(nameof(entryLine)); } if (remarks == null) { throw new ArgumentNullException(nameof(remarks)); } entryLine.UpdateRemarks(remarks); }
/// <summary> /// Show the Ledger Transactions view, for viewing and editing Balance Adjustments /// </summary> public void ShowBankBalanceAdjustmentsDialog(LedgerEntryLine ledgerEntryLine, bool isNew) { if (ledgerEntryLine == null) { return; } InBalanceAdjustmentMode = true; InLedgerEntryMode = false; LedgerEntry = null; this.entryLine = ledgerEntryLine; ShownTransactions = new ObservableCollection <LedgerTransaction>(ledgerEntryLine.BankBalanceAdjustments); Title = "Balance Adjustment Transactions"; ShowDialogCommon(isNew); }
/// <summary> /// Show the Ledger Transactions view for viewing and editing Ledger Transactions. /// </summary> public void ShowLedgerTransactionsDialog(LedgerEntryLine ledgerEntryLine, LedgerEntry ledgerEntry, bool isNew) { if (ledgerEntry == null) { return; } InBalanceAdjustmentMode = false; InLedgerEntryMode = true; LedgerEntry = ledgerEntry; this.entryLine = ledgerEntryLine; // Will be null when editing an existing LedgerEntry as opposed to creating a new reconciliation. ShownTransactions = new ObservableCollection <LedgerTransaction>(LedgerEntry.Transactions); Title = string.Format(CultureInfo.CurrentCulture, "{0} Transactions", ledgerEntry.LedgerBucket.BudgetBucket.Code); OpeningBalance = RetrieveOpeningBalance(); ShowDialogCommon(isNew); }
public void TestIntialise() { this.mockBucketRepo = new Mock <IBudgetBucketRepository>(); this.mockRuleService = new Mock <ITransactionRuleService>(); this.mockReconciliationConsistency = new Mock <IReconciliationConsistency>(); this.subject = new ReconciliationCreationManager(this.mockRuleService.Object, this.mockReconciliationConsistency.Object, new FakeLogger()); this.testDataLedgerBook = LedgerBookTestData.TestData5(() => new LedgerBookTestHarness(new Mock <IReconciliationBuilder>().Object)); this.testDataEntryLine = this.testDataLedgerBook.Reconciliations.First(); this.testDataEntryLine.Unlock(); this.surplusChqLedger = new SurplusLedger { StoredInAccount = StatementModelTestData.ChequeAccount }; this.insHomeSavLedger = this.testDataLedgerBook.Ledgers.Single(l => l.BudgetBucket == StatementModelTestData.InsHomeBucket); this.phNetChqLedger = this.testDataLedgerBook.Ledgers.Single(l => l.BudgetBucket == StatementModelTestData.PhoneBucket); }
private static decimal GetLedgerBalanceForBucket(BudgetModel budgetModel, LedgerEntryLine applicableLine, BudgetBucket bucket) { if (bucket is SurplusBucket) { return(applicableLine.CalculatedSurplus); } var ledger = applicableLine.Entries.FirstOrDefault(e => e.LedgerBucket.BudgetBucket == bucket); if (ledger != null) { return(ledger.Balance); } // The Ledger line might not actually have a ledger for the given bucket. return(GetBudgetModelTotalForBucket(budgetModel, bucket)); }
public void ShowDialog([NotNull] LedgerEntryLine ledgerLine) { if (ledgerLine == null) { throw new ArgumentNullException(nameof(ledgerLine)); } SurplusBalances = new ObservableCollection <BankBalance>(ledgerLine.SurplusBalances); this.ledgerEntryLine = ledgerLine; var dialogRequest = new ShellDialogRequestMessage(BudgetAnalyserFeature.LedgerBook, this, ShellDialogType.Ok) { CorrelationId = Guid.NewGuid(), Title = "Surplus Balances in all Accounts" }; MessengerInstance.Send(dialogRequest); }
private static string BuildToolTipForBankBalance(LedgerEntryLine line) { var individualLedgerBalances = new StringBuilder(); foreach (BankBalance bankBalance in line.BankBalances) { individualLedgerBalances.AppendFormat( CultureInfo.CurrentCulture, "{0}: {1:N}; ", bankBalance.Account, bankBalance.Balance + line.BankBalanceAdjustments.Where(a => a.BankAccount == bankBalance.Account).Sum(a => a.Amount)); } return(string.Format( CultureInfo.CurrentCulture, "Total Ledger Balance: {0:N}; Adjusted Bank Balance {1:N}; {2}", line.LedgerBalance, line.TotalBankBalance + line.TotalBalanceAdjustments, individualLedgerBalances)); }
/// <summary> /// Used to show the bank balances involved in this <see cref="LedgerEntryLine" />. /// Only shows balances at this stage, no editing allowed. /// </summary> public void ShowViewDialog([NotNull] Engine.Ledger.LedgerBook ledgerBook, [NotNull] LedgerEntryLine line) { if (ledgerBook == null) { throw new ArgumentNullException(nameof(ledgerBook)); } if (line == null) { throw new ArgumentNullException(nameof(line)); } this.parentBook = ledgerBook; Date = line.Date; BankBalances = new ObservableCollection <BankBalanceViewModel>(line.BankBalances.Select(b => new BankBalanceViewModel(line, b))); CreateMode = false; AddBalanceVisibility = false; Editable = false; // Bank balances are not editable after creating a new Ledger Line at this stage. ShowDialogCommon(Editable ? "Edit Bank Balances" : "Bank Balances"); }
public ReconciliationResult CreateNewMonthlyReconciliation( DateTime reconciliationDateExclusive, BudgetModel budget, StatementModel statement, params BankBalance[] bankBalances) { if (bankBalances == null) { throw new ArgumentNullException(nameof(bankBalances)); } if (budget == null) { throw new ArgumentNullException(nameof(budget)); } if (statement == null) { throw new ArgumentNullException(nameof(statement)); } if (LedgerBook == null) { throw new ArgumentException("The Ledger Book property cannot be null. You must set this prior to calling this method."); } try { this.newReconciliationLine = new LedgerEntryLine(reconciliationDateExclusive, bankBalances); AddNew(budget, statement, CalculateDateForReconcile(LedgerBook, reconciliationDateExclusive)); return(new ReconciliationResult { Reconciliation = this.newReconciliationLine, Tasks = this.toDoList }); } finally { this.newReconciliationLine = null; } }
private int AddSurplusCell(Grid grid, int gridRow, int gridColumn, LedgerEntryLine line) { AddBorderToGridCell(grid, SurplusBackground, false, gridRow, gridColumn); var stackPanel = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Right }; grid.Children.Add(stackPanel); Grid.SetRow(stackPanel, gridRow); Grid.SetColumn(stackPanel, gridColumn); if (line.SurplusBalances.Any(b => b.Balance < 0)) { var warningImage = new ContentControl { Template = (ControlTemplate)FindResource("WarningImage"), Width = 20, Height = 20, Margin = new Thickness(5), ToolTip = "There are one or more negative surplus balances!" }; stackPanel.Children.Add(warningImage); } var hyperlink = new Hyperlink(new Run(line.CalculatedSurplus.ToString("N", CultureInfo.CurrentCulture))) { Command = this.showSurplusBalancesCommand, CommandParameter = line }; var textBlock = new TextBlock(hyperlink) { Style = (Style)FindResource(ImportantNumberStyle), ToolTip = string.Format(CultureInfo.CurrentCulture, "Total Surplus: {0:N}. Click for more detail...", line.CalculatedSurplus), Foreground = (Brush)FindResource(SurplusTextBrush) }; stackPanel.Children.Add(textBlock); return(++gridRow); }
public LedgerTransaction CreateBalanceAdjustment(LedgerEntryLine entryLine, decimal amount, string narrative, Account account) { if (entryLine == null) { throw new ArgumentNullException(nameof(entryLine)); } if (narrative == null) { throw new ArgumentNullException(nameof(narrative)); } if (account == null) { throw new ArgumentNullException(nameof(account)); } var adjustmentTransaction = entryLine.BalanceAdjustment(amount, narrative, account); adjustmentTransaction.Date = entryLine.Date; return(adjustmentTransaction); }
private void OnShowSurplusBalancesCommandExecuted(LedgerEntryLine line) { this.uiContext.ShowSurplusBalancesController.ShowDialog(line); }
partial void ToDtoPostprocessing(ref LedgerEntryLineDto dto, LedgerEntryLine model) { dto.BankBalance = model.TotalBankBalance; }
partial void ToModelPostprocessing(LedgerEntryLineDto dto, ref LedgerEntryLine model) { model.Lock(); }