/// <summary> /// Load the given file into a <see cref="StatementModel" />. /// </summary> /// <param name="fileName">The file to load.</param> /// <param name="accountType"> /// The account type to classify these transactions. This is useful when merging one statement to another. For example, /// merging a cheque account /// export with visa account export, each can be classified using an account type. /// </param> public StatementModel Load(string fileName, AccountType accountType) { this.importUtilities.AbortIfFileDoesntExist(fileName, this.userMessageBox); var transactions = new List<Transaction>(); foreach (string line in ReadLines(fileName)) { if (string.IsNullOrWhiteSpace(line)) { continue; } string[] split = line.Split(','); var transaction = new Transaction { AccountType = accountType, TransactionType = FetchTransactionType(split, 0), Description = this.importUtilities.SafeArrayFetchString(split, 1), Reference1 = this.importUtilities.SafeArrayFetchString(split, 2), Reference2 = this.importUtilities.SafeArrayFetchString(split, 3), Reference3 = this.importUtilities.SafeArrayFetchString(split, 4), Amount = this.importUtilities.SafeArrayFetchDecimal(split, 5), Date = this.importUtilities.SafeArrayFetchDate(split, 6), }; transactions.Add(transaction); } StatementModel statement = new StatementModel(this.logger) { FileName = fileName, LastImport = DateTime.Now, }.LoadTransactions(transactions); return statement; }
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); }
public void Load(StatementModel statementModel, BudgetCollection budgets, GlobalFilterCriteria criteria) { Analysis = new OverallPerformanceBudgetAnalyser(statementModel, budgets, this.bucketRepository); Analysis.Analyse(criteria); OverallPerformance = (double)Analysis.OverallPerformance; ExpenseFilter = true; IncomeFilter = false; RaisePropertyChanged(() => Analysis); ICollectionView view = CollectionViewSource.GetDefaultView(Analysis.Analyses); view.Filter = x => { var bucketAnalysis = x as BucketPerformanceAnalyser; if (bucketAnalysis == null) { return true; } if (IncomeFilter) { return bucketAnalysis.Bucket is IncomeBudgetBucket; } bool result = !(bucketAnalysis.Bucket is IncomeBudgetBucket); return result; }; }
public void DetectDuplicateTransactions_ShouldSummaryText_GivenTestData4() { this.testData = StatementModelTestData.TestData4(); Arrange(); string result = this.subject.DetectDuplicateTransactions(); Console.WriteLine(result); Assert.IsFalse(string.IsNullOrWhiteSpace(result)); }
public override void Update([NotNull] params object[] input) { if (input == null) { throw new ArgumentNullException("input"); } if (!ValidateUpdateInput(input)) { Enabled = false; return; } Budget = (BudgetCurrencyContext)input[0]; this.statement = (StatementModel)input[1]; Filter = (GlobalFilterCriteria)input[2]; this.bucketRepository = (IBudgetBucketRepository)input[3]; if (!this.bucketRepository.IsValidCode(BucketCode)) { Enabled = false; return; } SetAdditionalDependencies(input); if (this.statement == null || Budget == null || Filter == null || Filter.Cleared || Filter.BeginDate == null || Filter.EndDate == null) { Enabled = false; return; } Enabled = true; decimal totalBudget = MonthlyBudgetAmount() * Filter.BeginDate.Value.DurationInMonths(Filter.EndDate.Value); Maximum = Convert.ToDouble(totalBudget); // Debit transactions are negative so normally the total spend will be a negative number. decimal remainingBudget = totalBudget + this.statement.Transactions.Where(t => t.BudgetBucket != null && t.BudgetBucket.Code == BucketCode).Sum(t => t.Amount); if (remainingBudget < 0) { remainingBudget = 0; } Value = Convert.ToDouble(remainingBudget); ToolTip = string.Format(CultureInfo.CurrentCulture, RemainingBudgetToolTip, remainingBudget); if (remainingBudget < 0.2M * totalBudget) { ColourStyleName = WidgetWarningStyle; } else { ColourStyleName = this.standardStyle; } }
public async Task CreateNewAndSaveAsync(string storageKey) { if (storageKey.IsNothing()) { throw new ArgumentNullException(nameof(storageKey)); } var newStatement = new StatementModel(this.logger) { StorageKey = storageKey }; await SaveAsync(newStatement, storageKey, false); }
private static DateTime CalculateEndDate(StatementModel statement, GlobalFilterCriteria criteria) { if (criteria.Cleared || criteria.EndDate == null) { DateTime maxDate = statement.AllTransactions.Max(t => t.Date).Date; return maxDate.LastDateInMonth(); } return criteria.EndDate.Value; }
private void Act(StatementModel testData) { var subject = new Mapper_TransactionSetDto_StatementModel( new FakeLogger(), new Mapper_TransactionDto_Transaction( new InMemoryAccountTypeRepository(), new BucketBucketRepoAlwaysFind(), new InMemoryTransactionTypeRepository())); Result = subject.ToDto(testData); }
/// <summary> /// Statement Model with transactions between 15/07/2013 and 14/09/2013 /// Includes income transactions. /// </summary> public static StatementModel TestData2() { var statement = new StatementModel(new FakeLogger()) { FileName = @"C:\TestData2\Foo2Statement.csv", LastImport = new DateTime(2013, 08, 15), }; var transactions = CreateTransactions2(); statement.LoadTransactions(transactions); return statement; }
/// <summary> /// Statement Model with transactions between 15/07/2013 and 14/09/2013 /// Includes income transactions. /// Adjusted for use with LedgerCalculator - No ledgers will be overdrawn when using LedgerBook TestData 1. /// </summary> public static StatementModel TestData3() { var statement = new StatementModel(new FakeLogger()) { StorageKey = @"C:\TestData3\Foo2Statement.csv", LastImport = new DateTime(2013, 08, 15) }; IEnumerable<Transaction> transactions = CreateTransactions3(); statement.LoadTransactions(transactions); return statement; }
/// <summary> /// Imports a bank statement file and merges it into an existing statement model. You cannot merge two Budget Analyser /// Statement files. /// </summary> public StatementModel ImportAndMergeBankStatement(StatementModel statementModel, bool throwIfFileNotFound = false) { var task = GetFileNameFromUser(OpenMode.Merge, statementModel); task.Wait(); var fileName = task.Result; if (string.IsNullOrWhiteSpace(fileName)) { // User cancelled return null; } return LoadAnyStatementFile(fileName); }
public override void Update([NotNull] params object[] input) { if (input == null) { throw new ArgumentNullException("input"); } if (!ValidateUpdateInput(input)) { Enabled = false; return; } this.statement = (StatementModel)input[0]; this.filter = (GlobalFilterCriteria)input[1]; this.ledgerBook = (LedgerBook)input[2]; if (this.ledgerBook == null || this.statement == null || this.filter == null || this.filter.Cleared || this.filter.BeginDate == null || this.filter.EndDate == null) { Enabled = false; return; } if (this.filter.BeginDate.Value.DurationInMonths(this.filter.EndDate.Value) != 1) { ToolTip = DesignedForOneMonthOnly; Enabled = false; return; } Enabled = true; decimal openingBalance = CalculateOpeningBalance(this.filter, this.ledgerBook); decimal remainingBalance = LedgerCalculation.CalculateCurrentMonthSurplusBalance(this.ledgerBook, this.filter, this.statement); Maximum = Convert.ToDouble(openingBalance); Value = Convert.ToDouble(remainingBalance); Minimum = 0; if (remainingBalance < 0.2M * openingBalance) { ColourStyleName = WidgetWarningStyle; } else { ColourStyleName = this.standardStyle; } ToolTip = string.Format(CultureInfo.CurrentCulture, "Remaining Surplus for period is {0:C} of {1:C}", remainingBalance, openingBalance); }
public StatementModel Build() { if (this.additionalTransactions.None()) { return this.model; } // IEnumerable<MethodInfo> privateMergeMethods = this.model.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic).Where(m => m.Name == "Merge"); // MethodInfo privateMergeMethod = privateMergeMethods.First(m => m.IsPrivate); // privateMergeMethod.Invoke(this.model, new object[] { this.additionalTransactions }); var additionalTransactionsModel = new StatementModel(new FakeLogger()) { LastImport = this.additionalTransactions.Max(t => t.Date).Date, }; additionalTransactionsModel.LoadTransactions(this.additionalTransactions); return this.model.Merge(additionalTransactionsModel); }
/// <summary> /// Creates a new LedgerEntryLine for this <see cref="LedgerBook" />. /// </summary> /// <param name="date"> /// The date for the <see cref="LedgerEntryLine" />. Also used to search for transactions in the /// <see cref="statement" />. /// </param> /// <param name="bankBalances"> /// The bank balances as at the <see cref="date" /> to include in this new single line of the /// ledger book. /// </param> /// <param name="budget">The current budget.</param> /// <param name="statement">The currently loaded statement.</param> /// <param name="ignoreWarnings">Ignores validation warnings if true, otherwise <see cref="ValidationWarningException" />.</param> /// <exception cref="InvalidOperationException">Thrown when this <see cref="LedgerBook" /> is in an invalid state.</exception> public LedgerEntryLine Reconcile( DateTime date, IEnumerable<BankBalance> bankBalances, BudgetModel budget, StatementModel statement = null, bool ignoreWarnings = false) { try { PreReconciliationValidation(date, statement); } catch (ValidationWarningException) { if (!ignoreWarnings) { throw; } } decimal consistencyCheck1 = DatedEntries.Sum(e => e.CalculatedSurplus); var newLine = new LedgerEntryLine(date, bankBalances); var previousEntries = new Dictionary<LedgerColumn, LedgerEntry>(); LedgerEntryLine previousLine = this.datedEntries.FirstOrDefault(); foreach (LedgerColumn ledger in Ledgers) { LedgerEntry previousEntry = null; if (previousLine != null) { previousEntry = previousLine.Entries.FirstOrDefault(e => e.LedgerColumn.Equals(ledger)); } previousEntries.Add(ledger, previousEntry); } newLine.AddNew(previousEntries, budget, statement, CalculateStartDateForReconcile(date)); decimal consistencyCheck2 = DatedEntries.Sum(e => e.CalculatedSurplus); if (consistencyCheck1 != consistencyCheck2) { throw new CorruptedLedgerBookException("Code Error: The previous dated entries have changed, this is not allowed. Data is corrupt."); } this.datedEntries.Insert(0, newLine); this.newlyAddedLedgers.Clear(); return newLine; }
public BurnDownCharts BuildAllCharts( StatementModel statementModel, BudgetModel budgetModel, LedgerBook ledgerBookModel, GlobalFilterCriteria criteria) { if (criteria == null) throw new ArgumentNullException(nameof(criteria)); if (criteria.Cleared) throw new ArgumentException("There is no date range criteria set. This graph is intended for one month of data."); if (criteria.EndDate == null || criteria.BeginDate == null) { throw new ArgumentException("There is no date range set; either the begin or end date is not set. This graph is intended for one month of data."); } if (criteria.EndDate.Value.Subtract(criteria.EndDate.Value).Days > 31) { throw new ArgumentException("The date range is too great for this graph. This graph is intended for one month of data."); } this.chartsBuilder.Build(criteria, statementModel, budgetModel, ledgerBookModel); return this.chartsBuilder.Results; }
public void Build( GlobalFilterCriteria criteria, StatementModel statementModel, BudgetModel budgetModel, LedgerBook ledgerBookModel) { var beginDate = CalculateBeginDate(criteria); var dateRangeDescription = string.Format(CultureInfo.CurrentCulture, "For the month starting {0:D} to {1:D} inclusive.", beginDate, beginDate.AddMonths(1).AddDays(-1)); var listOfCharts = new List<BurnDownChartAnalyserResult>(this.budgetBucketRepository.Buckets.Count()); foreach (var bucket in this.budgetBucketRepository.Buckets .Where(b => b is ExpenseBucket && b.Active) .OrderBy(b => b.Code)) { var analysis = AnalyseDataForChart(statementModel, budgetModel, ledgerBookModel, bucket, beginDate); analysis.ChartTitle = string.Format(CultureInfo.CurrentCulture, "{0} Spending Chart", bucket.Code); listOfCharts.Add(analysis); } listOfCharts = listOfCharts.ToList(); // Put surplus at the top. var analysisResult = AnalyseDataForChart(statementModel, budgetModel, ledgerBookModel, this.budgetBucketRepository.SurplusBucket, beginDate); analysisResult.ChartTitle = string.Format(CultureInfo.CurrentCulture, "{0} Spending Chart", this.budgetBucketRepository.SurplusBucket); listOfCharts.Insert(0, analysisResult); // Put any custom charts on top. foreach (var customChart in CustomCharts) { IEnumerable<BudgetBucket> buckets = this.budgetBucketRepository.Buckets .Join(customChart.BucketIds, bucket => bucket.Code, code => code, (bucket, code) => bucket); var analysis = AnalyseDataForChart(statementModel, budgetModel, ledgerBookModel, buckets, beginDate); analysis.ChartTitle = customChart.Name; analysis.IsCustomAggregateChart = true; listOfCharts.Insert(0, analysis); } Results = new BurnDownCharts(beginDate, dateRangeDescription, listOfCharts); }
internal virtual StatementModel Merge([NotNull] StatementModel additionalModel) { ThrowIfDisposed(); if (additionalModel == null) { throw new ArgumentNullException(nameof(additionalModel)); } var combinedModel = new StatementModel(this.logger) { LastImport = additionalModel.LastImport, StorageKey = StorageKey }; List <Transaction> mergedTransactions = AllTransactions.ToList().Merge(additionalModel.AllTransactions).ToList(); combinedModel.LoadTransactions(mergedTransactions); return(combinedModel); }
/// <summary> /// Updates the widget with new input. /// </summary> /// <exception cref="System.ArgumentNullException"></exception> public override void Update([NotNull] params object[] input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } Enabled = false; if (!ValidateUpdateInput(input)) return; LedgerBook = (LedgerBook) input[0]; StatementModel = (StatementModel) input[1]; BudgetCollection = (BudgetCollection) input[2]; Filter = (GlobalFilterCriteria) input[3]; if (LedgerBook == null || StatementModel == null || BudgetCollection == null || Filter == null) return; Enabled = true; }
public OverallPerformanceBudgetResult BuildChart(StatementModel statementModel, BudgetCollection budgets, GlobalFilterCriteria criteria) { if (statementModel == null) { throw new ArgumentNullException(nameof(statementModel)); } if (budgets == null) { throw new ArgumentNullException(nameof(budgets)); } if (criteria == null) { throw new ArgumentNullException(nameof(criteria)); } return this.analyser.Analyse(statementModel, budgets, criteria); }
public BurnDownChartAnalyserResult CreateNewCustomAggregateChart( StatementModel statementModel, BudgetModel budgetModel, IEnumerable<BudgetBucket> buckets, LedgerBook ledgerBookModel, DateTime beginDate, string chartTitle) { List<BudgetBucket> bucketsList = buckets.ToList(); var result = this.chartAnalyser.Analyse(statementModel, budgetModel, bucketsList, ledgerBookModel, beginDate); result.ChartTitle = chartTitle; var persistChart = new CustomAggregateBurnDownGraph { BucketIds = bucketsList.Select(b => b.Code).ToList(), Name = chartTitle }; this.chartsBuilder.CustomCharts = this.chartsBuilder.CustomCharts.Union(new[] { persistChart }).ToList(); return result; }
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 BucketBurnDownController Load( StatementModel statementModel, BudgetModel budgetModel, [NotNull] BudgetBucket bucket, DateTime beginDate, Engine.Ledger.LedgerBook ledgerBook) { if (bucket == null) { throw new ArgumentNullException("bucket"); } this.Background = ConverterHelper.TileBackgroundBrush; this.Bucket = bucket; this.ActualSpendingLabel = this.Bucket.Code; this.ChartTitle = string.Format(CultureInfo.CurrentCulture, "{0} Spending Chart", bucket.Code); this.burnDownGraphAnalyser.Analyse(statementModel, budgetModel, new[] { bucket }, beginDate, ledgerBook); CopyOutputFromAnalyser(); return this; }
public OverallPerformanceBudgetAnalyser([NotNull] StatementModel statement, [NotNull] BudgetCollection budgets, [NotNull] IBudgetBucketRepository bucketRepository) { if (statement == null) { throw new ArgumentNullException("statement"); } if (budgets == null) { throw new ArgumentNullException("budgets"); } if (bucketRepository == null) { throw new ArgumentNullException("bucketRepository"); } this.statement = statement; this.budgets = budgets; this.bucketRepository = bucketRepository; }
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)); CreateToDoForAnyOverdrawnSurplusBalance(); return new ReconciliationResult { Reconciliation = this.newReconciliationLine, Tasks = this.toDoList }; } finally { this.newReconciliationLine = null; } }
public GraphData BuildChart(StatementModel statementModel, GlobalFilterCriteria criteria) { if (statementModel == null) { throw new ArgumentNullException(nameof(statementModel)); } if (criteria == null) { throw new ArgumentNullException(nameof(criteria)); } if (statementModel.Transactions.Any(t => t.BudgetBucket == null)) { throw new ArgumentException("There are uncategorised transactions, finish assigning a bucket to all transactions before this running this graph."); } this.analyser.Analyse(statementModel, criteria); var result = this.analyser.Graph; this.analyser.Reset(); return result; }
public void Build(GlobalFilterCriteria criteria, StatementModel statementModel, BudgetModel budgetModel, Engine.Ledger.LedgerBook ledgerBookModel) { var beginDate = CalculateBeginDate(criteria); var dateRangeDescription = String.Format(CultureInfo.CurrentCulture, "For the month starting {0:D} to {1:D} inclusive.", beginDate, beginDate.AddMonths(1).AddDays(-1)); var listOfCharts = new List<BucketBurnDownController>(this.budgetBucketRepository.Buckets.Count()); foreach (BudgetBucket bucket in this.budgetBucketRepository.Buckets .Where(b => b is ExpenseBucket) .OrderBy(b => b.Code)) { BucketBurnDownController chartController = this.bucketSpendingFactory(); chartController.Load(statementModel, budgetModel, bucket, beginDate, ledgerBookModel); listOfCharts.Add(chartController); } listOfCharts = listOfCharts.OrderBy(x => x.Bucket).ToList(); // Put surplus at the top. listOfCharts.Insert( 0, this.bucketSpendingFactory().Load(statementModel, budgetModel, this.budgetBucketRepository.SurplusBucket, beginDate, ledgerBookModel)); // Put any custom charts on top. foreach (CustomAggregateBurnDownGraph customChart in this.CustomCharts) { BucketBurnDownController chartController = this.bucketSpendingFactory(); IEnumerable<BudgetBucket> buckets = this.budgetBucketRepository.Buckets .Join(customChart.BucketIds, bucket => bucket.Code, code => code, (bucket, code) => bucket); chartController.LoadCustomChart(statementModel, budgetModel, buckets, beginDate, ledgerBookModel, customChart.Name); listOfCharts.Insert(0, chartController); } this.Results = new BurnDownChartBuilderResults(beginDate, dateRangeDescription, listOfCharts); }
private static decimal CalculateSavingsToDateWithTrackedLedgers(StatementModel statement, LedgerBook ledger) { if (ledger == null) { return 0; } var trackedSavingsLedgers = ledger.Ledgers .Where(l => l.BudgetBucket is SavingsCommitmentBucket) .Select(l => l.BudgetBucket) .ToList(); if (!trackedSavingsLedgers.Any()) { return SumDebitSavingsTransactions(statement); } decimal savingsToDate = CalculateTrackedSavingLedgersContributions(statement, trackedSavingsLedgers); // Other non-ledger-book-tracked savings will appear as debits in the statement so need to be negated. var otherNontrackedSavings = statement.Transactions.Where(t => t.BudgetBucket is SavingsCommitmentBucket && trackedSavingsLedgers.All(b => b != t.BudgetBucket)); savingsToDate += otherNontrackedSavings.Sum(t => -t.Amount); return savingsToDate; }
internal virtual StatementModel Merge([NotNull] StatementModel additionalModel) { ThrowIfDisposed(); if (additionalModel == null) { throw new ArgumentNullException(nameof(additionalModel)); } var combinedModel = new StatementModel(this.logger) { LastImport = additionalModel.LastImport, StorageKey = StorageKey }; List<Transaction> mergedTransactions = AllTransactions.ToList().Merge(additionalModel.AllTransactions).ToList(); combinedModel.LoadTransactions(mergedTransactions); return combinedModel; }
public void Load( [NotNull] StatementModel statementModel, [NotNull] BudgetModel budgetModel, [NotNull] GlobalFilterCriteria criteria, Engine.Ledger.LedgerBook ledgerBookModel) { if (statementModel == null) { throw new ArgumentNullException("statementModel"); } if (budgetModel == null) { throw new ArgumentNullException("budgetModel"); } if (criteria == null) { throw new ArgumentNullException("criteria"); } this.statement = statementModel; this.budget = budgetModel; this.ledgerBook = ledgerBookModel; this.chartBuilder.Build(criteria, statementModel, budgetModel, ledgerBookModel); this.beginDate = this.chartBuilder.Results.BeginDate; DateRangeDescription = this.chartBuilder.Results.DateRangeDescription; ChartControllers = new BindingList<BucketBurnDownController>(this.chartBuilder.Results.Charts.ToList()); RaisePropertyChanged(() => ChartControllers); }
public async Task SaveAsync(StatementModel model, string storageKey, bool isEncrypted) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (storageKey.IsNothing()) { throw new ArgumentNullException(nameof(storageKey)); } var transactionSet = this.mapper.ToDto(model); transactionSet.VersionHash = VersionHash; transactionSet.StorageKey = storageKey; transactionSet.Checksum = CalculateTransactionCheckSum(transactionSet); if (model.AllTransactions.Count() != transactionSet.Transactions.Count()) { throw new StatementModelChecksumException( string.Format( CultureInfo.InvariantCulture, "Only {0} out of {1} transactions have been mapped correctly. Aborting the save, to avoid data loss and corruption.", transactionSet.Transactions.Count, model.AllTransactions.Count())); } var writer = this.readerWriterSelector.SelectReaderWriter(isEncrypted); using (var stream = writer.CreateWritableStream(storageKey)) { using (var streamWriter = new StreamWriter(stream)) { WriteHeader(streamWriter, transactionSet); foreach (var transaction in transactionSet.Transactions) { var line = new StringBuilder(); line.Append(transaction.TransactionType); line.Append(","); line.Append(transaction.Description); line.Append(","); line.Append(transaction.Reference1); line.Append(","); line.Append(transaction.Reference2); line.Append(","); line.Append(transaction.Reference3); line.Append(","); line.Append(transaction.Amount); line.Append(","); line.Append(transaction.Date.ToString("O", CultureInfo.InvariantCulture)); line.Append(","); line.Append(transaction.BudgetBucketCode); line.Append(","); line.Append(transaction.Account); line.Append(","); line.Append(transaction.Id); line.Append(","); await streamWriter.WriteLineAsync(line.ToString()); } await streamWriter.FlushAsync(); } } }
public StatementReadyMessage(StatementModel statement) { StatementModel = statement; }
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; }