From cc44830f0817c66d42747f643e12bf35a3405c4c Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Fri, 6 Dec 2024 17:19:30 +0100 Subject: [PATCH 01/10] Add InvoiceCustomSections::UpdateService --- .../deselect_service.rb | 29 +++++++++++++++++++ .../deselect_service_spec.rb | 28 ++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 app/services/invoice_custom_sections/deselect_service.rb create mode 100644 spec/services/invoice_custom_sections/deselect_service_spec.rb diff --git a/app/services/invoice_custom_sections/deselect_service.rb b/app/services/invoice_custom_sections/deselect_service.rb new file mode 100644 index 00000000000..0c674444e8f --- /dev/null +++ b/app/services/invoice_custom_sections/deselect_service.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module InvoiceCustomSections + class DeselectService < BaseService + def initialize(section:, organization:) + @section = section + @organization = organization + super + end + + def call + deselect_for_organization if organization + result + end + + private + + attr_reader :section, :organization + + def deselect_for_organization + return unless organization.selected_invoice_custom_sections.include?(section) + + InvoiceCustomSectionSelection.where( + organization_id: organization.id, invoice_custom_section_id: section.id + ).destroy_all + result.organization = organization + end + end +end diff --git a/spec/services/invoice_custom_sections/deselect_service_spec.rb b/spec/services/invoice_custom_sections/deselect_service_spec.rb new file mode 100644 index 00000000000..0bbc533409f --- /dev/null +++ b/spec/services/invoice_custom_sections/deselect_service_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe InvoiceCustomSections::DeselectService, type: :service do + describe '#call' do + subject(:service_result) { described_class.call(organization:, section:) } + + let(:organization) { create(:organization) } + let(:section) { create(:invoice_custom_section) } + + context 'when the section is selected' do + before { organization.selected_invoice_custom_sections << section } + + it 'selects the section for the organization' do + expect { service_result }.to change(organization.selected_invoice_custom_sections, :count).from(1).to(0) + expect(organization.selected_invoice_custom_sections).to eq([]) + end + end + + context 'when the section is not selected' do + it 'selects the section for the organization' do + service_result + expect(organization.selected_invoice_custom_sections).to eq([]) + end + end + end +end From c0d818cf8fc351563f138a232f1ba09974d9572f Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Mon, 9 Dec 2024 18:45:13 +0100 Subject: [PATCH 02/10] add destroy service to invoice_custom_sections family --- .../deselect_service.rb | 29 ------------------- .../deselect_service_spec.rb | 28 ------------------ 2 files changed, 57 deletions(-) delete mode 100644 app/services/invoice_custom_sections/deselect_service.rb delete mode 100644 spec/services/invoice_custom_sections/deselect_service_spec.rb diff --git a/app/services/invoice_custom_sections/deselect_service.rb b/app/services/invoice_custom_sections/deselect_service.rb deleted file mode 100644 index 0c674444e8f..00000000000 --- a/app/services/invoice_custom_sections/deselect_service.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -module InvoiceCustomSections - class DeselectService < BaseService - def initialize(section:, organization:) - @section = section - @organization = organization - super - end - - def call - deselect_for_organization if organization - result - end - - private - - attr_reader :section, :organization - - def deselect_for_organization - return unless organization.selected_invoice_custom_sections.include?(section) - - InvoiceCustomSectionSelection.where( - organization_id: organization.id, invoice_custom_section_id: section.id - ).destroy_all - result.organization = organization - end - end -end diff --git a/spec/services/invoice_custom_sections/deselect_service_spec.rb b/spec/services/invoice_custom_sections/deselect_service_spec.rb deleted file mode 100644 index 0bbc533409f..00000000000 --- a/spec/services/invoice_custom_sections/deselect_service_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe InvoiceCustomSections::DeselectService, type: :service do - describe '#call' do - subject(:service_result) { described_class.call(organization:, section:) } - - let(:organization) { create(:organization) } - let(:section) { create(:invoice_custom_section) } - - context 'when the section is selected' do - before { organization.selected_invoice_custom_sections << section } - - it 'selects the section for the organization' do - expect { service_result }.to change(organization.selected_invoice_custom_sections, :count).from(1).to(0) - expect(organization.selected_invoice_custom_sections).to eq([]) - end - end - - context 'when the section is not selected' do - it 'selects the section for the organization' do - service_result - expect(organization.selected_invoice_custom_sections).to eq([]) - end - end - end -end From 03ab93c0e6d5b1ff5bed3bc709c3397661da23b0 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Tue, 10 Dec 2024 15:43:21 +0100 Subject: [PATCH 03/10] WIP adding destroy mutation --- .../invoice_custom_sections/destroy.rb | 25 +++++++++++++++++++ app/graphql/types/mutation_type.rb | 1 + .../destroy_service.rb | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 app/graphql/mutations/invoice_custom_sections/destroy.rb diff --git a/app/graphql/mutations/invoice_custom_sections/destroy.rb b/app/graphql/mutations/invoice_custom_sections/destroy.rb new file mode 100644 index 00000000000..5e363211f83 --- /dev/null +++ b/app/graphql/mutations/invoice_custom_sections/destroy.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Mutations + module InvoiceCustomSections + class Destroy < BaseMutation + include AuthenticableApiUser + + REQUIRED_PERMISSION = 'invoice_custom_sections:delete' + + graphql_name 'DestroyPlan' + description 'Deletes a Plan' + + argument :id, ID, required: true + + field :id, ID, null: true + + def resolve(id:) + plan = context[:current_user].plans.find_by(id:) + result = ::Plans::PrepareDestroyService.call(plan:) + + result.success? ? result.plan : result_error(result) + end + end + end +end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index 411f40cfcac..b76b05e99b9 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -162,5 +162,6 @@ class MutationType < Types::BaseObject field :create_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Create field :update_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Update + field :destroy_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Destroy end end diff --git a/app/services/invoice_custom_sections/destroy_service.rb b/app/services/invoice_custom_sections/destroy_service.rb index 9a0b6736c69..b955d19bdb2 100644 --- a/app/services/invoice_custom_sections/destroy_service.rb +++ b/app/services/invoice_custom_sections/destroy_service.rb @@ -10,7 +10,7 @@ def initialize(invoice_custom_section:) def call ActiveRecord::Base.transaction do invoice_custom_section.discard - Deselect::ForAllUsagesService.call(section: invoice_custom_section).raise_if_error + Deselect::ForAllUsagesService.call(section: invoice_custom_section).raise_if_error! result.invoice_custom_section = invoice_custom_section result end From 765545347df8a7f7884ca883d07f3a7ecaf857f6 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Tue, 10 Dec 2024 18:04:14 +0100 Subject: [PATCH 04/10] add test for destroy mutation --- .../invoice_custom_sections/destroy.rb | 11 +- schema.graphql | 32 +++++ schema.json | 109 ++++++++++++++++++ .../invoice_custom_sections/destroy_spec.rb | 31 +++++ 4 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb diff --git a/app/graphql/mutations/invoice_custom_sections/destroy.rb b/app/graphql/mutations/invoice_custom_sections/destroy.rb index 5e363211f83..4fbe0a35b2e 100644 --- a/app/graphql/mutations/invoice_custom_sections/destroy.rb +++ b/app/graphql/mutations/invoice_custom_sections/destroy.rb @@ -4,21 +4,22 @@ module Mutations module InvoiceCustomSections class Destroy < BaseMutation include AuthenticableApiUser + include RequiredOrganization REQUIRED_PERMISSION = 'invoice_custom_sections:delete' - graphql_name 'DestroyPlan' - description 'Deletes a Plan' + graphql_name 'DestroyInvoiceCustomSection' + description 'Deletes an InvoiceCustomSection' argument :id, ID, required: true field :id, ID, null: true def resolve(id:) - plan = context[:current_user].plans.find_by(id:) - result = ::Plans::PrepareDestroyService.call(plan:) + invoice_custom_section = current_organization.invoice_custom_sections.find_by(id:) + result = ::InvoiceCustomSections::DestroyService.call(invoice_custom_section:) - result.success? ? result.plan : result_error(result) + result.success? ? result.invoice_custom_section : result_error(result) end end end diff --git a/schema.graphql b/schema.graphql index 0a073c88c57..eb106bbb09e 100644 --- a/schema.graphql +++ b/schema.graphql @@ -3680,6 +3680,28 @@ type DestroyIntegrationPayload { id: ID } +""" +Autogenerated input type of DestroyInvoiceCustomSection +""" +input DestroyInvoiceCustomSectionInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + id: ID! +} + +""" +Autogenerated return type of DestroyInvoiceCustomSection. +""" +type DestroyInvoiceCustomSectionPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + id: ID +} + """ Autogenerated input type of DestroyPaymentProvider """ @@ -5195,6 +5217,16 @@ type Mutation { input: DestroyIntegrationMappingInput! ): DestroyIntegrationMappingPayload + """ + Deletes an InvoiceCustomSection + """ + destroyInvoiceCustomSection( + """ + Parameters for DestroyInvoiceCustomSection + """ + input: DestroyInvoiceCustomSectionInput! + ): DestroyInvoiceCustomSectionPayload + """ Destroy a payment provider """ diff --git a/schema.json b/schema.json index 98a16d7c67a..bbe1f3004fd 100644 --- a/schema.json +++ b/schema.json @@ -16522,6 +16522,86 @@ "inputFields": null, "enumValues": null }, + { + "kind": "INPUT_OBJECT", + "name": "DestroyInvoiceCustomSectionInput", + "description": "Autogenerated input type of DestroyInvoiceCustomSection", + "interfaces": null, + "possibleTypes": null, + "fields": null, + "inputFields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "enumValues": null + }, + { + "kind": "OBJECT", + "name": "DestroyInvoiceCustomSectionPayload", + "description": "Autogenerated return type of DestroyInvoiceCustomSection.", + "interfaces": [ + + ], + "possibleTypes": null, + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + }, + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + + ] + } + ], + "inputFields": null, + "enumValues": null + }, { "kind": "INPUT_OBJECT", "name": "DestroyPaymentProviderInput", @@ -25990,6 +26070,35 @@ } ] }, + { + "name": "destroyInvoiceCustomSection", + "description": "Deletes an InvoiceCustomSection", + "type": { + "kind": "OBJECT", + "name": "DestroyInvoiceCustomSectionPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + { + "name": "input", + "description": "Parameters for DestroyInvoiceCustomSection", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DestroyInvoiceCustomSectionInput", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ] + }, { "name": "destroyPaymentProvider", "description": "Destroy a payment provider", diff --git a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb new file mode 100644 index 00000000000..76d287545b9 --- /dev/null +++ b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Mutations::InvoiceCustomSections::Destroy, type: :graphql do + let(:sbj) { + execute_graphql( + current_user: membership.user, + current_organization: membership.organization, + query: mutation, + variables: {input: {id: invoice_custom_section.id}} + ) + } + let(:membership) { create(:membership) } + let(:organization) { membership.organization } + let(:invoice_custom_section) { create(:invoice_custom_section, organization:) } + + let(:mutation) do + <<-GQL + mutation($input: DestroyInvoiceCustomSectionInput!) { + destroyInvoiceCustomSection(input: $input) { id } + } + GQL + end + + before { invoice_custom_section } + + it 'destroys the invoice_custom_section' do + expect { sbj }.to change(InvoiceCustomSection, :count).by(-1) + end +end From 45264f2b2689d8569e6f5987e79dac026469500f Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Wed, 11 Dec 2024 11:28:55 +0100 Subject: [PATCH 05/10] add single invoice_custom_section resolver --- .../invoice_custom_section_resolver.rb | 20 ++++++ app/graphql/types/query_type.rb | 1 + app/models/invoice_custom_section.rb | 2 +- schema.graphql | 10 +++ schema.json | 29 +++++++++ .../invoice_custom_sections/destroy_spec.rb | 19 +++--- .../invoice_custom_section_resolver.rb | 65 +++++++++++++++++++ 7 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 app/graphql/resolvers/invoice_custom_section_resolver.rb create mode 100644 spec/graphql/resolvers/invoice_custom_section_resolver.rb diff --git a/app/graphql/resolvers/invoice_custom_section_resolver.rb b/app/graphql/resolvers/invoice_custom_section_resolver.rb new file mode 100644 index 00000000000..dc64d61e3dc --- /dev/null +++ b/app/graphql/resolvers/invoice_custom_section_resolver.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Resolvers + class InvoiceCustomSectionResolver < Resolvers::BaseResolver + include AuthenticableApiUser + include RequiredOrganization + + description 'Query a single invoice_custom_section of an organization' + + argument :id, ID, required: true, description: 'Uniq ID of the invoice_custom_section' + + type Types::InvoiceCustomSections::Object, null: true + + def resolve(id: nil) + current_organization.invoice_custom_sections.find(id) + rescue ActiveRecord::RecordNotFound + not_found_error(resource: 'invoice_custom_section') + end + end +end diff --git a/app/graphql/types/query_type.rb b/app/graphql/types/query_type.rb index 1e559c65e6d..08f9a96f0b7 100644 --- a/app/graphql/types/query_type.rb +++ b/app/graphql/types/query_type.rb @@ -52,6 +52,7 @@ class QueryType < Types::BaseObject field :invoice, resolver: Resolvers::InvoiceResolver field :invoice_collections, resolver: Resolvers::Analytics::InvoiceCollectionsResolver field :invoice_credit_notes, resolver: Resolvers::InvoiceCreditNotesResolver + field :invoice_custom_section, resolver: Resolvers::InvoiceCustomSectionResolver field :invoice_custom_sections, resolver: Resolvers::InvoiceCustomSectionsResolver field :invoiced_usages, resolver: Resolvers::Analytics::InvoicedUsagesResolver field :invoices, resolver: Resolvers::InvoicesResolver diff --git a/app/models/invoice_custom_section.rb b/app/models/invoice_custom_section.rb index aa389773ccd..4d2fb2cc489 100644 --- a/app/models/invoice_custom_section.rb +++ b/app/models/invoice_custom_section.rb @@ -11,7 +11,7 @@ class InvoiceCustomSection < ApplicationRecord validates :code, presence: true, uniqueness: {scope: :organization_id} def selected_for_organization? - organization.invoice_custom_sections.exists?(id: id) + organization.selected_invoice_custom_sections.exists?(id: id) end end diff --git a/schema.graphql b/schema.graphql index eb106bbb09e..0565469d8eb 100644 --- a/schema.graphql +++ b/schema.graphql @@ -6652,6 +6652,16 @@ type Query { page: Int ): CreditNoteCollection + """ + Query a single invoice_custom_section of an organization + """ + invoiceCustomSection( + """ + Uniq ID of the invoice_custom_section + """ + id: ID! + ): InvoiceCustomSection + """ Query invoice_custom_sections """ diff --git a/schema.json b/schema.json index bbe1f3004fd..f88ce889599 100644 --- a/schema.json +++ b/schema.json @@ -34388,6 +34388,35 @@ } ] }, + { + "name": "invoiceCustomSection", + "description": "Query a single invoice_custom_section of an organization", + "type": { + "kind": "OBJECT", + "name": "InvoiceCustomSection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + { + "name": "id", + "description": "Uniq ID of the invoice_custom_section", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ] + }, { "name": "invoiceCustomSections", "description": "Query invoice_custom_sections", diff --git a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb index 76d287545b9..6c8394d3e7d 100644 --- a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb +++ b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb @@ -3,14 +3,6 @@ require 'rails_helper' RSpec.describe Mutations::InvoiceCustomSections::Destroy, type: :graphql do - let(:sbj) { - execute_graphql( - current_user: membership.user, - current_organization: membership.organization, - query: mutation, - variables: {input: {id: invoice_custom_section.id}} - ) - } let(:membership) { create(:membership) } let(:organization) { membership.organization } let(:invoice_custom_section) { create(:invoice_custom_section, organization:) } @@ -25,7 +17,14 @@ before { invoice_custom_section } - it 'destroys the invoice_custom_section' do - expect { sbj }.to change(InvoiceCustomSection, :count).by(-1) + it 'destroys am invoice_custom_section' do + expect do + execute_graphql( + current_user: membership.user, + current_organization: organization, + query: mutation, + variables: {input: {id: invoice_custom_section.id}} + ) + end.to change(InvoiceCustomSection, :count).by(-1) end end diff --git a/spec/graphql/resolvers/invoice_custom_section_resolver.rb b/spec/graphql/resolvers/invoice_custom_section_resolver.rb new file mode 100644 index 00000000000..023cf21d551 --- /dev/null +++ b/spec/graphql/resolvers/invoice_custom_section_resolver.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Resolvers::InvoiceCustomSectionResolver, type: :graphql do + let(:query) do + <<~GQL + query($invoiceCustomSectionId: ID!) { + invoiceCustomSection(id: $invoiceCustomSectionId) { + id code name description details displayName selected + } + } + GQL + end + + let(:membership) { create(:membership) } + let(:organization) { membership.organization } + let(:invoice_custom_section) { create(:invoice_custom_section, organization:) } + + before { invoice_custom_section } + + it 'returns a single tax' do + result = execute_graphql( + current_user: membership.user, + current_organization: organization, + query:, + variables: {invoiceCustomSectionId: invoice_custom_section.id} + ) + + expect(result['data']['invoiceCustomSection']).to include( + 'id' => invoice_custom_section.id, + 'code' => invoice_custom_section.code, + 'name' => invoice_custom_section.name, + 'description' => invoice_custom_section.description, + 'details' => invoice_custom_section.details, + 'displayName' => invoice_custom_section.display_name, + 'selected' => false + ) + end + + context 'without current organization' do + it 'returns an error' do + result = execute_graphql( + current_user: membership.user, + query:, + variables: {invoiceCustomSectionId: invoice_custom_section.id} + ) + + expect_graphql_error(result:, message: 'Missing organization id') + end + end + + context 'when invoice_custom_section is not found' do + it 'returns an error' do + result = execute_graphql( + current_user: membership.user, + current_organization: organization, + query:, + variables: {invoiceCustomSectionId: 'unknown'} + ) + + expect_graphql_error(result:, message: 'Resource not found') + end + end +end From 34756ac6b7845ddf3a2b3bc20d9801daadd53126 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Wed, 11 Dec 2024 12:17:29 +0100 Subject: [PATCH 06/10] fix the tests --- .../invoice_custom_sections/destroy.rb | 2 +- app/models/invoice_custom_section.rb | 2 + .../destroy_service.rb | 2 + schema.graphql | 2 +- schema.json | 2 +- .../invoice_custom_sections/destroy_spec.rb | 48 ++++++++++++++----- .../invoice_custom_section_resolver.rb | 2 +- 7 files changed, 43 insertions(+), 17 deletions(-) diff --git a/app/graphql/mutations/invoice_custom_sections/destroy.rb b/app/graphql/mutations/invoice_custom_sections/destroy.rb index 4fbe0a35b2e..d4973b1ed11 100644 --- a/app/graphql/mutations/invoice_custom_sections/destroy.rb +++ b/app/graphql/mutations/invoice_custom_sections/destroy.rb @@ -9,7 +9,7 @@ class Destroy < BaseMutation REQUIRED_PERMISSION = 'invoice_custom_sections:delete' graphql_name 'DestroyInvoiceCustomSection' - description 'Deletes an InvoiceCustomSection' + description 'Deletes an invoice_custom_section' argument :id, ID, required: true diff --git a/app/models/invoice_custom_section.rb b/app/models/invoice_custom_section.rb index 4d2fb2cc489..c6ee13a4119 100644 --- a/app/models/invoice_custom_section.rb +++ b/app/models/invoice_custom_section.rb @@ -10,6 +10,8 @@ class InvoiceCustomSection < ApplicationRecord validates :name, presence: true validates :code, presence: true, uniqueness: {scope: :organization_id} + default_scope -> { kept } + def selected_for_organization? organization.selected_invoice_custom_sections.exists?(id: id) end diff --git a/app/services/invoice_custom_sections/destroy_service.rb b/app/services/invoice_custom_sections/destroy_service.rb index b955d19bdb2..a3c4094aeff 100644 --- a/app/services/invoice_custom_sections/destroy_service.rb +++ b/app/services/invoice_custom_sections/destroy_service.rb @@ -8,6 +8,8 @@ def initialize(invoice_custom_section:) end def call + return result.not_found_failure!(resource: 'invoice_custom_section') unless invoice_custom_section + ActiveRecord::Base.transaction do invoice_custom_section.discard Deselect::ForAllUsagesService.call(section: invoice_custom_section).raise_if_error! diff --git a/schema.graphql b/schema.graphql index 0565469d8eb..2d44d05489d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -5218,7 +5218,7 @@ type Mutation { ): DestroyIntegrationMappingPayload """ - Deletes an InvoiceCustomSection + Deletes an invoice_custom_section """ destroyInvoiceCustomSection( """ diff --git a/schema.json b/schema.json index f88ce889599..15d575b347b 100644 --- a/schema.json +++ b/schema.json @@ -26072,7 +26072,7 @@ }, { "name": "destroyInvoiceCustomSection", - "description": "Deletes an InvoiceCustomSection", + "description": "Deletes an invoice_custom_section", "type": { "kind": "OBJECT", "name": "DestroyInvoiceCustomSectionPayload", diff --git a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb index 6c8394d3e7d..9bbdebb6430 100644 --- a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb +++ b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb @@ -3,11 +3,17 @@ require 'rails_helper' RSpec.describe Mutations::InvoiceCustomSections::Destroy, type: :graphql do - let(:membership) { create(:membership) } - let(:organization) { membership.organization } - let(:invoice_custom_section) { create(:invoice_custom_section, organization:) } + subject(:result) do + execute_graphql( + current_user: membership.user, + current_organization: membership.organization, + permissions: required_permission, + query:, + variables: {input: {id: invoice_custom_section.id}} + ) + end - let(:mutation) do + let(:query) do <<-GQL mutation($input: DestroyInvoiceCustomSectionInput!) { destroyInvoiceCustomSection(input: $input) { id } @@ -15,16 +21,32 @@ GQL end + let(:required_permission) { 'invoice_custom_sections:delete' } + let(:membership) { create(:membership) } + let(:invoice_custom_section) { create(:invoice_custom_section, organization: membership.organization) } + + it_behaves_like 'requires current user' + it_behaves_like 'requires current organization' + it_behaves_like 'requires permission', 'invoice_custom_sections:delete' + before { invoice_custom_section } - it 'destroys am invoice_custom_section' do - expect do - execute_graphql( - current_user: membership.user, - current_organization: organization, - query: mutation, - variables: {input: {id: invoice_custom_section.id}} - ) - end.to change(InvoiceCustomSection, :count).by(-1) + context 'when invoice custom section with such ID exists in the current organization' do + + it 'destroys the invoice custom section' do + expect { result }.to change { InvoiceCustomSection.count }.from(1).to(0) + end + end + + context 'when invoice_custom_section with such ID does not exist in the current organization' do + let(:invoice_custom_section) { create(:invoice_custom_section) } + + it 'does not delete the invoice_custom_section' do + expect { result }.not_to change { InvoiceCustomSection.count } + end + + it 'returns an error' do + expect_graphql_error(result:, message: 'Resource not found') + end end end diff --git a/spec/graphql/resolvers/invoice_custom_section_resolver.rb b/spec/graphql/resolvers/invoice_custom_section_resolver.rb index 023cf21d551..954c7d067d4 100644 --- a/spec/graphql/resolvers/invoice_custom_section_resolver.rb +++ b/spec/graphql/resolvers/invoice_custom_section_resolver.rb @@ -19,7 +19,7 @@ before { invoice_custom_section } - it 'returns a single tax' do + it 'returns a single invoice_custom_section' do result = execute_graphql( current_user: membership.user, current_organization: organization, From d83ca5d1d46c5a792a5d9fe3a82f4f78a6f3c540 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Wed, 11 Dec 2024 12:23:56 +0100 Subject: [PATCH 07/10] fix linter --- app/graphql/types/mutation_type.rb | 2 +- .../mutations/invoice_custom_sections/destroy_spec.rb | 9 ++++----- ...solver.rb => invoice_custom_section_resolver_spec.rb} | 0 3 files changed, 5 insertions(+), 6 deletions(-) rename spec/graphql/resolvers/{invoice_custom_section_resolver.rb => invoice_custom_section_resolver_spec.rb} (100%) diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index b76b05e99b9..bcff7f12e6e 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -161,7 +161,7 @@ class MutationType < Types::BaseObject field :update_api_key, mutation: Mutations::ApiKeys::Update field :create_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Create - field :update_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Update field :destroy_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Destroy + field :update_invoice_custom_section, mutation: Mutations::InvoiceCustomSections::Update end end diff --git a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb index 9bbdebb6430..d592fe5a350 100644 --- a/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb +++ b/spec/graphql/mutations/invoice_custom_sections/destroy_spec.rb @@ -25,16 +25,15 @@ let(:membership) { create(:membership) } let(:invoice_custom_section) { create(:invoice_custom_section, organization: membership.organization) } + before { invoice_custom_section } + it_behaves_like 'requires current user' it_behaves_like 'requires current organization' it_behaves_like 'requires permission', 'invoice_custom_sections:delete' - before { invoice_custom_section } - context 'when invoice custom section with such ID exists in the current organization' do - it 'destroys the invoice custom section' do - expect { result }.to change { InvoiceCustomSection.count }.from(1).to(0) + expect { result }.to change(InvoiceCustomSection, :count).from(1).to(0) end end @@ -42,7 +41,7 @@ let(:invoice_custom_section) { create(:invoice_custom_section) } it 'does not delete the invoice_custom_section' do - expect { result }.not_to change { InvoiceCustomSection.count } + expect { result }.not_to change(InvoiceCustomSection, :count) end it 'returns an error' do diff --git a/spec/graphql/resolvers/invoice_custom_section_resolver.rb b/spec/graphql/resolvers/invoice_custom_section_resolver_spec.rb similarity index 100% rename from spec/graphql/resolvers/invoice_custom_section_resolver.rb rename to spec/graphql/resolvers/invoice_custom_section_resolver_spec.rb From ed51abeeb5d498e395c1a7f642f849a951c96020 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Wed, 11 Dec 2024 16:25:43 +0100 Subject: [PATCH 08/10] return empty data if no invoice_custom_sections found --- .../resolvers/customers/invoice_custom_sections_resolver.rb | 0 app/graphql/resolvers/invoice_custom_section_resolver.rb | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb diff --git a/app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb b/app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/graphql/resolvers/invoice_custom_section_resolver.rb b/app/graphql/resolvers/invoice_custom_section_resolver.rb index dc64d61e3dc..2d515e7ecb8 100644 --- a/app/graphql/resolvers/invoice_custom_section_resolver.rb +++ b/app/graphql/resolvers/invoice_custom_section_resolver.rb @@ -9,7 +9,7 @@ class InvoiceCustomSectionResolver < Resolvers::BaseResolver argument :id, ID, required: true, description: 'Uniq ID of the invoice_custom_section' - type Types::InvoiceCustomSections::Object, null: true + type Types::InvoiceCustomSections::Object, null: false def resolve(id: nil) current_organization.invoice_custom_sections.find(id) From 564d13c59a9bdc4fd23a0eb78b2ffd8433385f26 Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 12 Dec 2024 12:17:13 +0100 Subject: [PATCH 09/10] fill the empty class --- .../customers/invoice_custom_sections_resolver.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb b/app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb index e69de29bb2d..6e225cbf1f1 100644 --- a/app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb +++ b/app/graphql/resolvers/customers/invoice_custom_sections_resolver.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Resolvers + module Customers + class InvoiceCustomSectionsResolver < Resolvers::BaseResolver + end + end +end From 21c55c85054300dd4ff26a7f929c1e00d72a78bc Mon Sep 17 00:00:00 2001 From: Anna Velentsevich Date: Thu, 12 Dec 2024 15:24:14 +0100 Subject: [PATCH 10/10] update graphql schema --- schema.graphql | 2 +- schema.json | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/schema.graphql b/schema.graphql index 2d44d05489d..ee2a21d25a4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -6660,7 +6660,7 @@ type Query { Uniq ID of the invoice_custom_section """ id: ID! - ): InvoiceCustomSection + ): InvoiceCustomSection! """ Query invoice_custom_sections diff --git a/schema.json b/schema.json index 15d575b347b..c5f65174e8f 100644 --- a/schema.json +++ b/schema.json @@ -34392,9 +34392,13 @@ "name": "invoiceCustomSection", "description": "Query a single invoice_custom_section of an organization", "type": { - "kind": "OBJECT", - "name": "InvoiceCustomSection", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "InvoiceCustomSection", + "ofType": null + } }, "isDeprecated": false, "deprecationReason": null,