diff --git a/app/models/error_detail.rb b/app/models/error_detail.rb new file mode 100644 index 00000000000..61e226f24c2 --- /dev/null +++ b/app/models/error_detail.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +class ErrorDetail < ApplicationRecord + include Discard::Model + self.discard_column = :deleted_at + + belongs_to :owner, polymorphic: true + belongs_to :organization + + ERROR_CODES = %w[not_provided tax_error] + enum error_code: ERROR_CODES +end diff --git a/app/models/integrations/anrok_integration.rb b/app/models/integrations/anrok_integration.rb index 1afb5a887a2..73fb45022fd 100644 --- a/app/models/integrations/anrok_integration.rb +++ b/app/models/integrations/anrok_integration.rb @@ -2,6 +2,10 @@ module Integrations class AnrokIntegration < BaseIntegration + has_many :error_details, -> { where({error_details: {error_code: 'tax_error'}}) }, + primary_key: :organization_id, + foreign_key: :organization_id + validates :connection_id, :api_key, presence: true secrets_accessors :connection_id, :api_key diff --git a/app/models/invoice.rb b/app/models/invoice.rb index e233170f418..1e4467ed909 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -28,6 +28,7 @@ class Invoice < ApplicationRecord has_many :applied_taxes, class_name: 'Invoice::AppliedTax', dependent: :destroy has_many :taxes, through: :applied_taxes has_many :integration_resources, as: :syncable + has_many :error_details, as: :owner, dependent: :destroy has_one_attached :file diff --git a/app/models/organization.rb b/app/models/organization.rb index 7788cf9e0ca..58e7353341f 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -33,6 +33,7 @@ class Organization < ApplicationRecord has_many :webhooks, through: :webhook_endpoints has_many :cached_aggregations has_many :data_exports + has_many :error_details has_many :stripe_payment_providers, class_name: 'PaymentProviders::StripeProvider' has_many :gocardless_payment_providers, class_name: 'PaymentProviders::GocardlessProvider' diff --git a/db/migrate/20240723150221_remove_integration_reference_from_error_detail.rb b/db/migrate/20240723150221_remove_integration_reference_from_error_detail.rb new file mode 100644 index 00000000000..984728e1a1f --- /dev/null +++ b/db/migrate/20240723150221_remove_integration_reference_from_error_detail.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +class RemoveIntegrationReferenceFromErrorDetail < ActiveRecord::Migration[7.1] + def up + change_table :error_details, bulk: true do |t| + t.remove :error_code + t.remove_references :integration, polymorphic: true + t.integer :error_code, null: false, default: 0, index: true + end + end + + def down + change_table :error_details, bulk: true do |t| + t.remove :error_code + t.references :integration, polymorphic: true + t.string :error_code, index: true, null: false, default: 'not_provided' + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 63354310a37..2fabef2b337 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_22_201341) do +ActiveRecord::Schema[7.1].define(version: 2024_07_23_150221) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -460,17 +460,14 @@ create_table "error_details", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.string "owner_type", null: false t.uuid "owner_id", null: false - t.string "integration_type" - t.uuid "integration_id" t.uuid "organization_id", null: false - t.string "error_code", default: "not_provided", null: false t.jsonb "details", default: {}, null: false t.datetime "deleted_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "error_code", default: 0, null: false t.index ["deleted_at"], name: "index_error_details_on_deleted_at" t.index ["error_code"], name: "index_error_details_on_error_code" - t.index ["integration_type", "integration_id"], name: "index_error_details_on_integration" t.index ["organization_id"], name: "index_error_details_on_organization_id" t.index ["owner_type", "owner_id"], name: "index_error_details_on_owner" end diff --git a/spec/factories/error_details.rb b/spec/factories/error_details.rb new file mode 100644 index 00000000000..d01158a097f --- /dev/null +++ b/spec/factories/error_details.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :error_detail do + organization + association :owner, factory: %i[invoice].sample + end +end diff --git a/spec/factories/invoices.rb b/spec/factories/invoices.rb index f19153e3a1a..ea6f4edaaad 100644 --- a/spec/factories/invoices.rb +++ b/spec/factories/invoices.rb @@ -24,6 +24,12 @@ payment_dispute_lost_at { DateTime.current - 1.day } end + trait :with_error do + after :create do |i| + create(:error_detail, owner: i) + end + end + trait :failed do status { :failed } end diff --git a/spec/models/error_detail_spec.rb b/spec/models/error_detail_spec.rb new file mode 100644 index 00000000000..13febf1feed --- /dev/null +++ b/spec/models/error_detail_spec.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe ErrorDetail, type: :model do + it { is_expected.to belong_to(:owner) } + it { is_expected.to belong_to(:organization) } +end diff --git a/spec/models/integrations/anrok_integration_spec.rb b/spec/models/integrations/anrok_integration_spec.rb index e18effbc808..0679f34c7bd 100644 --- a/spec/models/integrations/anrok_integration_spec.rb +++ b/spec/models/integrations/anrok_integration_spec.rb @@ -7,6 +7,7 @@ it { is_expected.to validate_presence_of(:name) } it { is_expected.to validate_presence_of(:connection_id) } + it { is_expected.to have_many(:error_details) } describe 'validations' do it 'validates uniqueness of the code' do diff --git a/spec/models/invoice_spec.rb b/spec/models/invoice_spec.rb index 29dc0a3dc71..90112702858 100644 --- a/spec/models/invoice_spec.rb +++ b/spec/models/invoice_spec.rb @@ -10,6 +10,7 @@ it_behaves_like 'paper_trail traceable' it { is_expected.to have_many(:integration_resources) } + it { is_expected.to have_many(:error_details) } describe 'validation' do describe 'of payment dispute lost absence' do