Skip to content
This repository was archived by the owner on Jul 27, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/models/account.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,14 @@ def create_and_sync(attributes)
transaction do
# Create 2 valuations for new accounts to establish a value history for users to see
account.entries.build(
name: "Current Balance",
name: Valuation.build_current_anchor_name(account.accountable_type),
date: Date.current,
amount: account.balance,
currency: account.currency,
entryable: Valuation.new
)
account.entries.build(
name: "Initial Balance",
name: Valuation.build_opening_anchor_name(account.accountable_type),
date: 1.day.ago.to_date,
amount: initial_balance,
currency: account.currency,
Expand Down
2 changes: 1 addition & 1 deletion app/models/account/balance_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def update

valuation_entry.amount = balance
valuation_entry.currency = currency if currency.present?
valuation_entry.name = "Manual #{account.accountable.balance_display_name} update"
valuation_entry.name = Valuation.build_reconciliation_name(account.accountable_type)
valuation_entry.notes = notes if notes.present?
valuation_entry.save!
end
Expand Down
4 changes: 2 additions & 2 deletions app/models/account_import.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def import!
account.entries.create!(
amount: row.amount,
currency: row.currency,
date: Date.current,
name: "Imported account value",
date: 2.years.ago.to_date,
name: Valuation.build_opening_anchor_name(account.accountable_type),
entryable: Valuation.new
)
end
Expand Down
10 changes: 5 additions & 5 deletions app/models/demo/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,7 @@ def reconcile_balances!(family)
@home.entries.create!(
entryable: Valuation.new,
amount: 350_000,
name: "Current Market Value",
name: Valuation.build_current_anchor_name(@home.accountable_type),
currency: "USD",
date: Date.current
)
Expand All @@ -1185,31 +1185,31 @@ def reconcile_balances!(family)
@honda_accord.entries.create!(
entryable: Valuation.new,
amount: 18_000,
name: "Current Market Value",
name: Valuation.build_current_anchor_name(@honda_accord.accountable_type),
currency: "USD",
date: Date.current
)

@tesla_model3.entries.create!(
entryable: Valuation.new,
amount: 4_500,
name: "Current Market Value",
name: Valuation.build_current_anchor_name(@tesla_model3.accountable_type),
currency: "USD",
date: Date.current
)

@jewelry.entries.create!(
entryable: Valuation.new,
amount: 2000,
name: "Current Market Value",
name: Valuation.build_reconciliation_name(@jewelry.accountable_type),
currency: "USD",
date: 90.days.ago.to_date
)

@personal_loc.entries.create!(
entryable: Valuation.new,
amount: 800,
name: "Owed",
name: Valuation.build_reconciliation_name(@personal_loc.accountable_type),
currency: "USD",
date: 120.days.ago.to_date
)
Expand Down
7 changes: 7 additions & 0 deletions app/models/trade.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ class Trade < ApplicationRecord
validates :qty, presence: true
validates :price, :currency, presence: true

class << self
def build_name(type, qty, ticker)
prefix = type == "buy" ? "Buy" : "Sell"
"#{prefix} #{qty.to_d.abs} shares of #{ticker}"
end
end

def unrealized_gain_loss
return nil if qty.negative?
current_price = security.current_price
Expand Down
4 changes: 1 addition & 3 deletions app/models/trade/create_form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@ def security
end

def create_trade
prefix = type == "sell" ? "Sell " : "Buy "
trade_name = prefix + "#{qty.to_i.abs} shares of #{security.ticker}"
signed_qty = type == "sell" ? -qty.to_d : qty.to_d
signed_amount = signed_qty * price.to_d

trade_entry = account.entries.new(
name: trade_name,
name: Trade.build_name(type, qty, security.ticker),
date: date,
amount: signed_amount,
currency: currency,
Expand Down
20 changes: 20 additions & 0 deletions app/models/valuation.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
class Valuation < ApplicationRecord
include Entryable

class << self
def build_reconciliation_name(accountable_type)
Valuation::Name.new("reconciliation", accountable_type).to_s
end

def build_opening_anchor_name(accountable_type)
Valuation::Name.new("opening_anchor", accountable_type).to_s
end

def build_current_anchor_name(accountable_type)
Valuation::Name.new("current_anchor", accountable_type).to_s
end
end

# TODO: Remove this method when `kind` column is added to valuations table
# This is a temporary implementation until the database migration is complete
def kind
"reconciliation"
end
end
57 changes: 57 additions & 0 deletions app/models/valuation/name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
class Valuation::Name
def initialize(valuation_kind, accountable_type)
@valuation_kind = valuation_kind
@accountable_type = accountable_type
end

def to_s
case valuation_kind
when "opening_anchor"
opening_anchor_name
when "current_anchor"
current_anchor_name
else
recon_name
end
end

private
attr_reader :valuation_kind, :accountable_type

def opening_anchor_name
case accountable_type
when "Property"
"Original purchase price"
when "Loan"
"Original principal"
when "Investment"
"Opening account value"
else
"Opening balance"
end
end

def current_anchor_name
case accountable_type
when "Property"
"Current market value"
when "Loan"
"Current loan balance"
when "Investment"
"Current account value"
else
"Current balance"
end
end

def recon_name
case accountable_type
when "Property", "Investment"
"Manual value update"
when "Loan"
"Manual principal update"
else
"Manual balance update"
end
end
end
2 changes: 1 addition & 1 deletion test/controllers/valuations_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ValuationsControllerTest < ActionDispatch::IntegrationTest
end

created_entry = Entry.order(created_at: :desc).first
assert_equal "Manual account value update", created_entry.name
assert_equal "Manual value update", created_entry.name
assert_equal Date.current, created_entry.date
assert_equal account.balance + 100, created_entry.amount_money.to_f

Expand Down
23 changes: 23 additions & 0 deletions test/models/trade_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require "test_helper"

class TradeTest < ActiveSupport::TestCase
test "build_name generates buy trade name" do
name = Trade.build_name("buy", 10, "AAPL")
assert_equal "Buy 10.0 shares of AAPL", name
end

test "build_name generates sell trade name" do
name = Trade.build_name("sell", 5, "MSFT")
assert_equal "Sell 5.0 shares of MSFT", name
end

test "build_name handles absolute value for negative quantities" do
name = Trade.build_name("sell", -5, "GOOGL")
assert_equal "Sell 5.0 shares of GOOGL", name
end

test "build_name handles decimal quantities" do
name = Trade.build_name("buy", 0.25, "BTC")
assert_equal "Buy 0.25 shares of BTC", name
end
end
66 changes: 66 additions & 0 deletions test/models/valuation/name_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require "test_helper"

class Valuation::NameTest < ActiveSupport::TestCase
# Opening anchor tests
test "generates opening anchor name for Property" do
name = Valuation::Name.new("opening_anchor", "Property")
assert_equal "Original purchase price", name.to_s
end

test "generates opening anchor name for Loan" do
name = Valuation::Name.new("opening_anchor", "Loan")
assert_equal "Original principal", name.to_s
end

test "generates opening anchor name for Investment" do
name = Valuation::Name.new("opening_anchor", "Investment")
assert_equal "Opening account value", name.to_s
end

test "generates opening anchor name for other account types" do
name = Valuation::Name.new("opening_anchor", "Depository")
assert_equal "Opening balance", name.to_s
end

# Current anchor tests
test "generates current anchor name for Property" do
name = Valuation::Name.new("current_anchor", "Property")
assert_equal "Current market value", name.to_s
end

test "generates current anchor name for Loan" do
name = Valuation::Name.new("current_anchor", "Loan")
assert_equal "Current loan balance", name.to_s
end

test "generates current anchor name for Investment" do
name = Valuation::Name.new("current_anchor", "Investment")
assert_equal "Current account value", name.to_s
end

test "generates current anchor name for other account types" do
name = Valuation::Name.new("current_anchor", "Depository")
assert_equal "Current balance", name.to_s
end

# Reconciliation tests
test "generates recon name for Property" do
name = Valuation::Name.new("reconciliation", "Property")
assert_equal "Manual value update", name.to_s
end

test "generates recon name for Investment" do
name = Valuation::Name.new("reconciliation", "Investment")
assert_equal "Manual value update", name.to_s
end

test "generates recon name for Loan" do
name = Valuation::Name.new("reconciliation", "Loan")
assert_equal "Manual principal update", name.to_s
end

test "generates recon name for other account types" do
name = Valuation::Name.new("reconciliation", "Depository")
assert_equal "Manual balance update", name.to_s
end
end
4 changes: 2 additions & 2 deletions test/system/trades_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class TradesTest < ApplicationSystemTestCase
visit_trades

within_trades do
assert_text "Buy #{shares_qty} shares of AAPL"
assert_text "Buy #{shares_qty}.0 shares of AAPL"
end
end

Expand All @@ -52,7 +52,7 @@ class TradesTest < ApplicationSystemTestCase
visit_trades

within_trades do
assert_text "Sell #{qty} shares of AAPL"
assert_text "Sell #{qty}.0 shares of AAPL"
end
end

Expand Down