mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 22:34:47 +00:00
90 lines
3.0 KiB
Ruby
90 lines
3.0 KiB
Ruby
class LunchflowAccount::Processor
|
|
include CurrencyNormalizable
|
|
|
|
attr_reader :lunchflow_account
|
|
|
|
def initialize(lunchflow_account)
|
|
@lunchflow_account = lunchflow_account
|
|
end
|
|
|
|
def process
|
|
unless lunchflow_account.current_account.present?
|
|
Rails.logger.info "LunchflowAccount::Processor - No linked account for lunchflow_account #{lunchflow_account.id}, skipping processing"
|
|
return
|
|
end
|
|
|
|
Rails.logger.info "LunchflowAccount::Processor - Processing lunchflow_account #{lunchflow_account.id} (account #{lunchflow_account.account_id})"
|
|
|
|
begin
|
|
process_account!
|
|
rescue StandardError => e
|
|
Rails.logger.error "LunchflowAccount::Processor - Failed to process account #{lunchflow_account.id}: #{e.message}"
|
|
Rails.logger.error "Backtrace: #{e.backtrace.join("\n")}"
|
|
report_exception(e, "account")
|
|
raise
|
|
end
|
|
|
|
process_transactions
|
|
process_investments
|
|
end
|
|
|
|
private
|
|
|
|
def process_account!
|
|
if lunchflow_account.current_account.blank?
|
|
Rails.logger.error("Lunchflow account #{lunchflow_account.id} has no associated Account")
|
|
return
|
|
end
|
|
|
|
# Update account balance from latest Lunchflow data
|
|
account = lunchflow_account.current_account
|
|
balance = lunchflow_account.current_balance || 0
|
|
|
|
# LunchFlow balance convention matches our app convention:
|
|
# - Positive balance = debt (you owe money)
|
|
# - Negative balance = credit balance (bank owes you, e.g., overpayment)
|
|
# No sign conversion needed - pass through as-is (same as Plaid)
|
|
#
|
|
# Exception: CreditCard and Loan accounts return inverted signs
|
|
# Provider returns negative for positive balance, so we negate it
|
|
if account.accountable_type == "CreditCard" || account.accountable_type == "Loan"
|
|
balance = -balance
|
|
end
|
|
|
|
# Normalize currency with fallback chain: parsed lunchflow currency -> existing account currency -> USD
|
|
currency = parse_currency(lunchflow_account.currency) || account.currency || "USD"
|
|
|
|
# Update account balance
|
|
account.update!(
|
|
balance: balance,
|
|
cash_balance: balance,
|
|
currency: currency
|
|
)
|
|
end
|
|
|
|
def process_transactions
|
|
LunchflowAccount::Transactions::Processor.new(lunchflow_account).process
|
|
rescue => e
|
|
report_exception(e, "transactions")
|
|
end
|
|
|
|
def process_investments
|
|
# Only process holdings for investment/crypto accounts with holdings support
|
|
return unless lunchflow_account.holdings_supported?
|
|
return unless [ "Investment", "Crypto" ].include?(lunchflow_account.current_account&.accountable_type)
|
|
|
|
LunchflowAccount::Investments::HoldingsProcessor.new(lunchflow_account).process
|
|
rescue => e
|
|
report_exception(e, "holdings")
|
|
end
|
|
|
|
def report_exception(error, context)
|
|
Sentry.capture_exception(error) do |scope|
|
|
scope.set_tags(
|
|
lunchflow_account_id: lunchflow_account.id,
|
|
context: context
|
|
)
|
|
end
|
|
end
|
|
end
|