A type representing any bank account.
        /// <summary>
        ///     Import the given file.  It is recommended to call <see cref="IBankStatementImporterRepository.CanImportAsync" />
        ///     first.
        ///     If the file cannot
        ///     be imported by any of this repositories importers a <see cref="NotSupportedException" /> will be thrown.
        /// </summary>
        public async Task<StatementModel> ImportAsync(string fullFileName, Account account)
        {
            foreach (var importer in this.importers)
            {
                if (await importer.TasteTestAsync(fullFileName))
                {
                    return await importer.LoadAsync(fullFileName, account);
                }
            }

            throw new NotSupportedException("The requested file name cannot be loaded. It is not of any known format.");
        }
        /// <summary>
        ///     Load the given file into a <see cref="StatementModel" />.
        /// </summary>
        /// <param name="fileName">The file to load.</param>
        /// <param name="account">
        ///     The account 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.
        /// </param>
        public async Task<StatementModel> LoadAsync(string fileName, Account account)
        {
            try
            {
                this.importUtilities.AbortIfFileDoesntExist(fileName);
            }
            catch (FileNotFoundException ex)
            {
                throw new KeyNotFoundException(ex.Message, ex);
            }

            var transactions = new List<Transaction>();
            var firstTime = true;
            foreach (var line in await ReadLinesAsync(fileName))
            {
                if (firstTime)
                {
                    // File contains column headers
                    firstTime = false;
                    continue;
                }

                if (string.IsNullOrWhiteSpace(line))
                {
                    continue;
                }

                string[] split = line.Split(',');
                var transaction = new Transaction
                {
                    Account = account,
                    Description = this.importUtilities.FetchString(split, DescriptionIndex),
                    Reference1 = this.importUtilities.FetchString(split, Reference1Index),
                    Reference2 = this.importUtilities.FetchString(split, Reference2Index),
                    Reference3 = this.importUtilities.FetchString(split, Reference3Index),
                    Amount = this.importUtilities.FetchDecimal(split, AmountIndex),
                    Date = this.importUtilities.FetchDate(split, DateIndex)
                };
                transaction.TransactionType = FetchTransactionType(split, transaction.Amount);
                transactions.Add(transaction);
            }

            var statement = new StatementModel(this.logger)
            {
                StorageKey = fileName,
                LastImport = DateTime.Now
            }.LoadTransactions(transactions);

            return statement;
        }
        public async Task<StatementModel> ImportBankStatementAsync(
            string storageKey,
            Account account)
        {
            if (string.IsNullOrWhiteSpace(storageKey))
            {
                throw new ArgumentNullException(nameof(storageKey));
            }

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

            return await this.importerRepository.ImportAsync(storageKey, account);
        }
        public LedgerBucket Build(string bucketCode, Account account)
        {
            var bucket = this.bucketRepo.GetByCode(bucketCode);
            if (bucket is SavedUpForExpenseBucket)
            {
                return new SavedUpForLedger { BudgetBucket = bucket, StoredInAccount = account };
            }

            if (bucket is SpentMonthlyExpenseBucket)
            {
                return new SpentMonthlyLedger { BudgetBucket = bucket, StoredInAccount = account };
            }

            if (bucket is SavingsCommitmentBucket)
            {
                return new SavedUpForLedger { BudgetBucket = bucket, StoredInAccount = account };
            }

            throw new NotSupportedException(
                $"Unsupported budget bucket {bucketCode} with type {bucket.GetType().Name}, found in ledger book");
        }
        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 Reset()
 {
     this.parentBook = null;
     Date = DateTime.MinValue;
     BankBalances = null;
     BankAccounts = null;
     SelectedBankAccount = null;
 }
 private void AddNewBankBalance()
 {
     BankBalances.Add(new BankBalanceViewModel(null, SelectedBankAccount, BankBalance));
     SelectedBankAccount = null;
     BankBalance = 0;
     RaisePropertyChanged(() => HasRequiredBalances);
 }
 private decimal TotalBankBalanceAdjustmentForAccount(Account account)
 {
     return BankBalanceAdjustments.Where(a => a.BankAccount == account).Sum(a => a.Amount);
 }
        internal BankBalanceAdjustmentTransaction BalanceAdjustment(decimal adjustment, string narrative,
                                                                    Account account)
        {
            if (!IsNew)
            {
                throw new InvalidOperationException(
                    "Cannot adjust existing ledger lines, only newly added lines can be adjusted.");
            }

            if (adjustment == 0)
            {
                throw new ArgumentException("The balance adjustment amount cannot be zero.", nameof(adjustment));
            }

            var newAdjustment = new BankBalanceAdjustmentTransaction
            {
                Date = Date,
                Narrative = narrative,
                Amount = adjustment,
                BankAccount = account
            };

            this.bankBalanceAdjustments.Add(newAdjustment);
            return newAdjustment;
        }
Exemple #10
0
        /// <summary>
        ///     Used to allow the UI to set a ledger's account, but only if it is an instance in the <see cref="Ledgers" />
        ///     collection.
        /// </summary>
        /// <param name="ledger"></param>
        /// <param name="storedInAccount"></param>
        internal void SetLedgerAccount(LedgerBucket ledger, Account storedInAccount)
        {
            if (Ledgers.Any(l => l == ledger))
            {
                ledger.StoredInAccount = storedInAccount;
                return;
            }

            throw new InvalidOperationException(
                "You cannot change the account in a ledger that is not in the Ledgers collection.");
        }
 private void Reset()
 {
     this.ledger = null;
     MonthlyBudgetAmount = 0;
     BankAccounts.Clear();
     StoredInAccount = null;
 }
        /// <summary>
        ///     Imports a bank's transaction extract and merges it with the currently loaded Budget Analyser Statement.
        ///     This method should not be used without a <see cref="StatementModel" /> loaded.
        ///     It is recommended to follow this up with <see cref="ValidateWithCurrentBudgetsAsync" />.
        /// </summary>
        /// <exception cref="System.ArgumentNullException">
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        ///     There are no transactions loaded, you must first load an existing
        ///     file or create a new one.
        /// </exception>
        /// <exception cref="BudgetAnalyser.Engine.Statement.TransactionsAlreadyImportedException"></exception>
        public async Task ImportAndMergeBankStatementAsync(string storageKey, Account account)
        {
            if (storageKey.IsNothing())
            {
                throw new ArgumentNullException(nameof(storageKey));
            }

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

            if (StatementModel == null)
            {
                throw new InvalidOperationException(
                    "There are no transactions loaded, you must first load an existing file or create a new one.");
            }

            var additionalModel = await this.statementRepository.ImportBankStatementAsync(storageKey, account);
            var combinedModel = StatementModel.Merge(additionalModel);
            IEnumerable<IGrouping<int, Transaction>> duplicates = combinedModel.ValidateAgainstDuplicates();
            if (duplicates.Count() == additionalModel.AllTransactions.Count())
            {
                throw new TransactionsAlreadyImportedException();
            }

            StatementModel.Dispose();
            StatementModel = combinedModel;
            NewDataAvailable();
        }
 public BudgetBucketChosenEventArgs(Guid correlationId, BudgetBucket bucket, Account storeInThisAccount)
     : this(correlationId, bucket)
 {
     StoreInThisAccount = storeInThisAccount;
 }
        private void ShowDialogCommon(string title)
        {
            Canceled = false;
            List<Account> accountsToShow = this.accountTypeRepository.ListCurrentlyUsedAccountTypes().ToList();
            BankAccounts = accountsToShow.OrderBy(a => a.Name);
            SelectedBankAccount = null;
            this.dialogCorrelationId = Guid.NewGuid();
            var dialogRequest = new ShellDialogRequestMessage(BudgetAnalyserFeature.LedgerBook, this, ShellDialogType.OkCancel)
            {
                CorrelationId = this.dialogCorrelationId,
                Title = title,
                HelpAvailable = CreateMode
            };

            MessengerInstance.Send(dialogRequest);
        }
        public void ShowDialog([NotNull] Engine.Ledger.LedgerBook parentLedgerBook, [NotNull] LedgerBucket ledgerBucket, [NotNull] BudgetModel budgetModel)
        {
            if (parentLedgerBook == null)
            {
                throw new ArgumentNullException(nameof(parentLedgerBook));
            }

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

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

            if (LedgerBucketHistoryAnalysis == null)
            {
                LedgerBucketHistoryAnalysis = CreateBucketHistoryAnalyser();
            }
            LedgerBucketHistoryAnalysis.Analyse(ledgerBucket, parentLedgerBook);
            this.ledger = ledgerBucket;
            BankAccounts = new ObservableCollection<Account>(this.accountRepo.ListCurrentlyUsedAccountTypes());
            BucketBeingTracked = ledgerBucket.BudgetBucket;
            StoredInAccount = ledgerBucket.StoredInAccount;
            MonthlyBudgetAmount = budgetModel.Expenses.Single(e => e.Bucket == BucketBeingTracked).Amount;
            this.correlationId = Guid.NewGuid();

            var dialogRequest = new ShellDialogRequestMessage(BudgetAnalyserFeature.LedgerBook, this, ShellDialogType.OkCancel)
            {
                CorrelationId = this.correlationId,
                Title = "Ledger - " + BucketBeingTracked,
                HelpAvailable = true
            };

            MessengerInstance.Send(dialogRequest);
        }
Exemple #16
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="BankBalance" /> class.
 /// </summary>
 public BankBalance(Account account, decimal balance)
 {
     Account = account;
     Balance = balance;
 }
        private void Reset()
        {
            if (this.filtered)
            {
                BudgetBuckets = this.bucketRepository.Buckets.ToList();
            }

            Selected = null;
            StoreInThisAccount = null;
        }