mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-23 15:19:38 +02:00
Account::Entry Delegated Type (namespace updates part 7) (#923)
* Initial entryable models * Update transfer and tests * Update transaction controllers and tests * Update sync process to use new entries model * Get dashboard working again * Update transfers, imports, and accounts to use Account::Entry * Update system tests * Consolidate transaction management into entries controller * Add permitted partial key helper * Move account transactions list to entries controller * Delegate transaction entries search * Move transfer relation to entry * Update bulk transaction management flows to use entries * Remove test code * Test fix attempt * Update demo data script * Consolidate remaining transaction partials to entries * Consolidate valuations controller to entries controller * Lint fix * Remove unused files, additional cleanup * Add back valuation creation * Make migrations fully reversible * Stale routes cleanup * Migrations reversible fix * Move types to entryable concern * Fix search when no entries found * Remove more unused code
This commit is contained in:
parent
320954282a
commit
c3314e62d1
105 changed files with 2150 additions and 1576 deletions
133
test/controllers/account/entries_controller_test.rb
Normal file
133
test/controllers/account/entries_controller_test.rb
Normal file
|
@ -0,0 +1,133 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::EntriesControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
@account = accounts(:savings)
|
||||
@transaction_entry = @account.entries.account_transactions.first
|
||||
@valuation_entry = @account.entries.account_valuations.first
|
||||
end
|
||||
|
||||
test "should edit valuation entry" do
|
||||
get edit_account_entry_url(@account, @valuation_entry)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should show transaction entry" do
|
||||
get account_entry_url(@account, @transaction_entry)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should show valuation entry" do
|
||||
get account_entry_url(@account, @valuation_entry)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get list of transaction entries" do
|
||||
get transaction_account_entries_url(@account)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should get list of valuation entries" do
|
||||
get valuation_account_entries_url(@account)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "gets new entry by type" do
|
||||
get new_account_entry_url(@account, entryable_type: "Account::Valuation")
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create valuation" do
|
||||
assert_difference [ "Account::Entry.count", "Account::Valuation.count" ], 1 do
|
||||
post account_entries_url(@account), params: {
|
||||
account_entry: {
|
||||
name: "Manual valuation",
|
||||
amount: 19800,
|
||||
date: Date.current,
|
||||
currency: @account.currency,
|
||||
entryable_type: "Account::Valuation",
|
||||
entryable_attributes: {}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_equal "Valuation created", flash[:notice]
|
||||
assert_enqueued_with job: AccountSyncJob
|
||||
assert_redirected_to account_path(@account)
|
||||
end
|
||||
|
||||
test "error when valuation already exists for date" do
|
||||
assert_no_difference_in_entries do
|
||||
post account_entries_url(@account), params: {
|
||||
account_entry: {
|
||||
amount: 19800,
|
||||
date: @valuation_entry.date,
|
||||
currency: @valuation_entry.currency,
|
||||
entryable_type: "Account::Valuation",
|
||||
entryable_attributes: {}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_equal "Date has already been taken", flash[:error]
|
||||
assert_redirected_to account_path(@account)
|
||||
end
|
||||
|
||||
test "can update entry without entryable attributes" do
|
||||
assert_no_difference_in_entries do
|
||||
patch account_entry_url(@account, @valuation_entry), params: {
|
||||
account_entry: {
|
||||
name: "Updated name"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to account_entry_url(@account, @valuation_entry)
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
|
||||
test "should update transaction entry with entryable attributes" do
|
||||
assert_no_difference_in_entries do
|
||||
patch account_entry_url(@account, @transaction_entry), params: {
|
||||
account_entry: {
|
||||
name: "Updated name",
|
||||
date: Date.current,
|
||||
currency: "USD",
|
||||
amount: 20,
|
||||
entryable_type: @transaction_entry.entryable_type,
|
||||
entryable_attributes: {
|
||||
id: @transaction_entry.entryable_id,
|
||||
tag_ids: [ Tag.first.id, Tag.second.id ],
|
||||
category_id: Category.first.id,
|
||||
merchant_id: Merchant.first.id,
|
||||
notes: "test notes",
|
||||
excluded: false
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to account_entry_url(@account, @transaction_entry)
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
|
||||
test "should destroy transaction entry" do
|
||||
[ @transaction_entry, @valuation_entry ].each do |entry|
|
||||
assert_difference -> { Account::Entry.count } => -1, -> { entry.entryable_class.count } => -1 do
|
||||
delete account_entry_url(@account, entry)
|
||||
end
|
||||
|
||||
assert_redirected_to account_url(@account)
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Simple guard to verify that nested attributes are passed the record ID to avoid new creation of record
|
||||
# See `update_only` option of accepts_nested_attributes_for
|
||||
def assert_no_difference_in_entries(&block)
|
||||
assert_no_difference [ "Account::Entry.count", "Account::Transaction.count", "Account::Valuation.count" ], &block
|
||||
end
|
||||
end
|
|
@ -1,40 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::TransactionsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
@transaction = account_transactions(:checking_one)
|
||||
@account = @transaction.account
|
||||
@recent_transactions = @user.family.transactions.ordered.limit(20).to_a
|
||||
end
|
||||
|
||||
test "should show transaction" do
|
||||
get account_transaction_url(@transaction.account, @transaction)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should update transaction" do
|
||||
patch account_transaction_url(@transaction.account, @transaction), params: {
|
||||
account_transaction: {
|
||||
account_id: @transaction.account_id,
|
||||
amount: @transaction.amount,
|
||||
currency: @transaction.currency,
|
||||
date: @transaction.date,
|
||||
name: @transaction.name,
|
||||
tag_ids: [ Tag.first.id, Tag.second.id ]
|
||||
}
|
||||
}
|
||||
|
||||
assert_redirected_to account_transaction_url(@transaction.account, @transaction)
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
|
||||
test "should destroy transaction" do
|
||||
assert_difference("Account::Transaction.count", -1) do
|
||||
delete account_transaction_url(@transaction.account, @transaction)
|
||||
end
|
||||
|
||||
assert_redirected_to account_url(@transaction.account)
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
end
|
||||
end
|
|
@ -1,71 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::ValuationsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
@valuation = account_valuations(:savings_one)
|
||||
@account = @valuation.account
|
||||
end
|
||||
|
||||
test "get valuations for an account" do
|
||||
get account_valuations_url(@account)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "new" do
|
||||
get new_account_valuation_url(@account)
|
||||
assert_response :success
|
||||
end
|
||||
|
||||
test "should create valuation" do
|
||||
assert_difference("Account::Valuation.count") do
|
||||
post account_valuations_url(@account), params: {
|
||||
account_valuation: {
|
||||
value: 19800,
|
||||
date: Date.current
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_equal "Valuation created", flash[:notice]
|
||||
assert_enqueued_with job: AccountSyncJob
|
||||
assert_redirected_to account_path(@account)
|
||||
end
|
||||
|
||||
test "error when valuation already exists for date" do
|
||||
assert_difference("Account::Valuation.count", 0) do
|
||||
post account_valuations_url(@account), params: {
|
||||
account_valuation: {
|
||||
value: 19800,
|
||||
date: @valuation.date
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_equal "Date has already been taken", flash[:error]
|
||||
assert_redirected_to account_path(@account)
|
||||
end
|
||||
|
||||
test "should update valuation" do
|
||||
patch account_valuation_url(@account, @valuation), params: {
|
||||
account_valuation: {
|
||||
value: 19550,
|
||||
date: Date.current
|
||||
}
|
||||
}
|
||||
|
||||
assert_equal "Valuation updated", flash[:notice]
|
||||
assert_enqueued_with job: AccountSyncJob
|
||||
assert_redirected_to account_path(@account)
|
||||
end
|
||||
|
||||
test "should destroy valuation" do
|
||||
assert_difference("Account::Valuation.count", -1) do
|
||||
delete account_valuation_url(@account, @valuation)
|
||||
end
|
||||
|
||||
assert_equal "Valuation deleted", flash[:notice]
|
||||
assert_enqueued_with job: AccountSyncJob
|
||||
assert_redirected_to account_path(@account)
|
||||
end
|
||||
end
|
|
@ -44,7 +44,7 @@ class AccountsControllerTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test "should create an account" do
|
||||
assert_difference [ "Account.count", "Account::Valuation.count" ], 1 do
|
||||
assert_difference [ "Account.count", "Account::Valuation.count", "Account::Entry.count" ], 1 do
|
||||
post accounts_path, params: {
|
||||
account: {
|
||||
accountable_type: "Depository",
|
||||
|
|
|
@ -3,8 +3,8 @@ require "test_helper"
|
|||
class TransactionsControllerTest < ActionDispatch::IntegrationTest
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
@transaction = account_transactions(:checking_one)
|
||||
@recent_transactions = @user.family.transactions.ordered.limit(20).to_a
|
||||
@transaction_entry = account_entries(:checking_one)
|
||||
@recent_transaction_entries = @user.family.entries.account_transactions.reverse_chronological.limit(20).to_a
|
||||
end
|
||||
|
||||
test "should get new" do
|
||||
|
@ -13,88 +13,96 @@ class TransactionsControllerTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test "prefills account_id" do
|
||||
get new_transaction_url(account_id: @transaction.account.id)
|
||||
get new_transaction_url(account_id: @transaction_entry.account.id)
|
||||
assert_response :success
|
||||
assert_select "option[selected][value='#{@transaction.account.id}']"
|
||||
assert_select "option[selected][value='#{@transaction_entry.account.id}']"
|
||||
end
|
||||
|
||||
test "should create transaction" do
|
||||
account = @user.family.accounts.first
|
||||
transaction_params = {
|
||||
entry_params = {
|
||||
account_id: account.id,
|
||||
amount: 100.45,
|
||||
currency: "USD",
|
||||
date: Date.current,
|
||||
name: "Test transaction"
|
||||
name: "Test transaction",
|
||||
entryable_type: "Account::Transaction",
|
||||
entryable_attributes: { category_id: categories(:food_and_drink).id }
|
||||
}
|
||||
|
||||
assert_difference("Account::Transaction.count") do
|
||||
post transactions_url, params: { transaction: transaction_params }
|
||||
assert_difference [ "Account::Entry.count", "Account::Transaction.count" ], 1 do
|
||||
post transactions_url, params: { account_entry: entry_params }
|
||||
end
|
||||
|
||||
assert_equal transaction_params[:amount].to_d, Account::Transaction.order(created_at: :desc).first.amount
|
||||
assert_equal entry_params[:amount].to_d, Account::Transaction.order(created_at: :desc).first.entry.amount
|
||||
assert_equal "New transaction created successfully", flash[:notice]
|
||||
assert_enqueued_with(job: AccountSyncJob)
|
||||
assert_redirected_to account_url(account)
|
||||
end
|
||||
|
||||
test "expenses are positive" do
|
||||
assert_difference("Account::Transaction.count") do
|
||||
assert_difference([ "Account::Transaction.count", "Account::Entry.count" ], 1) do
|
||||
post transactions_url, params: {
|
||||
transaction: {
|
||||
account_entry: {
|
||||
nature: "expense",
|
||||
account_id: @transaction.account_id,
|
||||
amount: @transaction.amount,
|
||||
currency: @transaction.currency,
|
||||
date: @transaction.date,
|
||||
name: @transaction.name
|
||||
account_id: @transaction_entry.account_id,
|
||||
amount: @transaction_entry.amount,
|
||||
currency: @transaction_entry.currency,
|
||||
date: @transaction_entry.date,
|
||||
name: @transaction_entry.name,
|
||||
entryable_type: "Account::Transaction",
|
||||
entryable_attributes: {}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
created_transaction = Account::Transaction.order(created_at: :desc).first
|
||||
created_entry = Account::Entry.order(created_at: :desc).first
|
||||
|
||||
assert_redirected_to account_url(@transaction.account)
|
||||
assert created_transaction.amount.positive?, "Amount should be positive"
|
||||
assert_redirected_to account_url(@transaction_entry.account)
|
||||
assert created_entry.amount.positive?, "Amount should be positive"
|
||||
end
|
||||
|
||||
test "incomes are negative" do
|
||||
assert_difference("Account::Transaction.count") do
|
||||
post transactions_url, params: {
|
||||
transaction: {
|
||||
account_entry: {
|
||||
nature: "income",
|
||||
account_id: @transaction.account_id,
|
||||
amount: @transaction.amount,
|
||||
currency: @transaction.currency,
|
||||
date: @transaction.date,
|
||||
name: @transaction.name
|
||||
account_id: @transaction_entry.account_id,
|
||||
amount: @transaction_entry.amount,
|
||||
currency: @transaction_entry.currency,
|
||||
date: @transaction_entry.date,
|
||||
name: @transaction_entry.name,
|
||||
entryable_type: "Account::Transaction",
|
||||
entryable_attributes: { category_id: categories(:food_and_drink).id }
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
created_transaction = Account::Transaction.order(created_at: :desc).first
|
||||
created_entry = Account::Entry.order(created_at: :desc).first
|
||||
|
||||
assert_redirected_to account_url(@transaction.account)
|
||||
assert created_transaction.amount.negative?, "Amount should be negative"
|
||||
assert_redirected_to account_url(@transaction_entry.account)
|
||||
assert created_entry.amount.negative?, "Amount should be negative"
|
||||
end
|
||||
|
||||
test "should get paginated index with most recent transactions first" do
|
||||
get transactions_url
|
||||
get transactions_url(per_page: 10)
|
||||
assert_response :success
|
||||
|
||||
@recent_transactions.first(10).each do |transaction|
|
||||
@recent_transaction_entries.first(10).each do |transaction|
|
||||
assert_dom "#" + dom_id(transaction), count: 1
|
||||
end
|
||||
end
|
||||
|
||||
test "transaction count represents filtered total" do
|
||||
get transactions_url
|
||||
assert_dom "#total-transactions", count: 1, text: @user.family.transactions.select { |t| t.currency == "USD" }.count.to_s
|
||||
get transactions_url(per_page: 10)
|
||||
assert_dom "#total-transactions", count: 1, text: @user.family.entries.account_transactions.select { |t| t.currency == "USD" }.count.to_s
|
||||
|
||||
new_transaction = @user.family.accounts.first.transactions.create! \
|
||||
new_transaction = @user.family.accounts.first.entries.create! \
|
||||
entryable: Account::Transaction.new,
|
||||
name: "Transaction to search for",
|
||||
date: Date.current,
|
||||
amount: 0
|
||||
amount: 0,
|
||||
currency: "USD"
|
||||
|
||||
get transactions_url(q: { search: new_transaction.name })
|
||||
|
||||
|
@ -104,28 +112,30 @@ class TransactionsControllerTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test "can navigate to paginated result" do
|
||||
get transactions_url(page: 2)
|
||||
get transactions_url(page: 2, per_page: 10)
|
||||
assert_response :success
|
||||
|
||||
@recent_transactions[10, 10].select { |t| t.transfer_id == nil }.each do |transaction|
|
||||
visible_transaction_entries = @recent_transaction_entries[10, 10].reject { |e| e.transfer.present? }
|
||||
|
||||
visible_transaction_entries.each do |transaction|
|
||||
assert_dom "#" + dom_id(transaction), count: 1
|
||||
end
|
||||
end
|
||||
|
||||
test "loads last page when page is out of range" do
|
||||
user_oldest_transaction = @user.family.transactions.ordered.reject(&:transfer?).last
|
||||
user_oldest_transaction_entry = @user.family.entries.account_transactions.chronological.first
|
||||
get transactions_url(page: 9999999999)
|
||||
|
||||
assert_response :success
|
||||
assert_dom "#" + dom_id(user_oldest_transaction), count: 1
|
||||
assert_dom "#" + dom_id(user_oldest_transaction_entry), count: 1
|
||||
end
|
||||
|
||||
test "can destroy many transactions at once" do
|
||||
delete_count = 10
|
||||
assert_difference("Account::Transaction.count", -delete_count) do
|
||||
assert_difference([ "Account::Transaction.count", "Account::Entry.count" ], -delete_count) do
|
||||
post bulk_delete_transactions_url, params: {
|
||||
bulk_delete: {
|
||||
transaction_ids: @recent_transactions.first(delete_count).pluck(:id)
|
||||
entry_ids: @recent_transaction_entries.first(delete_count).pluck(:id)
|
||||
}
|
||||
}
|
||||
end
|
||||
|
@ -135,36 +145,41 @@ class TransactionsControllerTest < ActionDispatch::IntegrationTest
|
|||
end
|
||||
|
||||
test "can update many transactions at once" do
|
||||
transactions = @user.family.transactions.ordered.limit(20)
|
||||
transactions = @user.family.entries.account_transactions.reverse_chronological.limit(20)
|
||||
|
||||
transactions.each do |transaction|
|
||||
transaction.update! \
|
||||
excluded: false,
|
||||
category_id: Category.first.id,
|
||||
merchant_id: Merchant.first.id,
|
||||
notes: "Starting note"
|
||||
date: Date.current,
|
||||
entryable_attributes: {
|
||||
id: transaction.account_transaction.id,
|
||||
category_id: Category.first.id,
|
||||
merchant_id: Merchant.first.id,
|
||||
notes: "Starting note"
|
||||
}
|
||||
end
|
||||
|
||||
post bulk_update_transactions_url, params: {
|
||||
bulk_update: {
|
||||
date: Date.current,
|
||||
transaction_ids: transactions.map(&:id),
|
||||
excluded: true,
|
||||
category_id: Category.second.id,
|
||||
merchant_id: Merchant.second.id,
|
||||
notes: "Updated note"
|
||||
assert_difference [ "Account::Entry.count", "Account::Transaction.count" ], 0 do
|
||||
post bulk_update_transactions_url, params: {
|
||||
bulk_update: {
|
||||
entry_ids: transactions.map(&:id),
|
||||
date: 1.day.ago.to_date,
|
||||
category_id: Category.second.id,
|
||||
merchant_id: Merchant.second.id,
|
||||
notes: "Updated note"
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
assert_redirected_to transactions_url
|
||||
assert_equal "#{transactions.count} transactions updated", flash[:notice]
|
||||
|
||||
transactions.reload.each do |transaction|
|
||||
assert_equal Date.current, transaction.date
|
||||
assert transaction.excluded
|
||||
assert_equal Category.second, transaction.category
|
||||
assert_equal Merchant.second, transaction.merchant
|
||||
assert_equal "Updated note", transaction.notes
|
||||
transactions.reload
|
||||
|
||||
transactions.each do |transaction|
|
||||
assert_equal 1.day.ago.to_date, transaction.date
|
||||
assert_equal Category.second, transaction.account_transaction.category
|
||||
assert_equal Merchant.second, transaction.account_transaction.merchant
|
||||
assert_equal "Updated note", transaction.account_transaction.notes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
323
test/fixtures/account/entries.yml
vendored
Normal file
323
test/fixtures/account/entries.yml
vendored
Normal file
|
@ -0,0 +1,323 @@
|
|||
# Checking account transactions
|
||||
checking_one:
|
||||
name: Starbucks
|
||||
date: <%= 5.days.ago.to_date %>
|
||||
amount: 10
|
||||
account: checking
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_one
|
||||
|
||||
checking_two:
|
||||
name: Chipotle
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
amount: 30
|
||||
account: checking
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_two
|
||||
|
||||
checking_three:
|
||||
name: Amazon
|
||||
date: <%= 15.days.ago.to_date %>
|
||||
amount: 20
|
||||
account: checking
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_three
|
||||
|
||||
checking_four:
|
||||
name: Paycheck
|
||||
date: <%= 22.days.ago.to_date %>
|
||||
amount: -1075
|
||||
account: checking
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_four
|
||||
|
||||
checking_five:
|
||||
name: Netflix
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: 15
|
||||
account: checking
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_five
|
||||
|
||||
checking_six_payment:
|
||||
name: Payment to Credit Card
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: 100
|
||||
account: checking
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_six_payment
|
||||
marked_as_transfer: true
|
||||
transfer: credit_card_payment
|
||||
|
||||
checking_seven_transfer:
|
||||
name: Transfer to Savings
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: 250
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: savings_transfer
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_seven_transfer
|
||||
|
||||
checking_eight_external_payment:
|
||||
name: Transfer TO external CC account (owned by user but not known to app)
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: 800
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_eight_external_payment
|
||||
|
||||
checking_nine_external_transfer:
|
||||
name: Transfer FROM external investing account (owned by user but not known to app)
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
amount: -200
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
entryable_type: Account::Transaction
|
||||
entryable: checking_nine_external_transfer
|
||||
|
||||
savings_one:
|
||||
name: Interest Received
|
||||
date: <%= 5.days.ago.to_date %>
|
||||
amount: -200
|
||||
account: savings
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: savings_one
|
||||
|
||||
savings_two:
|
||||
name: Check Deposit
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
amount: -50
|
||||
account: savings
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: savings_two
|
||||
|
||||
savings_three:
|
||||
name: Withdrawal
|
||||
date: <%= 18.days.ago.to_date %>
|
||||
amount: 2000
|
||||
account: savings
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: savings_three
|
||||
|
||||
savings_four:
|
||||
name: Check Deposit
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: -500
|
||||
account: savings
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: savings_four
|
||||
|
||||
savings_five_transfer:
|
||||
name: Received Transfer from Checking Account
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
amount: -250
|
||||
account: savings
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: savings_transfer
|
||||
entryable_type: Account::Transaction
|
||||
entryable: savings_five_transfer
|
||||
|
||||
credit_card_one:
|
||||
name: Starbucks
|
||||
date: <%= 5.days.ago.to_date %>
|
||||
amount: 10
|
||||
account: credit_card
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: credit_card_one
|
||||
|
||||
credit_card_two:
|
||||
name: Chipotle
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
amount: 30
|
||||
account: credit_card
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: credit_card_two
|
||||
|
||||
credit_card_three:
|
||||
name: Amazon
|
||||
date: <%= 15.days.ago.to_date %>
|
||||
amount: 20
|
||||
account: credit_card
|
||||
currency: USD
|
||||
entryable_type: Account::Transaction
|
||||
entryable: credit_card_three
|
||||
|
||||
credit_card_four_payment:
|
||||
name: Received CC Payment from Checking Account
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
amount: -100
|
||||
account: credit_card
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: credit_card_payment
|
||||
entryable_type: Account::Transaction
|
||||
entryable: credit_card_four_payment
|
||||
|
||||
eur_checking_one:
|
||||
name: Check
|
||||
date: <%= 9.days.ago.to_date %>
|
||||
amount: -50
|
||||
currency: EUR
|
||||
account: eur_checking
|
||||
entryable_type: Account::Transaction
|
||||
entryable: eur_checking_one
|
||||
|
||||
eur_checking_two:
|
||||
name: Shopping trip
|
||||
date: <%= 19.days.ago.to_date %>
|
||||
amount: 100
|
||||
currency: EUR
|
||||
account: eur_checking
|
||||
entryable_type: Account::Transaction
|
||||
entryable: eur_checking_two
|
||||
|
||||
eur_checking_three:
|
||||
name: Check
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
amount: -200
|
||||
currency: EUR
|
||||
account: eur_checking
|
||||
entryable_type: Account::Transaction
|
||||
entryable: eur_checking_three
|
||||
|
||||
multi_currency_one:
|
||||
name: Outflow 1
|
||||
date: <%= 4.days.ago.to_date %>
|
||||
amount: 800
|
||||
currency: EUR
|
||||
account: multi_currency
|
||||
entryable_type: Account::Transaction
|
||||
entryable: multi_currency_one
|
||||
|
||||
multi_currency_two:
|
||||
name: Inflow 1
|
||||
date: <%= 9.days.ago.to_date %>
|
||||
amount: -50
|
||||
currency: USD
|
||||
account: multi_currency
|
||||
entryable_type: Account::Transaction
|
||||
entryable: multi_currency_two
|
||||
|
||||
multi_currency_three:
|
||||
name: Outflow 2
|
||||
date: <%= 19.days.ago.to_date %>
|
||||
amount: 110.85
|
||||
currency: EUR
|
||||
account: multi_currency
|
||||
entryable_type: Account::Transaction
|
||||
entryable: multi_currency_three
|
||||
|
||||
multi_currency_four:
|
||||
name: Inflow 2
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: -200
|
||||
currency: USD
|
||||
account: multi_currency
|
||||
entryable_type: Account::Transaction
|
||||
entryable: multi_currency_four
|
||||
|
||||
collectable_one_valuation:
|
||||
amount: 550
|
||||
date: <%= 4.days.ago.to_date %>
|
||||
account: collectable
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: collectable_one
|
||||
|
||||
collectable_two_valuation:
|
||||
amount: 700
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
account: collectable
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: collectable_two
|
||||
|
||||
collectable_three_valuation:
|
||||
amount: 400
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: collectable
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: collectable_three
|
||||
|
||||
iou_one_valuation:
|
||||
amount: 200
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: iou
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: iou_one
|
||||
|
||||
multi_currency_one_valuation:
|
||||
amount: 10200
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: multi_currency
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: multi_currency_one
|
||||
|
||||
savings_one_valuation:
|
||||
amount: 19500
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
account: savings
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: savings_one
|
||||
|
||||
savings_two_valuation:
|
||||
amount: 21000
|
||||
date: <%= 25.days.ago.to_date %>
|
||||
account: savings
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: savings_two
|
||||
|
||||
brokerage_one_valuation:
|
||||
amount: 10000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: brokerage
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: brokerage_one
|
||||
|
||||
mortgage_loan_one_valuation:
|
||||
amount: 500000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: mortgage_loan
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: mortgage_loan_one
|
||||
|
||||
house_one_valuation:
|
||||
amount: 550000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: house
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: house_one
|
||||
|
||||
car_one_valuation:
|
||||
amount: 18000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: car
|
||||
currency: USD
|
||||
entryable_type: Account::Valuation
|
||||
entryable: car_one
|
168
test/fixtures/account/transactions.yml
vendored
168
test/fixtures/account/transactions.yml
vendored
|
@ -1,200 +1,60 @@
|
|||
# Checking account transactions
|
||||
checking_one:
|
||||
name: Starbucks
|
||||
date: <%= 5.days.ago.to_date %>
|
||||
amount: 10
|
||||
account: checking
|
||||
category: food_and_drink
|
||||
currency: USD
|
||||
|
||||
checking_two:
|
||||
name: Chipotle
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
amount: 30
|
||||
account: checking
|
||||
category: food_and_drink
|
||||
currency: USD
|
||||
|
||||
checking_three:
|
||||
name: Amazon
|
||||
date: <%= 15.days.ago.to_date %>
|
||||
amount: 20
|
||||
account: checking
|
||||
currency: USD
|
||||
merchant: amazon
|
||||
|
||||
checking_four:
|
||||
name: Paycheck
|
||||
date: <%= 22.days.ago.to_date %>
|
||||
amount: -1075
|
||||
account: checking
|
||||
category: income
|
||||
currency: USD
|
||||
|
||||
checking_five:
|
||||
name: Netflix
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: 15
|
||||
account: checking
|
||||
currency: USD
|
||||
merchant: netflix
|
||||
|
||||
checking_six_payment:
|
||||
name: Payment to Credit Card
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: 100
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: credit_card_payment
|
||||
checking_six_payment: { }
|
||||
|
||||
checking_seven_transfer:
|
||||
name: Transfer to Savings
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: 250
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: savings_transfer
|
||||
checking_seven_transfer: { }
|
||||
|
||||
checking_eight_external_payment:
|
||||
name: Transfer TO external CC account (owned by user but not known to app)
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: 800
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
checking_eight_external_payment: { }
|
||||
|
||||
checking_nine_external_transfer:
|
||||
name: Transfer FROM external investing account (owned by user but not known to app)
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: -200
|
||||
account: checking
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
checking_nine_external_transfer: { }
|
||||
|
||||
# Savings account that has transactions and valuation overrides
|
||||
savings_one:
|
||||
name: Interest Received
|
||||
date: <%= 5.days.ago.to_date %>
|
||||
amount: -200
|
||||
account: savings
|
||||
category: income
|
||||
currency: USD
|
||||
|
||||
savings_two:
|
||||
name: Check Deposit
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
amount: -50
|
||||
account: savings
|
||||
category: income
|
||||
currency: USD
|
||||
|
||||
savings_three:
|
||||
name: Withdrawal
|
||||
date: <%= 18.days.ago.to_date %>
|
||||
amount: 2000
|
||||
account: savings
|
||||
currency: USD
|
||||
savings_three: { }
|
||||
|
||||
savings_four:
|
||||
name: Check Deposit
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: -500
|
||||
account: savings
|
||||
category: income
|
||||
currency: USD
|
||||
|
||||
savings_five_transfer:
|
||||
name: Received Transfer from Checking Account
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: -250
|
||||
account: savings
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: savings_transfer
|
||||
savings_five_transfer: { }
|
||||
|
||||
# Credit card account transactions
|
||||
credit_card_one:
|
||||
name: Starbucks
|
||||
date: <%= 5.days.ago.to_date %>
|
||||
amount: 10
|
||||
account: credit_card
|
||||
category: food_and_drink
|
||||
currency: USD
|
||||
|
||||
credit_card_two:
|
||||
name: Chipotle
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
amount: 30
|
||||
account: credit_card
|
||||
category: food_and_drink
|
||||
currency: USD
|
||||
|
||||
credit_card_three:
|
||||
name: Amazon
|
||||
date: <%= 15.days.ago.to_date %>
|
||||
amount: 20
|
||||
account: credit_card
|
||||
currency: USD
|
||||
merchant: amazon
|
||||
|
||||
credit_card_four_payment:
|
||||
name: Received CC Payment from Checking Account
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: -100
|
||||
account: credit_card
|
||||
currency: USD
|
||||
marked_as_transfer: true
|
||||
transfer: credit_card_payment
|
||||
credit_card_four_payment: { }
|
||||
|
||||
# eur_checking transactions
|
||||
eur_checking_one:
|
||||
name: Check
|
||||
date: <%= 9.days.ago.to_date %>
|
||||
amount: -50
|
||||
currency: EUR
|
||||
account: eur_checking
|
||||
|
||||
eur_checking_two:
|
||||
name: Shopping trip
|
||||
date: <%= 19.days.ago.to_date %>
|
||||
amount: 100
|
||||
currency: EUR
|
||||
account: eur_checking
|
||||
|
||||
eur_checking_three:
|
||||
name: Check
|
||||
date: <%= 30.days.ago.to_date %>
|
||||
amount: -200
|
||||
currency: EUR
|
||||
account: eur_checking
|
||||
eur_checking_one: { }
|
||||
eur_checking_two: { }
|
||||
eur_checking_three: { }
|
||||
|
||||
# multi_currency transactions
|
||||
multi_currency_one:
|
||||
name: Outflow 1
|
||||
date: <%= 4.days.ago.to_date %>
|
||||
amount: 800
|
||||
currency: EUR
|
||||
account: multi_currency
|
||||
|
||||
multi_currency_two:
|
||||
name: Inflow 1
|
||||
date: <%= 9.days.ago.to_date %>
|
||||
amount: -50
|
||||
currency: USD
|
||||
account: multi_currency
|
||||
|
||||
multi_currency_three:
|
||||
name: Outflow 2
|
||||
date: <%= 19.days.ago.to_date %>
|
||||
amount: 110.85
|
||||
currency: EUR
|
||||
account: multi_currency
|
||||
|
||||
multi_currency_four:
|
||||
name: Inflow 2
|
||||
date: <%= 29.days.ago.to_date %>
|
||||
amount: -200
|
||||
currency: USD
|
||||
account: multi_currency
|
||||
multi_currency_one: { }
|
||||
multi_currency_two: { }
|
||||
multi_currency_three: { }
|
||||
multi_currency_four: { }
|
||||
|
|
59
test/fixtures/account/valuations.yml
vendored
59
test/fixtures/account/valuations.yml
vendored
|
@ -1,55 +1,18 @@
|
|||
# For collectable account that only has valuations (no transactions)
|
||||
collectable_one:
|
||||
value: 550
|
||||
date: <%= 4.days.ago.to_date %>
|
||||
account: collectable
|
||||
collectable_one: { }
|
||||
collectable_two: { }
|
||||
collectable_three: { }
|
||||
|
||||
collectable_two:
|
||||
value: 700
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
account: collectable
|
||||
iou_one: { }
|
||||
|
||||
collectable_three:
|
||||
value: 400
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: collectable
|
||||
multi_currency_one: { }
|
||||
|
||||
iou_one:
|
||||
value: 200
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: iou
|
||||
savings_one: { }
|
||||
savings_two: { }
|
||||
|
||||
multi_currency_one:
|
||||
value: 10200
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: multi_currency
|
||||
brokerage_one: { }
|
||||
|
||||
savings_one:
|
||||
value: 19500
|
||||
date: <%= 12.days.ago.to_date %>
|
||||
account: savings
|
||||
mortgage_loan_one: { }
|
||||
|
||||
savings_two:
|
||||
value: 21000
|
||||
date: <%= 25.days.ago.to_date %>
|
||||
account: savings
|
||||
house_one: { }
|
||||
|
||||
brokerage_one:
|
||||
value: 10000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: brokerage
|
||||
|
||||
mortgage_loan_one:
|
||||
value: 500000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: mortgage_loan
|
||||
|
||||
house_one:
|
||||
value: 550000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: house
|
||||
|
||||
car_one:
|
||||
value: 18000
|
||||
date: <%= 31.days.ago.to_date %>
|
||||
account: car
|
||||
car_one: { }
|
|
@ -1,33 +1,33 @@
|
|||
date_offset,collectable,iou,checking,credit_card,savings,eur_checking_eur,eur_checking_usd,multi_currency,brokerage,mortgage_loan,house,car,net_worth,assets,liabilities,depositories,investments,loans,credits,properties,vehicles,other_assets,other_liabilities,spending,income,rolling_spend,rolling_income,savings_rate
|
||||
31,400.00,200.00,4950.00,1040.00,20700.00,11850.00,13018.41,10200.00,10000.00,500000.00,550000.00,18000.00,126028.41,627268.41,501240.00,48868.41,10000.00,500000.00,1040.00,550000.00,18000.00,400.00,200.00,0.00,0.00,0.00,0.00,0.0000
|
||||
30,400.00,200.00,4100.00,940.00,20950.00,12050.00,13165.83,10200.00,10000.00,500000.00,550000.00,18000.00,125675.83,626815.83,501140.00,48415.83,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,218.52,0.00,218.52,1.0000
|
||||
29,400.00,200.00,3985.00,940.00,21450.00,12050.00,13182.70,10400.00,10000.00,500000.00,550000.00,18000.00,126277.70,627417.70,501140.00,49017.70,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,15.00,700.00,15.00,918.52,0.9837
|
||||
28,400.00,200.00,3985.00,940.00,21450.00,12050.00,13194.75,10400.00,10000.00,500000.00,550000.00,18000.00,126289.75,627429.75,501140.00,49029.75,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,918.52,0.9837
|
||||
27,400.00,200.00,3985.00,940.00,21450.00,12050.00,13132.09,10400.00,10000.00,500000.00,550000.00,18000.00,126227.09,627367.09,501140.00,48967.09,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,918.52,0.9837
|
||||
26,400.00,200.00,3985.00,940.00,21450.00,12050.00,13083.89,10400.00,10000.00,500000.00,550000.00,18000.00,126178.89,627318.89,501140.00,48918.89,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,918.52,0.9837
|
||||
25,400.00,200.00,3985.00,940.00,21000.00,12050.00,13081.48,10400.00,10000.00,500000.00,550000.00,18000.00,125726.48,626866.48,501140.00,48466.48,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,918.52,0.9837
|
||||
24,400.00,200.00,3985.00,940.00,21000.00,12050.00,13062.20,10400.00,10000.00,500000.00,550000.00,18000.00,125707.20,626847.20,501140.00,48447.20,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,918.52,0.9837
|
||||
23,400.00,200.00,3985.00,940.00,21000.00,12050.00,13022.44,10400.00,10000.00,500000.00,550000.00,18000.00,125667.44,626807.44,501140.00,48407.44,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,918.52,0.9837
|
||||
22,400.00,200.00,5060.00,940.00,21000.00,12050.00,13061.00,10400.00,10000.00,500000.00,550000.00,18000.00,126781.00,627921.00,501140.00,49521.00,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,1075.00,15.00,1993.52,0.9925
|
||||
21,400.00,200.00,5060.00,940.00,21000.00,12050.00,13068.23,10400.00,10000.00,500000.00,550000.00,18000.00,126788.23,627928.23,501140.00,49528.23,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,1993.52,0.9925
|
||||
20,400.00,200.00,5060.00,940.00,21000.00,12050.00,13079.07,10400.00,10000.00,500000.00,550000.00,18000.00,126799.07,627939.07,501140.00,49539.07,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,1993.52,0.9925
|
||||
19,400.00,200.00,5060.00,940.00,21000.00,11950.00,12932.29,10280.04,10000.00,500000.00,550000.00,18000.00,126532.33,627672.33,501140.00,49272.33,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,228.18,0.00,243.18,1993.52,0.8780
|
||||
18,400.00,200.00,5060.00,940.00,19000.00,11950.00,12934.68,10280.04,10000.00,500000.00,550000.00,18000.00,124534.72,625674.72,501140.00,47274.72,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,2000.00,0.00,2243.18,1993.52,-0.1252
|
||||
17,400.00,200.00,5060.00,940.00,19000.00,11950.00,12927.51,10280.04,10000.00,500000.00,550000.00,18000.00,124527.55,625667.55,501140.00,47267.55,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2243.18,1993.52,-0.1252
|
||||
16,400.00,200.00,5060.00,940.00,19000.00,11950.00,12916.76,10280.04,10000.00,500000.00,550000.00,18000.00,124516.79,625656.79,501140.00,47256.79,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2243.18,1993.52,-0.1252
|
||||
15,400.00,200.00,5040.00,960.00,19000.00,11950.00,12882.10,10280.04,10000.00,500000.00,550000.00,18000.00,124442.14,625602.14,501160.00,47202.14,10000.00,500000.00,960.00,550000.00,18000.00,400.00,200.00,40.00,0.00,2283.18,1993.52,-0.1453
|
||||
14,400.00,200.00,5040.00,960.00,19000.00,11950.00,12879.71,10280.04,10000.00,500000.00,550000.00,18000.00,124439.75,625599.75,501160.00,47199.75,10000.00,500000.00,960.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2283.18,1993.52,-0.1453
|
||||
13,400.00,200.00,5040.00,960.00,19000.00,11950.00,12873.74,10280.04,10000.00,500000.00,550000.00,18000.00,124433.77,625593.77,501160.00,47193.77,10000.00,500000.00,960.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2283.18,1993.52,-0.1453
|
||||
12,700.00,200.00,5010.00,990.00,19500.00,11950.00,12821.16,10280.04,10000.00,500000.00,550000.00,18000.00,125121.19,626311.19,501190.00,47611.19,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,60.00,50.00,2343.18,2043.52,-0.1466
|
||||
11,700.00,200.00,5010.00,990.00,19500.00,11950.00,12797.26,10280.04,10000.00,500000.00,550000.00,18000.00,125097.29,626287.29,501190.00,47587.29,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2043.52,-0.1466
|
||||
10,700.00,200.00,5010.00,990.00,19500.00,11950.00,12873.74,10280.04,10000.00,500000.00,550000.00,18000.00,125173.77,626363.77,501190.00,47663.77,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2043.52,-0.1466
|
||||
9,700.00,200.00,5010.00,990.00,19500.00,12000.00,12939.60,10330.04,10000.00,500000.00,550000.00,18000.00,125289.64,626479.64,501190.00,47779.64,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,103.92,2343.18,2147.44,-0.0912
|
||||
8,700.00,200.00,5010.00,990.00,19500.00,12000.00,12933.60,10330.04,10000.00,500000.00,550000.00,18000.00,125283.64,626473.64,501190.00,47773.64,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2147.44,-0.0912
|
||||
7,700.00,200.00,5010.00,990.00,19500.00,12000.00,12928.80,10330.04,10000.00,500000.00,550000.00,18000.00,125278.84,626468.84,501190.00,47768.84,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2147.44,-0.0912
|
||||
6,700.00,200.00,5010.00,990.00,19500.00,12000.00,12906.00,10330.04,10000.00,500000.00,550000.00,18000.00,125256.04,626446.04,501190.00,47746.04,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2147.44,-0.0912
|
||||
5,700.00,200.00,5000.00,1000.00,19700.00,12000.00,12891.60,10330.04,10000.00,500000.00,550000.00,18000.00,125421.64,626621.64,501200.00,47921.64,10000.00,500000.00,1000.00,550000.00,18000.00,700.00,200.00,20.00,200.00,2363.18,2347.44,-0.0067
|
||||
4,550.00,200.00,5000.00,1000.00,19700.00,12000.00,12945.60,9467.00,10000.00,500000.00,550000.00,18000.00,124462.60,625662.60,501200.00,47112.60,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,863.04,0.00,3226.22,2347.44,-0.3744
|
||||
3,550.00,200.00,5000.00,1000.00,19700.00,12000.00,13046.40,9467.00,10000.00,500000.00,550000.00,18000.00,124563.40,625763.40,501200.00,47213.40,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2347.44,-0.3744
|
||||
2,550.00,200.00,5000.00,1000.00,19700.00,12000.00,12982.80,9467.00,10000.00,500000.00,550000.00,18000.00,124499.80,625699.80,501200.00,47149.80,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2347.44,-0.3744
|
||||
1,550.00,200.00,5000.00,1000.00,19700.00,12000.00,13014.00,9467.00,10000.00,500000.00,550000.00,18000.00,124531.00,625731.00,501200.00,47181.00,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2347.44,-0.3744
|
||||
0,550.00,200.00,5000.00,1000.00,19700.00,12000.00,13000.80,9467.00,10000.00,500000.00,550000.00,18000.00,124517.80,625717.80,501200.00,47167.80,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2347.44,-0.3744
|
||||
31,400.00,200.00,5150.00,940.00,20950.00,12050.00,13238.13,10200.00,10000.00,500000.00,550000.00,18000.00,126798.13,627938.13,501140.00,49538.13,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,219.72,0.00,0.00,0.0000
|
||||
30,400.00,200.00,4100.00,940.00,20950.00,12050.00,13165.83,10200.00,10000.00,500000.00,550000.00,18000.00,125675.83,626815.83,501140.00,48415.83,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,0.00,219.72,1.0000
|
||||
29,400.00,200.00,3985.00,940.00,21450.00,12050.00,13182.70,10400.00,10000.00,500000.00,550000.00,18000.00,126277.70,627417.70,501140.00,49017.70,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,15.00,700.00,15.00,919.72,0.9837
|
||||
28,400.00,200.00,3985.00,940.00,21450.00,12050.00,13194.75,10400.00,10000.00,500000.00,550000.00,18000.00,126289.75,627429.75,501140.00,49029.75,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,919.72,0.9837
|
||||
27,400.00,200.00,3985.00,940.00,21450.00,12050.00,13132.09,10400.00,10000.00,500000.00,550000.00,18000.00,126227.09,627367.09,501140.00,48967.09,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,919.72,0.9837
|
||||
26,400.00,200.00,3985.00,940.00,21450.00,12050.00,13083.89,10400.00,10000.00,500000.00,550000.00,18000.00,126178.89,627318.89,501140.00,48918.89,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,919.72,0.9837
|
||||
25,400.00,200.00,3985.00,940.00,21000.00,12050.00,13081.48,10400.00,10000.00,500000.00,550000.00,18000.00,125726.48,626866.48,501140.00,48466.48,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,919.72,0.9837
|
||||
24,400.00,200.00,3985.00,940.00,21000.00,12050.00,13062.20,10400.00,10000.00,500000.00,550000.00,18000.00,125707.20,626847.20,501140.00,48447.20,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,919.72,0.9837
|
||||
23,400.00,200.00,3985.00,940.00,21000.00,12050.00,13022.44,10400.00,10000.00,500000.00,550000.00,18000.00,125667.44,626807.44,501140.00,48407.44,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,919.72,0.9837
|
||||
22,400.00,200.00,5060.00,940.00,21000.00,12050.00,13061.00,10400.00,10000.00,500000.00,550000.00,18000.00,126781.00,627921.00,501140.00,49521.00,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,1075.00,15.00,1994.72,0.9925
|
||||
21,400.00,200.00,5060.00,940.00,21000.00,12050.00,13068.23,10400.00,10000.00,500000.00,550000.00,18000.00,126788.23,627928.23,501140.00,49528.23,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,1994.72,0.9925
|
||||
20,400.00,200.00,5060.00,940.00,21000.00,12050.00,13079.07,10400.00,10000.00,500000.00,550000.00,18000.00,126799.07,627939.07,501140.00,49539.07,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,15.00,1994.72,0.9925
|
||||
19,400.00,200.00,5060.00,940.00,21000.00,11950.00,12932.29,10280.04,10000.00,500000.00,550000.00,18000.00,126532.33,627672.33,501140.00,49272.33,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,228.18,0.00,243.18,1994.72,0.8781
|
||||
18,400.00,200.00,5060.00,940.00,19000.00,11950.00,12934.68,10280.04,10000.00,500000.00,550000.00,18000.00,124534.72,625674.72,501140.00,47274.72,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,2000.00,0.00,2243.18,1994.72,-0.1246
|
||||
17,400.00,200.00,5060.00,940.00,19000.00,11950.00,12927.51,10280.04,10000.00,500000.00,550000.00,18000.00,124527.55,625667.55,501140.00,47267.55,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2243.18,1994.72,-0.1246
|
||||
16,400.00,200.00,5060.00,940.00,19000.00,11950.00,12916.76,10280.04,10000.00,500000.00,550000.00,18000.00,124516.79,625656.79,501140.00,47256.79,10000.00,500000.00,940.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2243.18,1994.72,-0.1246
|
||||
15,400.00,200.00,5040.00,960.00,19000.00,11950.00,12882.10,10280.04,10000.00,500000.00,550000.00,18000.00,124442.14,625602.14,501160.00,47202.14,10000.00,500000.00,960.00,550000.00,18000.00,400.00,200.00,40.00,0.00,2283.18,1994.72,-0.1446
|
||||
14,400.00,200.00,5040.00,960.00,19000.00,11950.00,12879.71,10280.04,10000.00,500000.00,550000.00,18000.00,124439.75,625599.75,501160.00,47199.75,10000.00,500000.00,960.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2283.18,1994.72,-0.1446
|
||||
13,400.00,200.00,5040.00,960.00,19000.00,11950.00,12873.74,10280.04,10000.00,500000.00,550000.00,18000.00,124433.77,625593.77,501160.00,47193.77,10000.00,500000.00,960.00,550000.00,18000.00,400.00,200.00,0.00,0.00,2283.18,1994.72,-0.1446
|
||||
12,700.00,200.00,5010.00,990.00,19500.00,11950.00,12821.16,10280.04,10000.00,500000.00,550000.00,18000.00,125121.19,626311.19,501190.00,47611.19,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,60.00,50.00,2343.18,2044.72,-0.1460
|
||||
11,700.00,200.00,5010.00,990.00,19500.00,11950.00,12797.26,10280.04,10000.00,500000.00,550000.00,18000.00,125097.29,626287.29,501190.00,47587.29,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2044.72,-0.1460
|
||||
10,700.00,200.00,5010.00,990.00,19500.00,11950.00,12873.74,10280.04,10000.00,500000.00,550000.00,18000.00,125173.77,626363.77,501190.00,47663.77,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2044.72,-0.1460
|
||||
9,700.00,200.00,5010.00,990.00,19500.00,12000.00,12939.60,10330.04,10000.00,500000.00,550000.00,18000.00,125289.64,626479.64,501190.00,47779.64,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,103.92,2343.18,2148.64,-0.0905
|
||||
8,700.00,200.00,5010.00,990.00,19500.00,12000.00,12933.60,10330.04,10000.00,500000.00,550000.00,18000.00,125283.64,626473.64,501190.00,47773.64,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2148.64,-0.0905
|
||||
7,700.00,200.00,5010.00,990.00,19500.00,12000.00,12928.80,10330.04,10000.00,500000.00,550000.00,18000.00,125278.84,626468.84,501190.00,47768.84,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2148.64,-0.0905
|
||||
6,700.00,200.00,5010.00,990.00,19500.00,12000.00,12906.00,10330.04,10000.00,500000.00,550000.00,18000.00,125256.04,626446.04,501190.00,47746.04,10000.00,500000.00,990.00,550000.00,18000.00,700.00,200.00,0.00,0.00,2343.18,2148.64,-0.0905
|
||||
5,700.00,200.00,5000.00,1000.00,19700.00,12000.00,12891.60,10330.04,10000.00,500000.00,550000.00,18000.00,125421.64,626621.64,501200.00,47921.64,10000.00,500000.00,1000.00,550000.00,18000.00,700.00,200.00,20.00,200.00,2363.18,2348.64,-0.0062
|
||||
4,550.00,200.00,5000.00,1000.00,19700.00,12000.00,12945.60,9467.00,10000.00,500000.00,550000.00,18000.00,124462.60,625662.60,501200.00,47112.60,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,863.04,0.00,3226.22,2348.64,-0.3737
|
||||
3,550.00,200.00,5000.00,1000.00,19700.00,12000.00,13046.40,9467.00,10000.00,500000.00,550000.00,18000.00,124563.40,625763.40,501200.00,47213.40,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2348.64,-0.3737
|
||||
2,550.00,200.00,5000.00,1000.00,19700.00,12000.00,12982.80,9467.00,10000.00,500000.00,550000.00,18000.00,124499.80,625699.80,501200.00,47149.80,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2348.64,-0.3737
|
||||
1,550.00,200.00,5000.00,1000.00,19700.00,12000.00,13014.00,9467.00,10000.00,500000.00,550000.00,18000.00,124531.00,625731.00,501200.00,47181.00,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2348.64,-0.3737
|
||||
0,550.00,200.00,5000.00,1000.00,19700.00,12000.00,13000.80,9467.00,10000.00,500000.00,550000.00,18000.00,124517.80,625717.80,501200.00,47167.80,10000.00,500000.00,1000.00,550000.00,18000.00,550.00,200.00,0.00,0.00,3226.22,2348.64,-0.3737
|
|
|
@ -78,6 +78,6 @@ class Account::Balance::CalculatorTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
def calculated_balances_for(account_key)
|
||||
Account::Balance::Calculator.new(accounts(account_key)).calculate.daily_balances
|
||||
Account::Balance::Calculator.new(accounts(account_key)).daily_balances
|
||||
end
|
||||
end
|
||||
|
|
75
test/models/account/entry_test.rb
Normal file
75
test/models/account/entry_test.rb
Normal file
|
@ -0,0 +1,75 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::EntryTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@entry = account_entries :checking_one
|
||||
@family = families :dylan_family
|
||||
end
|
||||
|
||||
test "valuations cannot have more than one entry per day" do
|
||||
new_entry = Account::Entry.new \
|
||||
entryable: Account::Valuation.new,
|
||||
date: @entry.date, # invalid
|
||||
currency: @entry.currency,
|
||||
amount: @entry.amount
|
||||
|
||||
assert new_entry.invalid?
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when transaction is set to prior date" do
|
||||
prior_date = @entry.date - 1
|
||||
@entry.update! date: prior_date
|
||||
|
||||
@entry.account.expects(:sync_later).with(prior_date)
|
||||
@entry.sync_account_later
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when transaction is set to future date" do
|
||||
prior_date = @entry.date
|
||||
@entry.update! date: @entry.date + 1
|
||||
|
||||
@entry.account.expects(:sync_later).with(prior_date)
|
||||
@entry.sync_account_later
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when transaction deleted" do
|
||||
prior_entry = account_entries(:checking_two) # 12 days ago
|
||||
current_entry = account_entries(:checking_one) # 5 days ago
|
||||
current_entry.destroy!
|
||||
|
||||
current_entry.account.expects(:sync_later).with(prior_entry.date)
|
||||
current_entry.sync_account_later
|
||||
end
|
||||
|
||||
test "can search entries" do
|
||||
params = { search: "a" }
|
||||
|
||||
assert_equal 12, Account::Entry.search(params).size
|
||||
|
||||
params = params.merge(categories: [ "Food & Drink" ]) # transaction specific search param
|
||||
|
||||
assert_equal 2, Account::Entry.search(params).size
|
||||
end
|
||||
|
||||
test "can calculate total spending for a group of transactions" do
|
||||
assert_equal Money.new(2135), @family.entries.expense_total("USD")
|
||||
assert_equal Money.new(1010.85, "EUR"), @family.entries.expense_total("EUR")
|
||||
end
|
||||
|
||||
test "can calculate total income for a group of transactions" do
|
||||
assert_equal -Money.new(2075), @family.entries.income_total("USD")
|
||||
assert_equal -Money.new(250, "EUR"), @family.entries.income_total("EUR")
|
||||
end
|
||||
|
||||
# See: https://github.com/maybe-finance/maybe/wiki/vision#signage-of-money
|
||||
test "transactions with negative amounts are inflows, positive amounts are outflows to an account" do
|
||||
inflow_transaction = account_entries(:checking_four)
|
||||
outflow_transaction = account_entries(:checking_five)
|
||||
|
||||
assert inflow_transaction.amount < 0
|
||||
assert inflow_transaction.inflow?
|
||||
|
||||
assert outflow_transaction.amount >= 0
|
||||
assert outflow_transaction.outflow?
|
||||
end
|
||||
end
|
|
@ -7,6 +7,32 @@ class Account::SyncableTest < ActiveSupport::TestCase
|
|||
@account = accounts(:savings)
|
||||
end
|
||||
|
||||
test "calculates effective start date of an account" do
|
||||
assert_equal 31.days.ago.to_date, accounts(:collectable).effective_start_date
|
||||
assert_equal 31.days.ago.to_date, @account.effective_start_date
|
||||
end
|
||||
|
||||
test "syncs regular account" do
|
||||
@account.sync
|
||||
assert_equal "ok", @account.status
|
||||
assert_equal 32, @account.balances.count
|
||||
end
|
||||
|
||||
test "syncs foreign currency account" do
|
||||
account = accounts(:eur_checking)
|
||||
account.sync
|
||||
assert_equal "ok", account.status
|
||||
assert_equal 32, account.balances.where(currency: "USD").count
|
||||
assert_equal 32, account.balances.where(currency: "EUR").count
|
||||
end
|
||||
|
||||
test "syncs multi currency account" do
|
||||
account = accounts(:multi_currency)
|
||||
account.sync
|
||||
assert_equal "ok", account.status
|
||||
assert_equal 32, account.balances.where(currency: "USD").count
|
||||
end
|
||||
|
||||
test "triggers sync job" do
|
||||
assert_enqueued_with(job: AccountSyncJob, args: [ @account, Date.current ]) do
|
||||
@account.sync_later(Date.current)
|
||||
|
@ -42,31 +68,26 @@ class Account::SyncableTest < ActiveSupport::TestCase
|
|||
assert_equal 19500, account.balances.find_by(date: balance_date)[:balance]
|
||||
end
|
||||
|
||||
test "balances before sync start date are not updated after syncing" do
|
||||
account = accounts(:savings)
|
||||
balance_date = 10.days.ago
|
||||
account.balances.create!(date: balance_date, balance: 1000)
|
||||
account.sync 5.days.ago.to_date
|
||||
test "can perform a partial sync with a given sync start date" do
|
||||
# Perform a full sync to populate all balances
|
||||
@account.sync
|
||||
|
||||
assert_equal 1000, account.balances.find_by(date: balance_date)[:balance]
|
||||
end
|
||||
# Perform partial sync
|
||||
sync_start_date = 5.days.ago.to_date
|
||||
balances_before_sync = @account.balances.to_a
|
||||
@account.sync sync_start_date
|
||||
balances_after_sync = @account.reload.balances.to_a
|
||||
|
||||
test "balances after sync start date are updated after syncing" do
|
||||
account = accounts(:savings)
|
||||
balance_date = 10.days.ago
|
||||
account.balances.create!(date: balance_date, balance: 1000)
|
||||
account.sync 20.days.ago.to_date
|
||||
# Balances on or after should be updated
|
||||
balances_after_sync.each do |balance_after_sync|
|
||||
balance_before_sync = balances_before_sync.find { |b| b.date == balance_after_sync.date }
|
||||
|
||||
assert_equal 19500, account.balances.find_by(date: balance_date)[:balance]
|
||||
end
|
||||
|
||||
test "balance on the sync date is updated after syncing" do
|
||||
account = accounts(:savings)
|
||||
balance_date = 5.days.ago
|
||||
account.balances.create!(date: balance_date, balance: 1000)
|
||||
account.sync balance_date.to_date
|
||||
|
||||
assert_equal 19700, account.balances.find_by(date: balance_date)[:balance]
|
||||
if balance_after_sync.date >= sync_start_date
|
||||
assert balance_before_sync.updated_at < balance_after_sync.updated_at
|
||||
else
|
||||
assert_equal balance_before_sync.updated_at, balance_after_sync.updated_at
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
test "foreign currency account has balances in each currency after syncing" do
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::TransactionTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@transaction = account_transactions(:checking_one)
|
||||
@family = families(:dylan_family)
|
||||
end
|
||||
|
||||
# See: https://github.com/maybe-finance/maybe/wiki/vision#signage-of-money
|
||||
test "negative amounts are inflows, positive amounts are outflows to an account" do
|
||||
inflow_transaction = account_transactions(:checking_four)
|
||||
outflow_transaction = account_transactions(:checking_five)
|
||||
|
||||
assert inflow_transaction.amount < 0
|
||||
assert inflow_transaction.inflow?
|
||||
|
||||
assert outflow_transaction.amount >= 0
|
||||
assert outflow_transaction.outflow?
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when transaction is set to prior date" do
|
||||
prior_date = @transaction.date - 1
|
||||
@transaction.update! date: prior_date
|
||||
|
||||
@transaction.account.expects(:sync_later).with(prior_date)
|
||||
@transaction.sync_account_later
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when transaction is set to future date" do
|
||||
prior_date = @transaction.date
|
||||
@transaction.update! date: @transaction.date + 1
|
||||
|
||||
@transaction.account.expects(:sync_later).with(prior_date)
|
||||
@transaction.sync_account_later
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when transaction deleted" do
|
||||
prior_transaction = account_transactions(:checking_two) # 12 days ago
|
||||
current_transaction = account_transactions(:checking_one) # 5 days ago
|
||||
current_transaction.destroy!
|
||||
|
||||
current_transaction.account.expects(:sync_later).with(prior_transaction.date)
|
||||
current_transaction.sync_account_later
|
||||
end
|
||||
|
||||
test "can calculate total spending for a group of transactions" do
|
||||
assert_equal Money.new(2135), @family.transactions.expense_total("USD")
|
||||
assert_equal Money.new(1010.85, "EUR"), @family.transactions.expense_total("EUR")
|
||||
end
|
||||
|
||||
test "can calculate total income for a group of transactions" do
|
||||
assert_equal -Money.new(2075), @family.transactions.income_total("USD")
|
||||
assert_equal -Money.new(250, "EUR"), @family.transactions.income_total("EUR")
|
||||
end
|
||||
end
|
|
@ -3,19 +3,32 @@ require "test_helper"
|
|||
class Account::TransferTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
# Transfers can be posted on different dates
|
||||
@outflow = accounts(:checking).transactions.create! date: 1.day.ago.to_date, name: "Transfer to Savings", amount: 100, marked_as_transfer: true
|
||||
@inflow = accounts(:savings).transactions.create! date: Date.current, name: "Transfer from Savings", amount: -100, marked_as_transfer: true
|
||||
@outflow = accounts(:checking).entries.create! \
|
||||
date: 1.day.ago.to_date,
|
||||
name: "Transfer to Savings",
|
||||
amount: 100,
|
||||
currency: "USD",
|
||||
marked_as_transfer: true,
|
||||
entryable: Account::Transaction.new
|
||||
|
||||
@inflow = accounts(:savings).entries.create! \
|
||||
date: Date.current,
|
||||
name: "Transfer from Savings",
|
||||
amount: -100,
|
||||
currency: "USD",
|
||||
marked_as_transfer: true,
|
||||
entryable: Account::Transaction.new
|
||||
end
|
||||
|
||||
test "transfer valid if it has inflow and outflow from different accounts for the same amount" do
|
||||
transfer = Account::Transfer.create! transactions: [ @inflow, @outflow ]
|
||||
transfer = Account::Transfer.create! entries: [ @inflow, @outflow ]
|
||||
|
||||
assert transfer.valid?
|
||||
end
|
||||
|
||||
test "transfer must have 2 transactions" do
|
||||
invalid_transfer_1 = Account::Transfer.new transactions: [ @outflow ]
|
||||
invalid_transfer_2 = Account::Transfer.new transactions: [ @inflow, @outflow, account_transactions(:savings_four) ]
|
||||
invalid_transfer_1 = Account::Transfer.new entries: [ @outflow ]
|
||||
invalid_transfer_2 = Account::Transfer.new entries: [ @inflow, @outflow, account_entries(:savings_four) ]
|
||||
|
||||
assert invalid_transfer_1.invalid?
|
||||
assert invalid_transfer_2.invalid?
|
||||
|
@ -23,11 +36,24 @@ class Account::TransferTest < ActiveSupport::TestCase
|
|||
|
||||
test "transfer cannot have 2 transactions from the same account" do
|
||||
account = accounts(:checking)
|
||||
inflow = account.transactions.create! date: Date.current, name: "Inflow", amount: -100
|
||||
outflow = account.transactions.create! date: Date.current, name: "Outflow", amount: 100
|
||||
inflow = account.entries.create! \
|
||||
date: Date.current,
|
||||
name: "Inflow",
|
||||
amount: -100,
|
||||
currency: "USD",
|
||||
marked_as_transfer: true,
|
||||
entryable: Account::Transaction.new
|
||||
|
||||
outflow = account.entries.create! \
|
||||
date: Date.current,
|
||||
name: "Outflow",
|
||||
amount: 100,
|
||||
currency: "USD",
|
||||
marked_as_transfer: true,
|
||||
entryable: Account::Transaction.new
|
||||
|
||||
assert_raise ActiveRecord::RecordInvalid do
|
||||
Account::Transfer.create! transactions: [ inflow, outflow ]
|
||||
Account::Transfer.create! entries: [ inflow, outflow ]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,7 +61,7 @@ class Account::TransferTest < ActiveSupport::TestCase
|
|||
@inflow.update! marked_as_transfer: false
|
||||
|
||||
assert_raise ActiveRecord::RecordInvalid do
|
||||
Account::Transfer.create! transactions: [ @inflow, @outflow ]
|
||||
Account::Transfer.create! entries: [ @inflow, @outflow ]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -43,13 +69,13 @@ class Account::TransferTest < ActiveSupport::TestCase
|
|||
@outflow.update! amount: 105
|
||||
|
||||
assert_raises ActiveRecord::RecordInvalid do
|
||||
Account::Transfer.create! transactions: [ @inflow, @outflow ]
|
||||
Account::Transfer.create! entries: [ @inflow, @outflow ]
|
||||
end
|
||||
end
|
||||
|
||||
test "multi-currency transfer transactions do not have to net to zero" do
|
||||
@outflow.update! amount: 105, currency: "EUR"
|
||||
transfer = Account::Transfer.create! transactions: [ @inflow, @outflow ]
|
||||
transfer = Account::Transfer.create! entries: [ @inflow, @outflow ]
|
||||
|
||||
assert transfer.valid?
|
||||
end
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::ValuationTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@valuation = account_valuations :savings_one
|
||||
@family = families :dylan_family
|
||||
end
|
||||
|
||||
test "one valuation per day" do
|
||||
assert_equal 12.days.ago.to_date, account_valuations(:savings_one).date
|
||||
invalid_valuation = Account::Valuation.new date: 12.days.ago.to_date, value: 20000
|
||||
assert invalid_valuation.invalid?
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when valuation is set to prior date" do
|
||||
prior_date = @valuation.date - 1
|
||||
@valuation.update! date: prior_date
|
||||
|
||||
@valuation.account.expects(:sync_later).with(prior_date)
|
||||
@valuation.sync_account_later
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when valuation is set to future date" do
|
||||
prior_date = @valuation.date
|
||||
@valuation.update! date: @valuation.date + 1
|
||||
|
||||
@valuation.account.expects(:sync_later).with(prior_date)
|
||||
@valuation.sync_account_later
|
||||
end
|
||||
|
||||
test "triggers sync with correct start date when valuation deleted" do
|
||||
prior_valuation = account_valuations :savings_two # 25 days ago
|
||||
current_valuation = account_valuations :savings_one # 12 days ago
|
||||
current_valuation.destroy!
|
||||
|
||||
current_valuation.account.expects(:sync_later).with(prior_valuation.date)
|
||||
current_valuation.sync_account_later
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::BalanceTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -7,12 +7,6 @@ class AccountTest < ActiveSupport::TestCase
|
|||
@family = families(:dylan_family)
|
||||
end
|
||||
|
||||
test "new account should be valid" do
|
||||
assert @account.valid?
|
||||
assert_not_nil @account.accountable_id
|
||||
assert_not_nil @account.accountable
|
||||
end
|
||||
|
||||
test "recognizes foreign currency account" do
|
||||
regular_account = accounts(:checking)
|
||||
foreign_account = accounts(:eur_checking)
|
||||
|
@ -34,20 +28,6 @@ class AccountTest < ActiveSupport::TestCase
|
|||
assert_not multi_currency_account.foreign_currency?
|
||||
end
|
||||
|
||||
test "syncs regular account" do
|
||||
@account.sync
|
||||
assert_equal "ok", @account.status
|
||||
assert_equal 32, @account.balances.count
|
||||
end
|
||||
|
||||
test "syncs foreign currency account" do
|
||||
account = accounts(:eur_checking)
|
||||
account.sync
|
||||
assert_equal "ok", account.status
|
||||
assert_equal 32, account.balances.where(currency: "USD").count
|
||||
assert_equal 32, account.balances.where(currency: "EUR").count
|
||||
end
|
||||
|
||||
test "groups accounts by type" do
|
||||
@family.accounts.each do |account|
|
||||
account.sync
|
||||
|
|
|
@ -46,6 +46,7 @@ class ImportTest < ActiveSupport::TestCase
|
|||
# "Shopping" is a new category, but should only be created 1x during import
|
||||
assert_difference \
|
||||
-> { Account::Transaction.count } => 4,
|
||||
-> { Account::Entry.count } => 4,
|
||||
-> { Category.count } => 1,
|
||||
-> { Tagging.count } => 4,
|
||||
-> { Tag.count } => 2 do
|
||||
|
@ -59,11 +60,13 @@ class ImportTest < ActiveSupport::TestCase
|
|||
|
||||
test "publishes a valid import with missing data" do
|
||||
@empty_import.update! raw_csv_str: valid_csv_with_missing_data
|
||||
assert_difference -> { Category.count } => 1, -> { Account::Transaction.count } => 2 do
|
||||
assert_difference -> { Category.count } => 1,
|
||||
-> { Account::Transaction.count } => 2,
|
||||
-> { Account::Entry.count } => 2 do
|
||||
@empty_import.publish
|
||||
end
|
||||
|
||||
assert_not_nil Account::Transaction.find_sole_by(name: Import::FALLBACK_TRANSACTION_NAME)
|
||||
assert_not_nil Account::Entry.find_sole_by(name: Import::FALLBACK_TRANSACTION_NAME)
|
||||
|
||||
@empty_import.reload
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class SettingsTest < ApplicationSystemTestCase
|
|||
[ "Tags", "Tags", tags_path ],
|
||||
[ "Categories", "Categories", categories_path ],
|
||||
[ "Merchants", "Merchants", merchants_path ],
|
||||
[ "Rules", "Rules", account_transaction_rules_path ],
|
||||
[ "Rules", "Rules", rules_transactions_path ],
|
||||
[ "Imports", "Imports", imports_path ],
|
||||
[ "What's New", "What's New", changelog_path ],
|
||||
[ "Feedback", "Feedback", feedback_path ],
|
||||
|
|
|
@ -4,17 +4,25 @@ class TransactionsTest < ApplicationSystemTestCase
|
|||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
|
||||
@latest_transactions = @user.family.transactions.ordered.limit(20).to_a
|
||||
@page_size = 10
|
||||
|
||||
@latest_transactions = @user.family.entries
|
||||
.account_transactions
|
||||
.without_transfers
|
||||
.reverse_chronological
|
||||
.limit(20).to_a
|
||||
@test_category = @user.family.categories.create! name: "System Test Category"
|
||||
@test_merchant = @user.family.merchants.create! name: "System Test Merchant"
|
||||
@target_txn = @user.family.accounts.first.transactions.create! \
|
||||
|
||||
@target_txn = @user.family.accounts.first.entries.create! \
|
||||
name: "Oldest transaction",
|
||||
date: 10.years.ago.to_date,
|
||||
category: @test_category,
|
||||
merchant: @test_merchant,
|
||||
amount: 100
|
||||
currency: @user.family.currency,
|
||||
amount: 100,
|
||||
entryable: Account::Transaction.new(category: @test_category,
|
||||
merchant: @test_merchant)
|
||||
|
||||
visit transactions_url
|
||||
visit transactions_url(per_page: @page_size)
|
||||
end
|
||||
|
||||
test "can search for a transaction" do
|
||||
|
@ -45,7 +53,7 @@ class TransactionsTest < ApplicationSystemTestCase
|
|||
|
||||
within "#transaction-search-filters" do
|
||||
assert_text @target_txn.account.name
|
||||
assert_text @target_txn.category.name
|
||||
assert_text @target_txn.account_transaction.category.name
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -75,22 +83,22 @@ class TransactionsTest < ApplicationSystemTestCase
|
|||
click_button "Apply"
|
||||
end
|
||||
|
||||
assert_text "No transactions found"
|
||||
assert_text "No entries found"
|
||||
|
||||
# Page reload doesn't affect results
|
||||
visit current_url
|
||||
|
||||
assert_text "No transactions found"
|
||||
assert_text "No entries found"
|
||||
|
||||
within "ul#transaction-search-filters" do
|
||||
find("li", text: @target_txn.account.name).first("a").click
|
||||
find("li", text: "on or after #{10.days.ago.to_date}").first("a").click
|
||||
find("li", text: "on or before #{Date.current}").first("a").click
|
||||
find("li", text: @target_txn.category.name).first("a").click
|
||||
find("li", text: @target_txn.merchant.name).first("a").click
|
||||
find("li", text: @target_txn.account_transaction.category.name).first("a").click
|
||||
find("li", text: @target_txn.account_transaction.merchant.name).first("a").click
|
||||
end
|
||||
|
||||
assert_selector "#" + dom_id(@user.family.transactions.ordered.first), count: 1
|
||||
assert_selector "#" + dom_id(@user.family.entries.reverse_chronological.first), count: 1
|
||||
end
|
||||
|
||||
test "can select and deselect entire page of transactions" do
|
||||
|
@ -132,17 +140,15 @@ class TransactionsTest < ApplicationSystemTestCase
|
|||
private
|
||||
|
||||
def number_of_transactions_on_page
|
||||
page_size = 10
|
||||
|
||||
[ @user.family.transactions.where(transfer_id: nil).count, page_size ].min
|
||||
[ @user.family.entries.without_transfers.count, @page_size ].min
|
||||
end
|
||||
|
||||
def all_transactions_checkbox
|
||||
find("#selection_transaction")
|
||||
find("#selection_entry")
|
||||
end
|
||||
|
||||
def date_transactions_checkbox(date)
|
||||
find("#selection_transaction_#{date}")
|
||||
find("#selection_entry_#{date}")
|
||||
end
|
||||
|
||||
def transaction_checkbox(transaction)
|
||||
|
@ -151,9 +157,9 @@ class TransactionsTest < ApplicationSystemTestCase
|
|||
|
||||
def assert_selection_count(count)
|
||||
if count == 0
|
||||
assert_no_selector("#transaction-selection-bar")
|
||||
assert_no_selector("#entry-selection-bar")
|
||||
else
|
||||
within "#transaction-selection-bar" do
|
||||
within "#entry-selection-bar" do
|
||||
assert_text "#{count} transaction#{count == 1 ? "" : "s"} selected"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,45 +22,52 @@ class TransfersTest < ApplicationSystemTestCase
|
|||
select savings_name, from: "To"
|
||||
fill_in "account_transfer[amount]", with: 500
|
||||
fill_in "Date", with: transfer_date
|
||||
|
||||
click_button "Create transfer"
|
||||
|
||||
within "#date-group-" + transfer_date.to_s do
|
||||
transfer_name = "Transfer from #{checking_name} to #{savings_name}"
|
||||
find("details", text: transfer_name).click
|
||||
assert_text "Transfer txn name", count: 2
|
||||
within "#entry-group-" + transfer_date.to_s do
|
||||
assert_text "Transfer from"
|
||||
end
|
||||
end
|
||||
|
||||
test "can match 2 transactions and create a transfer" do
|
||||
transfer_date = Date.current
|
||||
outflow = Account::Transaction.create! name: "Outflow from savings account", date: transfer_date, account: accounts(:savings), amount: 100
|
||||
inflow = Account::Transaction.create! name: "Inflow to checking account", date: transfer_date, account: accounts(:checking), amount: -100
|
||||
outflow = accounts(:savings).entries.create! \
|
||||
name: "Outflow from savings account",
|
||||
date: transfer_date,
|
||||
amount: 100,
|
||||
currency: "USD",
|
||||
entryable: Account::Transaction.new
|
||||
|
||||
inflow = accounts(:checking).entries.create! \
|
||||
name: "Inflow to checking account",
|
||||
date: transfer_date,
|
||||
amount: -100,
|
||||
currency: "USD",
|
||||
entryable: Account::Transaction.new
|
||||
|
||||
visit transactions_url
|
||||
|
||||
transaction_checkbox(inflow).check
|
||||
transaction_checkbox(outflow).check
|
||||
transaction_entry_checkbox(inflow).check
|
||||
transaction_entry_checkbox(outflow).check
|
||||
|
||||
bulk_transfer_action_button.click
|
||||
|
||||
click_on "Mark as transfers"
|
||||
|
||||
within "#date-group-" + transfer_date.to_s do
|
||||
transfer_name = "Transfer from #{outflow.account.name} to #{inflow.account.name}"
|
||||
find("details", text: transfer_name).click
|
||||
assert_text inflow.name
|
||||
assert_text outflow.name
|
||||
within "#entry-group-" + transfer_date.to_s do
|
||||
assert_text "Transfer from"
|
||||
end
|
||||
end
|
||||
|
||||
test "can mark a single transaction as a transfer" do
|
||||
txn = @user.family.transactions.ordered.first
|
||||
txn = @user.family.entries.reverse_chronological.first
|
||||
|
||||
within "#" + dom_id(txn) do
|
||||
assert_text "Uncategorized"
|
||||
end
|
||||
|
||||
transaction_checkbox(txn).check
|
||||
transaction_entry_checkbox(txn).check
|
||||
|
||||
bulk_transfer_action_button.click
|
||||
click_on "Mark as transfers"
|
||||
|
@ -72,8 +79,8 @@ class TransfersTest < ApplicationSystemTestCase
|
|||
|
||||
private
|
||||
|
||||
def transaction_checkbox(transaction)
|
||||
find("#" + dom_id(transaction, "selection"))
|
||||
def transaction_entry_checkbox(transaction_entry)
|
||||
find("#" + dom_id(transaction_entry, "selection"))
|
||||
end
|
||||
|
||||
def bulk_transfer_action_button
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue