mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-18 20:59:39 +02:00
Centralize entry naming (#2454)
* Centralize entry naming * Lint fixes, code style
This commit is contained in:
parent
afbfb474c2
commit
9110ab27d2
12 changed files with 187 additions and 16 deletions
|
@ -64,14 +64,14 @@ class Account < ApplicationRecord
|
|||
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,
|
||||
|
|
|
@ -23,7 +23,7 @@ class Account::BalanceUpdater
|
|||
|
||||
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
|
||||
|
|
|
@ -18,8 +18,8 @@ class AccountImport < 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
|
||||
|
|
|
@ -1176,7 +1176,7 @@ class Demo::Generator
|
|||
@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
|
||||
)
|
||||
|
@ -1185,7 +1185,7 @@ class Demo::Generator
|
|||
@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
|
||||
)
|
||||
|
@ -1193,7 +1193,7 @@ class Demo::Generator
|
|||
@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
|
||||
)
|
||||
|
@ -1201,7 +1201,7 @@ class Demo::Generator
|
|||
@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
|
||||
)
|
||||
|
@ -1209,7 +1209,7 @@ class Demo::Generator
|
|||
@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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,13 +29,11 @@ class Trade::CreateForm
|
|||
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,
|
||||
|
|
|
@ -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
app/models/valuation/name.rb
Normal file
57
app/models/valuation/name.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
23
test/models/trade_test.rb
Normal file
23
test/models/trade_test.rb
Normal file
|
@ -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
test/models/valuation/name_test.rb
Normal file
66
test/models/valuation/name_test.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue