mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 05:09:38 +02:00
Add Local Development Demo Data (#502)
* Clean up seeds, add development demo data * Handle liability account display and sync * Fix tests
This commit is contained in:
parent
dbf575c02a
commit
14641d16de
12 changed files with 368 additions and 62 deletions
|
@ -31,12 +31,15 @@ cd maybe
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
bin/setup
|
bin/setup
|
||||||
bin/dev
|
bin/dev
|
||||||
|
|
||||||
|
# Optionally, load demo data
|
||||||
|
rake demo_data:reset
|
||||||
```
|
```
|
||||||
|
|
||||||
And visit http://localhost:3000 to see the app. You can use the following credentials to log in (generated by DB seed):
|
And visit http://localhost:3000 to see the app. You can use the following credentials to log in (generated by DB seed):
|
||||||
|
|
||||||
Email: `user@maybe.local`
|
- Email: `user@maybe.local`
|
||||||
Password: `password`
|
- Password: `password`
|
||||||
|
|
||||||
For further instructions, see guides below.
|
For further instructions, see guides below.
|
||||||
|
|
||||||
|
|
|
@ -49,12 +49,13 @@ module ApplicationHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
# Styles to use when displaying a change in value
|
# Styles to use when displaying a change in value
|
||||||
def trend_styles(trend)
|
def trend_styles(trend, mode: :asset)
|
||||||
|
puts mode == :liability ? "it is a liability" : "it is an asset"
|
||||||
bg_class, text_class, symbol, icon = case trend.direction
|
bg_class, text_class, symbol, icon = case trend.direction
|
||||||
when "up"
|
when "up"
|
||||||
[ "bg-green-500/5", "text-green-500", "+", "arrow-up" ]
|
mode == :liability ? [ "bg-red-500/5", "text-red-500", "+", "arrow-up" ] : [ "bg-green-500/5", "text-green-500", "+", "arrow-up" ]
|
||||||
when "down"
|
when "down"
|
||||||
[ "bg-red-500/5", "text-red-500", "-", "arrow-down" ]
|
mode == :liability ? [ "bg-green-500/5", "text-green-500", "-", "arrow-down" ] : [ "bg-red-500/5", "text-red-500", "-", "arrow-down" ]
|
||||||
when "flat"
|
when "flat"
|
||||||
[ "bg-gray-500/5", "text-gray-500", "", "minus" ]
|
[ "bg-gray-500/5", "text-gray-500", "", "minus" ]
|
||||||
else
|
else
|
||||||
|
|
|
@ -12,6 +12,21 @@ class Account < ApplicationRecord
|
||||||
delegate :type_name, to: :accountable
|
delegate :type_name, to: :accountable
|
||||||
before_create :check_currency
|
before_create :check_currency
|
||||||
|
|
||||||
|
def classification
|
||||||
|
classifications = {
|
||||||
|
"Account::Depository" => :asset,
|
||||||
|
"Account::Investment" => :asset,
|
||||||
|
"Account::Property" => :asset,
|
||||||
|
"Account::Vehicle" => :asset,
|
||||||
|
"Account::OtherAsset" => :asset,
|
||||||
|
"Account::Loan" => :liability,
|
||||||
|
"Account::Credit" => :liability,
|
||||||
|
"Account::OtherLiability" => :liability
|
||||||
|
}
|
||||||
|
|
||||||
|
classifications[accountable_type]
|
||||||
|
end
|
||||||
|
|
||||||
def balance_series(period)
|
def balance_series(period)
|
||||||
filtered_balances = balances.in_period(period).order(:date)
|
filtered_balances = balances.in_period(period).order(:date)
|
||||||
return nil if filtered_balances.empty?
|
return nil if filtered_balances.empty?
|
||||||
|
|
|
@ -11,6 +11,7 @@ class Account::BalanceCalculator
|
||||||
oldest_entry = [ valuations.first, transactions.first ].compact.min_by(&:date)
|
oldest_entry = [ valuations.first, transactions.first ].compact.min_by(&:date)
|
||||||
|
|
||||||
net_transaction_flows = transactions.sum(&:amount)
|
net_transaction_flows = transactions.sum(&:amount)
|
||||||
|
net_transaction_flows *= -1 if @account.classification == :liability
|
||||||
implied_start_balance = oldest_entry.is_a?(Valuation) ? oldest_entry.value : @account.balance + net_transaction_flows
|
implied_start_balance = oldest_entry.is_a?(Valuation) ? oldest_entry.value : @account.balance + net_transaction_flows
|
||||||
|
|
||||||
prior_balance = implied_start_balance
|
prior_balance = implied_start_balance
|
||||||
|
@ -21,6 +22,7 @@ class Account::BalanceCalculator
|
||||||
current_balance = valuation.value
|
current_balance = valuation.value
|
||||||
else
|
else
|
||||||
current_day_net_transaction_flows = transactions.select { |t| t.date == date }.sum(&:amount)
|
current_day_net_transaction_flows = transactions.select { |t| t.date == date }.sum(&:amount)
|
||||||
|
current_day_net_transaction_flows *= -1 if @account.classification == :liability
|
||||||
current_balance = prior_balance - current_day_net_transaction_flows
|
current_balance = prior_balance - current_day_net_transaction_flows
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<div class="rounded-lg bg-white border-alpha-black-25 shadow-xs">
|
<div class="rounded-lg bg-white border-alpha-black-25 shadow-xs">
|
||||||
<%= turbo_frame_tag dom_id(Valuation.new) %>
|
<%= turbo_frame_tag dom_id(Valuation.new) %>
|
||||||
<%= turbo_frame_tag "valuations_list" do %>
|
<%= turbo_frame_tag "valuations_list" do %>
|
||||||
<%= render partial: "accounts/account_valuation_list", locals: { valuation_series: valuation_series } %>
|
<%= render partial: "accounts/account_valuation_list", locals: { valuation_series: valuation_series, classification: account.classification } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<%# locals: (valuation_series:) %>
|
<%# locals: (valuation_series:, classification:) %>
|
||||||
<% valuation_series.with_index do |valuation_item, index| %>
|
<% valuation_series.with_index do |valuation_item, index| %>
|
||||||
<% valuation, trend = valuation_item.values_at(:value, :trend) %>
|
<% valuation, trend = valuation_item.values_at(:value, :trend) %>
|
||||||
<% valuation_styles = trend_styles(valuation_item[:trend]) %>
|
<% valuation_styles = trend_styles(valuation_item[:trend], mode: classification) %>
|
||||||
<%= turbo_frame_tag dom_id(valuation) do %>
|
<%= turbo_frame_tag dom_id(valuation) do %>
|
||||||
<div class="p-4 flex items-center">
|
<div class="p-4 flex items-center">
|
||||||
<div class="w-16">
|
<div class="w-16">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<%= turbo_stream_from @account %>
|
<%= turbo_stream_from @account %>
|
||||||
<% balance_trend_styles = @balance_series.nil? ? {} : trend_styles(@balance_series[:trend]) %>
|
<% balance_trend_styles = @balance_series.nil? ? {} : trend_styles(@balance_series[:trend], mode: @account.classification) %>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
|
|
54
db/seeds.rb
54
db/seeds.rb
|
@ -1,60 +1,8 @@
|
||||||
# This file should ensure the existence of records required to run the application in every environment (production,
|
# This file should ensure the existence of records required to run the application in every environment (production,
|
||||||
# development, test). The code here should be idempotent so that it can be executed at any point in every environment.
|
# development, test). The code here should be idempotent so that it can be executed at any point in every environment.
|
||||||
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
|
# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup).
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
#
|
|
||||||
# ["Action", "Comedy", "Drama", "Horror"].each do |genre_name|
|
|
||||||
# MovieGenre.find_or_create_by!(name: genre_name)
|
|
||||||
# end
|
|
||||||
|
|
||||||
# https://github.com/rails/rails/issues/29112#issuecomment-320653056
|
|
||||||
ApplicationRecord.reset_column_information
|
|
||||||
|
|
||||||
# Create the default user
|
|
||||||
family = Family.create_or_find_by(name: "The Maybe Family")
|
|
||||||
puts "Family created: #{family.name}"
|
|
||||||
user = User.create_or_find_by(email: "user@maybe.local") do |u|
|
|
||||||
u.first_name = "Josh"
|
|
||||||
u.last_name = "Maybe"
|
|
||||||
u.password = "password"
|
|
||||||
u.password_confirmation = "password"
|
|
||||||
u.family_id = family.id
|
|
||||||
end
|
|
||||||
puts "User created: #{user.email} for family: #{family.name}"
|
|
||||||
|
|
||||||
# Create default currency
|
# Create default currency
|
||||||
Currency.find_or_create_by(iso_code: "USD", name: "United States Dollar")
|
Currency.find_or_create_by(iso_code: "USD", name: "United States Dollar")
|
||||||
|
|
||||||
checking_account = Account::Depository.new
|
puts 'Run the following command to create demo data: `rake demo_data:reset`' if Rails.env.development?
|
||||||
account = Account.create_or_find_by(
|
|
||||||
name: "Seed Checking Account",
|
|
||||||
accountable: checking_account,
|
|
||||||
family: family,
|
|
||||||
balance: 5000
|
|
||||||
)
|
|
||||||
puts "Account created: #{account.name}"
|
|
||||||
|
|
||||||
valuations = [
|
|
||||||
{ date: 1.year.ago.to_date, value: 4200 },
|
|
||||||
{ date: 250.days.ago.to_date, value: 4500 },
|
|
||||||
{ date: 200.days.ago.to_date, value: 4444.96 }
|
|
||||||
]
|
|
||||||
|
|
||||||
account.valuations.upsert_all(valuations, unique_by: :index_valuations_on_account_id_and_date)
|
|
||||||
|
|
||||||
puts "Valuations created: #{valuations.count}"
|
|
||||||
|
|
||||||
transactions = [
|
|
||||||
{ date: Date.today - 27, amount: 7.56, name: "Starbucks" },
|
|
||||||
{ date: Date.today - 18, amount: -500, name: "Paycheck" },
|
|
||||||
{ date: Date.today - 18, amount: 18.20, name: "Walgreens" },
|
|
||||||
{ date: Date.today - 13, amount: 34.20, name: "Chipotle" },
|
|
||||||
{ date: Date.today - 9, amount: -200, name: "Birthday check" },
|
|
||||||
{ date: Date.today - 5, amount: 85.00, name: "Amazon stuff" }
|
|
||||||
]
|
|
||||||
transactions.each do |t|
|
|
||||||
account.transactions.find_or_create_by(t)
|
|
||||||
end
|
|
||||||
|
|
||||||
puts "Transactions created: #{transactions.count}"
|
|
||||||
|
|
291
lib/tasks/demo_data.rake
Normal file
291
lib/tasks/demo_data.rake
Normal file
|
@ -0,0 +1,291 @@
|
||||||
|
namespace :demo_data do
|
||||||
|
desc "Creates or resets demo data used in development environment"
|
||||||
|
task reset: :environment do
|
||||||
|
family = Family.find_or_create_by(name: "Demo Family")
|
||||||
|
user = User.find_or_create_by(email: "user@maybe.local") do |u|
|
||||||
|
u.password = "password"
|
||||||
|
u.family = family
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "Reset user: #{user.email} with family: #{family.name}"
|
||||||
|
|
||||||
|
|
||||||
|
checking = Account.find_or_create_by(name: "Demo Checking") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Depository.new
|
||||||
|
a.balance = 5000
|
||||||
|
end
|
||||||
|
|
||||||
|
checking_transactions = [
|
||||||
|
{ date: Date.today - 84, amount: -3000, name: "Direct Deposit" },
|
||||||
|
{ date: Date.today - 70, amount: 1500, name: "Credit Card Payment" },
|
||||||
|
{ date: Date.today - 70, amount: 200, name: "Utility Bill" },
|
||||||
|
{ date: Date.today - 56, amount: -3000, name: "Direct Deposit" },
|
||||||
|
{ date: Date.today - 42, amount: 1500, name: "Credit Card Payment" },
|
||||||
|
{ date: Date.today - 42, amount: 100, name: "Internet Bill" },
|
||||||
|
{ date: Date.today - 28, amount: -3000, name: "Direct Deposit" },
|
||||||
|
{ date: Date.today - 28, amount: 1500, name: "Credit Card Payment" },
|
||||||
|
{ date: Date.today - 28, amount: 50, name: "Mobile Bill" },
|
||||||
|
{ date: Date.today - 14, amount: -3000, name: "Direct Deposit" },
|
||||||
|
{ date: Date.today - 14, amount: 1500, name: "Credit Card Payment" },
|
||||||
|
{ date: Date.today - 14, amount: 200, name: "Car Loan Payment" },
|
||||||
|
{ date: Date.today - 7, amount: 150, name: "Insurance" },
|
||||||
|
{ date: Date.today - 2, amount: 100, name: "Gym Membership" }
|
||||||
|
]
|
||||||
|
|
||||||
|
checking_transactions.each do |t|
|
||||||
|
checking.transactions.find_or_create_by(date: t[:date], amount: t[:amount], name: t[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
checking.sync
|
||||||
|
|
||||||
|
savings = Account.find_or_create_by(name: "Demo Savings") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Depository.new
|
||||||
|
a.balance = 20000
|
||||||
|
end
|
||||||
|
|
||||||
|
savings_transactions = [
|
||||||
|
{ date: Date.today - 360, amount: -1000, name: "Initial Deposit" },
|
||||||
|
{ date: Date.today - 330, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 300, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 270, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 240, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 210, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 180, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 150, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 120, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 90, amount: 1000, name: "Withdrawal" },
|
||||||
|
{ date: Date.today - 60, amount: -200, name: "Monthly Savings" },
|
||||||
|
{ date: Date.today - 30, amount: -200, name: "Monthly Savings" }
|
||||||
|
]
|
||||||
|
|
||||||
|
savings_transactions.each do |t|
|
||||||
|
savings.transactions.find_or_create_by(date: t[:date], amount: t[:amount], name: t[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
savings.sync
|
||||||
|
|
||||||
|
credit_card = Account.find_or_create_by(name: "Demo Credit Card") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Credit.new
|
||||||
|
a.balance = 1500
|
||||||
|
end
|
||||||
|
|
||||||
|
credit_card_transactions = [
|
||||||
|
{ date: Date.today - 90, amount: 75, name: "Grocery Store" },
|
||||||
|
{ date: Date.today - 89, amount: 30, name: "Gas Station" },
|
||||||
|
{ date: Date.today - 88, amount: 12, name: "Coffee Shop" },
|
||||||
|
{ date: Date.today - 85, amount: 50, name: "Restaurant" },
|
||||||
|
{ date: Date.today - 84, amount: 25, name: "Online Subscription" },
|
||||||
|
{ date: Date.today - 82, amount: 100, name: "Clothing Store" },
|
||||||
|
{ date: Date.today - 80, amount: 60, name: "Pharmacy" },
|
||||||
|
{ date: Date.today - 78, amount: 40, name: "Utility Bill" },
|
||||||
|
{ date: Date.today - 75, amount: 90, name: "Home Improvement Store" },
|
||||||
|
{ date: Date.today - 74, amount: 20, name: "Book Store" },
|
||||||
|
{ date: Date.today - 72, amount: 15, name: "Movie Theater" },
|
||||||
|
{ date: Date.today - 70, amount: 200, name: "Electronics Store" },
|
||||||
|
{ date: Date.today - 68, amount: 35, name: "Pet Store" },
|
||||||
|
{ date: Date.today - 65, amount: 80, name: "Sporting Goods Store" },
|
||||||
|
{ date: Date.today - 63, amount: 55, name: "Department Store" },
|
||||||
|
{ date: Date.today - 60, amount: 110, name: "Auto Repair Shop" },
|
||||||
|
{ date: Date.today - 58, amount: 45, name: "Beauty Salon" },
|
||||||
|
{ date: Date.today - 55, amount: 95, name: "Furniture Store" },
|
||||||
|
{ date: Date.today - 53, amount: 22, name: "Fast Food" },
|
||||||
|
{ date: Date.today - 50, amount: 120, name: "Airline Ticket" },
|
||||||
|
{ date: Date.today - 48, amount: 65, name: "Hotel" },
|
||||||
|
{ date: Date.today - 45, amount: 30, name: "Car Rental" },
|
||||||
|
{ date: Date.today - 43, amount: 18, name: "Music Store" },
|
||||||
|
{ date: Date.today - 40, amount: 70, name: "Grocery Store" },
|
||||||
|
{ date: Date.today - 38, amount: 32, name: "Gas Station" },
|
||||||
|
{ date: Date.today - 36, amount: 14, name: "Coffee Shop" },
|
||||||
|
{ date: Date.today - 33, amount: 52, name: "Restaurant" },
|
||||||
|
{ date: Date.today - 31, amount: 28, name: "Online Subscription" },
|
||||||
|
{ date: Date.today - 29, amount: 105, name: "Clothing Store" },
|
||||||
|
{ date: Date.today - 27, amount: 62, name: "Pharmacy" },
|
||||||
|
{ date: Date.today - 25, amount: 42, name: "Utility Bill" },
|
||||||
|
{ date: Date.today - 22, amount: 92, name: "Home Improvement Store" },
|
||||||
|
{ date: Date.today - 20, amount: 23, name: "Book Store" },
|
||||||
|
{ date: Date.today - 18, amount: 17, name: "Movie Theater" },
|
||||||
|
{ date: Date.today - 15, amount: 205, name: "Electronics Store" },
|
||||||
|
{ date: Date.today - 13, amount: 37, name: "Pet Store" },
|
||||||
|
{ date: Date.today - 10, amount: 83, name: "Sporting Goods Store" },
|
||||||
|
{ date: Date.today - 8, amount: 57, name: "Department Store" },
|
||||||
|
{ date: Date.today - 5, amount: 115, name: "Auto Repair Shop" },
|
||||||
|
{ date: Date.today - 3, amount: 47, name: "Beauty Salon" },
|
||||||
|
{ date: Date.today - 1, amount: 98, name: "Furniture Store" },
|
||||||
|
{ date: Date.today - 60, amount: -800, name: "Credit Card Payment" },
|
||||||
|
{ date: Date.today - 30, amount: -900, name: "Credit Card Payment" },
|
||||||
|
{ date: Date.today, amount: -1000, name: "Credit Card Payment" }
|
||||||
|
]
|
||||||
|
|
||||||
|
credit_card_transactions.each do |t|
|
||||||
|
credit_card.transactions.find_or_create_by(date: t[:date], amount: t[:amount], name: t[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
credit_card.sync
|
||||||
|
|
||||||
|
retirement = Account.find_or_create_by(name: "Demo 401k") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Investment.new
|
||||||
|
a.balance = 100000
|
||||||
|
end
|
||||||
|
|
||||||
|
retirement_valuations = [
|
||||||
|
{ date: 1.year.ago.to_date, value: 90000 },
|
||||||
|
{ date: 200.days.ago.to_date, value: 95000 },
|
||||||
|
{ date: 100.days.ago.to_date, value: 94444.96 },
|
||||||
|
{ date: 20.days.ago.to_date, value: 100000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
retirement.valuations.upsert_all(retirement_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
retirement.sync
|
||||||
|
|
||||||
|
brokerage = Account.find_or_create_by(name: "Demo Brokerage Account") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Investment.new
|
||||||
|
a.balance = 10000
|
||||||
|
end
|
||||||
|
|
||||||
|
brokerage_valuations = [
|
||||||
|
{ date: 1.year.ago.to_date, value: 9000 },
|
||||||
|
{ date: 200.days.ago.to_date, value: 9500 },
|
||||||
|
{ date: 100.days.ago.to_date, value: 9444.96 },
|
||||||
|
{ date: 20.days.ago.to_date, value: 10000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
brokerage.valuations.upsert_all(brokerage_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
brokerage.sync
|
||||||
|
|
||||||
|
mortgage = Account.find_or_create_by(name: "Demo Mortgage") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Loan.new
|
||||||
|
a.balance = 450000
|
||||||
|
end
|
||||||
|
|
||||||
|
mortgage_transactions = [
|
||||||
|
{ date: Date.today - 90, amount: -1500, name: "Mortgage Payment" },
|
||||||
|
{ date: Date.today - 60, amount: -1500, name: "Mortgage Payment" },
|
||||||
|
{ date: Date.today - 30, amount: -1500, name: "Mortgage Payment" }
|
||||||
|
]
|
||||||
|
|
||||||
|
mortgage_transactions.each do |t|
|
||||||
|
mortgage.transactions.find_or_create_by(date: t[:date], amount: t[:amount], name: t[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
mortgage_valuations = [
|
||||||
|
{ date: 2.years.ago.to_date, value: 500000 },
|
||||||
|
{ date: 6.months.ago.to_date, value: 455000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
mortgage.valuations.upsert_all(mortgage_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
mortgage.sync
|
||||||
|
|
||||||
|
car_loan = Account.find_or_create_by(name: "Demo Car Loan") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Loan.new
|
||||||
|
a.balance = 10000
|
||||||
|
end
|
||||||
|
|
||||||
|
car_loan_transactions = [
|
||||||
|
{ date: 12.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 11.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 10.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 9.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 8.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 7.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 6.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 5.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 4.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 3.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 2.months.ago.to_date, amount: -1250, name: "Car Loan Payment" },
|
||||||
|
{ date: 1.month.ago.to_date, amount: -1250, name: "Car Loan Payment" }
|
||||||
|
]
|
||||||
|
|
||||||
|
car_loan_transactions.each do |t|
|
||||||
|
car_loan.transactions.find_or_create_by(date: t[:date], amount: t[:amount], name: t[:name])
|
||||||
|
end
|
||||||
|
|
||||||
|
car_loan.sync
|
||||||
|
|
||||||
|
house = Account.find_or_create_by(name: "Demo Primary Residence") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Property.new
|
||||||
|
a.balance = 500000
|
||||||
|
end
|
||||||
|
|
||||||
|
house_valuations = [
|
||||||
|
{ date: 5.years.ago.to_date, value: 450000 },
|
||||||
|
{ date: 4.years.ago.to_date, value: 470000 },
|
||||||
|
{ date: 3.years.ago.to_date, value: 460000 },
|
||||||
|
{ date: 2.years.ago.to_date, value: 480000 },
|
||||||
|
{ date: 1.year.ago.to_date, value: 500000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
house.valuations.upsert_all(house_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
house.sync
|
||||||
|
|
||||||
|
main_car = Account.find_or_create_by(name: "Demo Main Car") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Vehicle.new
|
||||||
|
a.balance = 25000
|
||||||
|
end
|
||||||
|
|
||||||
|
main_car_valuations = [
|
||||||
|
{ date: 1.year.ago.to_date, value: 25000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
main_car.valuations.upsert_all(main_car_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
main_car.sync
|
||||||
|
|
||||||
|
second_car = Account.find_or_create_by(name: "Demo Secondary Car") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::Vehicle.new
|
||||||
|
a.balance = 12000
|
||||||
|
end
|
||||||
|
|
||||||
|
second_car_valuations = [
|
||||||
|
{ date: 2.years.ago.to_date, value: 11000 },
|
||||||
|
{ date: 1.year.ago.to_date, value: 12000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
second_car.valuations.upsert_all(second_car_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
second_car.sync
|
||||||
|
|
||||||
|
cash = Account.find_or_create_by(name: "Demo Physical Cash") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::OtherAsset.new
|
||||||
|
a.balance = 500
|
||||||
|
end
|
||||||
|
|
||||||
|
cash_valuations = [
|
||||||
|
{ date: 1.month.ago.to_date, value: 500 }
|
||||||
|
]
|
||||||
|
|
||||||
|
cash.valuations.upsert_all(cash_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
cash.sync
|
||||||
|
|
||||||
|
personal_iou = Account.find_or_create_by(name: "Demo Personal IOU") do |a|
|
||||||
|
a.family = family
|
||||||
|
a.accountable = Account::OtherLiability.new
|
||||||
|
a.balance = 1000
|
||||||
|
end
|
||||||
|
|
||||||
|
personal_iou_valuations = [
|
||||||
|
{ date: 1.month.ago.to_date, value: 1000 }
|
||||||
|
]
|
||||||
|
|
||||||
|
personal_iou.valuations.upsert_all(personal_iou_valuations, unique_by: :index_valuations_on_account_id_and_date)
|
||||||
|
|
||||||
|
personal_iou.sync
|
||||||
|
|
||||||
|
puts "Demo data reset complete"
|
||||||
|
end
|
||||||
|
end
|
6
test/fixtures/accounts.yml
vendored
6
test/fixtures/accounts.yml
vendored
|
@ -21,3 +21,9 @@ savings_with_valuation_overrides:
|
||||||
family: dylan_family
|
family: dylan_family
|
||||||
name: Savings account with valuation overrides
|
name: Savings account with valuation overrides
|
||||||
balance: 20000
|
balance: 20000
|
||||||
|
|
||||||
|
# Liability account
|
||||||
|
credit_card:
|
||||||
|
family: dylan_family
|
||||||
|
name: Credit Card
|
||||||
|
balance: 1000
|
||||||
|
|
25
test/fixtures/transactions.yml
vendored
25
test/fixtures/transactions.yml
vendored
|
@ -53,3 +53,28 @@ savings_four:
|
||||||
date: <%= 29.days.ago.to_date %>
|
date: <%= 29.days.ago.to_date %>
|
||||||
amount: -500
|
amount: -500
|
||||||
account: savings_with_valuation_overrides
|
account: savings_with_valuation_overrides
|
||||||
|
|
||||||
|
# Credit card account transactions
|
||||||
|
credit_card_one:
|
||||||
|
name: Starbucks
|
||||||
|
date: <%= 5.days.ago.to_date %>
|
||||||
|
amount: 10
|
||||||
|
account: credit_card
|
||||||
|
|
||||||
|
credit_card_two:
|
||||||
|
name: Chipotle
|
||||||
|
date: <%= 12.days.ago.to_date %>
|
||||||
|
amount: 30
|
||||||
|
account: credit_card
|
||||||
|
|
||||||
|
credit_card_three:
|
||||||
|
name: Amazon
|
||||||
|
date: <%= 15.days.ago.to_date %>
|
||||||
|
amount: 20
|
||||||
|
account: credit_card
|
||||||
|
|
||||||
|
credit_card_four:
|
||||||
|
name: CC Payment
|
||||||
|
date: <%= 29.days.ago.to_date %>
|
||||||
|
amount: -100
|
||||||
|
account: credit_card
|
||||||
|
|
|
@ -47,4 +47,19 @@ class Account::BalanceCalculatorTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
assert_equal expected_balances, daily_balances.map { |b| b[:balance] }
|
assert_equal expected_balances, daily_balances.map { |b| b[:balance] }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "syncs liability account" do
|
||||||
|
account = accounts(:credit_card)
|
||||||
|
account.accountable = account_credits(:one)
|
||||||
|
daily_balances = Account::BalanceCalculator.new(account).daily_balances
|
||||||
|
|
||||||
|
expected_balances = [
|
||||||
|
1040, 940, 940, 940, 940, 940, 940, 940, 940, 940,
|
||||||
|
940, 940, 940, 940, 940, 960, 960, 960, 990, 990,
|
||||||
|
990, 990, 990, 990, 990, 1000, 1000, 1000, 1000, 1000,
|
||||||
|
1000
|
||||||
|
].map(&:to_d)
|
||||||
|
|
||||||
|
assert_equal expected_balances, daily_balances.map { |b| b[:balance] }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue