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

Checkpoint

This commit is contained in:
Zach Gollwitzer 2025-07-08 10:25:16 -04:00
parent 15f8d827b5
commit b7acef1e7a
9 changed files with 56 additions and 23 deletions

View file

@ -2,7 +2,7 @@ module AccountableResource
extend ActiveSupport::Concern
included do
include ScrollFocusable, Periodable
include ScrollFocusable, Periodable, StreamExtensions
before_action :set_account, only: [ :show, :edit, :update, :destroy ]
before_action :set_link_options, only: :new
@ -39,7 +39,10 @@ module AccountableResource
@account = Current.family.accounts.create_and_sync(account_params.except(:return_to))
@account.lock_saved_attributes!
redirect_to account_params[:return_to].presence || @account, notice: t("accounts.create.success", type: accountable_type.name.underscore.humanize)
respond_to do |format|
format.html { redirect_to account_params[:return_to].presence || @account, notice: accountable_type.name.underscore.humanize + " account created" }
format.turbo_stream { stream_redirect_to account_params[:return_to].presence || account_path(@account), notice: accountable_type.name.underscore.humanize + " account created" }
end
end
def update
@ -54,7 +57,7 @@ module AccountableResource
end
# Update remaining account attributes
update_params = account_params.except(:return_to, :balance, :currency)
update_params = account_params.except(:return_to, :balance, :currency, :tracking_start_date)
unless @account.update(update_params)
@error_message = @account.errors.full_messages.join(", ")
render :edit, status: :unprocessable_entity
@ -62,7 +65,11 @@ module AccountableResource
end
@account.lock_saved_attributes!
redirect_back_or_to @account, notice: t("accounts.update.success", type: accountable_type.name.underscore.humanize)
respond_to do |format|
format.html { redirect_back_or_to @account, notice: accountable_type.name.underscore.humanize + " account updated" }
format.turbo_stream { stream_redirect_to @account, notice: accountable_type.name.underscore.humanize + " account updated" }
end
end
def destroy
@ -90,7 +97,7 @@ module AccountableResource
def account_params
params.require(:account).permit(
:name, :balance, :subtype, :currency, :accountable_type, :return_to,
:name, :balance, :subtype, :currency, :accountable_type, :return_to, :tracking_start_date,
accountable_attributes: self.class.permitted_accountable_attributes
)
end

View file

@ -57,20 +57,20 @@ class Account < ApplicationRecord
class << self
def create_and_sync(attributes)
start_date = attributes.delete(:tracking_start_date) || 2.years.ago.to_date
attributes[:accountable_attributes] ||= {} # Ensure accountable is created, even if empty
account = new(attributes.merge(cash_balance: attributes[:balance]))
initial_balance = attributes.dig(:accountable_attributes, :initial_balance)&.to_d || account.balance
account.entries.build(
name: Valuation::Name.new("opening_anchor", account.accountable_type).to_s,
date: 2.years.ago.to_date,
date: start_date,
amount: initial_balance,
currency: account.currency,
entryable: Valuation.new(
kind: "opening_anchor",
balance: initial_balance,
cash_balance: initial_balance,
currency: account.currency
cash_balance: initial_balance
)
)

View file

@ -18,12 +18,16 @@ class Account::BalanceUpdater
end
valuation_entry = account.entries.valuations.find_or_initialize_by(date: date) do |entry|
entry.entryable = Valuation.new
entry.entryable = Valuation.new(
kind: "recon",
balance: balance,
cash_balance: balance
)
end
valuation_entry.amount = balance
valuation_entry.currency = currency if currency.present?
valuation_entry.name = valuation_name(valuation_entry.entryable, account)
valuation_entry.name = valuation_name(valuation_entry, account)
valuation_entry.notes = notes if notes.present?
valuation_entry.save!
end

View file

@ -11,6 +11,7 @@ class Valuation < ApplicationRecord
# Each account can have at most 1 opening anchor and 1 current anchor. All valuations between these anchors should
# be either "recon" or "snapshot". This ensures we can reliably construct the account balance history solely from Entries.
validate :unique_anchor_per_account, if: -> { opening_anchor? || current_anchor? }
validate :manual_accounts_cannot_have_current_anchor
private
def unique_anchor_per_account
@ -26,4 +27,12 @@ class Valuation < ApplicationRecord
errors.add(:kind, "#{kind.humanize} already exists for this account")
end
end
def manual_accounts_cannot_have_current_anchor
return unless entry&.account
if entry.account.unlinked? && current_anchor?
errors.add(:kind, "Manual accounts cannot have a current anchor")
end
end
end

View file

@ -1,10 +1,12 @@
<%# locals: (account:, url:) %>
<% if @error_message.present? %>
<%= render AlertComponent.new(message: @error_message, variant: :error) %>
<div class="mb-4">
<%= render AlertComponent.new(message: @error_message, variant: :error) %>
</div>
<% end %>
<%= styled_form_with model: account, url: url, scope: :account, data: { turbo: false }, class: "flex flex-col gap-4 justify-between grow text-primary" do |form| %>
<%= styled_form_with model: account, url: url, scope: :account, class: "flex flex-col gap-4 justify-between grow text-primary" do |form| %>
<div class="grow space-y-2">
<%= form.hidden_field :accountable_type %>
<%= form.hidden_field :return_to, value: params[:return_to] %>
@ -12,7 +14,19 @@
<%= form.text_field :name, placeholder: t(".name_placeholder"), required: "required", label: t(".name_label") %>
<% unless account.linked? %>
<%= form.money_field :balance, label: t(".balance"), required: true, default_currency: Current.family.currency %>
<%= form.money_field :balance,
label: t(".balance"),
required: true,
default_currency: Current.family.currency,
label_tooltip: "The current balance or value of the account, which is typically the balance reported by your financial institution." %>
<% unless account.persisted? %>
<%= form.date_field :tracking_start_date,
label: "Tracking start date",
required: true,
value: 2.years.ago.to_date,
label_tooltip: "The date we will start tracking the balance for this account. If you're not sure, we recommend using the default of 2 years ago so net worth graphs have adequate historical data." %>
<% end %>
<% end %>
<%= yield form %>