diff --git a/app/models/family.rb b/app/models/family.rb index bb88495a..68487f40 100644 --- a/app/models/family.rb +++ b/app/models/family.rb @@ -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 diff --git a/app/models/provider/simple_fin.rb b/app/models/provider/simple_fin.rb index 749ec4f4..25f56b21 100644 --- a/app/models/provider/simple_fin.rb +++ b/app/models/provider/simple_fin.rb @@ -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 diff --git a/app/models/simple_fin_account.rb b/app/models/simple_fin_account.rb index 732589d8..3368f7cc 100644 --- a/app/models/simple_fin_account.rb +++ b/app/models/simple_fin_account.rb @@ -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"