mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 13:19:39 +02:00
Handle case sensitive values when creating securities
This commit is contained in:
parent
867318cbc1
commit
d8e058d7c6
4 changed files with 49 additions and 8 deletions
|
@ -106,8 +106,8 @@ class PlaidInvestmentSync
|
|||
|
||||
# Find any matching security
|
||||
security = Security.find_or_create_by!(
|
||||
ticker: plaid_security.ticker_symbol,
|
||||
exchange_operating_mic: operating_mic
|
||||
ticker: plaid_security.ticker_symbol&.upcase,
|
||||
exchange_operating_mic: operating_mic&.upcase
|
||||
)
|
||||
|
||||
[ security, plaid_security ]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class Security < ApplicationRecord
|
||||
include Provided
|
||||
|
||||
before_save :upcase_ticker
|
||||
before_validation :upcase_symbols
|
||||
|
||||
has_many :trades, dependent: :nullify, class_name: "Trade"
|
||||
has_many :prices, dependent: :destroy
|
||||
|
@ -29,8 +29,8 @@ class Security < ApplicationRecord
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
def upcase_ticker
|
||||
def upcase_symbols
|
||||
self.ticker = ticker.upcase
|
||||
self.exchange_operating_mic = exchange_operating_mic.upcase if exchange_operating_mic.present?
|
||||
end
|
||||
end
|
||||
|
|
|
@ -90,7 +90,7 @@ class TradeImport < Import
|
|||
return internal_security if internal_security.present?
|
||||
|
||||
# If security prices provider isn't properly configured or available, create with nil exchange_operating_mic
|
||||
return Security.find_or_create_by!(ticker: ticker, exchange_operating_mic: nil) unless Security.provider.present?
|
||||
return Security.find_or_create_by!(ticker: ticker&.upcase, exchange_operating_mic: nil) unless Security.provider.present?
|
||||
|
||||
# Cache provider responses so that when we're looping through rows and importing,
|
||||
# we only hit our provider for the unique combinations of ticker / exchange_operating_mic
|
||||
|
@ -104,9 +104,9 @@ class TradeImport < Import
|
|||
).first
|
||||
end
|
||||
|
||||
return Security.find_or_create_by!(ticker: ticker, exchange_operating_mic: nil) if provider_security.nil?
|
||||
return Security.find_or_create_by!(ticker: ticker&.upcase, exchange_operating_mic: nil) if provider_security.nil?
|
||||
|
||||
Security.find_or_create_by!(ticker: provider_security[:ticker], exchange_operating_mic: provider_security[:exchange_operating_mic]) do |security|
|
||||
Security.find_or_create_by!(ticker: provider_security[:ticker]&.upcase, exchange_operating_mic: provider_security[:exchange_operating_mic]&.upcase) do |security|
|
||||
security.name = provider_security[:name]
|
||||
security.country_code = provider_security[:country_code]
|
||||
security.logo_url = provider_security[:logo_url]
|
||||
|
|
41
test/models/security_test.rb
Normal file
41
test/models/security_test.rb
Normal file
|
@ -0,0 +1,41 @@
|
|||
require "test_helper"
|
||||
|
||||
class SecurityTest < ActiveSupport::TestCase
|
||||
# Below has 3 example scenarios:
|
||||
# 1. Original ticker
|
||||
# 2. Duplicate ticker on a different exchange (different market price)
|
||||
# 3. "Offline" version of the same ticker (for users not connected to a provider)
|
||||
test "can have duplicate tickers if exchange is different" do
|
||||
original = Security.create!(ticker: "TEST", exchange_operating_mic: "XNAS")
|
||||
duplicate = Security.create!(ticker: "TEST", exchange_operating_mic: "CBOE")
|
||||
offline = Security.create!(ticker: "TEST", exchange_operating_mic: nil)
|
||||
|
||||
assert original.valid?
|
||||
assert duplicate.valid?
|
||||
assert offline.valid?
|
||||
end
|
||||
|
||||
test "cannot have duplicate tickers if exchange is the same" do
|
||||
original = Security.create!(ticker: "TEST", exchange_operating_mic: "XNAS")
|
||||
duplicate = Security.new(ticker: "TEST", exchange_operating_mic: "XNAS")
|
||||
|
||||
assert_not duplicate.valid?
|
||||
assert_equal [ "has already been taken" ], duplicate.errors[:ticker]
|
||||
end
|
||||
|
||||
test "cannot have duplicate tickers if exchange is nil" do
|
||||
original = Security.create!(ticker: "TEST", exchange_operating_mic: nil)
|
||||
duplicate = Security.new(ticker: "TEST", exchange_operating_mic: nil)
|
||||
|
||||
assert_not duplicate.valid?
|
||||
assert_equal [ "has already been taken" ], duplicate.errors[:ticker]
|
||||
end
|
||||
|
||||
test "casing is ignored when checking for duplicates" do
|
||||
original = Security.create!(ticker: "TEST", exchange_operating_mic: "XNAS")
|
||||
duplicate = Security.new(ticker: "tEst", exchange_operating_mic: "xNaS")
|
||||
|
||||
assert_not duplicate.valid?
|
||||
assert_equal [ "has already been taken" ], duplicate.errors[:ticker]
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue