diff --git a/app/controllers/concerns/accountable_resource.rb b/app/controllers/concerns/accountable_resource.rb index 9daa0ae2..a508764d 100644 --- a/app/controllers/concerns/accountable_resource.rb +++ b/app/controllers/concerns/accountable_resource.rb @@ -45,12 +45,13 @@ module AccountableResource def update # Handle balance update if provided if account_params[:balance].present? - result = @account.update_balance(balance: account_params[:balance], currency: account_params[:currency]) + result = @account.set_current_balance(account_params[:balance].to_d) unless result.success? @error_message = result.error_message render :edit, status: :unprocessable_entity return end + @account.sync_later end # Update remaining account attributes diff --git a/app/controllers/properties_controller.rb b/app/controllers/properties_controller.rb index 8b2ec062..7a1db5de 100644 --- a/app/controllers/properties_controller.rb +++ b/app/controllers/properties_controller.rb @@ -37,10 +37,10 @@ class PropertiesController < ApplicationController end def update_balances - result = @account.update_balance(balance: balance_params[:balance], currency: balance_params[:currency]) + result = @account.set_current_balance(balance_params[:balance].to_d) if result.success? - @success_message = result.updated? ? "Balance updated successfully." : "No changes made. Account is already up to date." + @success_message = "Balance updated successfully." if @account.active? render :balances diff --git a/app/models/account.rb b/app/models/account.rb index 684736ce..6a21c3e3 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -114,11 +114,6 @@ class Account < ApplicationRecord .order(amount: :desc) end - - def update_balance(balance:, date: Date.current, currency: nil, notes: nil, existing_valuation_id: nil) - Account::BalanceUpdater.new(self, balance:, currency:, date:, notes:, existing_valuation_id:).update - end - def start_date first_entry_date = entries.minimum(:date) || Date.current first_entry_date - 1.day @@ -146,4 +141,23 @@ class Account < ApplicationRecord def long_subtype_label accountable_class.long_subtype_label_for(subtype) || accountable_class.display_name end + + # The balance type determines which "component" of balance is being tracked. + # This is primarily used for balance related calculations and updates. + # + # "Cash" = "Liquid" + # "Non-cash" = "Illiquid" + # "Investment" = A mix of both, including brokerage cash (liquid) and holdings (illiquid) + def balance_type + case accountable_type + when "Depository", "CreditCard" + :cash + when "Property", "Vehicle", "OtherAsset", "Loan", "OtherLiability" + :non_cash + when "Investment", "Crypto" + :investment + else + raise "Unknown account type: #{accountable_type}" + end + end end diff --git a/app/models/account/anchorable.rb b/app/models/account/anchorable.rb index 750fb067..bb797c85 100644 --- a/app/models/account/anchorable.rb +++ b/app/models/account/anchorable.rb @@ -10,7 +10,9 @@ module Account::Anchorable end def set_opening_anchor_balance(**opts) - opening_balance_manager.set_opening_balance(**opts) + result = opening_balance_manager.set_opening_balance(**opts) + sync_later if result.success? + result end def opening_anchor_date @@ -25,8 +27,10 @@ module Account::Anchorable opening_balance_manager.has_opening_anchor? end - def set_current_anchor_balance(balance) - current_balance_manager.set_current_balance(balance) + def set_current_balance(balance) + result = current_balance_manager.set_current_balance(balance) + sync_later if result.success? + result end def current_anchor_balance diff --git a/app/models/account/balance_updater.rb b/app/models/account/balance_updater.rb deleted file mode 100644 index 1c1b1556..00000000 --- a/app/models/account/balance_updater.rb +++ /dev/null @@ -1,53 +0,0 @@ -class Account::BalanceUpdater - def initialize(account, balance:, currency: nil, date: Date.current, notes: nil, existing_valuation_id: nil) - @account = account - @balance = balance.to_d - @currency = currency - @date = date.to_date - @notes = notes - @existing_valuation_id = existing_valuation_id - end - - def update - return Result.new(success?: true, updated?: false) unless requires_update? - - Account.transaction do - if date == Date.current - account.balance = balance - account.currency = currency if currency.present? - account.save! - end - - valuation_entry = if existing_valuation_id - account.entries.find(existing_valuation_id) - else - account.entries.valuations.find_or_initialize_by(date: date) do |entry| - entry.entryable = Valuation.new(kind: "reconciliation") - end - end - - valuation_entry.date = date - valuation_entry.amount = balance - valuation_entry.currency = currency if currency.present? - valuation_entry.name = Valuation.build_reconciliation_name(account.accountable_type) - valuation_entry.notes = notes if notes.present? - valuation_entry.save! - end - - account.sync_later - - Result.new(success?: true, updated?: true) - rescue => e - message = Rails.env.development? ? e.message : "Unable to update account values. Please try again." - Result.new(success?: false, updated?: false, error_message: message) - end - - private - attr_reader :account, :balance, :currency, :date, :notes, :existing_valuation_id - - Result = Struct.new(:success?, :updated?, :error_message) - - def requires_update? - date != Date.current || account.balance != balance || account.currency != currency - end -end diff --git a/app/models/account/current_balance_manager.rb b/app/models/account/current_balance_manager.rb index 24303213..2b1ba630 100644 --- a/app/models/account/current_balance_manager.rb +++ b/app/models/account/current_balance_manager.rb @@ -31,22 +31,77 @@ class Account::CurrentBalanceManager end def set_current_balance(balance) - # A current balance anchor implies there is an external data source that will keep it updated. Since manual accounts - # are tracked by the user, a current balance anchor is not appropriate. - raise InvalidOperation, "Manual accounts cannot set current balance anchor. Set opening balance or use a reconciliation instead." if account.manual? - - if current_anchor_valuation - changes_made = update_current_anchor(balance) - Result.new(success?: true, changes_made?: changes_made, error: nil) + if account.linked? + result = set_current_balance_for_linked_account(balance) else - create_current_anchor(balance) - Result.new(success?: true, changes_made?: true, error: nil) + result = set_current_balance_for_manual_account(balance) end + + # Update cache field so changes appear immediately to the user + account.update!(balance: balance) + + result + rescue => e + Result.new(success?: false, changes_made?: false, error: e.message) end private attr_reader :account + def opening_balance_manager + @opening_balance_manager ||= Account::OpeningBalanceManager.new(account) + end + + def reconciliation_manager + @reconciliation_manager ||= Account::ReconciliationManager.new(account) + end + + # Manual accounts do not manage the `current_anchor` valuation (otherwise, user would need to continually update it, which is bad UX) + # Instead, we use a combination of "auto-update strategies" to set the current balance according to the user's intent. + # + # The "auto-update strategies" are: + # 1. Value tracking - If the account has a reconciliation already, we assume they are tracking the account value primarily with reconciliations, so we append a new one + # 2. Transaction adjustment - If the account doesn't have recons, we assume user is tracking with transactions, so we adjust the opening balance with a delta until it + # gets us to the desired balance. This ensures we don't append unnecessary reconciliations to the account, which "reset" the value from that + # date forward (not user's intent). + # + # For more documentation on these auto-update strategies, see the test cases. + def set_current_balance_for_manual_account(balance) + # If we're dealing with a cash account that has no reconciliations, use "Transaction adjustment" strategy (update opening balance to "back in" to the desired current balance) + if account.balance_type == :cash && account.valuations.reconciliation.empty? + adjust_opening_balance_with_delta(new_balance: balance, old_balance: account.balance) + else + existing_reconciliation = account.entries.valuations.find_by(date: Date.current) + + result = reconciliation_manager.reconcile_balance(balance: balance, date: Date.current, existing_valuation_entry: existing_reconciliation) + + # Normalize to expected result format + Result.new(success?: result.success?, changes_made?: true, error: result.error_message) + end + end + + def adjust_opening_balance_with_delta(new_balance:, old_balance:) + delta = new_balance - old_balance + + result = opening_balance_manager.set_opening_balance(balance: account.opening_anchor_balance + delta) + + # Normalize to expected result format + Result.new(success?: result.success?, changes_made?: true, error: result.error) + end + + # Linked accounts manage "current balance" via the special `current_anchor` valuation. + # This is NOT a user-facing feature, and is primarily used in "processors" while syncing + # linked account data (e.g. via Plaid) + def set_current_balance_for_linked_account(balance) + if current_anchor_valuation + changes_made = update_current_anchor(balance) + Result.new(success?: true, changes_made?: changes_made, error: nil) + else + create_current_anchor(balance) + Result.new(success?: true, changes_made?: true, error: nil) + end + end + def current_anchor_valuation @current_anchor_valuation ||= account.valuations.current_anchor.includes(:entry).first end diff --git a/app/models/account/reconcileable.rb b/app/models/account/reconcileable.rb index bad855a9..b8805236 100644 --- a/app/models/account/reconcileable.rb +++ b/app/models/account/reconcileable.rb @@ -2,11 +2,15 @@ module Account::Reconcileable extend ActiveSupport::Concern def create_reconciliation(balance:, date:, dry_run: false) - reconciliation_manager.reconcile_balance(balance: balance, date: date, dry_run: dry_run) + result = reconciliation_manager.reconcile_balance(balance: balance, date: date, dry_run: dry_run) + sync_later if result.success? + result end def update_reconciliation(existing_valuation_entry, balance:, date:, dry_run: false) - reconciliation_manager.reconcile_balance(balance: balance, date: date, existing_valuation_entry: existing_valuation_entry, dry_run: dry_run) + result = reconciliation_manager.reconcile_balance(balance: balance, date: date, existing_valuation_entry: existing_valuation_entry, dry_run: dry_run) + sync_later if result.success? + result end private diff --git a/app/models/account/reconciliation_manager.rb b/app/models/account/reconciliation_manager.rb index e1300143..aac821b2 100644 --- a/app/models/account/reconciliation_manager.rb +++ b/app/models/account/reconciliation_manager.rb @@ -12,7 +12,6 @@ class Account::ReconciliationManager unless dry_run prepared_valuation.save! - account.sync_later end ReconciliationResult.new( diff --git a/app/models/balance/base_calculator.rb b/app/models/balance/base_calculator.rb index 3360bcec..92ef5d3e 100644 --- a/app/models/balance/base_calculator.rb +++ b/app/models/balance/base_calculator.rb @@ -20,9 +20,9 @@ class Balance::BaseCalculator end def derive_cash_balance_on_date_from_total(total_balance:, date:) - if balance_type == :investment + if account.balance_type == :investment total_balance - holdings_value_for_date(date) - elsif balance_type == :cash + elsif account.balance_type == :cash total_balance else 0 @@ -32,7 +32,7 @@ class Balance::BaseCalculator def derive_cash_balance(cash_balance, date) entries = sync_cache.get_entries(date) - if balance_type == :non_cash + if account.balance_type == :non_cash 0 else cash_balance + signed_entry_flows(entries) @@ -42,9 +42,9 @@ class Balance::BaseCalculator def derive_non_cash_balance(non_cash_balance, date, direction: :forward) entries = sync_cache.get_entries(date) # Loans are a special case (loan payment reducing principal, which is non-cash) - if balance_type == :non_cash && account.accountable_type == "Loan" + if account.balance_type == :non_cash && account.accountable_type == "Loan" non_cash_balance + signed_entry_flows(entries) - elsif balance_type == :investment + elsif account.balance_type == :investment # For reverse calculations, we need the previous day's holdings target_date = direction == :forward ? date : date.prev_day holdings_value_for_date(target_date) @@ -57,19 +57,6 @@ class Balance::BaseCalculator raise NotImplementedError, "Directional calculators must implement this method" end - def balance_type - case account.accountable_type - when "Depository", "CreditCard" - :cash - when "Property", "Vehicle", "OtherAsset", "Loan", "OtherLiability" - :non_cash - when "Investment", "Crypto" - :investment - else - raise "Unknown account type: #{account.accountable_type}" - end - end - def build_balance(date:, cash_balance:, non_cash_balance:) Balance.new( account_id: account.id, diff --git a/app/models/plaid_account/processor.rb b/app/models/plaid_account/processor.rb index 5b16f90d..b42bdf3b 100644 --- a/app/models/plaid_account/processor.rb +++ b/app/models/plaid_account/processor.rb @@ -57,7 +57,7 @@ class PlaidAccount::Processor # to properly track the holdings vs. cash breakdown, but for now we're only tracking # the total balance in the current anchor. The cash_balance field on the account model # is still being used for the breakdown. - account.set_current_anchor_balance(balance_calculator.balance) + account.set_current_balance(balance_calculator.balance) end end diff --git a/test/controllers/properties_controller_test.rb b/test/controllers/properties_controller_test.rb index b5f1305f..34f76734 100644 --- a/test/controllers/properties_controller_test.rb +++ b/test/controllers/properties_controller_test.rb @@ -71,10 +71,6 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest test "updates balances tab" do original_balance = @account.balance - # Mock the update_balance method to return a successful result - Account::BalanceUpdater::Result.any_instance.stubs(:success?).returns(true) - Account::BalanceUpdater::Result.any_instance.stubs(:updated?).returns(true) - patch update_balances_property_path(@account), params: { account: { balance: 600000, @@ -116,9 +112,7 @@ class PropertiesControllerTest < ActionDispatch::IntegrationTest end test "balances update handles validation errors" do - # Mock update_balance to return a failure result - Account::BalanceUpdater::Result.any_instance.stubs(:success?).returns(false) - Account::BalanceUpdater::Result.any_instance.stubs(:error_message).returns("Invalid balance") + Account.any_instance.stubs(:set_current_balance).returns(OpenStruct.new(success?: false, error_message: "Invalid balance")) patch update_balances_property_path(@account), params: { account: { diff --git a/test/models/account/current_balance_manager_test.rb b/test/models/account/current_balance_manager_test.rb index d48eb927..0d7b914b 100644 --- a/test/models/account/current_balance_manager_test.rb +++ b/test/models/account/current_balance_manager_test.rb @@ -2,15 +2,185 @@ require "test_helper" class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase setup do - @connected_account = accounts(:connected) # Connected account - can update current balance - @manual_account = accounts(:depository) # Manual account - cannot update current balance + @family = families(:empty) + @linked_account = accounts(:connected) end - test "when no existing anchor, creates new anchor" do - manager = Account::CurrentBalanceManager.new(@connected_account) + # ------------------------------------------------------------------------------------------------- + # Manual account current balance management + # + # Manual accounts do not manage `current_anchor` valuations and have "auto-update strategies" to set the current balance. + # ------------------------------------------------------------------------------------------------- - assert_difference -> { @connected_account.entries.count } => 1, - -> { @connected_account.valuations.count } => 1 do + test "when one or more reconciliations exist, append new reconciliation to represent the current balance" do + account = @family.accounts.create!( + name: "Test", + balance: 1000, + cash_balance: 1000, + currency: "USD", + accountable: Depository.new + ) + + # A reconciliation tells us that the user is tracking this account's value with balance-only updates + account.entries.create!( + date: 30.days.ago.to_date, + name: "First manual recon valuation", + amount: 1200, + currency: "USD", + entryable: Valuation.new(kind: "reconciliation") + ) + + manager = Account::CurrentBalanceManager.new(account) + + assert_equal 1, account.valuations.count + + # Here, we assume user is once again "overriding" the balance to 1400 + manager.set_current_balance(1400) + + today_valuation = account.entries.valuations.find_by(date: Date.current) + + assert_equal 2, account.valuations.count + assert_equal 1400, today_valuation.amount + + assert_equal 1400, account.balance + end + + test "all manual non cash accounts append reconciliations for current balance updates" do + [ Property, Vehicle, OtherAsset, Loan, OtherLiability ].each do |account_type| + account = @family.accounts.create!( + name: "Test", + balance: 1000, + cash_balance: 1000, + currency: "USD", + accountable: account_type.new + ) + + manager = Account::CurrentBalanceManager.new(account) + + assert_equal 0, account.valuations.count + + manager.set_current_balance(1400) + + assert_equal 1, account.valuations.count + + today_valuation = account.entries.valuations.find_by(date: Date.current) + + assert_equal 1400, today_valuation.amount + assert_equal 1400, account.balance + end + end + + # Scope: Depository, CreditCard only (i.e. all-cash accounts) + # + # If a user has an opening balance (valuation) for their manual *Depository* or *CreditCard* account and has 1+ transactions, the intent of + # "updating current balance" typically means that their start balance is incorrect. We follow that user intent + # by default and find the delta required, and update the opening balance so that the timeline reflects this current balance + # + # The purpose of this is so we're not cluttering up their timeline with "balance reconciliations" that reset the balance + # on the current date. Our goal is to keep the timeline with as few "Valuations" as possible. + # + # If we ever build a UI that gives user options, this test expectation may require some updates, but for now this + # is the least surprising outcome. + test "when no reconciliations exist on cash accounts, adjust opening balance with delta until it gets us to the desired balance" do + account = @family.accounts.create!( + name: "Test", + balance: 900, # the balance after opening valuation + transaction have "synced" (1000 - 100 = 900) + cash_balance: 900, + currency: "USD", + accountable: Depository.new + ) + + account.entries.create!( + date: 1.year.ago.to_date, + name: "Test opening valuation", + amount: 1000, + currency: "USD", + entryable: Valuation.new(kind: "opening_anchor") + ) + + account.entries.create!( + date: 10.days.ago.to_date, + name: "Test expense transaction", + amount: 100, + currency: "USD", + entryable: Transaction.new + ) + + # What we're asserting here: + # 1. User creates the account with an opening balance of 1000 + # 2. User creates a transaction of 100, which then reduces the balance to 900 (the current balance value on account above) + # 3. User requests "current balance update" back to 1000, which was their intention + # 4. We adjust the opening balance by the delta (100) to 1100, which is the new opening balance, so that the transaction + # of 100 reduces it down to 1000, which is the current balance they intended. + assert_equal 1, account.valuations.count + assert_equal 1, account.transactions.count + + # No new valuation is appended; we're just adjusting the opening valuation anchor + assert_no_difference "account.entries.count" do + manager = Account::CurrentBalanceManager.new(account) + manager.set_current_balance(1000) + end + + opening_valuation = account.valuations.find_by(kind: "opening_anchor") + + assert_equal 1100, opening_valuation.entry.amount + assert_equal 1000, account.balance + end + + # (SEE ABOVE TEST FOR MORE DETAILED EXPLANATION) + # Same assertions as the test above, but Credit Card accounts are liabilities, which means expenses increase balance; not decrease + test "when no reconciliations exist on credit card accounts, adjust opening balance with delta until it gets us to the desired balance" do + account = @family.accounts.create!( + name: "Test", + balance: 1100, # the balance after opening valuation + transaction have "synced" (1000 + 100 = 1100) (expenses increase balance) + cash_balance: 1100, + currency: "USD", + accountable: CreditCard.new + ) + + account.entries.create!( + date: 1.year.ago.to_date, + name: "Test opening valuation", + amount: 1000, + currency: "USD", + entryable: Valuation.new(kind: "opening_anchor") + ) + + account.entries.create!( + date: 10.days.ago.to_date, + name: "Test expense transaction", + amount: 100, + currency: "USD", + entryable: Transaction.new + ) + + assert_equal 1, account.valuations.count + assert_equal 1, account.transactions.count + + assert_no_difference "account.entries.count" do + manager = Account::CurrentBalanceManager.new(account) + manager.set_current_balance(1000) + end + + opening_valuation = account.valuations.find_by(kind: "opening_anchor") + + assert_equal 900, opening_valuation.entry.amount + assert_equal 1000, account.balance + end + + # ------------------------------------------------------------------------------------------------- + # Linked account current balance management + # + # Linked accounts manage "current balance" via the special `current_anchor` valuation. + # This is NOT a user-facing feature, and is primarily used in "processors" while syncing + # linked account data (e.g. via Plaid) + # ------------------------------------------------------------------------------------------------- + + test "when no existing anchor for linked account, creates new anchor" do + manager = Account::CurrentBalanceManager.new(@linked_account) + + assert_difference -> { @linked_account.entries.count } => 1, + -> { @linked_account.valuations.count } => 1 do result = manager.set_current_balance(1000) assert result.success? @@ -18,7 +188,7 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase assert_nil result.error end - current_anchor = @connected_account.valuations.current_anchor.first + current_anchor = @linked_account.valuations.current_anchor.first assert_not_nil current_anchor assert_equal 1000, current_anchor.entry.amount assert_equal "current_anchor", current_anchor.kind @@ -27,23 +197,25 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase assert_equal 1000, entry.amount assert_equal Date.current, entry.date assert_equal "Current balance", entry.name # Depository type returns "Current balance" + + assert_equal 1000, @linked_account.balance end - test "updates existing anchor" do + test "updates existing anchor for linked account" do # First create a current anchor - manager = Account::CurrentBalanceManager.new(@connected_account) + manager = Account::CurrentBalanceManager.new(@linked_account) result = manager.set_current_balance(1000) assert result.success? - current_anchor = @connected_account.valuations.current_anchor.first + current_anchor = @linked_account.valuations.current_anchor.first original_id = current_anchor.id original_entry_id = current_anchor.entry.id # Travel to tomorrow to ensure date change travel_to Date.current + 1.day do # Now update it - assert_no_difference -> { @connected_account.entries.count } do - assert_no_difference -> { @connected_account.valuations.count } do + assert_no_difference -> { @linked_account.entries.count } do + assert_no_difference -> { @linked_account.valuations.count } do result = manager.set_current_balance(2000) assert result.success? assert result.changes_made? @@ -56,24 +228,13 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase assert_equal 2000, current_anchor.entry.amount assert_equal Date.current, current_anchor.entry.date # Should be updated to current date end - end - test "when manual account, raises InvalidOperation error" do - manager = Account::CurrentBalanceManager.new(@manual_account) - - error = assert_raises(Account::CurrentBalanceManager::InvalidOperation) do - manager.set_current_balance(1000) - end - - assert_equal "Manual accounts cannot set current balance anchor. Set opening balance or use a reconciliation instead.", error.message - - # Verify no current anchor was created - assert_nil @manual_account.valuations.current_anchor.first + assert_equal 2000, @linked_account.balance end test "when no changes made, returns success with no changes made" do # First create a current anchor - manager = Account::CurrentBalanceManager.new(@connected_account) + manager = Account::CurrentBalanceManager.new(@linked_account) result = manager.set_current_balance(1000) assert result.success? assert result.changes_made? @@ -84,16 +245,18 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase assert result.success? assert_not result.changes_made? assert_nil result.error + + assert_equal 1000, @linked_account.balance end test "updates only amount when balance changes" do - manager = Account::CurrentBalanceManager.new(@connected_account) + manager = Account::CurrentBalanceManager.new(@linked_account) # Create initial anchor result = manager.set_current_balance(1000) assert result.success? - current_anchor = @connected_account.valuations.current_anchor.first + current_anchor = @linked_account.valuations.current_anchor.first original_date = current_anchor.entry.date # Update only the balance @@ -104,16 +267,18 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase current_anchor.reload assert_equal 1500, current_anchor.entry.amount assert_equal original_date, current_anchor.entry.date # Date should remain the same if on same day + + assert_equal 1500, @linked_account.balance end test "updates date when called on different day" do - manager = Account::CurrentBalanceManager.new(@connected_account) + manager = Account::CurrentBalanceManager.new(@linked_account) # Create initial anchor result = manager.set_current_balance(1000) assert result.success? - current_anchor = @connected_account.valuations.current_anchor.first + current_anchor = @linked_account.valuations.current_anchor.first original_amount = current_anchor.entry.amount # Travel to tomorrow and update with same balance @@ -126,10 +291,12 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase assert_equal original_amount, current_anchor.entry.amount assert_equal Date.current, current_anchor.entry.date # Should be updated to new current date end + + assert_equal 1000, @linked_account.balance end test "current_balance returns balance from current anchor" do - manager = Account::CurrentBalanceManager.new(@connected_account) + manager = Account::CurrentBalanceManager.new(@linked_account) # Create a current anchor manager.set_current_balance(1500) @@ -142,12 +309,16 @@ class Account::CurrentBalanceManagerTest < ActiveSupport::TestCase # Should return the updated balance assert_equal 2500, manager.current_balance + + assert_equal 2500, @linked_account.balance end test "current_balance falls back to account balance when no anchor exists" do - manager = Account::CurrentBalanceManager.new(@connected_account) + manager = Account::CurrentBalanceManager.new(@linked_account) # When no current anchor exists, should fall back to account.balance - assert_equal @connected_account.balance, manager.current_balance + assert_equal @linked_account.balance, manager.current_balance + + assert_equal @linked_account.balance, @linked_account.balance end end diff --git a/test/models/account/reconciliation_manager_test.rb b/test/models/account/reconciliation_manager_test.rb index 0e7a39a9..794c2cc5 100644 --- a/test/models/account/reconciliation_manager_test.rb +++ b/test/models/account/reconciliation_manager_test.rb @@ -88,7 +88,7 @@ class Account::ReconciliationManagerTest < ActiveSupport::TestCase end end - test "dry run does not persist or sync account" do + test "dry run does not persist account" do @account.balances.create!(date: Date.current, balance: 1000, cash_balance: 500, currency: @account.currency) assert_no_difference "Valuation.count" do @@ -96,7 +96,6 @@ class Account::ReconciliationManagerTest < ActiveSupport::TestCase end assert_difference "Valuation.count", 1 do - @account.expects(:sync_later).once @manager.reconcile_balance(balance: 1200, date: Date.current) end end