mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-24 15:49:39 +02:00
perf(transactions): add kind
to Transaction
model and remove expensive Transfer joins in aggregations (#2388)
* add kind to transaction model * Basic transfer creator * Fix method naming conflict * Creator form pattern * Remove stale methods * Tweak migration * Remove BaseQuery, write entire query in each class for clarity * Query optimizations * Remove unused exchange rate query lines * Remove temporary cache-warming strategy * Fix test * Update transaction search * Decouple transactions endpoint from IncomeStatement * Clean up transactions controller * Update cursor rules * Cleanup comments, logic in search * Fix totals logic on transactions view * Fix pagination * Optimize search totals query * Default to last 30 days on transactions page if no filters * Decouple transactions list from transfer details * Revert transfer route * Migration reset * Bundle update * Fix matching logic, tests * Remove unused code
This commit is contained in:
parent
7aca5a2277
commit
1aae00f586
49 changed files with 1749 additions and 705 deletions
85
app/models/transfer/creator.rb
Normal file
85
app/models/transfer/creator.rb
Normal file
|
@ -0,0 +1,85 @@
|
|||
class Transfer::Creator
|
||||
def initialize(family:, source_account_id:, destination_account_id:, date:, amount:)
|
||||
@family = family
|
||||
@source_account = family.accounts.find(source_account_id) # early throw if not found
|
||||
@destination_account = family.accounts.find(destination_account_id) # early throw if not found
|
||||
@date = date
|
||||
@amount = amount.to_d
|
||||
end
|
||||
|
||||
def create
|
||||
transfer = Transfer.new(
|
||||
inflow_transaction: inflow_transaction,
|
||||
outflow_transaction: outflow_transaction,
|
||||
status: "confirmed"
|
||||
)
|
||||
|
||||
if transfer.save
|
||||
source_account.sync_later
|
||||
destination_account.sync_later
|
||||
end
|
||||
|
||||
transfer
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :family, :source_account, :destination_account, :date, :amount
|
||||
|
||||
def outflow_transaction
|
||||
name = "#{name_prefix} to #{destination_account.name}"
|
||||
|
||||
Transaction.new(
|
||||
kind: outflow_transaction_kind,
|
||||
entry: source_account.entries.build(
|
||||
amount: amount.abs,
|
||||
currency: source_account.currency,
|
||||
date: date,
|
||||
name: name,
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def inflow_transaction
|
||||
name = "#{name_prefix} from #{source_account.name}"
|
||||
|
||||
Transaction.new(
|
||||
kind: "funds_movement",
|
||||
entry: destination_account.entries.build(
|
||||
amount: inflow_converted_money.amount.abs * -1,
|
||||
currency: destination_account.currency,
|
||||
date: date,
|
||||
name: name,
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
# If destination account has different currency, its transaction should show up as converted
|
||||
# Future improvement: instead of a 1:1 conversion fallback, add a UI/UX flow for missing rates
|
||||
def inflow_converted_money
|
||||
Money.new(amount.abs, source_account.currency)
|
||||
.exchange_to(
|
||||
destination_account.currency,
|
||||
date: date,
|
||||
fallback_rate: 1.0
|
||||
)
|
||||
end
|
||||
|
||||
# The "expense" side of a transfer is treated different in analytics based on where it goes.
|
||||
def outflow_transaction_kind
|
||||
if destination_account.loan?
|
||||
"loan_payment"
|
||||
elsif destination_account.liability?
|
||||
"cc_payment"
|
||||
else
|
||||
"funds_movement"
|
||||
end
|
||||
end
|
||||
|
||||
def name_prefix
|
||||
if destination_account.liability?
|
||||
"Payment"
|
||||
else
|
||||
"Transfer"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue