From 11f82b6a77668d39178e5e2fdc049d9d67404dfc Mon Sep 17 00:00:00 2001 From: Ivan Novosad Date: Thu, 7 Nov 2024 09:47:25 +0100 Subject: [PATCH] feat(salesforce): Add integration models --- app/models/integrations/base_integration.rb | 2 ++ .../integrations/salesforce_integration.rb | 34 +++++++++++++++++++ app/models/organization.rb | 5 ++- spec/factories/integrations.rb | 11 ++++++ .../integrations/base_integration_spec.rb | 6 ++++ .../salesforce_integration_spec.rb | 30 ++++++++++++++++ spec/models/organization_spec.rb | 1 + 7 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 app/models/integrations/salesforce_integration.rb create mode 100644 spec/models/integrations/salesforce_integration_spec.rb diff --git a/app/models/integrations/base_integration.rb b/app/models/integrations/base_integration.rb index c6067282178..0afe05b16c2 100644 --- a/app/models/integrations/base_integration.rb +++ b/app/models/integrations/base_integration.rb @@ -40,6 +40,8 @@ def self.integration_type(type) 'Integrations::XeroIntegration' when 'hubspot' 'Integrations::HubspotIntegration' + when 'salesforce' + 'Integrations::SalesforceIntegration' else raise(NotImplementedError) end diff --git a/app/models/integrations/salesforce_integration.rb b/app/models/integrations/salesforce_integration.rb new file mode 100644 index 00000000000..6b04fe8453f --- /dev/null +++ b/app/models/integrations/salesforce_integration.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Integrations + class SalesforceIntegration < BaseIntegration + validates :instance_id, presence: true + validates :code, inclusion: {in: %w[salesforce]} + + settings_accessors :instance_id + end +end + +# == Schema Information +# +# Table name: integrations +# +# id :uuid not null, primary key +# code :string not null +# name :string not null +# secrets :string +# settings :jsonb not null +# type :string not null +# created_at :datetime not null +# updated_at :datetime not null +# organization_id :uuid not null +# +# Indexes +# +# index_integrations_on_code_and_organization_id (code,organization_id) UNIQUE +# index_integrations_on_organization_id (organization_id) +# +# Foreign Keys +# +# fk_rails_... (organization_id => organizations.id) +# diff --git a/app/models/organization.rb b/app/models/organization.rb index 1dc39c32279..9d709fe80e9 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -46,6 +46,7 @@ class Organization < ApplicationRecord has_many :hubspot_integrations, class_name: "Integrations::HubspotIntegration" has_many :netsuite_integrations, class_name: "Integrations::NetsuiteIntegration" has_many :xero_integrations, class_name: "Integrations::XeroIntegration" + has_one :salesforce_integration, class_name: "Integrations::SalesforceIntegration" has_one :applied_dunning_campaign, -> { where(applied_to_organization: true) }, class_name: "DunningCampaign" @@ -58,7 +59,9 @@ class Organization < ApplicationRecord :per_organization ].freeze - INTEGRATIONS = %w[netsuite okta anrok xero progressive_billing hubspot auto_dunning revenue_analytics].freeze + INTEGRATIONS = %w[ + netsuite okta anrok xero progressive_billing hubspot auto_dunning revenue_analytics salesforce + ].freeze PREMIUM_INTEGRATIONS = INTEGRATIONS - %w[anrok] enum document_numbering: DOCUMENT_NUMBERINGS diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index 13d3833ed0e..6c896cce495 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -77,4 +77,15 @@ {connection_id: SecureRandom.uuid}.to_json end end + + factory :salesforce_integration, class: 'Integrations::SalesforceIntegration' do + organization + type { 'Integrations::SalesforceIntegration' } + code { 'salesforce' } + name { 'Salesforce Integration' } + + settings do + {instance_id: SecureRandom.uuid} + end + end end diff --git a/spec/models/integrations/base_integration_spec.rb b/spec/models/integrations/base_integration_spec.rb index a894a5608d5..b901a4e6f7a 100644 --- a/spec/models/integrations/base_integration_spec.rb +++ b/spec/models/integrations/base_integration_spec.rb @@ -95,6 +95,12 @@ end end + context 'when type is salesforce' do + it 'returns the correct class name' do + expect(described_class.integration_type('salesforce')).to eq('Integrations::SalesforceIntegration') + end + end + context 'when type is unknown' do it 'raises a NotImplementedError' do expect { described_class.integration_type('unknown') }.to raise_error(NotImplementedError) diff --git a/spec/models/integrations/salesforce_integration_spec.rb b/spec/models/integrations/salesforce_integration_spec.rb new file mode 100644 index 00000000000..eb3a258a2e1 --- /dev/null +++ b/spec/models/integrations/salesforce_integration_spec.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Integrations::SalesforceIntegration, type: :model do + subject(:salesforce_integration) { build(:salesforce_integration) } + + it { is_expected.to validate_presence_of(:name) } + it { is_expected.to validate_presence_of(:instance_id) } + it { is_expected.to validate_inclusion_of(:code).in_array(%w[salesforce]) } + + describe 'validations' do + it 'validates uniqueness of the code' do + expect(salesforce_integration).to validate_uniqueness_of(:code).scoped_to(:organization_id) + end + end + + describe '#instance_id' do + it 'assigns and retrieve a setting' do + salesforce_integration.instance_id = 'instance_id_1' + expect(salesforce_integration.instance_id).to eq('instance_id_1') + end + end + + describe '#code' do + it 'returns salesforce' do + expect(salesforce_integration.code).to eq('salesforce') + end + end +end diff --git a/spec/models/organization_spec.rb b/spec/models/organization_spec.rb index 1cdb63ebb1d..5b82ecbc1ec 100644 --- a/spec/models/organization_spec.rb +++ b/spec/models/organization_spec.rb @@ -22,6 +22,7 @@ it { is_expected.to have_many(:hubspot_integrations) } it { is_expected.to have_many(:netsuite_integrations) } it { is_expected.to have_many(:xero_integrations) } + it { is_expected.to have_one(:salesforce_integration) } it { is_expected.to have_many(:data_exports) } it { is_expected.to have_many(:dunning_campaigns) } it { is_expected.to have_many(:daily_usages) }