1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-25 08:09:38 +02:00

Multi-step account forms + clearer balance editing (#2427)
Some checks failed
Publish Docker image / ci (push) Has been cancelled
Publish Docker image / Build docker image (push) Has been cancelled

* Initial multi-step property form

* Improve form structure, add optional tooltip help icons to form fields

* Add basic inline alert component

* Clean up and improve property form lifecycle

* Implement Account status concept

* Lint fixes

* Remove whitespace

* Balance editing, scope updates for account

* Passing tests

* Fix brakeman warning

* Remove stale columns

* data constraint tweaks

* Redundant property
This commit is contained in:
Zach Gollwitzer 2025-07-03 09:33:07 -04:00 committed by GitHub
parent ba7e8d3893
commit 662f2c04ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
66 changed files with 1036 additions and 427 deletions

View file

@ -1,5 +1,6 @@
class Account < ApplicationRecord
include Syncable, Monetizable, Chartable, Linkable, Enrichable
include AASM
validates :name, :balance, :currency, presence: true
@ -18,7 +19,7 @@ class Account < ApplicationRecord
enum :classification, { asset: "asset", liability: "liability" }, validate: { allow_nil: true }
scope :active, -> { where(is_active: true) }
scope :visible, -> { where(status: [ "draft", "active" ]) }
scope :assets, -> { where(classification: "asset") }
scope :liabilities, -> { where(classification: "liability") }
scope :alphabetically, -> { order(:name) }
@ -30,6 +31,30 @@ class Account < ApplicationRecord
accepts_nested_attributes_for :accountable, update_only: true
# Account state machine
aasm column: :status, timestamps: true do
state :active, initial: true
state :draft
state :disabled
state :pending_deletion
event :activate do
transitions from: [ :draft, :disabled ], to: :active
end
event :disable do
transitions from: [ :draft, :active ], to: :disabled
end
event :enable do
transitions from: :disabled, to: :active
end
event :mark_for_deletion do
transitions from: [ :draft, :active, :disabled ], to: :pending_deletion
end
end
class << self
def create_and_sync(attributes)
attributes[:accountable_attributes] ||= {} # Ensure accountable is created, even if empty
@ -77,10 +102,20 @@ class Account < ApplicationRecord
end
def destroy_later
update!(scheduled_for_deletion: true, is_active: false)
mark_for_deletion!
DestroyJob.perform_later(self)
end
# Override destroy to handle error recovery for accounts
def destroy
super
rescue => e
# If destruction fails, transition back to disabled state
# This provides a cleaner recovery path than the generic scheduled_for_deletion flag
disable! if may_disable?
raise e
end
def current_holdings
holdings.where(currency: currency)
.where.not(qty: 0)
@ -92,49 +127,9 @@ class Account < ApplicationRecord
.order(amount: :desc)
end
def update_with_sync!(attributes)
should_update_balance = attributes[:balance] && attributes[:balance].to_d != balance
initial_balance = attributes.dig(:accountable_attributes, :initial_balance)
should_update_initial_balance = initial_balance && initial_balance.to_d != accountable.initial_balance
transaction do
update!(attributes)
update_balance!(attributes[:balance]) if should_update_balance
update_inital_balance!(attributes[:accountable_attributes][:initial_balance]) if should_update_initial_balance
end
sync_later
end
def update_balance!(balance)
valuation = entries.valuations.find_by(date: Date.current)
if valuation
valuation.update! amount: balance
else
entries.create! \
date: Date.current,
name: "Balance update",
amount: balance,
currency: currency,
entryable: Valuation.new
end
end
def update_inital_balance!(initial_balance)
valuation = first_valuation
if valuation
valuation.update! amount: initial_balance
else
entries.create! \
date: Date.current,
name: "Initial Balance",
amount: initial_balance,
currency: currency,
entryable: Valuation.new
end
def update_balance(balance:, date: Date.current, currency: nil, notes: nil)
Account::BalanceUpdater.new(self, balance:, currency:, date:, notes:).update
end
def start_date