2024-02-02 09:05:04 -06:00
|
|
|
require "test_helper"
|
2024-03-11 16:32:13 -04:00
|
|
|
require "csv"
|
2024-02-02 09:05:04 -06:00
|
|
|
|
|
|
|
class FamilyTest < ActiveSupport::TestCase
|
2024-07-10 11:22:59 -04:00
|
|
|
include Account::EntriesTestHelper
|
2024-11-15 13:49:37 -05:00
|
|
|
include SyncableInterfaceTest
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-02-03 13:07:23 -06:00
|
|
|
def setup
|
2024-11-15 13:49:37 -05:00
|
|
|
@family = families(:empty)
|
|
|
|
@syncable = families(:dylan_family)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "syncs plaid items and manual accounts" do
|
|
|
|
family_sync = syncs(:family)
|
|
|
|
|
|
|
|
manual_accounts_count = @syncable.accounts.manual.count
|
|
|
|
items_count = @syncable.plaid_items.count
|
|
|
|
|
|
|
|
Account.any_instance.expects(:sync_data)
|
|
|
|
.with(start_date: nil)
|
|
|
|
.times(manual_accounts_count)
|
|
|
|
|
|
|
|
PlaidItem.any_instance.expects(:sync_data)
|
|
|
|
.with(start_date: nil)
|
|
|
|
.times(items_count)
|
|
|
|
|
|
|
|
@syncable.sync_data(start_date: family_sync.start_date)
|
2024-07-10 11:22:59 -04:00
|
|
|
end
|
2024-07-08 09:04:59 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "calculates assets" do
|
|
|
|
assert_equal Money.new(0, @family.currency), @family.assets
|
2024-07-08 09:04:59 -04:00
|
|
|
|
2024-07-17 14:18:12 -04:00
|
|
|
create_account(balance: 1000, accountable: Depository.new)
|
|
|
|
create_account(balance: 5000, accountable: OtherAsset.new)
|
|
|
|
create_account(balance: 10000, accountable: CreditCard.new) # ignored
|
2024-07-08 09:04:59 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal Money.new(1000 + 5000, @family.currency), @family.assets
|
2024-02-03 13:07:23 -06:00
|
|
|
end
|
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "calculates liabilities" do
|
|
|
|
assert_equal Money.new(0, @family.currency), @family.liabilities
|
2024-02-03 13:07:23 -06:00
|
|
|
|
2024-07-17 14:18:12 -04:00
|
|
|
create_account(balance: 1000, accountable: CreditCard.new)
|
|
|
|
create_account(balance: 5000, accountable: OtherLiability.new)
|
|
|
|
create_account(balance: 10000, accountable: Depository.new) # ignored
|
2024-02-03 13:07:23 -06:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal Money.new(1000 + 5000, @family.currency), @family.liabilities
|
2024-02-03 13:07:23 -06:00
|
|
|
end
|
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "calculates net worth" do
|
|
|
|
assert_equal Money.new(0, @family.currency), @family.net_worth
|
2024-03-04 08:31:22 -05:00
|
|
|
|
2024-07-17 14:18:12 -04:00
|
|
|
create_account(balance: 1000, accountable: CreditCard.new)
|
|
|
|
create_account(balance: 50000, accountable: Depository.new)
|
2024-03-07 19:15:50 +01:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal Money.new(50000 - 1000, @family.currency), @family.net_worth
|
2024-04-29 21:17:28 +02:00
|
|
|
end
|
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "should exclude disabled accounts from calculations" do
|
2024-07-17 14:18:12 -04:00
|
|
|
cc = create_account(balance: 1000, accountable: CreditCard.new)
|
|
|
|
create_account(balance: 50000, accountable: Depository.new)
|
2024-03-04 08:31:22 -05:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal Money.new(50000 - 1000, @family.currency), @family.net_worth
|
|
|
|
|
|
|
|
cc.update! is_active: false
|
2024-03-04 08:31:22 -05:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal Money.new(50000, @family.currency), @family.net_worth
|
2024-03-04 08:31:22 -05:00
|
|
|
end
|
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "calculates snapshot" do
|
2024-07-17 14:18:12 -04:00
|
|
|
asset = create_account(balance: 500, accountable: Depository.new)
|
|
|
|
liability = create_account(balance: 100, accountable: CreditCard.new)
|
2024-04-24 13:34:50 +01:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
asset.balances.create! date: 1.day.ago.to_date, currency: "USD", balance: 450
|
|
|
|
asset.balances.create! date: Date.current, currency: "USD", balance: 500
|
2024-04-24 13:34:50 +01:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
liability.balances.create! date: 1.day.ago.to_date, currency: "USD", balance: 50
|
|
|
|
liability.balances.create! date: Date.current, currency: "USD", balance: 100
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
expected_asset_series = [
|
|
|
|
{ date: 1.day.ago.to_date, value: Money.new(450) },
|
|
|
|
{ date: Date.current, value: Money.new(500) }
|
|
|
|
]
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
expected_liability_series = [
|
|
|
|
{ date: 1.day.ago.to_date, value: Money.new(50) },
|
|
|
|
{ date: Date.current, value: Money.new(100) }
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_net_worth_series = [
|
|
|
|
{ date: 1.day.ago.to_date, value: Money.new(450 - 50) },
|
|
|
|
{ date: Date.current, value: Money.new(500 - 100) }
|
|
|
|
]
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal expected_asset_series, @family.snapshot[:asset_series].values.map { |v| { date: v.date, value: v.value } }
|
|
|
|
assert_equal expected_liability_series, @family.snapshot[:liability_series].values.map { |v| { date: v.date, value: v.value } }
|
|
|
|
assert_equal expected_net_worth_series, @family.snapshot[:net_worth_series].values.map { |v| { date: v.date, value: v.value } }
|
2024-04-24 13:34:50 +01:00
|
|
|
end
|
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "calculates top movers" do
|
2024-07-17 14:18:12 -04:00
|
|
|
checking_account = create_account(balance: 500, accountable: Depository.new)
|
|
|
|
savings_account = create_account(balance: 1000, accountable: Depository.new)
|
2024-07-10 11:22:59 -04:00
|
|
|
create_transaction(account: checking_account, date: 2.days.ago.to_date, amount: -1000)
|
|
|
|
create_transaction(account: checking_account, date: 1.day.ago.to_date, amount: 10)
|
|
|
|
create_transaction(account: savings_account, date: 2.days.ago.to_date, amount: -5000)
|
2024-03-07 10:55:51 -05:00
|
|
|
|
2024-08-20 15:44:32 -04:00
|
|
|
zero_income_zero_expense_account = create_account(balance: 200, accountable: Depository.new)
|
|
|
|
create_transaction(account: zero_income_zero_expense_account, amount: 0)
|
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
snapshot = @family.snapshot_account_transactions
|
|
|
|
top_spenders = snapshot[:top_spenders]
|
|
|
|
top_earners = snapshot[:top_earners]
|
|
|
|
top_savers = snapshot[:top_savers]
|
2024-03-07 10:55:51 -05:00
|
|
|
|
2024-08-20 15:44:32 -04:00
|
|
|
assert_equal [ 10 ], top_spenders.map(&:spending)
|
|
|
|
assert_equal [ 5000, 1000 ], top_earners.map(&:income)
|
|
|
|
assert_equal [ 1, 0.99 ], top_savers.map(&:savings_rate)
|
2024-03-07 10:55:51 -05:00
|
|
|
end
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-08-20 15:44:32 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
test "calculates rolling transaction totals" do
|
2024-07-17 14:18:12 -04:00
|
|
|
account = create_account(balance: 1000, accountable: Depository.new)
|
2024-10-31 13:05:01 +00:00
|
|
|
liability_account = create_account(balance: 1000, accountable: Loan.new)
|
2024-07-10 11:22:59 -04:00
|
|
|
create_transaction(account: account, date: 2.days.ago.to_date, amount: -500)
|
|
|
|
create_transaction(account: account, date: 1.day.ago.to_date, amount: 100)
|
|
|
|
create_transaction(account: account, date: Date.current, amount: 20)
|
2024-12-30 17:29:59 -05:00
|
|
|
create_transaction(account: liability_account, date: 2.days.ago.to_date, amount: -333, category: categories(:payment))
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
snapshot = @family.snapshot_transactions
|
|
|
|
|
|
|
|
expected_income_series = [
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 500, 500, 500
|
|
|
|
]
|
2024-06-19 06:52:08 -04:00
|
|
|
|
2024-07-10 11:22:59 -04:00
|
|
|
assert_equal expected_income_series, snapshot[:income_series].values.map(&:value).map(&:amount)
|
|
|
|
|
|
|
|
expected_spending_series = [
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 100, 120
|
|
|
|
]
|
|
|
|
|
|
|
|
assert_equal expected_spending_series, snapshot[:spending_series].values.map(&:value).map(&:amount)
|
|
|
|
|
|
|
|
expected_savings_rate_series = [
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 1, 0.8, 0.76
|
|
|
|
]
|
|
|
|
|
|
|
|
assert_equal expected_savings_rate_series, snapshot[:savings_rate_series].values.map(&:value).map { |v| v.round(2) }
|
|
|
|
end
|
2024-07-17 14:18:12 -04:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def create_account(attributes = {})
|
|
|
|
account = @family.accounts.create! name: "Test", currency: "USD", **attributes
|
|
|
|
account
|
|
|
|
end
|
2024-02-02 09:05:04 -06:00
|
|
|
end
|