mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 15:59:02 +00:00
* Display multi-currency holdings correctly * Implement IBKR provider * Fix: Use historical exchange rate for historical prices * Add brokerage exchange rate for trades * Sync historical balances from IBKR * Add logos in activity history * Fix privacy mode blur in account view * Improve IBKR XML Flex report parser errors
79 lines
2.0 KiB
Ruby
79 lines
2.0 KiB
Ruby
module IbkrAccount::DataHelpers
|
|
extend ActiveSupport::Concern
|
|
|
|
private
|
|
|
|
def parse_decimal(value)
|
|
return nil if value.nil?
|
|
|
|
normalized = value.is_a?(String) ? value.delete(",").strip : value.to_s
|
|
return nil if normalized.blank? || normalized == "-"
|
|
|
|
BigDecimal(normalized)
|
|
rescue ArgumentError
|
|
nil
|
|
end
|
|
|
|
def parse_date(value)
|
|
return nil if value.blank?
|
|
|
|
case value
|
|
when Date
|
|
value
|
|
when Time, DateTime, ActiveSupport::TimeWithZone
|
|
value.to_date
|
|
else
|
|
normalized = value.to_s.tr(";", " ")
|
|
Time.zone.parse(normalized)&.to_date || Date.parse(normalized)
|
|
end
|
|
rescue ArgumentError, TypeError
|
|
nil
|
|
end
|
|
|
|
def parse_datetime(value)
|
|
return nil if value.blank?
|
|
|
|
case value
|
|
when Time, DateTime, ActiveSupport::TimeWithZone
|
|
value.in_time_zone
|
|
when Date
|
|
value.in_time_zone
|
|
else
|
|
Time.zone.parse(value.to_s.tr(";", " "))
|
|
end
|
|
rescue ArgumentError, TypeError
|
|
nil
|
|
end
|
|
|
|
def resolve_security(row)
|
|
data = row.with_indifferent_access
|
|
ticker = data[:symbol].to_s.strip.upcase
|
|
return nil if ticker.blank?
|
|
|
|
Security.find_by(ticker: ticker) || create_security_from_row(ticker)
|
|
rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique
|
|
Security.find_by(ticker: ticker)
|
|
end
|
|
|
|
def trade_date_for(row)
|
|
data = row.with_indifferent_access
|
|
parsed_trade_date = parse_date(data[:trade_date])
|
|
return parsed_trade_date if parsed_trade_date
|
|
|
|
Rails.logger.warn(
|
|
"IbkrAccount::DataHelpers - Missing or invalid trade_date, falling back to Date.current. " \
|
|
"trade_id=#{data[:trade_id].inspect}"
|
|
)
|
|
Date.current
|
|
end
|
|
|
|
def extract_currency(row, fallback: nil)
|
|
value = row.with_indifferent_access[:currency]
|
|
value.present? ? value.to_s.upcase : fallback
|
|
end
|
|
|
|
def create_security_from_row(ticker)
|
|
Security.create!(ticker: ticker, name: ticker)
|
|
end
|
|
end
|