mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-08 06:55:21 +02:00
Checkpoint
This commit is contained in:
parent
3bd7baf2f5
commit
31eafbf578
7 changed files with 162 additions and 0 deletions
16
app/models/plaid_account/credit_liability_processor.rb
Normal file
16
app/models/plaid_account/credit_liability_processor.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
class PlaidAccount::CreditLiabilityProcessor
|
||||
def initialize(plaid_account)
|
||||
@plaid_account = plaid_account
|
||||
end
|
||||
|
||||
def process
|
||||
puts "processing credit liability!"
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :plaid_account
|
||||
|
||||
def account
|
||||
plaid_account.account
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
# Plaid Investment balances have a ton of edge cases. This processor is responsible
|
||||
# for deriving "brokerage cash" vs. "total value" based on Plaid's reported balances and holdings.
|
||||
class PlaidAccount::InvestmentBalanceProcessor
|
||||
include PlaidAccount::Securitizable
|
||||
|
||||
attr_reader :plaid_account
|
||||
|
||||
def initialize(plaid_account)
|
||||
|
|
18
app/models/plaid_account/investment_holdings_processor.rb
Normal file
18
app/models/plaid_account/investment_holdings_processor.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
class PlaidAccount::InvestmentHoldingsProcessor
|
||||
include PlaidAccount::Securitizable
|
||||
|
||||
def initialize(plaid_account)
|
||||
@plaid_account = plaid_account
|
||||
end
|
||||
|
||||
def process
|
||||
puts "processing investment holdings!"
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :plaid_account
|
||||
|
||||
def account
|
||||
plaid_account.account
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class PlaidAccount::InvestmentTransactionsProcessor
|
||||
include PlaidAccount::Securitizable
|
||||
|
||||
def initialize(plaid_account)
|
||||
@plaid_account = plaid_account
|
||||
end
|
||||
|
||||
def process
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :plaid_account
|
||||
|
||||
def account
|
||||
plaid_account.account
|
||||
end
|
||||
end
|
39
app/models/plaid_account/securitizable.rb
Normal file
39
app/models/plaid_account/securitizable.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
module PlaidAccount::Securitizable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# TODO
|
||||
def get_security(plaid_security_id)
|
||||
plaid_security = get_plaid_security(plaid_security_id)
|
||||
|
||||
|
||||
|
||||
return [ nil, nil ] if plaid_security.nil? || plaid_security["ticker_symbol"].blank?
|
||||
return [ nil, plaid_security ] if plaid_security["ticker_symbol"] == "CUR:USD" # internally, we do not consider cash a security and track it separately
|
||||
|
||||
operating_mic = plaid_security["market_identifier_code"]
|
||||
|
||||
# Find any matching security
|
||||
security = Security.find_or_create_by!(
|
||||
ticker: plaid_security["ticker_symbol"]&.upcase,
|
||||
exchange_operating_mic: operating_mic&.upcase
|
||||
)
|
||||
|
||||
[ security, plaid_security ]
|
||||
end
|
||||
|
||||
|
||||
|
||||
private
|
||||
def securities
|
||||
@securities ||= plaid_account.raw_investments_payload["securities"] || []
|
||||
end
|
||||
|
||||
# These are the tickers that Plaid considers a "security", but we do not (mostly cash-like tickers)
|
||||
#
|
||||
# For example, "CUR:USD" is what Plaid uses for the "Cash Holding" and represents brokerage cash sitting
|
||||
# in the brokerage account. Internally, we treat brokerage cash as a separate concept. It is NOT a holding
|
||||
# in the Maybe app (although in the UI, we show it next to other holdings).
|
||||
def ignored_plaid_security_tickers
|
||||
[ "CUR:USD" ]
|
||||
end
|
||||
end
|
22
app/models/plaid_account/security_processor.rb
Normal file
22
app/models/plaid_account/security_processor.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Resolves a Plaid security to an internal Security record, or nil
|
||||
class PlaidAccount::SecurityProcessor
|
||||
def initialize(plaid_security_id, plaid_securities)
|
||||
@plaid_security_id = plaid_security_id
|
||||
@plaid_securities = plaid_securities
|
||||
end
|
||||
|
||||
def process
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :plaid_security_id, :plaid_securities
|
||||
|
||||
# Tries to find security, or returns the "proxy security" (common with options contracts that have underlying securities)
|
||||
def plaid_security
|
||||
security = securities.find { |s| s["security_id"] == plaid_security_id && s["ticker_symbol"].present? }
|
||||
|
||||
return security if security.present?
|
||||
|
||||
securities.find { |s| s["proxy_security_id"] == plaid_security_id }
|
||||
end
|
||||
end
|
48
app/models/security/resolver.rb
Normal file
48
app/models/security/resolver.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
class Security::Resolver
|
||||
def initialize(symbol, exchange_operating_mic: nil, country_code: nil)
|
||||
@symbol = symbol
|
||||
@exchange_operating_mic = exchange_operating_mic
|
||||
@country_code = country_code
|
||||
end
|
||||
|
||||
def resolve
|
||||
return nil unless symbol
|
||||
|
||||
exact_match = Security.find_by(
|
||||
ticker: symbol,
|
||||
exchange_operating_mic: exchange_operating_mic
|
||||
)
|
||||
|
||||
exact_match if exact_match.present?
|
||||
end
|
||||
|
||||
private
|
||||
attr_reader :symbol, :exchange_operating_mic, :country_code
|
||||
|
||||
def fetch_from_provider
|
||||
return nil unless Security.provider.present?
|
||||
|
||||
result = Security.search_provider(
|
||||
symbol,
|
||||
exchange_operating_mic: exchange_operating_mic
|
||||
)
|
||||
|
||||
return nil unless result.success?
|
||||
|
||||
selection = if exchange_operating_mic.present?
|
||||
result.data.find do |s|
|
||||
s.ticker == symbol && s.exchange_operating_mic == exchange_operating_mic
|
||||
end
|
||||
else
|
||||
result.data.sort_by
|
||||
end
|
||||
|
||||
unless selection.present?
|
||||
|
||||
end
|
||||
|
||||
selection
|
||||
end
|
||||
|
||||
def
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue