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

fix(sync): Fixing various sync issues

- Fixing credit card charges being considered income
- Fixing family syncs not re-syncing SimpleFIN accounts
- Fixing considerations for "credit card" account types
This commit is contained in:
Cameron Roudebush 2025-05-17 12:12:03 -04:00
parent bf4ee058ec
commit a4bbc22b4c
3 changed files with 35 additions and 26 deletions

View file

@ -75,6 +75,11 @@ class Family < ApplicationRecord
account.sync_later(start_date: start_date, parent_sync: sync)
end
Rails.logger.info("Syncing simple_fin items for family #{id}")
simple_fin_items.each do |simple_fin_item|
simple_fin_item.sync_later(start_date: start_date, parent_sync: sync)
end
Rails.logger.info("Applying rules for family #{id}")
rules.each do |rule|
rule.apply_later

View file

@ -89,7 +89,7 @@ class Provider::SimpleFin
# @param [Boolean] trans_pending If we should include pending transactions. Default is false as I don't think maybe supports pending.
def get_available_accounts(accountable_type, trans_start_date = nil, trans_end_date = nil, trans_pending = false)
check_rate_limit
endpoint = "/accounts?pending=#{trans_pending}"
endpoint = "/accounts"
if trans_end_date == nil
trans_end_date = Time.now.to_i
@ -100,6 +100,11 @@ class Provider::SimpleFin
end
# Add any parameters we care about
if trans_pending
endpoint += "?pending=1"
else
endpoint += "?"
end
if trans_start_date
endpoint += "&start-date=#{trans_start_date}"
end
@ -107,20 +112,10 @@ class Provider::SimpleFin
endpoint += "&end-date=#{trans_end_date}"
end
# request_content = send_request_to_sf(endpoint)
# # TODO: Remove JSON Reading for real requests. Disabled currently due to preventing rate limits.
json_file_path = Rails.root.join("sample.simple.fin.json")
accounts = []
error_messages = []
if File.exist?(json_file_path)
request_content = File.read(json_file_path)
else
Rails.logger.warn "SimpleFIN: Sample JSON file not found at #{json_file_path}. Returning empty accounts."
end
response = send_request_to_sf(endpoint)
# Parse our content
parsed_json = JSON.parse(request_content)
accounts = parsed_json["accounts"] || []
error_messages = parsed_json["errors"] || []
accounts = response["accounts"] || []
error_messages = response["errors"] || []
# The only way we can really determine types right now is by some properties. Try and set their types
@ -128,7 +123,7 @@ class Provider::SimpleFin
# Accounts can be considered Investment accounts if they have any holdings associated to them
if account.key?("holdings") && account["holdings"].is_a?(Array) && !account["holdings"].empty?
account["type"] = "Investment"
elsif account["balance"].to_d <= 0 && account["name"]&.downcase&.include?("card")
elsif account["balance"].to_d <= 0 && (account["name"]&.downcase&.include?("card") || account["name"]&.downcase&.include?("signature"))
account["type"] = "CreditCard"
elsif account["balance"].to_d.negative? # Could be loan or credit card
account["type"] = "Loan" # Default for negative balance if not clearly a card

View file

@ -19,21 +19,24 @@ class SimpleFinAccount < ApplicationRecord
class << self
# Gets what balance we should use as our account balance
def get_adjusted_balance(sf_account_data)
balance_from_sf = sf_account_data["balance"].to_d
account_type = sf_account_data["type"]
##
# In most instances, SimpleFIN returns either negative or positive values based on the account type. So credit would be negative, cash would be positive.
# This is however an issue for this application as it tries to handle that for you. This function is intended just to invert the type, based on the account type.
def get_adjusted_number(sf_num, acc_type)
# Adjust balance: liabilities (CreditCard, Loan) should be negative
if [ "CreditCard", "Loan" ].include?(account_type)
balance_from_sf * -1
if [ "CreditCard", "Loan" ].include?(acc_type)
sf_num * -1
else
balance_from_sf
sf_num
end
end
def find_or_create_from_simple_fin_data!(sf_account_data, sfc)
sfc.simple_fin_accounts.find_or_create_by!(external_id: sf_account_data["id"]) do |sfa|
balance = get_adjusted_balance(sf_account_data)
balance_from_sf = sf_account_data["balance"].to_d
account_type = sf_account_data["type"]
balance = get_adjusted_number(balance_from_sf, account_type)
sfa.current_balance = balance
sfa.available_balance = sf_account_data["available-balance"]&.to_d
sfa.currency = sf_account_data["currency"]
@ -93,8 +96,9 @@ class SimpleFinAccount < ApplicationRecord
##
# Syncs all account data for the given sf_account_data parameter
def sync_account_data!(sf_account_data)
balance = SimpleFinAccount.get_adjusted_balance(sf_account_data)
puts "SFA #{sf_account_data} #{self.account.inspect}"
balance_from_sf = sf_account_data["balance"].to_d
account_type = sf_account_data["type"]
balance = SimpleFinAccount.get_adjusted_number(balance_from_sf, account_type)
self.update!(
current_balance: balance,
available_balance: sf_account_data["available-balance"]&.to_d
@ -166,9 +170,14 @@ class SimpleFinAccount < ApplicationRecord
sf_transactions_data.each do |transaction_data|
entry = self.account.entries.find_or_initialize_by(simple_fin_transaction_id: transaction_data["id"])
amount_from_sf = transaction_data["amount"].to_d
account_type = self.account.accountable_type
amount = SimpleFinAccount.get_adjusted_number(amount_from_sf, account_type)
puts "AMOUNT #{amount} #{amount_from_sf} #{transaction_data}"
entry.assign_attributes(
name: transaction_data["description"],
amount: transaction_data["amount"].to_d,
amount: amount,
currency: self.account.currency,
date: Time.at(transaction_data["posted"].to_i).to_date,
source: "simple_fin"