From d71663abd2c30c245f7b9acd20ed9a174ba170cf Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 11:00:59 +0200 Subject: [PATCH 01/12] add category to integration --- app/graphql/types/integrations/anrok.rb | 1 + app/graphql/types/integrations/netsuite.rb | 1 + app/graphql/types/integrations/okta.rb | 1 + app/graphql/types/integrations/xero.rb | 1 + .../integration_customers/base_customer.rb | 2 +- app/models/integrations/base_integration.rb | 3 + db/schema.rb | 4 +- schema.graphql | 4 ++ schema.json | 56 +++++++++++++++++++ 9 files changed, 71 insertions(+), 2 deletions(-) diff --git a/app/graphql/types/integrations/anrok.rb b/app/graphql/types/integrations/anrok.rb index c6ef0810cff..7203ce97738 100644 --- a/app/graphql/types/integrations/anrok.rb +++ b/app/graphql/types/integrations/anrok.rb @@ -11,6 +11,7 @@ class Anrok < Types::BaseObject field :has_mappings_configured, Boolean field :id, ID, null: false field :name, String, null: false + field :category, String, null: true # NOTE: Client secret is a sensitive information. It should not be sent back to the # front end application. Instead we send an obfuscated value diff --git a/app/graphql/types/integrations/netsuite.rb b/app/graphql/types/integrations/netsuite.rb index 20eb5a42144..96cefce6212 100644 --- a/app/graphql/types/integrations/netsuite.rb +++ b/app/graphql/types/integrations/netsuite.rb @@ -20,6 +20,7 @@ class Netsuite < Types::BaseObject field :sync_sales_orders, Boolean field :token_id, String, null: true field :token_secret, String, null: true + field :category, String, null: true # NOTE: Client secret is a sensitive information. It should not be sent back to the # front end application. Instead we send an obfuscated value diff --git a/app/graphql/types/integrations/okta.rb b/app/graphql/types/integrations/okta.rb index d7b2f102230..57fbb739756 100644 --- a/app/graphql/types/integrations/okta.rb +++ b/app/graphql/types/integrations/okta.rb @@ -12,6 +12,7 @@ class Okta < Types::BaseObject field :id, ID, null: false field :name, String, null: false field :organization_name, String, null: false + field :category, String, null: true # NOTE: Client secret is a sensitive information. It should not be sent back to the # front end application. Instead we send an obfuscated value diff --git a/app/graphql/types/integrations/xero.rb b/app/graphql/types/integrations/xero.rb index 4e6b5e53435..2fd0ece6e65 100644 --- a/app/graphql/types/integrations/xero.rb +++ b/app/graphql/types/integrations/xero.rb @@ -13,6 +13,7 @@ class Xero < Types::BaseObject field :sync_credit_notes, Boolean field :sync_invoices, Boolean field :sync_payments, Boolean + field :category, String, null: true def has_mappings_configured object.integration_collection_mappings.where(type: 'IntegrationCollectionMappings::XeroCollectionMapping').any? diff --git a/app/models/integration_customers/base_customer.rb b/app/models/integration_customers/base_customer.rb index dceaa841fe0..81003dd9e1c 100644 --- a/app/models/integration_customers/base_customer.rb +++ b/app/models/integration_customers/base_customer.rb @@ -13,7 +13,7 @@ class BaseCustomer < ApplicationRecord validates :customer_id, uniqueness: {scope: :type} scope :accounting_kind, -> do - where(type: %w[IntegrationCustomers::NetsuiteCustomer IntegrationCustomers::XeroCustomer]) + includes(:integration).where(integration: { category: 'accounting'}) end settings_accessors :sync_with_provider diff --git a/app/models/integrations/base_integration.rb b/app/models/integrations/base_integration.rb index 5d184003041..0499f72e0ca 100644 --- a/app/models/integrations/base_integration.rb +++ b/app/models/integrations/base_integration.rb @@ -28,6 +28,9 @@ class BaseIntegration < ApplicationRecord validates :code, uniqueness: {scope: :organization_id} validates :name, presence: true + INTEGRATION_CATEGORIES = %w[system accounting tax_provider] + enum category: INTEGRATION_CATEGORIES + def self.integration_type(type) case type when 'netsuite' diff --git a/db/schema.rb b/db/schema.rb index 2fabef2b337..85df747dc3c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_07_23_150221) do +ActiveRecord::Schema[7.1].define(version: 2024_07_24_154417) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -664,6 +664,8 @@ t.jsonb "settings", default: {}, null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "category" + t.index ["category"], name: "index_integrations_on_category" t.index ["code", "organization_id"], name: "index_integrations_on_code_and_organization_id", unique: true t.index ["organization_id"], name: "index_integrations_on_organization_id" end diff --git a/schema.graphql b/schema.graphql index 94e73ff1e82..05c4004217d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -146,6 +146,7 @@ type AnrokFeeObjectCollection { type AnrokIntegration { apiKey: String! + category: String code: String! externalAccountId: String hasMappingsConfigured: Boolean @@ -5100,6 +5101,7 @@ type NetsuiteCustomer { type NetsuiteIntegration { accountId: String + category: String clientId: String clientSecret: String code: String! @@ -5142,6 +5144,7 @@ input OktaAuthorizeInput { } type OktaIntegration { + category: String clientId: String clientSecret: String code: String! @@ -7547,6 +7550,7 @@ type XeroCustomer { } type XeroIntegration { + category: String code: String! connectionId: ID! hasMappingsConfigured: Boolean diff --git a/schema.json b/schema.json index f546ffbdfd0..507704510cf 100644 --- a/schema.json +++ b/schema.json @@ -1262,6 +1262,20 @@ ] }, + { + "name": "category", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, { "name": "code", "description": null, @@ -24014,6 +24028,20 @@ ] }, + { + "name": "category", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, { "name": "clientId", "description": null, @@ -24365,6 +24393,20 @@ ], "possibleTypes": null, "fields": [ + { + "name": "category", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, { "name": "clientId", "description": null, @@ -38246,6 +38288,20 @@ ], "possibleTypes": null, "fields": [ + { + "name": "category", + "description": null, + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, { "name": "code", "description": null, From 5893e435acb8d3e63c66edebece47e750156814f Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 11:05:36 +0200 Subject: [PATCH 02/12] add migration to add category to integrations --- ...0724154417_add_category_to_integrations.rb | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 db/migrate/20240724154417_add_category_to_integrations.rb diff --git a/db/migrate/20240724154417_add_category_to_integrations.rb b/db/migrate/20240724154417_add_category_to_integrations.rb new file mode 100644 index 00000000000..9da65e80a86 --- /dev/null +++ b/db/migrate/20240724154417_add_category_to_integrations.rb @@ -0,0 +1,36 @@ +class AddCategoryToIntegrations < ActiveRecord::Migration[7.1] + module Integrations + class BaseIntegration < ApplicationRecord + self.table_name = 'integrations' + INTEGRATION_CATEGORIES = %w[system accounting tax_provider] + enum category: INTEGRATION_CATEGORIES + end + + class AnrokIntegration < BaseIntegration + end + + class NetsuiteIntegration < BaseIntegration + end + + class XeroIntegration < BaseIntegration + end + + class OktaIntegration < BaseIntegration + end + end + + def up + add_column :integrations, :category, :integer + add_index :integrations, :category + + Integrations::AnrokIntegration.update_all(category: 'tax_provider') + Integrations::NetsuiteIntegration.update_all(category: 'accounting') + Integrations::XeroIntegration.update_all(category: 'accounting') + Integrations::OktaIntegration.update_all(category: 'system') + end + + def down + remove_index :integrations, :category + remove_column :integrations, :category + end +end From 514d121b369dee75279d423fa21f5b663e565ac4 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 11:13:55 +0200 Subject: [PATCH 03/12] fix linter comments --- app/graphql/types/integrations/anrok.rb | 2 +- app/graphql/types/integrations/netsuite.rb | 2 +- app/graphql/types/integrations/okta.rb | 2 +- app/graphql/types/integrations/xero.rb | 2 +- app/models/integration_customers/base_customer.rb | 2 +- .../20240724154417_add_category_to_integrations.rb | 10 ++++++---- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/graphql/types/integrations/anrok.rb b/app/graphql/types/integrations/anrok.rb index 7203ce97738..482882a669f 100644 --- a/app/graphql/types/integrations/anrok.rb +++ b/app/graphql/types/integrations/anrok.rb @@ -6,12 +6,12 @@ class Anrok < Types::BaseObject graphql_name 'AnrokIntegration' field :api_key, String, null: false + field :category, String, null: true field :code, String, null: false field :external_account_id, String, null: true field :has_mappings_configured, Boolean field :id, ID, null: false field :name, String, null: false - field :category, String, null: true # NOTE: Client secret is a sensitive information. It should not be sent back to the # front end application. Instead we send an obfuscated value diff --git a/app/graphql/types/integrations/netsuite.rb b/app/graphql/types/integrations/netsuite.rb index 96cefce6212..c53d3f58e53 100644 --- a/app/graphql/types/integrations/netsuite.rb +++ b/app/graphql/types/integrations/netsuite.rb @@ -6,6 +6,7 @@ class Netsuite < Types::BaseObject graphql_name 'NetsuiteIntegration' field :account_id, String, null: true + field :category, String, null: true field :client_id, String, null: true field :client_secret, String, null: true field :code, String, null: false @@ -20,7 +21,6 @@ class Netsuite < Types::BaseObject field :sync_sales_orders, Boolean field :token_id, String, null: true field :token_secret, String, null: true - field :category, String, null: true # NOTE: Client secret is a sensitive information. It should not be sent back to the # front end application. Instead we send an obfuscated value diff --git a/app/graphql/types/integrations/okta.rb b/app/graphql/types/integrations/okta.rb index 57fbb739756..586a1c6e43f 100644 --- a/app/graphql/types/integrations/okta.rb +++ b/app/graphql/types/integrations/okta.rb @@ -5,6 +5,7 @@ module Integrations class Okta < Types::BaseObject graphql_name 'OktaIntegration' + field :category, String, null: true field :client_id, String, null: true field :client_secret, String, null: true field :code, String, null: false @@ -12,7 +13,6 @@ class Okta < Types::BaseObject field :id, ID, null: false field :name, String, null: false field :organization_name, String, null: false - field :category, String, null: true # NOTE: Client secret is a sensitive information. It should not be sent back to the # front end application. Instead we send an obfuscated value diff --git a/app/graphql/types/integrations/xero.rb b/app/graphql/types/integrations/xero.rb index 2fd0ece6e65..f8e15be88f8 100644 --- a/app/graphql/types/integrations/xero.rb +++ b/app/graphql/types/integrations/xero.rb @@ -5,6 +5,7 @@ module Integrations class Xero < Types::BaseObject graphql_name 'XeroIntegration' + field :category, String, null: true field :code, String, null: false field :connection_id, ID, null: false field :has_mappings_configured, Boolean @@ -13,7 +14,6 @@ class Xero < Types::BaseObject field :sync_credit_notes, Boolean field :sync_invoices, Boolean field :sync_payments, Boolean - field :category, String, null: true def has_mappings_configured object.integration_collection_mappings.where(type: 'IntegrationCollectionMappings::XeroCollectionMapping').any? diff --git a/app/models/integration_customers/base_customer.rb b/app/models/integration_customers/base_customer.rb index 81003dd9e1c..fe999e8e325 100644 --- a/app/models/integration_customers/base_customer.rb +++ b/app/models/integration_customers/base_customer.rb @@ -13,7 +13,7 @@ class BaseCustomer < ApplicationRecord validates :customer_id, uniqueness: {scope: :type} scope :accounting_kind, -> do - includes(:integration).where(integration: { category: 'accounting'}) + includes(:integration).where(integration: {category: 'accounting'}) end settings_accessors :sync_with_provider diff --git a/db/migrate/20240724154417_add_category_to_integrations.rb b/db/migrate/20240724154417_add_category_to_integrations.rb index 9da65e80a86..f9d1ea83f8b 100644 --- a/db/migrate/20240724154417_add_category_to_integrations.rb +++ b/db/migrate/20240724154417_add_category_to_integrations.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + class AddCategoryToIntegrations < ActiveRecord::Migration[7.1] module Integrations class BaseIntegration < ApplicationRecord @@ -23,10 +25,10 @@ def up add_column :integrations, :category, :integer add_index :integrations, :category - Integrations::AnrokIntegration.update_all(category: 'tax_provider') - Integrations::NetsuiteIntegration.update_all(category: 'accounting') - Integrations::XeroIntegration.update_all(category: 'accounting') - Integrations::OktaIntegration.update_all(category: 'system') + Integrations::AnrokIntegration.update_all(category: 'tax_provider') # rubocop:disable Rails/SkipsModelValidations + Integrations::NetsuiteIntegration.update_all(category: 'accounting') # rubocop:disable Rails/SkipsModelValidations + Integrations::XeroIntegration.update_all(category: 'accounting') # rubocop:disable Rails/SkipsModelValidations + Integrations::OktaIntegration.update_all(category: 'system') # rubocop:disable Rails/SkipsModelValidations end def down From 4443ec7a4114930053668de0943dcfeb6a9e1cc5 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 11:42:55 +0200 Subject: [PATCH 04/12] add category to integration factories --- spec/factories/integrations.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index ba14602289a..84651902be4 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -6,6 +6,7 @@ type { 'Integrations::NetsuiteIntegration' } code { "netsuite_#{SecureRandom.uuid}" } name { 'Accounting integration 1' } + category { 'accounting' } secrets do {connection_id: SecureRandom.uuid, client_secret: SecureRandom.uuid}.to_json @@ -21,6 +22,7 @@ type { 'Integrations::OktaIntegration' } code { 'okta' } name { 'Okta Integration' } + category { 'system' } settings do {client_id: SecureRandom.uuid, domain: 'foo.test', organization_name: 'Foobar'} @@ -36,6 +38,7 @@ type { 'Integrations::AnrokIntegration' } code { 'anrok' } name { 'Anrok Integration' } + category { 'tax_provider' } secrets do {connection_id: SecureRandom.uuid, api_key: SecureRandom.uuid}.to_json @@ -47,6 +50,7 @@ type { 'Integrations::XeroIntegration' } code { 'xero' } name { 'Xero Integration' } + category { 'accounting' } secrets do {connection_id: SecureRandom.uuid}.to_json From 421cec26c4622a074bcee3b9dd42ca437f4d18c1 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 17:39:32 +0200 Subject: [PATCH 05/12] wip extract general payment_provider_customer and integration_type_customer --- app/graphql/types/customers/object.rb | 9 +-------- app/models/customer.rb | 17 +++++++++-------- app/serializers/v1/customer_serializer.rb | 16 +++------------- app/services/customers/update_service.rb | 15 +++------------ .../invoices/compute_amounts_from_fees.rb | 2 +- 5 files changed, 17 insertions(+), 42 deletions(-) diff --git a/app/graphql/types/customers/object.rb b/app/graphql/types/customers/object.rb index 0f9438c4cc4..65ba01b738e 100644 --- a/app/graphql/types/customers/object.rb +++ b/app/graphql/types/customers/object.rb @@ -103,14 +103,7 @@ def active_subscriptions_count end def provider_customer - case object&.payment_provider&.to_sym - when :stripe - object.stripe_customer - when :gocardless - object.gocardless_customer - when :adyen - object.adyen_customer - end + object&.payment_provider_customer end def credit_notes_credits_available_count diff --git a/app/models/customer.rb b/app/models/customer.rb index d2a56898332..fd3cdccdd57 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -42,6 +42,14 @@ class Customer < ApplicationRecord has_one :anrok_customer, class_name: 'IntegrationCustomers::AnrokCustomer' has_one :xero_customer, class_name: 'IntegrationCustomers::XeroCustomer' + has_one :tax_provider_customer, -> { + includes(:integration).where(integration: {category: 'tax_provider'}) + }, class_name: 'IntegrationCustomers::BaseCustomer' + has_one :accounting_customer, -> { + includes(:integration).where(integration: {category: 'accounting'}) + }, class_name: 'IntegrationCustomers::BaseCustomer' + has_one :payment_provider_customer, class_name: 'PaymentProviderCustomers::BaseCustomer' + PAYMENT_PROVIDERS = %w[stripe gocardless adyen].freeze default_scope -> { kept } @@ -105,14 +113,7 @@ def preferred_document_locale end def provider_customer - case payment_provider&.to_sym - when :stripe - stripe_customer - when :gocardless - gocardless_customer - when :adyen - adyen_customer - end + payment_provider_customer end def shipping_address diff --git a/app/serializers/v1/customer_serializer.rb b/app/serializers/v1/customer_serializer.rb index c823fd0f5d6..ed5e6e957c3 100644 --- a/app/serializers/v1/customer_serializer.rb +++ b/app/serializers/v1/customer_serializer.rb @@ -59,19 +59,9 @@ def billing_configuration document_locale: model.document_locale } - case model.payment_provider&.to_sym - when :stripe - configuration[:provider_customer_id] = model.stripe_customer&.provider_customer_id - configuration[:provider_payment_methods] = model.stripe_customer&.provider_payment_methods - configuration.merge!(model.stripe_customer&.settings || {}) - when :gocardless - configuration[:provider_customer_id] = model.gocardless_customer&.provider_customer_id - configuration.merge!(model.gocardless_customer&.settings || {}) - when :adyen - configuration[:provider_customer_id] = model.adyen_customer&.provider_customer_id - configuration.merge!(model.adyen_customer&.settings || {}) - end - + configuration[:provider_customer_id] = model.payment_provider_customer&.provider_customer_id + configuration.merge!(model.payment_provider_customer&.settings || {}) + configuration[:provider_payment_methods] = model.payment_provider_customer&.provider_payment_methods configuration end diff --git a/app/services/customers/update_service.rb b/app/services/customers/update_service.rb index a65087305ea..4e1ba3afc19 100644 --- a/app/services/customers/update_service.rb +++ b/app/services/customers/update_service.rb @@ -172,25 +172,16 @@ def assign_premium_attributes(customer, args) def create_or_update_provider_customer(customer, payment_provider, billing_configuration = {}) handle_provider_customer = customer.payment_provider.present? handle_provider_customer ||= (billing_configuration || {})[:provider_customer_id].present? + handle_provider_customer ||= customer.payment_provider_customer&.provider_customer_id.present? + + return unless handle_provider_customer case payment_provider when 'stripe' - handle_provider_customer ||= customer.stripe_customer&.provider_customer_id.present? - - return unless handle_provider_customer - update_stripe_customer(customer, billing_configuration) when 'gocardless' - handle_provider_customer ||= customer.gocardless_customer&.provider_customer_id.present? - - return unless handle_provider_customer - update_gocardless_customer(customer, billing_configuration) when 'adyen' - handle_provider_customer ||= customer.adyen_customer&.provider_customer_id.present? - - return unless handle_provider_customer - update_adyen_customer(customer, billing_configuration) end end diff --git a/app/services/invoices/compute_amounts_from_fees.rb b/app/services/invoices/compute_amounts_from_fees.rb index ef39865f09c..779b9f74d85 100644 --- a/app/services/invoices/compute_amounts_from_fees.rb +++ b/app/services/invoices/compute_amounts_from_fees.rb @@ -51,7 +51,7 @@ def call attr_reader :invoice, :provider_taxes def customer_provider_taxation? - @customer_provider_taxation ||= invoice.customer.anrok_customer + @customer_provider_taxation ||= invoice.customer.tax_provider_customer end def fee_taxes(fee) From 536c9d73a901fac1ec2d707591d769929a779805 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 18:06:25 +0200 Subject: [PATCH 06/12] update more usage of specific integration customer type --- app/graphql/types/credit_notes/object.rb | 2 +- app/graphql/types/invoices/object.rb | 2 +- app/models/credit_note.rb | 2 +- app/models/customer.rb | 3 +++ app/models/integration_customers/base_customer.rb | 4 ---- app/models/invoice.rb | 7 +++---- app/models/payment.rb | 2 +- .../integrations/aggregator/invoices/base_service.rb | 2 +- 8 files changed, 11 insertions(+), 13 deletions(-) diff --git a/app/graphql/types/credit_notes/object.rb b/app/graphql/types/credit_notes/object.rb index 0df230791c7..1d4f7d63043 100644 --- a/app/graphql/types/credit_notes/object.rb +++ b/app/graphql/types/credit_notes/object.rb @@ -58,7 +58,7 @@ def integration_syncable end def external_integration_id - integration_customer = object.customer&.integration_customers&.accounting_kind&.first + integration_customer = object.customer&.accounting_customer return nil unless integration_customer diff --git a/app/graphql/types/invoices/object.rb b/app/graphql/types/invoices/object.rb index bc438bc297e..b1df85b5557 100644 --- a/app/graphql/types/invoices/object.rb +++ b/app/graphql/types/invoices/object.rb @@ -66,7 +66,7 @@ def integration_syncable end def external_integration_id - integration_customer = object.customer&.integration_customers&.accounting_kind&.first + integration_customer = object.customer&.accounting_customer return nil unless integration_customer diff --git a/app/models/credit_note.rb b/app/models/credit_note.rb index e8c8796b724..ec044eac004 100644 --- a/app/models/credit_note.rb +++ b/app/models/credit_note.rb @@ -106,7 +106,7 @@ def add_on_items end def should_sync_credit_note? - finalized? && customer.integration_customers.accounting_kind.any? { |c| c.integration.sync_credit_notes } + finalized? && customer.accounting_customer.integration.sync_credit_notes end def voidable? diff --git a/app/models/customer.rb b/app/models/customer.rb index fd3cdccdd57..24efba25947 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -42,12 +42,15 @@ class Customer < ApplicationRecord has_one :anrok_customer, class_name: 'IntegrationCustomers::AnrokCustomer' has_one :xero_customer, class_name: 'IntegrationCustomers::XeroCustomer' + # customer can have only one integration customer per integration_category has_one :tax_provider_customer, -> { includes(:integration).where(integration: {category: 'tax_provider'}) }, class_name: 'IntegrationCustomers::BaseCustomer' has_one :accounting_customer, -> { includes(:integration).where(integration: {category: 'accounting'}) }, class_name: 'IntegrationCustomers::BaseCustomer' + + # customer can have only one payment_provider_customer has_one :payment_provider_customer, class_name: 'PaymentProviderCustomers::BaseCustomer' PAYMENT_PROVIDERS = %w[stripe gocardless adyen].freeze diff --git a/app/models/integration_customers/base_customer.rb b/app/models/integration_customers/base_customer.rb index fe999e8e325..f8d9c3f0a8d 100644 --- a/app/models/integration_customers/base_customer.rb +++ b/app/models/integration_customers/base_customer.rb @@ -12,10 +12,6 @@ class BaseCustomer < ApplicationRecord validates :customer_id, uniqueness: {scope: :type} - scope :accounting_kind, -> do - includes(:integration).where(integration: {category: 'accounting'}) - end - settings_accessors :sync_with_provider def self.customer_type(type) diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 365a653ec6a..6733f568e99 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -287,14 +287,13 @@ def mark_as_dispute_lost!(timestamp = Time.current) end def should_sync_invoice? - finalized? && customer.integration_customers.accounting_kind.any? { |c| c.integration.sync_invoices } + finalized? && customer.accounting_customer.integration.sync_invoices end def should_sync_sales_order? finalized? && - customer.integration_customers.accounting_kind.any? do |c| - c.integration.respond_to?(:sync_sales_orders) && c.integration.sync_sales_orders - end + customer.accounting_customer.integration.respond_to?(:sync_sales_orders) && + customer.accounting_customer.integration.sync_sales_orders end private diff --git a/app/models/payment.rb b/app/models/payment.rb index 6570d2eba87..e5bfc80f841 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -13,6 +13,6 @@ class Payment < ApplicationRecord delegate :customer, to: :invoice def should_sync_payment? - invoice.finalized? && customer.integration_customers.accounting_kind.any? { |c| c.integration.sync_payments } + invoice.finalized? && customer.accounting_customer.integration.sync_payments end end diff --git a/app/services/integrations/aggregator/invoices/base_service.rb b/app/services/integrations/aggregator/invoices/base_service.rb index 3e7b78ae758..b5ebf018500 100644 --- a/app/services/integrations/aggregator/invoices/base_service.rb +++ b/app/services/integrations/aggregator/invoices/base_service.rb @@ -31,7 +31,7 @@ def integration end def integration_customer - @integration_customer ||= customer&.integration_customers&.accounting_kind&.first + @integration_customer ||= customer&.accounting_customer end def payload(type) From 9f85b42ccbe81a85247d908856fdc66d63b4b33a Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 18:13:32 +0200 Subject: [PATCH 07/12] add condition on stripe payment provider type to not have nil serialized if now needed --- app/serializers/v1/customer_serializer.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/serializers/v1/customer_serializer.rb b/app/serializers/v1/customer_serializer.rb index ed5e6e957c3..86adf74a943 100644 --- a/app/serializers/v1/customer_serializer.rb +++ b/app/serializers/v1/customer_serializer.rb @@ -61,7 +61,9 @@ def billing_configuration configuration[:provider_customer_id] = model.payment_provider_customer&.provider_customer_id configuration.merge!(model.payment_provider_customer&.settings || {}) - configuration[:provider_payment_methods] = model.payment_provider_customer&.provider_payment_methods + if model.payment_provider&.to_sym == :stripe + configuration[:provider_payment_methods] = model.payment_provider_customer&.provider_payment_methods + end configuration end From 73f4d70f187ff84e63b555b4a926a4a77b480f5d Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 25 Jul 2024 18:22:26 +0200 Subject: [PATCH 08/12] add category when create integration --- app/models/credit_note.rb | 2 +- app/models/invoice.rb | 6 +++--- app/services/integrations/anrok/create_service.rb | 3 ++- app/services/integrations/netsuite/create_service.rb | 3 ++- app/services/integrations/okta/create_service.rb | 3 ++- app/services/integrations/xero/create_service.rb | 3 ++- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/app/models/credit_note.rb b/app/models/credit_note.rb index ec044eac004..39071ef9c7e 100644 --- a/app/models/credit_note.rb +++ b/app/models/credit_note.rb @@ -106,7 +106,7 @@ def add_on_items end def should_sync_credit_note? - finalized? && customer.accounting_customer.integration.sync_credit_notes + finalized? && customer.accounting_customer&.integration&.sync_credit_notes end def voidable? diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 6733f568e99..b5c3697226d 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -287,13 +287,13 @@ def mark_as_dispute_lost!(timestamp = Time.current) end def should_sync_invoice? - finalized? && customer.accounting_customer.integration.sync_invoices + finalized? && customer.accounting_customer&.integration&.sync_invoices end def should_sync_sales_order? finalized? && - customer.accounting_customer.integration.respond_to?(:sync_sales_orders) && - customer.accounting_customer.integration.sync_sales_orders + customer.accounting_customer&.integration&.respond_to?(:sync_sales_orders) && + customer.accounting_customer&.integration&.sync_sales_orders end private diff --git a/app/services/integrations/anrok/create_service.rb b/app/services/integrations/anrok/create_service.rb index ef98a1e7224..784c28c6faf 100644 --- a/app/services/integrations/anrok/create_service.rb +++ b/app/services/integrations/anrok/create_service.rb @@ -15,7 +15,8 @@ def call(**args) name: args[:name], code: args[:code], connection_id: args[:connection_id], - api_key: args[:api_key] + api_key: args[:api_key], + category: 'tax_provider' ) integration.save! diff --git a/app/services/integrations/netsuite/create_service.rb b/app/services/integrations/netsuite/create_service.rb index 48ae5af5fd9..3648b946bfa 100644 --- a/app/services/integrations/netsuite/create_service.rb +++ b/app/services/integrations/netsuite/create_service.rb @@ -24,7 +24,8 @@ def call(**args) sync_credit_notes: ActiveModel::Type::Boolean.new.cast(args[:sync_credit_notes]), sync_invoices: ActiveModel::Type::Boolean.new.cast(args[:sync_invoices]), sync_payments: ActiveModel::Type::Boolean.new.cast(args[:sync_payments]), - sync_sales_orders: ActiveModel::Type::Boolean.new.cast(args[:sync_sales_orders]) + sync_sales_orders: ActiveModel::Type::Boolean.new.cast(args[:sync_sales_orders]), + category: 'accounting' ) integration.save! diff --git a/app/services/integrations/okta/create_service.rb b/app/services/integrations/okta/create_service.rb index 0e68bdd694e..35f54759355 100644 --- a/app/services/integrations/okta/create_service.rb +++ b/app/services/integrations/okta/create_service.rb @@ -17,7 +17,8 @@ def call(**args) client_id: args[:client_id], client_secret: args[:client_secret], domain: args[:domain], - organization_name: args[:organization_name] + organization_name: args[:organization_name], + category: 'system' ) integration.save! diff --git a/app/services/integrations/xero/create_service.rb b/app/services/integrations/xero/create_service.rb index 77388633791..b74999cd716 100644 --- a/app/services/integrations/xero/create_service.rb +++ b/app/services/integrations/xero/create_service.rb @@ -17,7 +17,8 @@ def call(**args) connection_id: args[:connection_id], sync_credit_notes: ActiveModel::Type::Boolean.new.cast(args[:sync_credit_notes]), sync_invoices: ActiveModel::Type::Boolean.new.cast(args[:sync_invoices]), - sync_payments: ActiveModel::Type::Boolean.new.cast(args[:sync_payments]) + sync_payments: ActiveModel::Type::Boolean.new.cast(args[:sync_payments]), + category: 'accounting' ) integration.save! From 8bd834bfcf998b4cc3ad13b185b61cdfa1197ed1 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Fri, 26 Jul 2024 09:50:45 +0200 Subject: [PATCH 09/12] fix another case of not existing integration on customer --- app/models/payment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index e5bfc80f841..ce0d78636a4 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -13,6 +13,6 @@ class Payment < ApplicationRecord delegate :customer, to: :invoice def should_sync_payment? - invoice.finalized? && customer.accounting_customer.integration.sync_payments + invoice.finalized? && customer.accounting_customer&.integration&.sync_payments end end From 669d95897ee49886f6aefa362f53f0ebb8889730 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Fri, 26 Jul 2024 10:15:21 +0200 Subject: [PATCH 10/12] use bitwise and for boolean methods --- app/models/credit_note.rb | 2 +- app/models/invoice.rb | 6 ++---- app/models/payment.rb | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/models/credit_note.rb b/app/models/credit_note.rb index 39071ef9c7e..2ab578ff271 100644 --- a/app/models/credit_note.rb +++ b/app/models/credit_note.rb @@ -106,7 +106,7 @@ def add_on_items end def should_sync_credit_note? - finalized? && customer.accounting_customer&.integration&.sync_credit_notes + finalized? & customer.accounting_customer&.integration&.sync_credit_notes end def voidable? diff --git a/app/models/invoice.rb b/app/models/invoice.rb index b5c3697226d..2d580a54def 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -287,13 +287,11 @@ def mark_as_dispute_lost!(timestamp = Time.current) end def should_sync_invoice? - finalized? && customer.accounting_customer&.integration&.sync_invoices + finalized? & customer.accounting_customer&.integration&.sync_invoices end def should_sync_sales_order? - finalized? && - customer.accounting_customer&.integration&.respond_to?(:sync_sales_orders) && - customer.accounting_customer&.integration&.sync_sales_orders + finalized? & customer.accounting_customer&.integration&.sync_sales_orders end private diff --git a/app/models/payment.rb b/app/models/payment.rb index ce0d78636a4..fbc78d54c68 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -13,6 +13,6 @@ class Payment < ApplicationRecord delegate :customer, to: :invoice def should_sync_payment? - invoice.finalized? && customer.accounting_customer&.integration&.sync_payments + invoice.finalized? & customer.accounting_customer&.integration&.sync_payments end end From a610720a8c7c403ae6683b65e865e03ba70854c2 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Fri, 26 Jul 2024 18:00:31 +0200 Subject: [PATCH 11/12] declare provider_customer on customer as alias to payment_provider_customer --- app/models/customer.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/models/customer.rb b/app/models/customer.rb index 24efba25947..9f9901ca1d5 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -71,6 +71,8 @@ class Customer < ApplicationRecord validates :payment_provider, inclusion: {in: PAYMENT_PROVIDERS}, allow_nil: true validates :timezone, timezone: true, allow_nil: true + alias :provider_customer :payment_provider_customer + def self.ransackable_attributes(_auth_object = nil) %w[id name external_id email] end @@ -115,10 +117,6 @@ def preferred_document_locale organization.document_locale.to_sym end - def provider_customer - payment_provider_customer - end - def shipping_address { address_line1: shipping_address_line1, From 3327258c60cd6c0f7d7b9138b2c28b68e0254a3f Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Mon, 29 Jul 2024 09:53:40 +0200 Subject: [PATCH 12/12] fix linter error --- app/models/customer.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/customer.rb b/app/models/customer.rb index 9f9901ca1d5..2e6e798ae88 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -71,7 +71,7 @@ class Customer < ApplicationRecord validates :payment_provider, inclusion: {in: PAYMENT_PROVIDERS}, allow_nil: true validates :timezone, timezone: true, allow_nil: true - alias :provider_customer :payment_provider_customer + alias_method :provider_customer, :payment_provider_customer def self.ransackable_attributes(_auth_object = nil) %w[id name external_id email]