mirror of
https://github.com/we-promise/sure.git
synced 2026-04-18 11:34:13 +00:00
* feat: Add Brand Fetch logo link for logos * docs: brand fetch integration docs * Document CLIENT_ID location? Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Signed-off-by: Juan José Mata <jjmata@jjmata.com> --------- Signed-off-by: Juan José Mata <jjmata@jjmata.com> Co-authored-by: Vincent Teo <vinteo@gmail.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
This commit is contained in:
@@ -19,6 +19,10 @@ class Settings::HostingsController < ApplicationController
|
||||
Setting.require_email_confirmation = hosting_params[:require_email_confirmation]
|
||||
end
|
||||
|
||||
if hosting_params.key?(:brand_fetch_client_id)
|
||||
Setting.brand_fetch_client_id = hosting_params[:brand_fetch_client_id]
|
||||
end
|
||||
|
||||
if hosting_params.key?(:twelve_data_api_key)
|
||||
Setting.twelve_data_api_key = hosting_params[:twelve_data_api_key]
|
||||
end
|
||||
@@ -36,7 +40,7 @@ class Settings::HostingsController < ApplicationController
|
||||
|
||||
private
|
||||
def hosting_params
|
||||
params.require(:setting).permit(:require_invite_for_signup, :require_email_confirmation, :twelve_data_api_key)
|
||||
params.require(:setting).permit(:require_invite_for_signup, :require_email_confirmation, :brand_fetch_client_id, :twelve_data_api_key)
|
||||
end
|
||||
|
||||
def ensure_admin
|
||||
|
||||
@@ -31,12 +31,14 @@ class Family::AutoMerchantDetector
|
||||
|
||||
merchant_id = user_merchants_input.find { |m| m[:name] == auto_detection&.business_name }&.dig(:id)
|
||||
|
||||
if merchant_id.nil? && auto_detection&.business_url.present? && auto_detection&.business_name.present?
|
||||
if merchant_id.nil? && auto_detection&.business_url.present? && auto_detection&.business_name.present? && Setting.brand_fetch_client_id.present?
|
||||
ai_provider_merchant = ProviderMerchant.find_or_create_by!(
|
||||
source: "ai",
|
||||
name: auto_detection.business_name,
|
||||
website_url: auto_detection.business_url,
|
||||
)
|
||||
) do |pm|
|
||||
pm.logo_url = "#{default_logo_provider_url}/#{auto_detection.business_url}/icon/fallback/lettermark/w/40/h/40?c=#{Setting.brand_fetch_client_id}"
|
||||
end
|
||||
end
|
||||
|
||||
merchant_id = merchant_id || ai_provider_merchant&.id
|
||||
@@ -63,6 +65,9 @@ class Family::AutoMerchantDetector
|
||||
Provider::Registry.get_provider(:openai)
|
||||
end
|
||||
|
||||
def default_logo_provider_url
|
||||
"https://cdn.brandfetch.io"
|
||||
end
|
||||
|
||||
def user_merchants_input
|
||||
family.merchants.map do |merchant|
|
||||
|
||||
@@ -4,6 +4,7 @@ class Setting < RailsSettings::Base
|
||||
|
||||
field :twelve_data_api_key, type: :string, default: ENV["TWELVE_DATA_API_KEY"]
|
||||
field :openai_access_token, type: :string, default: ENV["OPENAI_ACCESS_TOKEN"]
|
||||
field :brand_fetch_client_id, type: :string, default: ENV["BRAND_FETCH_CLIENT_ID"]
|
||||
|
||||
field :require_invite_for_signup, type: :boolean, default: false
|
||||
field :require_email_confirmation, type: :boolean, default: ENV.fetch("REQUIRE_EMAIL_CONFIRMATION", "true") == "true"
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
"full" => "w-full h-full"
|
||||
} %>
|
||||
|
||||
<% if account.logo.attached? %>
|
||||
<% if account.plaid_account_id? && account.institution_domain.present? && Setting.brand_fetch_client_id.present? %>
|
||||
<%= image_tag "https://cdn.brandfetch.io/#{account.institution_domain}/icon/fallback/lettermark/w/40/h/40?c=#{Setting.brand_fetch_client_id}", class: "shrink-0 rounded-full #{size_classes[size]}" %>
|
||||
<% elsif account.logo.attached? %>
|
||||
<%= image_tag account.logo, class: "shrink-0 rounded-full #{size_classes[size]}" %>
|
||||
<% else %>
|
||||
<%= render DS::FilledIcon.new(variant: :text, hex_color: color || account.accountable.color, text: account.name, size: size, rounded: true) %>
|
||||
|
||||
@@ -3,10 +3,13 @@
|
||||
<%= turbo_frame_tag dom_id(holding) do %>
|
||||
<div class="grid grid-cols-12 items-center text-primary text-sm font-medium p-4">
|
||||
<div class="col-span-4 flex items-center gap-4">
|
||||
<% if holding.security.logo_url.present? %>
|
||||
<% if Setting.brand_fetch_client_id.present? %>
|
||||
<%= image_tag "https://cdn.brandfetch.io/#{holding.ticker}/icon/fallback/lettermark/w/40/h/40?c=#{Setting.brand_fetch_client_id}", class: "w-9 h-9 rounded-full", loading: "lazy" %>
|
||||
<% elsif holding.security.logo_url.present? %>
|
||||
<%= image_tag holding.security.logo_url, class: "w-9 h-9 rounded-full", loading: "lazy" %>
|
||||
<% else %>
|
||||
<%= render DS::FilledIcon.new(variant: :text, text: holding.name, size: "md", rounded: true) %>
|
||||
<% end %>
|
||||
|
||||
<div class="space-y-0.5">
|
||||
<%= link_to holding.name, holding_path(holding), data: { turbo_frame: :drawer }, class: "hover:underline" %>
|
||||
|
||||
|
||||
@@ -6,8 +6,12 @@
|
||||
<%= tag.p @holding.ticker, class: "text-sm text-secondary" %>
|
||||
</div>
|
||||
|
||||
<% if @holding.security.logo_url.present? %>
|
||||
<% if Setting.brand_fetch_client_id.present? %>
|
||||
<%= image_tag "https://cdn.brandfetch.io/#{@holding.ticker}/icon/fallback/lettermark/w/40/h/40?c=#{Setting.brand_fetch_client_id}", loading: "lazy", class: "w-9 h-9 rounded-full" %>
|
||||
<% elsif @holding.security.logo_url.present? %>
|
||||
<%= image_tag @holding.security.logo_url, loading: "lazy", class: "w-9 h-9 rounded-full" %>
|
||||
<% else %>
|
||||
<%= render DS::FilledIcon.new(variant: :text, text: @holding.name, size: "md", rounded: true) %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
26
app/views/settings/hostings/_brand_fetch_settings.html.erb
Normal file
26
app/views/settings/hostings/_brand_fetch_settings.html.erb
Normal file
@@ -0,0 +1,26 @@
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<h2 class="font-medium mb-1"><%= t(".title") %></h2>
|
||||
<% if ENV["BRAND_FETCH_CLIENT_ID"].present? %>
|
||||
<p class="text-sm text-secondary">You have successfully configured your Brand Fetch Client ID through the BRAND_FETCH_CLIENT_ID environment variable.</p>
|
||||
<% else %>
|
||||
<p class="text-secondary text-sm mb-4"><%= t(".description") %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= styled_form_with model: Setting.new,
|
||||
url: settings_hosting_path,
|
||||
method: :patch,
|
||||
data: {
|
||||
controller: "auto-submit-form",
|
||||
"auto-submit-form-trigger-event-value": "blur"
|
||||
} do |form| %>
|
||||
<%= form.text_field :brand_fetch_client_id,
|
||||
label: t(".label"),
|
||||
type: "password",
|
||||
placeholder: t(".placeholder"),
|
||||
value: ENV.fetch("BRAND_FETCH_CLIENT_ID", Setting.brand_fetch_client_id),
|
||||
disabled: ENV["BRAND_FETCH_CLIENT_ID"].present?,
|
||||
data: { "auto-submit-form-target": "auto" } %>
|
||||
<% end %>
|
||||
</div>
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<%= settings_section title: t(".general") do %>
|
||||
<div class="space-y-6">
|
||||
<%= render "settings/hostings/brand_fetch_settings" %>
|
||||
<%= render "settings/hostings/twelve_data_settings" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -21,6 +21,11 @@ en:
|
||||
confirm_clear_cache:
|
||||
title: Clear data cache?
|
||||
body: Are you sure you want to clear the data cache? This will remove all exchange rates, security prices, account balances, and other data. This action cannot be undone.
|
||||
brand_fetch_settings:
|
||||
description: Input the Client ID provided by Brand Fetch
|
||||
label: Client ID
|
||||
placeholder: Enter your Client ID here
|
||||
title: Brand Fetch Settings
|
||||
twelve_data_settings:
|
||||
api_calls_used: "%{used} / %{limit} API daily calls used (%{percentage})"
|
||||
description: Input the API key provided by Twelve Data
|
||||
|
||||
BIN
docs/hosting/logos-clientid.png
Normal file
BIN
docs/hosting/logos-clientid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 117 KiB |
20
docs/hosting/logos.md
Normal file
20
docs/hosting/logos.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Account, Merchant and Security Logos
|
||||
|
||||
Sure has integration with the [Brand Fetch Logo Link](https://brandfetch.com/developers/logo-api) service to provide logos for accounts, merchants and securities.
|
||||
Logos are currently matched in the following ways:
|
||||
|
||||
- For accounts, Plaid integration for the account is required and matched via FQDN (fully qualified domain name) from the Plaid integration
|
||||
- For merchants, OpenAI integration is required and automatically matched to the merchant name and matched via FQDN
|
||||
- For securities, logos are matched using the ticker symbol
|
||||
|
||||
> [!NOTE]
|
||||
> Currently ticker symbol matching cannot specify the exchange and since US exchanges are prioritized, securities from other exchanges might not have the right logo.
|
||||
|
||||
## Enabling Brand Fetch Integration
|
||||
|
||||
A Brand Fetch Client ID is required and to obtain a client ID, sign up for an account [here](https://brandfetch.com/developers/logo-api).
|
||||
|
||||
Once you enter the Client ID into the Sure settings under the `Self hosting` section, logos from Brand Fetch integration will be enabled.
|
||||
Alternatively, you can provide the client id using the `BRAND_FETCH_CLIENT_ID` environment variable to the web and worker services.
|
||||
|
||||

|
||||
@@ -8,6 +8,7 @@ class Family::AutoMerchantDetectorTest < ActiveSupport::TestCase
|
||||
@account = @family.accounts.create!(name: "Rule test", balance: 100, currency: "USD", accountable: Depository.new)
|
||||
@llm_provider = mock
|
||||
Provider::Registry.stubs(:get_provider).with(:openai).returns(@llm_provider)
|
||||
Setting.stubs(:brand_fetch_client_id).returns("123")
|
||||
end
|
||||
|
||||
test "auto detects transaction merchants" do
|
||||
@@ -29,8 +30,8 @@ class Family::AutoMerchantDetectorTest < ActiveSupport::TestCase
|
||||
|
||||
assert_equal "McDonalds", txn1.reload.merchant.name
|
||||
assert_equal "Chipotle", txn2.reload.merchant.name
|
||||
assert_nil txn1.reload.merchant.logo_url
|
||||
assert_nil txn2.reload.merchant.logo_url
|
||||
assert_equal "https://cdn.brandfetch.io/mcdonalds.com/icon/fallback/lettermark/w/40/h/40?c=123", txn1.reload.merchant.logo_url
|
||||
assert_equal "https://cdn.brandfetch.io/chipotle.com/icon/fallback/lettermark/w/40/h/40?c=123", txn2.reload.merchant.logo_url
|
||||
assert_nil txn3.reload.merchant
|
||||
|
||||
# After auto-detection, all transactions are locked and no longer enrichable
|
||||
|
||||
Reference in New Issue
Block a user