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

Allow offline trade tickers (#1925)

This commit is contained in:
Zach Gollwitzer 2025-02-28 09:34:14 -05:00 committed by GitHub
parent 882857fcf0
commit 9138bd2b76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 21 additions and 6 deletions

View file

@ -10,7 +10,7 @@ class Account::TradesController < ApplicationController
def create_entry_params def create_entry_params
params.require(:account_entry).permit( params.require(:account_entry).permit(
:account_id, :date, :amount, :currency, :qty, :price, :ticker, :type, :transfer_account_id :account_id, :date, :amount, :currency, :qty, :price, :ticker, :manual_ticker, :type, :transfer_account_id
).tap do |params| ).tap do |params|
account_id = params.delete(:account_id) account_id = params.delete(:account_id)
params[:account] = Current.family.accounts.find(account_id) params[:account] = Current.family.accounts.find(account_id)

View file

@ -2,7 +2,7 @@ class Account::TradeBuilder
include ActiveModel::Model include ActiveModel::Model
attr_accessor :account, :date, :amount, :currency, :qty, attr_accessor :account, :date, :amount, :currency, :qty,
:price, :ticker, :type, :transfer_account_id :price, :ticker, :manual_ticker, :type, :transfer_account_id
attr_reader :buildable attr_reader :buildable
@ -110,8 +110,9 @@ class Account::TradeBuilder
account.family account.family
end end
# Users can either look up a ticker from our provider (Synth) or enter a manual, "offline" ticker (that we won't fetch prices for)
def security def security
ticker_symbol, exchange_operating_mic = ticker.split("|") ticker_symbol, exchange_operating_mic = ticker.present? ? ticker.split("|") : [ manual_ticker, nil ]
Security.find_or_create_by(ticker: ticker_symbol, exchange_operating_mic: exchange_operating_mic) do |s| Security.find_or_create_by(ticker: ticker_symbol, exchange_operating_mic: exchange_operating_mic) do |s|
FetchSecurityInfoJob.perform_later(s.id) FetchSecurityInfoJob.perform_later(s.id)

View file

@ -1,5 +1,6 @@
class Security < ApplicationRecord class Security < ApplicationRecord
include Providable include Providable
before_save :upcase_ticker before_save :upcase_ticker
has_many :trades, dependent: :nullify, class_name: "Account::Trade" has_many :trades, dependent: :nullify, class_name: "Account::Trade"
@ -9,6 +10,10 @@ class Security < ApplicationRecord
validates :ticker, uniqueness: { scope: :exchange_operating_mic, case_sensitive: false } validates :ticker, uniqueness: { scope: :exchange_operating_mic, case_sensitive: false }
class << self class << self
def provider
security_prices_provider
end
def search(query) def search(query)
security_prices_provider.search_securities( security_prices_provider.search_securities(
query: query[:search], query: query[:search],

View file

@ -27,9 +27,18 @@
}} %> }} %>
<% if %w[buy sell].include?(type) %> <% if %w[buy sell].include?(type) %>
<div class="form-field combobox"> <% if Security.provider.present? %>
<%= form.combobox :ticker, securities_path(country_code: Current.family.country), label: t(".holding"), placeholder: t(".ticker_placeholder"), required: true %> <div class="form-field combobox">
</div> <%= form.combobox :ticker,
securities_path(country_code: Current.family.country),
name_when_new: "account_entry[manual_ticker]",
label: t(".holding"),
placeholder: t(".ticker_placeholder"),
required: true %>
</div>
<% else %>
<%= form.text_field :manual_ticker, label: "Ticker", placeholder: "AAPL", required: true %>
<% end %>
<% end %> <% end %>
<%= form.date_field :date, label: true, value: Date.current, required: true %> <%= form.date_field :date, label: true, value: Date.current, required: true %>