mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-18 20:59:39 +02:00
Account namespace updates: part 1 (#893)
* Rename accountable types * Merge conflicts * Fix broken tests * Add back sidebar changes
This commit is contained in:
parent
778098ebb0
commit
a947db92b2
54 changed files with 349 additions and 184 deletions
|
@ -27,14 +27,14 @@ module AccountsHelper
|
|||
|
||||
def class_mapping(accountable_type)
|
||||
{
|
||||
"Account::Credit" => { text: "text-red-500", bg: "bg-red-500", bg_transparent: "bg-red-500/10", fill: "fill-red-500", hex: "#F13636" },
|
||||
"Account::Loan" => { text: "text-fuchsia-500", bg: "bg-fuchsia-500", bg_transparent: "bg-fuchsia-500/10", fill: "fill-fuchsia-500", hex: "#D444F1" },
|
||||
"Account::OtherLiability" => { text: "text-gray-500", bg: "bg-gray-500", bg_transparent: "bg-gray-500/10", fill: "fill-gray-500", hex: "#737373" },
|
||||
"Account::Depository" => { text: "text-violet-500", bg: "bg-violet-500", bg_transparent: "bg-violet-500/10", fill: "fill-violet-500", hex: "#875BF7" },
|
||||
"Account::Investment" => { text: "text-blue-600", bg: "bg-blue-600", bg_transparent: "bg-blue-600/10", fill: "fill-blue-600", hex: "#1570EF" },
|
||||
"Account::OtherAsset" => { text: "text-green-500", bg: "bg-green-500", bg_transparent: "bg-green-500/10", fill: "fill-green-500", hex: "#12B76A" },
|
||||
"Account::Property" => { text: "text-cyan-500", bg: "bg-cyan-500", bg_transparent: "bg-cyan-500/10", fill: "fill-cyan-500", hex: "#06AED4" },
|
||||
"Account::Vehicle" => { text: "text-pink-500", bg: "bg-pink-500", bg_transparent: "bg-pink-500/10", fill: "fill-pink-500", hex: "#F23E94" }
|
||||
"CreditCard" => { text: "text-red-500", bg: "bg-red-500", bg_transparent: "bg-red-500/10", fill: "fill-red-500", hex: "#F13636" },
|
||||
"Loan" => { text: "text-fuchsia-500", bg: "bg-fuchsia-500", bg_transparent: "bg-fuchsia-500/10", fill: "fill-fuchsia-500", hex: "#D444F1" },
|
||||
"OtherLiability" => { text: "text-gray-500", bg: "bg-gray-500", bg_transparent: "bg-gray-500/10", fill: "fill-gray-500", hex: "#737373" },
|
||||
"Depository" => { text: "text-violet-500", bg: "bg-violet-500", bg_transparent: "bg-violet-500/10", fill: "fill-violet-500", hex: "#875BF7" },
|
||||
"Investment" => { text: "text-blue-600", bg: "bg-blue-600", bg_transparent: "bg-blue-600/10", fill: "fill-blue-600", hex: "#1570EF" },
|
||||
"OtherAsset" => { text: "text-green-500", bg: "bg-green-500", bg_transparent: "bg-green-500/10", fill: "fill-green-500", hex: "#12B76A" },
|
||||
"Property" => { text: "text-cyan-500", bg: "bg-cyan-500", bg_transparent: "bg-cyan-500/10", fill: "fill-cyan-500", hex: "#06AED4" },
|
||||
"Vehicle" => { text: "text-pink-500", bg: "bg-pink-500", bg_transparent: "bg-pink-500/10", fill: "fill-pink-500", hex: "#F23E94" }
|
||||
}.fetch(accountable_type, { text: "text-gray-500", bg: "bg-gray-500", bg_transparent: "bg-gray-500/10", fill: "fill-gray-500", hex: "#737373" })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
class Account::Credit < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::Crypto < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::Depository < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::Loan < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::OtherAsset < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::OtherLiability < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::Property < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
class Account::Vehicle < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,28 +1,19 @@
|
|||
module Accountable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
ASSET_TYPES = %w[ Account::Depository Account::Investment Account::Crypto Account::OtherAsset Account::Property Account::Vehicle ]
|
||||
LIABILITY_TYPES = %w[ Account::Credit Account::Loan Account::OtherLiability ]
|
||||
ASSET_TYPES = %w[ Depository Investment Crypto Property Vehicle OtherAsset ]
|
||||
LIABILITY_TYPES = %w[ CreditCard Loan OtherLiability ]
|
||||
TYPES = ASSET_TYPES + LIABILITY_TYPES
|
||||
|
||||
def self.from_type(type)
|
||||
return nil unless types.include?(type) || TYPES.include?(type)
|
||||
"Account::#{type.demodulize}".constantize
|
||||
return nil unless TYPES.include?(type)
|
||||
type.constantize
|
||||
end
|
||||
|
||||
def self.by_classification
|
||||
{ assets: ASSET_TYPES, liabilities: LIABILITY_TYPES }
|
||||
end
|
||||
|
||||
def self.types(classification = nil)
|
||||
types = classification ? (classification.to_sym == :asset ? ASSET_TYPES : LIABILITY_TYPES) : TYPES
|
||||
types.map { |type| type.demodulize }
|
||||
end
|
||||
|
||||
def self.classification(type)
|
||||
ASSET_TYPES.include?(type) ? :asset : :liability
|
||||
end
|
||||
|
||||
included do
|
||||
has_one :account, as: :accountable, touch: true
|
||||
end
|
||||
|
|
3
app/models/credit_card.rb
Normal file
3
app/models/credit_card.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class CreditCard < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
3
app/models/crypto.rb
Normal file
3
app/models/crypto.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Crypto < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
3
app/models/depository.rb
Normal file
3
app/models/depository.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Depository < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
class Account::Investment < ApplicationRecord
|
||||
class Investment < ApplicationRecord
|
||||
include Accountable
|
||||
|
||||
SUBTYPES = [
|
3
app/models/loan.rb
Normal file
3
app/models/loan.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Loan < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
3
app/models/other_asset.rb
Normal file
3
app/models/other_asset.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class OtherAsset < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
3
app/models/other_liability.rb
Normal file
3
app/models/other_liability.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class OtherLiability < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
3
app/models/property.rb
Normal file
3
app/models/property.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Property < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
3
app/models/vehicle.rb
Normal file
3
app/models/vehicle.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
class Vehicle < ApplicationRecord
|
||||
include Accountable
|
||||
end
|
|
@ -1 +1 @@
|
|||
<%= f.select :subtype, options_for_select(Account::Investment::SUBTYPES, selected: ""), { label: true } %>
|
||||
<%= f.select :subtype, options_for_select(Investment::SUBTYPES, selected: ""), { label: true } %>
|
||||
|
|
|
@ -8,14 +8,15 @@
|
|||
<div class="flex flex-col p-2 text-sm grow">
|
||||
<button hidden data-controller="hotkey" data-hotkey="k,K,ArrowUp,ArrowLeft" data-action="list-keyboard-navigation#focusPrevious">Previous</button>
|
||||
<button hidden data-controller="hotkey" data-hotkey="j,J,ArrowDown,ArrowRight" data-action="list-keyboard-navigation#focusNext">Next</button>
|
||||
<%= render "account_type", type: Account::Depository.new, bg_color: "bg-blue-50", text_color: "text-blue-500", icon: "landmark" %>
|
||||
<%= render "account_type", type: Account::Investment.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "line-chart" %>
|
||||
<%= render "account_type", type: Account::Property.new, bg_color: "bg-pink-50", text_color: "text-pink-500", icon: "home" %>
|
||||
<%= render "account_type", type: Account::Vehicle.new, bg_color: "bg-indigo-50", text_color: "text-indigo-500", icon: "car-front" %>
|
||||
<%= render "account_type", type: Account::Credit.new, bg_color: "bg-violet-50", text_color: "text-violet-500", icon: "credit-card" %>
|
||||
<%= render "account_type", type: Account::Loan.new, bg_color: "bg-yellow-50", text_color: "text-yellow-500", icon: "hand-coins" %>
|
||||
<%= render "account_type", type: Account::OtherAsset.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "plus" %>
|
||||
<%= render "account_type", type: Account::OtherLiability.new, bg_color: "bg-red-50", text_color: "text-red-500", icon: "minus" %>
|
||||
<%= render "account_type", type: Depository.new, bg_color: "bg-blue-50", text_color: "text-blue-500", icon: "landmark" %>
|
||||
<%= render "account_type", type: Investment.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "line-chart" %>
|
||||
<%= render "account_type", type: Crypto.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "bitcoin" %>
|
||||
<%= render "account_type", type: Property.new, bg_color: "bg-pink-50", text_color: "text-pink-500", icon: "home" %>
|
||||
<%= render "account_type", type: Vehicle.new, bg_color: "bg-indigo-50", text_color: "text-indigo-500", icon: "car-front" %>
|
||||
<%= render "account_type", type: CreditCard.new, bg_color: "bg-violet-50", text_color: "text-violet-500", icon: "credit-card" %>
|
||||
<%= render "account_type", type: Loan.new, bg_color: "bg-yellow-50", text_color: "text-yellow-500", icon: "hand-coins" %>
|
||||
<%= render "account_type", type: OtherAsset.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "plus" %>
|
||||
<%= render "account_type", type: OtherLiability.new, bg_color: "bg-red-50", text_color: "text-red-500", icon: "minus" %>
|
||||
</div>
|
||||
<div class="border-t border-alpha-black-25 p-4 text-gray-500 text-sm flex justify-between">
|
||||
<div class="flex space-x-5">
|
||||
|
@ -77,7 +78,7 @@
|
|||
<%= f.hidden_field :accountable_type %>
|
||||
<%= f.text_field :name, placeholder: t(".name.placeholder"), required: "required", label: t(".name.label"), autofocus: true %>
|
||||
<%= f.collection_select :institution_id, Current.family.institutions.alphabetically, :id, :name, { include_blank: t(".ungrouped"), label: t(".institution") } %>
|
||||
<%= render "accounts/#{permitted_accountable_partial(@account.accountable_type)}", f: f %>
|
||||
<%= render "accounts/account/#{permitted_accountable_partial(@account.accountable_type)}", f: f %>
|
||||
<%= f.money_field :balance_money, label: t(".balance"), required: "required" %>
|
||||
|
||||
<div>
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
<%= render partial: "shared/period_select", locals: { button_class: "flex items-center gap-1 w-full cursor-pointer font-bold tracking-wide" } %>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= link_to new_account_path, class: "block hover:bg-gray-100 p-2 text-sm font-semibold text-gray-900 flex items-center rounded", title: t(".new_account"), data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_account_path, id: "sidebar-new-account", class: "block hover:bg-gray-100 p-2 text-sm font-semibold text-gray-900 flex items-center rounded", title: t(".new_account"), data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -68,10 +68,19 @@ Rails.application.routes.draw do
|
|||
resources :transfers, only: %i[ new create destroy ]
|
||||
|
||||
resources :accounts, shallow: true do
|
||||
get :summary, on: :collection
|
||||
get :list, on: :collection
|
||||
post :sync, on: :member
|
||||
resource :logo, only: %i[show], module: :accounts
|
||||
collection do
|
||||
get :summary
|
||||
get :list
|
||||
end
|
||||
|
||||
member do
|
||||
post :sync
|
||||
end
|
||||
|
||||
scope module: :accounts do
|
||||
resource :logo, only: :show
|
||||
end
|
||||
|
||||
resources :valuations
|
||||
end
|
||||
|
||||
|
|
87
db/migrate/20240619125949_rename_accountable_tables.rb
Normal file
87
db/migrate/20240619125949_rename_accountable_tables.rb
Normal file
|
@ -0,0 +1,87 @@
|
|||
class RenameAccountableTables < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
rename_table :account_depositories, :depositories
|
||||
rename_table :account_investments, :investments
|
||||
rename_table :account_credits, :credit_cards
|
||||
rename_table :account_properties, :properties
|
||||
rename_table :account_vehicles, :vehicles
|
||||
rename_table :account_loans, :loans
|
||||
rename_table :account_cryptos, :cryptos
|
||||
rename_table :account_other_assets, :other_assets
|
||||
rename_table :account_other_liabilities, :other_liabilities
|
||||
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
update_accountable_types(
|
||||
'Account::Depository' => 'Depository',
|
||||
'Account::Investment' => 'Investment',
|
||||
'Account::Credit' => 'CreditCard',
|
||||
'Account::Property' => 'Property',
|
||||
'Account::Vehicle' => 'Vehicle',
|
||||
'Account::Loan' => 'Loan',
|
||||
'Account::Crypto' => 'Crypto',
|
||||
'Account::OtherAsset' => 'OtherAsset',
|
||||
'Account::OtherLiability' => 'OtherLiability'
|
||||
)
|
||||
|
||||
remove_column :accounts, :classification, :virtual
|
||||
|
||||
change_table :accounts do |t|
|
||||
t.virtual(
|
||||
:classification,
|
||||
type: :string,
|
||||
stored: true,
|
||||
as: <<-SQL
|
||||
CASE
|
||||
WHEN accountable_type IN ('Loan', 'CreditCard', 'OtherLiability')
|
||||
THEN 'liability'
|
||||
ELSE 'asset'
|
||||
END
|
||||
SQL
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
dir.down do
|
||||
update_accountable_types(
|
||||
'Depository' => 'Account::Depository',
|
||||
'Investment' => 'Account::Investment',
|
||||
'CreditCard' => 'Account::Credit',
|
||||
'Property' => 'Account::Property',
|
||||
'Vehicle' => 'Account::Vehicle',
|
||||
'Loan' => 'Account::Loan',
|
||||
'Crypto' => 'Account::Crypto',
|
||||
'OtherAsset' => 'Account::OtherAsset',
|
||||
'OtherLiability' => 'Account::OtherLiability'
|
||||
)
|
||||
|
||||
remove_column :accounts, :classification, :virtual
|
||||
|
||||
change_table :accounts do |t|
|
||||
t.virtual(
|
||||
:classification,
|
||||
type: :string,
|
||||
stored: true,
|
||||
as: <<-SQL
|
||||
CASE
|
||||
WHEN accountable_type IN ('Account::Loan', 'Account::Credit', 'Account::OtherLiability')
|
||||
THEN 'liability'
|
||||
ELSE 'asset'
|
||||
END
|
||||
SQL
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_accountable_types(mapping)
|
||||
Account.reset_column_information
|
||||
|
||||
mapping.each do |old_type, new_type|
|
||||
Account.where(accountable_type: old_type).update_all(accountable_type: new_type)
|
||||
end
|
||||
end
|
||||
end
|
94
db/schema.rb
generated
94
db/schema.rb
generated
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_06_19_125949) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pgcrypto"
|
||||
enable_extension "plpgsql"
|
||||
|
@ -32,51 +32,6 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
|||
t.index ["account_id"], name: "index_account_balances_on_account_id"
|
||||
end
|
||||
|
||||
create_table "account_credits", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_cryptos", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_depositories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_investments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_loans", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_other_assets", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_other_liabilities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_properties", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "account_vehicles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "accounts", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "subtype"
|
||||
t.uuid "family_id", null: false
|
||||
|
@ -87,13 +42,13 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
|||
t.uuid "accountable_id"
|
||||
t.decimal "balance", precision: 19, scale: 4, default: "0.0"
|
||||
t.string "currency", default: "USD"
|
||||
t.virtual "classification", type: :string, as: "\nCASE\n WHEN ((accountable_type)::text = ANY ((ARRAY['Account::Loan'::character varying, 'Account::Credit'::character varying, 'Account::OtherLiability'::character varying])::text[])) THEN 'liability'::text\n ELSE 'asset'::text\nEND", stored: true
|
||||
t.boolean "is_active", default: true, null: false
|
||||
t.enum "status", default: "ok", null: false, enum_type: "account_status"
|
||||
t.jsonb "sync_warnings", default: [], null: false
|
||||
t.jsonb "sync_errors", default: [], null: false
|
||||
t.date "last_sync_date"
|
||||
t.uuid "institution_id"
|
||||
t.virtual "classification", type: :string, as: "\nCASE\n WHEN ((accountable_type)::text = ANY ((ARRAY['Loan'::character varying, 'CreditCard'::character varying, 'OtherLiability'::character varying])::text[])) THEN 'liability'::text\n ELSE 'asset'::text\nEND", stored: true
|
||||
t.index ["accountable_type"], name: "index_accounts_on_accountable_type"
|
||||
t.index ["family_id"], name: "index_accounts_on_family_id"
|
||||
t.index ["institution_id"], name: "index_accounts_on_institution_id"
|
||||
|
@ -127,6 +82,21 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
|||
t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
|
||||
end
|
||||
|
||||
create_table "credit_cards", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "cryptos", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "depositories", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "exchange_rates", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "base_currency", null: false
|
||||
t.string "converted_currency", null: false
|
||||
|
@ -245,6 +215,11 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
|||
t.index ["family_id"], name: "index_institutions_on_family_id"
|
||||
end
|
||||
|
||||
create_table "investments", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "invite_codes", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.string "token", null: false
|
||||
t.datetime "created_at", null: false
|
||||
|
@ -252,6 +227,26 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
|||
t.index ["token"], name: "index_invite_codes_on_token", unique: true
|
||||
end
|
||||
|
||||
create_table "loans", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "other_assets", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "other_liabilities", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "properties", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "settings", force: :cascade do |t|
|
||||
t.string "var", null: false
|
||||
t.text "value"
|
||||
|
@ -351,6 +346,11 @@ ActiveRecord::Schema[7.2].define(version: 2024_06_14_121110) do
|
|||
t.index ["account_id"], name: "index_valuations_on_account_id"
|
||||
end
|
||||
|
||||
create_table "vehicles", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
add_foreign_key "account_balances", "accounts", on_delete: :cascade
|
||||
add_foreign_key "accounts", "families"
|
||||
add_foreign_key "accounts", "institutions"
|
||||
|
|
|
@ -60,22 +60,22 @@ namespace :demo_data do
|
|||
puts "Loaded mock exchange rates for last 60 days"
|
||||
|
||||
# ========== Accounts ================
|
||||
empty_account = Account.create(name: "Demo Empty Account", family: family, accountable: Account::Depository.new, balance: 500, currency: "USD")
|
||||
multi_currency_checking = Account.create(name: "Demo Multi-Currency Checking", family: family, accountable: Account::Depository.new, balance: 4000, currency: "EUR")
|
||||
checking = Account.create(name: "Demo Checking", family: family, accountable: Account::Depository.new, balance: 5000, currency: "USD")
|
||||
savings = Account.create(name: "Demo Savings", family: family, accountable: Account::Depository.new, balance: 20000, currency: "USD")
|
||||
credit_card = Account.create(name: "Demo Credit Card", family: family, accountable: Account::Credit.new, balance: 1500, currency: "USD")
|
||||
retirement = Account.create(name: "Demo 401k", family: family, accountable: Account::Investment.new, balance: 100000, currency: "USD")
|
||||
euro_savings = Account.create(name: "Demo Euro Savings", family: family, accountable: Account::Depository.new, balance: 10000, currency: "EUR")
|
||||
brokerage = Account.create(name: "Demo Brokerage Account", family: family, accountable: Account::Investment.new, balance: 10000, currency: "USD")
|
||||
crypto = Account.create(name: "Bitcoin Account", family: family, accountable: Account::Crypto.new, balance: 0.1, currency: "BTC")
|
||||
mortgage = Account.create(name: "Demo Mortgage", family: family, accountable: Account::Loan.new, balance: 450000, currency: "USD")
|
||||
main_car = Account.create(name: "Demo Main Car", family: family, accountable: Account::Vehicle.new, balance: 25000, currency: "USD")
|
||||
cash = Account.create(name: "Demo Physical Cash", family: family, accountable: Account::OtherAsset.new, balance: 500, currency: "USD")
|
||||
car_loan = Account.create(name: "Demo Car Loan", family: family, accountable: Account::Loan.new, balance: 10000, currency: "USD")
|
||||
house = Account.create(name: "Demo Primary Residence", family: family, accountable: Account::Property.new, balance: 2500000, currency: "USD")
|
||||
personal_iou = Account.create(name: "Demo Personal IOU", family: family, accountable: Account::OtherLiability.new, balance: 1000, currency: "USD")
|
||||
second_car = Account.create(name: "Demo Secondary Car", family: family, accountable: Account::Vehicle.new, balance: 12000, currency: "USD")
|
||||
empty_account = Account.create(name: "Demo Empty Account", family: family, accountable: Depository.new, balance: 500, currency: "USD")
|
||||
multi_currency_checking = Account.create(name: "Demo Multi-Currency Checking", family: family, accountable: Depository.new, balance: 4000, currency: "EUR")
|
||||
checking = Account.create(name: "Demo Checking", family: family, accountable: Depository.new, balance: 5000, currency: "USD")
|
||||
savings = Account.create(name: "Demo Savings", family: family, accountable: Depository.new, balance: 20000, currency: "USD")
|
||||
credit_card = Account.create(name: "Demo Credit Card", family: family, accountable: CreditCard.new, balance: 1500, currency: "USD")
|
||||
retirement = Account.create(name: "Demo 401k", family: family, accountable: Investment.new, balance: 100000, currency: "USD")
|
||||
euro_savings = Account.create(name: "Demo Euro Savings", family: family, accountable: Depository.new, balance: 10000, currency: "EUR")
|
||||
brokerage = Account.create(name: "Demo Brokerage Account", family: family, accountable: Investment.new, balance: 10000, currency: "USD")
|
||||
crypto = Account.create(name: "Bitcoin Account", family: family, accountable: Crypto.new, balance: 0.1, currency: "BTC")
|
||||
mortgage = Account.create(name: "Demo Mortgage", family: family, accountable: Loan.new, balance: 450000, currency: "USD")
|
||||
main_car = Account.create(name: "Demo Main Car", family: family, accountable: Vehicle.new, balance: 25000, currency: "USD")
|
||||
cash = Account.create(name: "Demo Physical Cash", family: family, accountable: OtherAsset.new, balance: 500, currency: "USD")
|
||||
car_loan = Account.create(name: "Demo Car Loan", family: family, accountable: Loan.new, balance: 10000, currency: "USD")
|
||||
house = Account.create(name: "Demo Primary Residence", family: family, accountable: Property.new, balance: 2500000, currency: "USD")
|
||||
personal_iou = Account.create(name: "Demo Personal IOU", family: family, accountable: OtherLiability.new, balance: 1000, currency: "USD")
|
||||
second_car = Account.create(name: "Demo Secondary Car", family: family, accountable: Vehicle.new, balance: 12000, currency: "USD")
|
||||
|
||||
|
||||
# ========== Transactions ================
|
||||
|
|
|
@ -47,7 +47,7 @@ class AccountsControllerTest < ActionDispatch::IntegrationTest
|
|||
assert_difference [ "Account.count", "Valuation.count" ], 1 do
|
||||
post accounts_path, params: {
|
||||
account: {
|
||||
accountable_type: "Account::Depository",
|
||||
accountable_type: "Depository",
|
||||
balance: 200,
|
||||
subtype: "checking",
|
||||
institution_id: institutions(:chase).id
|
||||
|
@ -63,7 +63,7 @@ class AccountsControllerTest < ActionDispatch::IntegrationTest
|
|||
assert_difference -> { Account.count } => 1, -> { Valuation.count } => 2 do
|
||||
post accounts_path, params: {
|
||||
account: {
|
||||
accountable_type: "Account::Depository",
|
||||
accountable_type: "Depository",
|
||||
balance: 200,
|
||||
subtype: "checking",
|
||||
institution_id: institutions(:chase).id,
|
||||
|
|
22
test/fixtures/accounts.yml
vendored
22
test/fixtures/accounts.yml
vendored
|
@ -2,21 +2,21 @@ collectable:
|
|||
family: dylan_family
|
||||
name: Collectable Account
|
||||
balance: 550
|
||||
accountable_type: Account::OtherAsset
|
||||
accountable_type: OtherAsset
|
||||
accountable: other_asset_collectable
|
||||
|
||||
iou:
|
||||
family: dylan_family
|
||||
name: IOU (personal debt to friend)
|
||||
balance: 200
|
||||
accountable_type: Account::OtherLiability
|
||||
accountable_type: OtherLiability
|
||||
accountable: other_liability_iou
|
||||
|
||||
checking:
|
||||
family: dylan_family
|
||||
name: Checking Account
|
||||
balance: 5000
|
||||
accountable_type: Account::Depository
|
||||
accountable_type: Depository
|
||||
accountable: depository_checking
|
||||
institution: chase
|
||||
|
||||
|
@ -24,7 +24,7 @@ savings:
|
|||
family: dylan_family
|
||||
name: Savings account with valuation overrides
|
||||
balance: 19700
|
||||
accountable_type: Account::Depository
|
||||
accountable_type: Depository
|
||||
accountable: depository_savings
|
||||
institution: chase
|
||||
|
||||
|
@ -32,7 +32,7 @@ credit_card:
|
|||
family: dylan_family
|
||||
name: Credit Card
|
||||
balance: 1000
|
||||
accountable_type: Account::Credit
|
||||
accountable_type: CreditCard
|
||||
accountable: credit_one
|
||||
institution: chase
|
||||
|
||||
|
@ -41,7 +41,7 @@ eur_checking:
|
|||
name: Euro Checking Account
|
||||
currency: EUR
|
||||
balance: 12000
|
||||
accountable_type: Account::Depository
|
||||
accountable_type: Depository
|
||||
accountable: depository_eur_checking
|
||||
institution: revolut
|
||||
|
||||
|
@ -51,7 +51,7 @@ multi_currency:
|
|||
name: Multi Currency Account
|
||||
currency: USD # multi-currency accounts still have a "primary" currency
|
||||
balance: 9467
|
||||
accountable_type: Account::Depository
|
||||
accountable_type: Depository
|
||||
accountable: depository_multi_currency
|
||||
institution: revolut
|
||||
|
||||
|
@ -60,7 +60,7 @@ brokerage:
|
|||
name: Robinhood Brokerage Account
|
||||
currency: USD
|
||||
balance: 10000
|
||||
accountable_type: Account::Investment
|
||||
accountable_type: Investment
|
||||
accountable: investment_brokerage
|
||||
|
||||
mortgage_loan:
|
||||
|
@ -68,7 +68,7 @@ mortgage_loan:
|
|||
name: Mortgage Loan
|
||||
currency: USD
|
||||
balance: 500000
|
||||
accountable_type: Account::Loan
|
||||
accountable_type: Loan
|
||||
accountable: loan_mortgage
|
||||
|
||||
house:
|
||||
|
@ -76,7 +76,7 @@ house:
|
|||
name: 123 Maybe Court
|
||||
currency: USD
|
||||
balance: 550000
|
||||
accountable_type: Account::Property
|
||||
accountable_type: Property
|
||||
accountable: property_house
|
||||
|
||||
car:
|
||||
|
@ -84,5 +84,5 @@ car:
|
|||
name: Honda Accord
|
||||
currency: USD
|
||||
balance: 18000
|
||||
accountable_type: Account::Vehicle
|
||||
accountable_type: Vehicle
|
||||
accountable: vehicle_honda_accord
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::DepositoryTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::InvestmentTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::OtherAssetTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::OtherLiabilityTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::PropertyTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -60,15 +60,15 @@ class AccountTest < ActiveSupport::TestCase
|
|||
assert_equal @family.assets, assets.sum
|
||||
assert_equal @family.liabilities, liabilities.sum
|
||||
|
||||
depositories = assets.children.find { |group| group.name == "Account::Depository" }
|
||||
properties = assets.children.find { |group| group.name == "Account::Property" }
|
||||
vehicles = assets.children.find { |group| group.name == "Account::Vehicle" }
|
||||
investments = assets.children.find { |group| group.name == "Account::Investment" }
|
||||
other_assets = assets.children.find { |group| group.name == "Account::OtherAsset" }
|
||||
depositories = assets.children.find { |group| group.name == "Depository" }
|
||||
properties = assets.children.find { |group| group.name == "Property" }
|
||||
vehicles = assets.children.find { |group| group.name == "Vehicle" }
|
||||
investments = assets.children.find { |group| group.name == "Investment" }
|
||||
other_assets = assets.children.find { |group| group.name == "OtherAsset" }
|
||||
|
||||
credits = liabilities.children.find { |group| group.name == "Account::Credit" }
|
||||
loans = liabilities.children.find { |group| group.name == "Account::Loan" }
|
||||
other_liabilities = liabilities.children.find { |group| group.name == "Account::OtherLiability" }
|
||||
credits = liabilities.children.find { |group| group.name == "CreditCard" }
|
||||
loans = liabilities.children.find { |group| group.name == "Loan" }
|
||||
other_liabilities = liabilities.children.find { |group| group.name == "OtherLiability" }
|
||||
|
||||
assert_equal 4, depositories.children.count
|
||||
assert_equal 1, properties.children.count
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::CreditTest < ActiveSupport::TestCase
|
||||
class CreditCardTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
|
@ -1,6 +1,6 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::CryptoTest < ActiveSupport::TestCase
|
||||
class CryptoTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
7
test/models/depository_test.rb
Normal file
7
test/models/depository_test.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class DepositoryTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/investment_test.rb
Normal file
7
test/models/investment_test.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class InvestmentTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::LoanTest < ActiveSupport::TestCase
|
||||
class LoanTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
7
test/models/other_asset_test.rb
Normal file
7
test/models/other_asset_test.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class OtherAssetTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/other_liability_test.rb
Normal file
7
test/models/other_liability_test.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class OtherLiabilityTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
7
test/models/property_test.rb
Normal file
7
test/models/property_test.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "test_helper"
|
||||
|
||||
class PropertyTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
require "test_helper"
|
||||
|
||||
class Account::VehicleTest < ActiveSupport::TestCase
|
||||
class VehicleTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
77
test/system/accounts_test.rb
Normal file
77
test/system/accounts_test.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
require "application_system_test_case"
|
||||
|
||||
class AccountsTest < ApplicationSystemTestCase
|
||||
setup do
|
||||
sign_in @user = users(:family_admin)
|
||||
|
||||
visit root_url
|
||||
open_new_account_modal
|
||||
end
|
||||
|
||||
test "can create depository account" do
|
||||
assert_account_created("Depository")
|
||||
end
|
||||
|
||||
test "can create investment account" do
|
||||
assert_account_created("Investment")
|
||||
end
|
||||
|
||||
test "can create crypto account" do
|
||||
assert_account_created("Crypto")
|
||||
end
|
||||
|
||||
test "can create property account" do
|
||||
assert_account_created("Property")
|
||||
end
|
||||
|
||||
test "can create vehicle account" do
|
||||
assert_account_created("Vehicle")
|
||||
end
|
||||
|
||||
test "can create other asset account" do
|
||||
assert_account_created("OtherAsset")
|
||||
end
|
||||
|
||||
test "can create credit card account" do
|
||||
assert_account_created("CreditCard")
|
||||
end
|
||||
|
||||
test "can create loan account" do
|
||||
assert_account_created("Loan")
|
||||
end
|
||||
|
||||
test "can create other liability account" do
|
||||
assert_account_created("OtherLiability")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def open_new_account_modal
|
||||
click_link "sidebar-new-account"
|
||||
end
|
||||
|
||||
def assert_account_created(accountable_type)
|
||||
click_link humanized_accountable(accountable_type)
|
||||
click_link "Enter account balance manually"
|
||||
|
||||
account_name = "[system test] #{accountable_type} Account"
|
||||
|
||||
fill_in "Account name", with: account_name
|
||||
select "Chase", from: "Financial institution"
|
||||
fill_in "account[balance]", with: 100.99
|
||||
check "Add a start balance for this account"
|
||||
fill_in "Start date (optional)", with: 10.days.ago.to_date.to_s
|
||||
fill_in "Start balance (optional)", with: 95
|
||||
click_button "Add #{humanized_accountable(accountable_type).downcase}"
|
||||
|
||||
find("details", text: humanized_accountable(accountable_type)).click
|
||||
assert_text account_name
|
||||
|
||||
visit accounts_url
|
||||
assert_text account_name
|
||||
end
|
||||
|
||||
def humanized_accountable(accountable_type)
|
||||
accountable_type.constantize.model_name.human
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue