Пример #1
0
        // Assumes we're parsing for a credit card, specifically AMEX
        private List <TransactionForDisplay> ParseCsv(StreamReader reader, Guid accountId, DateTime?fromDate)
        {
            var transactions = new List <TransactionForDisplay>();

            // Trash the header line
            reader.ReadLine();

            while (reader.Peek() >= 0)
            {
                var line = reader.ReadLine().Split(',');
                var trx  = new TransactionForDisplay
                {
                    TransactionId   = Guid.NewGuid(),
                    AccountId       = accountId,
                    EnteredDate     = DateTime.Now,
                    Vendor          = "",
                    TransactionDate = DateTime.Parse(line[0]),
                    Description     = line[1],
                    Amount          = -decimal.Parse(line[4])
                };
                trx.SetDebitAndCredit();
                if (!fromDate.HasValue || trx.TransactionDate >= fromDate.Value)
                {
                    transactions.Add(trx);
                }
            }
            return(transactions);
        }
Пример #2
0
 public void InsertRelatedTransaction(TransactionForDisplay first, TransactionForDisplay second)
 {
     first.RelatedTransactionId = null;
     Insert(first);
     Insert(second);
     first.RelatedTransactionId = second.TransactionId;
     Update(first);
 }
Пример #3
0
        public IActionResult PostTransaction([FromBody] TransactionForDisplay transaction)
        {
            var transactions = new List <TransactionForDisplay>();

            if (transaction.TransactionId == null || transaction.TransactionId == Guid.Empty)
            {
                transaction.TransactionId = Guid.NewGuid();
            }
            if (transaction.AccountId == null)
            {
                transaction.AccountId = _accountRepo.GetAll().Single(a => a.Name.Equals(transaction.AccountName, StringComparison.CurrentCultureIgnoreCase)).AccountId;
            }
            transaction.SetAmount();
            transaction.EnteredDate = DateTime.Now;
            if (transaction.CategoryId.IsNullOrEmpty() && !string.IsNullOrWhiteSpace(transaction.CategoryName))
            {
                var category = _categoryRepo.GetAll().SingleOrDefault(c => (c.Name.Equals(transaction.CategoryName, StringComparison.CurrentCultureIgnoreCase)));
                if (category == null)
                {
                    category = new Category
                    {
                        CategoryId = Guid.NewGuid(),
                        Name       = transaction.CategoryName,
                        Type       = "Expenses"
                    };
                    _categoryRepo.Insert(category);
                }
                transaction.CategoryId = category.CategoryId;
            }

            var bankFeeTransactions = TransactionHelpers.GetBankFeeTransactions(transaction, _categoryRepo, _accountRepo);

            transactions.Add(transaction);
            transactions.AddRange(bankFeeTransactions);
            foreach (var trx in transactions)
            {
                _transactionRepo.Insert(trx);
            }

            var accountBalances       = _accountRepo.GetAccountBalances().Select(a => new { a.AccountId, a.CurrentBalance });
            InvoiceForPosting invoice = null;

            if (transaction.InvoiceId.HasValue)
            {
                invoice = _invoiceRepo.Get(transaction.InvoiceId.Value);
            }
            var vendor = _vendorRepo.GetAll().SingleOrDefault(v => v.Name == transaction.Vendor);

            return(CreatedAtAction("PostTransaction", new { id = transaction.TransactionId }, new { transactions, accountBalances, invoice, vendor }));
        }
Пример #4
0
        public IActionResult PostAccount([FromBody] AccountForPosting account)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            var newAccount = new Account
            {
                AccountId       = Guid.NewGuid(),
                Name            = account.Name,
                Currency        = account.Currency,
                Vendor          = account.Vendor,
                AccountType     = account.AccountType,
                MortgagePayment = account.MortgagePayment,
                MortgageType    = account.MortgageType
            };

            _accountRepo.Insert(newAccount);

            var category    = TransactionHelpers.GetOrCreateCategory("Starting Balance", _categoryRepo);
            var transaction = new TransactionForDisplay
            {
                TransactionId   = Guid.NewGuid(),
                AccountId       = newAccount.AccountId,
                Amount          = account.StartingBalance,
                TransactionDate = account.StartDate,
                Vendor          = "",
                Description     = "",
                CategoryId      = category.CategoryId,
                CategoryName    = category.Name,
                EnteredDate     = account.StartDate,
                IsReconciled    = true
            };

            _transactionRepo.Insert(transaction);

            var model = new AccountWithTransactions
            {
                AccountId      = newAccount.AccountId,
                Name           = newAccount.Name,
                Transactions   = new List <TransactionForDisplay>(new[] { transaction }),
                CurrentBalance = account.StartingBalance
            };

            return(CreatedAtAction("PostAccount", new { id = newAccount.AccountId }, model));
        }
Пример #5
0
        public IActionResult PostTransfer([FromBody] TransactionForDisplay transaction)
        {
            var transactions = new List <TransactionForDisplay>();

            if (transaction.TransactionId == null || transaction.TransactionId == Guid.Empty)
            {
                transaction.TransactionId = Guid.NewGuid();
            }
            if (!transaction.AccountId.HasValue)
            {
                transaction.AccountId = _accountRepo.GetAll().Single(
                    a => a.Name.Equals(transaction.AccountName, StringComparison.CurrentCultureIgnoreCase)).AccountId;
            }
            transaction.SetAmount();
            var relatedTransactionId = Guid.NewGuid();
            var relatedTransaction   = new TransactionForDisplay {
                TransactionDate      = transaction.TransactionDate,
                TransactionId        = relatedTransactionId,
                Vendor               = transaction.Vendor,
                Description          = transaction.Description,
                AccountId            = transaction.RelatedAccountId.Value,
                Amount               = 0 - transaction.Amount,
                EnteredDate          = DateTime.Now,
                RelatedTransactionId = transaction.TransactionId
            };

            relatedTransaction.SetDebitAndCredit();

            transaction.RelatedTransactionId = relatedTransactionId;

            var bankFeeTransactions = TransactionHelpers.GetBankFeeTransactions(transaction, _categoryRepo, _accountRepo);

            transactions.Add(transaction);
            transactions.Add(relatedTransaction);
            transactions.AddRange(bankFeeTransactions);
            _transactionRepo.InsertRelatedTransaction(transaction, relatedTransaction);
            foreach (var trx in bankFeeTransactions)
            {
                _transactionRepo.Insert(trx);
            }

            var accountBalances = _accountRepo.GetAccountBalances().Select(a => new { a.AccountId, a.CurrentBalance });

            return(CreatedAtAction("PostTransfer",
                                   new { id = transaction.TransactionId }, new { transactions, accountBalances }));
        }
Пример #6
0
        public IActionResult MakeCorrectingEntries()
        {
            var investments        = GetInvestments();
            var currencyController = new CurrenciesController(_currencyRepo);
            var currency           = currencyController.GetExchangeRateFor("CAD").GetAwaiter().GetResult();
            var investmentsTotal   = investments.Sum(i => i.Price * i.Shares);
            var totalInUsd         = investmentsTotal / currency;
            var investmentAccount  = _accountRepo.GetAll().FirstOrDefault(a => a.AccountType == "Investment");

            if (investmentAccount == null)
            {
                return(Ok());
            }

            var bookBalance = _transactionRepo.GetByAccount(investmentAccount.AccountId).Sum(i => i.Amount);

            var difference = Math.Round(totalInUsd - bookBalance, 2);

            if (Math.Abs(difference) >= 1)
            {
                var category    = TransactionHelpers.GetOrCreateCategory("Gain/loss on investments", _categoryRepo);
                var transaction = new TransactionForDisplay {
                    TransactionId   = Guid.NewGuid(),
                    AccountId       = investmentAccount.AccountId,
                    Amount          = difference,
                    CategoryId      = category.CategoryId,
                    CategoryName    = category.Name,
                    CategoryDisplay = category.Name,
                    TransactionDate = DateTime.Now,
                    EnteredDate     = DateTime.Now,
                    Description     = "Gain/loss"
                };
                transaction.SetDebitAndCredit();
                _transactionRepo.Insert(transaction);
                var accountBalances = _accountRepo.GetAccountBalances().Select(a => new { a.AccountId, a.CurrentBalance });
                var transactions    = new[] { transaction };

                return(CreatedAtAction("PostTransaction", new { id = transaction.TransactionId }, new { transactions, accountBalances }));
            }
            else
            {
                return(Ok());
            }
        }
Пример #7
0
        public static IEnumerable <TransactionForDisplay> GetBankFeeTransactions(TransactionForDisplay newTransaction,
                                                                                 ICategoryRepository categoryRepo, IAccountRepository accountRepo)
        {
            var transactions = new List <TransactionForDisplay>();
            var description  = newTransaction.Description;

            var category = GetOrCreateCategory("Bank Fees", categoryRepo);
            var account  = accountRepo.Get(newTransaction.AccountId.Value);

            if (description.Contains("bf:", StringComparison.CurrentCultureIgnoreCase))
            {
                newTransaction.Description = description.Substring(0, description.IndexOf("bf:", StringComparison.CurrentCultureIgnoreCase));
                var parsed = description.Substring(description.IndexOf("bf:", 0, StringComparison.CurrentCultureIgnoreCase));
                while (parsed.StartsWith("bf:", StringComparison.CurrentCultureIgnoreCase))
                {
                    var next = parsed.IndexOf("bf:", 1, StringComparison.CurrentCultureIgnoreCase);
                    if (next == -1)
                    {
                        next = parsed.Length;
                    }
                    var     transactionData = (parsed.Substring(3, next - 3)).Trim().Split(" ");
                    decimal amount;
                    if (decimal.TryParse(transactionData[0], out amount))
                    {
                        var bankFeeDescription = string.Join(" ", transactionData.Skip(1).ToArray());
                        var transaction        = new TransactionForDisplay {
                            TransactionId   = Guid.NewGuid(),
                            TransactionDate = newTransaction.TransactionDate,
                            AccountId       = newTransaction.AccountId,
                            CategoryId      = category.CategoryId,
                            Description     = bankFeeDescription,
                            Vendor          = account.Vendor,
                            Amount          = 0 - amount,
                            Debit           = amount,
                            EnteredDate     = newTransaction.EnteredDate
                        };
                        transactions.Add(transaction);
                    }
                    parsed = parsed.Substring(next);
                }
            }
            return(transactions);
        }
Пример #8
0
        public IActionResult UpdateTransaction([FromRoute] Guid id,
                                               [FromBody] TransactionForDisplay transaction)
        {
            if (id != transaction.TransactionId)
            {
                return(BadRequest());
            }

            var originalAmount = _transactionRepo.Get(transaction.TransactionId).Amount;

            transaction.SetAmount();
            _transactionRepo.Update(transaction);
            InvoiceForPosting invoice = null;

            if (transaction.InvoiceId.HasValue)
            {
                invoice = _invoiceRepo.Get(transaction.InvoiceId.Value);
            }

            return(Ok(new { transaction, originalAmount, accountBalances = _accountRepo.GetAccountBalances(), invoice }));
        }
Пример #9
0
 public void Insert(TransactionForDisplay transaction)
 {
     using (var conn = Connection)
     {
         conn.Open();
         using (var trx = conn.BeginTransaction())
         {
             try
             {
                 conn.Execute(
                     @"INSERT INTO transactions (transaction_id, account_id, vendor, description, is_reconciled, transaction_date, category_id,
             entered_date, amount, related_transaction_id, invoice_id)
             VALUES (@TransactionId, @AccountId, @Vendor, @Description, @IsReconciled, @TransactionDate, @CategoryId,
             @EnteredDate, @Amount, @RelatedTransactionId, @InvoiceId)
         ", transaction, trx);
                 if (transaction.InvoiceId.HasValue)
                 {
                     UpdateInvoice(transaction.InvoiceId.Value, conn, trx);
                 }
                 if (transaction.CategoryId.HasValue)
                 {
                     UpdateVendor(transaction.Vendor, transaction.CategoryId.Value, conn, trx);
                 }
                 trx.Commit();
             }
             catch
             {
                 trx.Rollback();
                 throw;
             }
             finally
             {
                 conn.Close();
             }
         }
     }
 }
Пример #10
0
 public void Update(TransactionForDisplay transaction)
 {
     using (var conn = Connection)
     {
         conn.Open();
         using (var trx = conn.BeginTransaction())
         {
             try
             {
                 conn.Execute(
                     @"UPDATE transactions
         SET account_id = @AccountId, vendor = @Vendor, description = @Description, is_reconciled = @IsReconciled, 
         transaction_date = @TransactionDate, category_id = @CategoryId, amount = @Amount, 
         related_transaction_id = @RelatedTransactionId, invoice_id = @InvoiceId
         WHERE transaction_id = @TransactionId", transaction);
                 if (transaction.InvoiceId.HasValue)
                 {
                     UpdateInvoice(transaction.InvoiceId.Value, conn, trx);
                 }
                 if (transaction.CategoryId.HasValue)
                 {
                     UpdateVendor(transaction.Vendor, transaction.CategoryId.Value, conn, trx);
                 }
                 trx.Commit();
             }
             catch
             {
                 trx.Rollback();
             }
             finally
             {
                 conn.Close();
             }
         }
     }
 }
Пример #11
0
        private List <TransactionForDisplay> ParseQif(StreamReader reader, Guid accountId, DateTime?fromDate)
        {
            var transactions = new List <TransactionForDisplay>();
            var trx          = new TransactionForDisplay
            {
                TransactionId = Guid.NewGuid(),
                AccountId     = accountId,
                EnteredDate   = DateTime.Now,
                Vendor        = ""
            };

            while (reader.Peek() >= 0)
            {
                var line = reader.ReadLine();
                if (line.Length > 1 || line == "^")
                {
                    switch (line[0])
                    {
                    case '^':
                        if (!fromDate.HasValue || trx.TransactionDate >= fromDate.Value)
                        {
                            if (trx.Vendor.StartsWith("Transfer :", StringComparison.CurrentCultureIgnoreCase))
                            {
                                // For positive transfers, assume they've been handled elsewhere
                                if (trx.Amount > 0)
                                {
                                    break;
                                }
                                var accountName        = trx.Vendor.Replace("Transfer : ", "");
                                var account            = _accountRepo.GetAll().Single(a => a.Name == accountName);
                                var relatedTransaction = new TransactionForDisplay
                                {
                                    TransactionId        = Guid.NewGuid(),
                                    AccountId            = account.AccountId,
                                    EnteredDate          = trx.EnteredDate,
                                    Amount               = 0 - trx.Amount,
                                    Description          = trx.Description,
                                    IsReconciled         = trx.IsReconciled,
                                    TransactionDate      = trx.TransactionDate,
                                    RelatedTransactionId = trx.TransactionId
                                };
                                trx.Vendor = "";
                                trx.RelatedTransactionId = relatedTransaction.TransactionId;
                                transactions.Add(relatedTransaction);
                            }
                            trx.SetDebitAndCredit();
                            transactions.Add(trx);
                        }
                        trx = new TransactionForDisplay
                        {
                            TransactionId = Guid.NewGuid(),
                            AccountId     = accountId,
                            EnteredDate   = DateTime.Now,
                            Vendor        = ""
                        };
                        break;

                    case 'D':
                        trx.TransactionDate = DateTime.Parse(line.Substring(1));
                        break;

                    case 'T':
                        trx.Amount = decimal.Parse(line.Substring(1));
                        break;

                    case 'P':
                        trx.Vendor = line.Substring(1);
                        break;

                    case 'L':
                        var category = line.Substring(1)
                                       .Replace("Everyday Expenses:", "")
                                       .Replace("Rainy Day Funds:", "")
                                       .Replace("Monthly Bills:", "");
                        trx.CategoryId = TransactionHelpers.GetOrCreateCategory(category, _categoryRepo).CategoryId;
                        break;

                    case 'M':
                        trx.Description = line.Substring(1);
                        break;

                    case 'C':
                        trx.IsReconciled = line.Substring(1) == "c";
                        break;
                    }
                }
            }
            return(transactions);
        }
Пример #12
0
        public IActionResult PostMortgagePayment([FromBody] TransactionForDisplay transaction)
        {
            var principal = transaction.Debit.Value;
            var interest  = transaction.Credit.Value;

            transaction.Credit = null;
            var transactions = new List <TransactionForDisplay>();

            if (transaction.TransactionId == null || transaction.TransactionId == Guid.Empty)
            {
                transaction.TransactionId = Guid.NewGuid();
            }
            if (!transaction.AccountId.HasValue)
            {
                transaction.AccountId = _accountRepo.GetAll().Single(
                    a => a.Name.Equals(transaction.AccountName, StringComparison.CurrentCultureIgnoreCase)).AccountId;
            }
            transaction.SetAmount();
            var relatedTransactionId = Guid.NewGuid();
            var relatedTransaction   = new TransactionForDisplay {
                TransactionDate      = transaction.TransactionDate,
                TransactionId        = relatedTransactionId,
                Vendor               = transaction.Vendor,
                Description          = string.IsNullOrWhiteSpace(transaction.Description) ? "Mortgage Payment" : transaction.Description,
                AccountId            = transaction.RelatedAccountId.Value,
                Amount               = 0 - transaction.Amount,
                EnteredDate          = DateTime.Now,
                RelatedTransactionId = transaction.TransactionId
            };

            relatedTransaction.SetDebitAndCredit();

            transaction.RelatedTransactionId = relatedTransactionId;

            var mortgageInterestCategoryId = TransactionHelpers.GetOrCreateCategory("Mortgage Interest", _categoryRepo).CategoryId;
            var interestTransaction        = new TransactionForDisplay {
                TransactionDate = transaction.TransactionDate,
                TransactionId   = Guid.NewGuid(),
                Vendor          = transaction.Vendor,
                AccountId       = transaction.AccountId,
                Amount          = 0 - interest,
                Debit           = interest,
                EnteredDate     = DateTime.Now,
                CategoryId      = mortgageInterestCategoryId,
                CategoryDisplay = "Mortgage Interest"
            };

            var bankFeeTransactions = TransactionHelpers.GetBankFeeTransactions(transaction, _categoryRepo, _accountRepo);

            transactions.Add(transaction);
            transactions.Add(relatedTransaction);
            transactions.Add(interestTransaction);
            transactions.AddRange(bankFeeTransactions);
            _transactionRepo.InsertRelatedTransaction(transaction, relatedTransaction);
            _transactionRepo.Insert(interestTransaction);
            foreach (var trx in bankFeeTransactions)
            {
                _transactionRepo.Insert(trx);
            }

            var accountBalances = _accountRepo.GetAccountBalances();

            return(CreatedAtAction("PostTransfer",
                                   new { id = transaction.TransactionId }, new { transactions, accountBalances }));
        }