maybe-finance / maybe

The OS for your personal finances
https://maybe.co
GNU Affero General Public License v3.0
28.71k stars 2.19k forks source link

Account::Entry Delegated Type (namespace updates part 7) #923

Closed zachgoll closed 6 days ago

zachgoll commented 1 week ago

See #892 for a detailed proposal of these changes.

Part 7 is the largest and final update needed to enable investment transactions. There is a lot here out of necessity since this reworks the existing Account::Transaction and Account::Valuation models to now be a subtypes of an Account::Entry.

Changes overview

Introduction of Account::Entry

As described in #892, an Account::Entry is an abstract concept representing a "Financial entry" to an account. In general, an "entry" is something that alters the history of an account. For example, a Account::Transaction will increase/decrease the account's historical balance on date by amount, while an Account::Valuation will override the historical balance on date by amount.

This consolidation simplifies the "sync" logic for an account by allowing us to iterate a single array of "entries" and deciding how to "sync" the balance based on the entry type.

Consolidation of controllers / helpers / views

We previously had a lot of duplicated resource logic for Transactions and Valuations that has all been consolidated into EntriesController.

Each action (i.e. show, edit, etc.) delegates to the resource's entryable_type to determine which view partial to render. For example, Account::EntriesController#show renders the _show.html.erb partial for the relevant "entryable":

<%= render partial: permitted_entryable_partial_path(@entry, "show"), locals: { entry: @entry } %>

If @entry.entryable_type == "Account::Valuation", the views/account/entries/entryables/valuation/_show.html.erb partial is rendered.

This delegation allows for shared view logic while keeping flexibility to customize based on the entryable's type.

While we currently have a divergence in views for Transactions and Valuations, as we add investment transactions, each "entry" will follow the view convention:

Account sync logic consolidation

Now that we're working with a single Account::Entry that has all the information needed to "sync" an account (i.e. date, currency, amount), the account sync process performed in account/syncable.rb and account/balance/calculator.rb could be significantly consolidated and simplified.

Furthermore, while refactoring, this uncovered a bug where the first balance of a sync was not being calculated correctly. The expected family results have been updated to reflect this corrected balance.

Test coverage

While there are a few test deletions (due to redundancy), I've attempted to preserve almost 100% of the coverage that existed prior to this branch.

Codebase cleanup

Due to the vast number of structural changes to the codebase that this branch introduced out of necessity, I've used it as an opportunity to delete stale code, rename and reorganize files, and clean up the UI a bit.