1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-02 20:15:22 +02:00

Transaction transfers, payments, and matching (#883)

* Add transfer model and clean up family snapshot fixtures

* Ignore transfers in income and expense snapshots

* Add transfer validations

* Implement basic transfer matching UI

* Fix merge conflicts

* Add missing translations

* Tweak selection states for transfer types

* Add missing i18n translation
This commit is contained in:
Zach Gollwitzer 2024-06-19 06:52:08 -04:00 committed by GitHub
parent b462bc8f8c
commit ca39b26070
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
57 changed files with 991 additions and 427 deletions

View file

@ -4,6 +4,7 @@ class Transaction < ApplicationRecord
monetize :amount
belongs_to :account
belongs_to :transfer, optional: true
belongs_to :category, optional: true
belongs_to :merchant, optional: true
has_many :taggings, as: :taggable, dependent: :destroy
@ -42,6 +43,10 @@ class Transaction < ApplicationRecord
amount > 0
end
def transfer?
marked_as_transfer
end
def sync_account_later
if destroyed?
sync_start_date = previous_transaction_date
@ -53,6 +58,21 @@ class Transaction < ApplicationRecord
end
class << self
def income_total(currency = "USD")
inflows.reject(&:transfer?).select { |t| t.currency == currency }.sum(&:amount_money)
end
def expense_total(currency = "USD")
outflows.reject(&:transfer?).select { |t| t.currency == currency }.sum(&:amount_money)
end
def mark_transfers!
update_all marked_as_transfer: true
# Attempt to "auto match" and save a transfer if 2 transactions selected
Transfer.new(transactions: all).save if all.count == 2
end
def daily_totals(transactions, period: Period.last_30_days, currency: Current.family.currency)
# Sum spending and income for each day in the period with the given currency
select(
@ -60,7 +80,7 @@ class Transaction < ApplicationRecord
"COALESCE(SUM(converted_amount) FILTER (WHERE converted_amount > 0), 0) AS spending",
"COALESCE(SUM(-converted_amount) FILTER (WHERE converted_amount < 0), 0) AS income"
)
.from(transactions.with_converted_amount(currency), :t)
.from(transactions.with_converted_amount(currency).where(marked_as_transfer: false), :t)
.joins(sanitize_sql([ "RIGHT JOIN generate_series(?, ?, interval '1 day') AS gs(date) ON t.date = gs.date", period.date_range.first, period.date_range.last ]))
.group("gs.date")
end
@ -83,7 +103,7 @@ class Transaction < ApplicationRecord
end
def search(params)
query = all
query = all.includes(:transfer)
query = query.by_name(params[:search]) if params[:search].present?
query = query.with_categories(params[:categories]) if params[:categories].present?
query = query.with_accounts(params[:accounts]) if params[:accounts].present?
@ -96,7 +116,6 @@ class Transaction < ApplicationRecord
end
private
def previous_transaction_date
self.account
.transactions