From 6eb1b742b988b86a24580b43fe0797f585dfbfcb Mon Sep 17 00:00:00 2001 From: Ancor Cruz Date: Thu, 21 Nov 2024 12:51:17 +0000 Subject: [PATCH 1/3] Update dunning campaign and threshold graphql types prep for update dunning campaings and its thresholds --- .../mutations/dunning_campaigns/update.rb | 2 +- .../{create_input.rb => input.rb} | 6 +- .../dunning_campaign_thresholds/object.rb | 2 + .../types/dunning_campaigns/create_input.rb | 2 +- .../types/dunning_campaigns/update_input.rb | 4 +- schema.graphql | 22 +- schema.json | 228 ++++++++++++++---- .../{create_input_spec.rb => input_spec.rb} | 4 +- .../object_spec.rb | 2 + .../dunning_campaigns/create_input_spec.rb | 2 +- 10 files changed, 209 insertions(+), 65 deletions(-) rename app/graphql/types/dunning_campaign_thresholds/{create_input.rb => input.rb} (63%) rename spec/graphql/types/dunning_campaign_thresholds/{create_input_spec.rb => input_spec.rb} (67%) diff --git a/app/graphql/mutations/dunning_campaigns/update.rb b/app/graphql/mutations/dunning_campaigns/update.rb index ecf07284592..ab96cd9c21b 100644 --- a/app/graphql/mutations/dunning_campaigns/update.rb +++ b/app/graphql/mutations/dunning_campaigns/update.rb @@ -9,7 +9,7 @@ class Update < BaseMutation REQUIRED_PERMISSION = "dunning_campaigns:update" graphql_name "UpdateDunningCampaign" - description "Updates a dunning campaign" + description "Updates a dunning campaign and its thresholds" input_object_class Types::DunningCampaigns::UpdateInput type Types::DunningCampaigns::Object diff --git a/app/graphql/types/dunning_campaign_thresholds/create_input.rb b/app/graphql/types/dunning_campaign_thresholds/input.rb similarity index 63% rename from app/graphql/types/dunning_campaign_thresholds/create_input.rb rename to app/graphql/types/dunning_campaign_thresholds/input.rb index dc55c6a375b..2ebe0274876 100644 --- a/app/graphql/types/dunning_campaign_thresholds/create_input.rb +++ b/app/graphql/types/dunning_campaign_thresholds/input.rb @@ -2,8 +2,10 @@ module Types module DunningCampaignThresholds - class CreateInput < Types::BaseInputObject - graphql_name "CreateDunningCampaignThresholdInput" + class Input < Types::BaseInputObject + graphql_name "DunningCampaignThresholdInput" + + argument :id, ID, required: false argument :amount_cents, GraphQL::Types::BigInt, required: true argument :currency, Types::CurrencyEnum, required: true diff --git a/app/graphql/types/dunning_campaign_thresholds/object.rb b/app/graphql/types/dunning_campaign_thresholds/object.rb index 8f632f0cff2..0da1403c70f 100644 --- a/app/graphql/types/dunning_campaign_thresholds/object.rb +++ b/app/graphql/types/dunning_campaign_thresholds/object.rb @@ -5,6 +5,8 @@ module DunningCampaignThresholds class Object < Types::BaseObject graphql_name "DunningCampaignThreshold" + field :id, ID, null: false + field :amount_cents, GraphQL::Types::BigInt, null: false field :currency, Types::CurrencyEnum, null: false end diff --git a/app/graphql/types/dunning_campaigns/create_input.rb b/app/graphql/types/dunning_campaigns/create_input.rb index c23cbced3d9..30bbd3ccb83 100644 --- a/app/graphql/types/dunning_campaigns/create_input.rb +++ b/app/graphql/types/dunning_campaigns/create_input.rb @@ -10,7 +10,7 @@ class CreateInput < Types::BaseInputObject argument :days_between_attempts, Integer, required: true argument :max_attempts, Integer, required: true argument :name, String, required: true - argument :thresholds, [Types::DunningCampaignThresholds::CreateInput], required: true + argument :thresholds, [Types::DunningCampaignThresholds::Input], required: true argument :description, String, required: false end diff --git a/app/graphql/types/dunning_campaigns/update_input.rb b/app/graphql/types/dunning_campaigns/update_input.rb index ffc8dc01061..95cdba24245 100644 --- a/app/graphql/types/dunning_campaigns/update_input.rb +++ b/app/graphql/types/dunning_campaigns/update_input.rb @@ -2,12 +2,10 @@ module Types module DunningCampaigns - class UpdateInput < Types::BaseInputObject + class UpdateInput < Types::DunningCampaigns::CreateInput graphql_name "UpdateDunningCampaignInput" argument :id, ID, required: true - - argument :applied_to_organization, Boolean, required: true end end end diff --git a/schema.graphql b/schema.graphql index 617991537b0..c4edac83450 100644 --- a/schema.graphql +++ b/schema.graphql @@ -2037,12 +2037,7 @@ input CreateDunningCampaignInput { description: String maxAttempts: Int! name: String! - thresholds: [CreateDunningCampaignThresholdInput!]! -} - -input CreateDunningCampaignThresholdInput { - amountCents: BigInt! - currency: CurrencyEnum! + thresholds: [DunningCampaignThresholdInput!]! } """ @@ -3814,6 +3809,13 @@ type DunningCampaignCollection { type DunningCampaignThreshold { amountCents: BigInt! currency: CurrencyEnum! + id: ID! +} + +input DunningCampaignThresholdInput { + amountCents: BigInt! + currency: CurrencyEnum! + id: ID } """ @@ -5625,7 +5627,7 @@ type Mutation { ): Wallet """ - Updates a dunning campaign + Updates a dunning campaign and its thresholds """ updateDunningCampaign( """ @@ -8120,7 +8122,13 @@ input UpdateDunningCampaignInput { A unique identifier for the client performing the mutation. """ clientMutationId: String + code: String! + daysBetweenAttempts: Int! + description: String id: ID! + maxAttempts: Int! + name: String! + thresholds: [DunningCampaignThresholdInput!]! } """ diff --git a/schema.json b/schema.json index 4a76fb7aed4..f740b024801 100644 --- a/schema.json +++ b/schema.json @@ -8176,7 +8176,7 @@ "name": null, "ofType": { "kind": "INPUT_OBJECT", - "name": "CreateDunningCampaignThresholdInput", + "name": "DunningCampaignThresholdInput", "ofType": null } } @@ -8213,49 +8213,6 @@ ], "enumValues": null }, - { - "kind": "INPUT_OBJECT", - "name": "CreateDunningCampaignThresholdInput", - "description": null, - "interfaces": null, - "possibleTypes": null, - "fields": null, - "inputFields": [ - { - "name": "amountCents", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "BigInt", - "ofType": null - } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - }, - { - "name": "currency", - "description": null, - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "ENUM", - "name": "CurrencyEnum", - "ofType": null - } - }, - "defaultValue": null, - "isDeprecated": false, - "deprecationReason": null - } - ], - "enumValues": null - }, { "kind": "INPUT_OBJECT", "name": "CreateHubspotIntegrationInput", @@ -17122,12 +17079,85 @@ "deprecationReason": null, "args": [ + ] + }, + { + "name": "id", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null, + "args": [ + ] } ], "inputFields": null, "enumValues": null }, + { + "kind": "INPUT_OBJECT", + "name": "DunningCampaignThresholdInput", + "description": null, + "interfaces": null, + "possibleTypes": null, + "fields": null, + "inputFields": [ + { + "name": "id", + "description": null, + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "amountCents", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "BigInt", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "currency", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "CurrencyEnum", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + } + ], + "enumValues": null + }, { "kind": "ENUM", "name": "EmailSettingsEnum", @@ -26961,7 +26991,7 @@ }, { "name": "updateDunningCampaign", - "description": "Updates a dunning campaign", + "description": "Updates a dunning campaign and its thresholds", "type": { "kind": "OBJECT", "name": "DunningCampaign", @@ -40148,14 +40178,14 @@ "fields": null, "inputFields": [ { - "name": "id", + "name": "appliedToOrganization", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "ID", + "name": "Boolean", "ofType": null } }, @@ -40164,14 +40194,114 @@ "deprecationReason": null }, { - "name": "appliedToOrganization", + "name": "code", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "daysBetweenAttempts", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "maxAttempts", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "thresholds", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DunningCampaignThresholdInput", + "ofType": null + } + } + } + }, + "defaultValue": null, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "description", + "description": null, + "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 } }, diff --git a/spec/graphql/types/dunning_campaign_thresholds/create_input_spec.rb b/spec/graphql/types/dunning_campaign_thresholds/input_spec.rb similarity index 67% rename from spec/graphql/types/dunning_campaign_thresholds/create_input_spec.rb rename to spec/graphql/types/dunning_campaign_thresholds/input_spec.rb index 86d87030cbf..b49d70bd384 100644 --- a/spec/graphql/types/dunning_campaign_thresholds/create_input_spec.rb +++ b/spec/graphql/types/dunning_campaign_thresholds/input_spec.rb @@ -2,9 +2,11 @@ require "rails_helper" -RSpec.describe Types::DunningCampaignThresholds::CreateInput do +RSpec.describe Types::DunningCampaignThresholds::Input do subject { described_class } + it { is_expected.to accept_argument(:id).of_type("ID") } + it { is_expected.to accept_argument(:amount_cents).of_type("BigInt!") } it { is_expected.to accept_argument(:currency).of_type("CurrencyEnum!") } end diff --git a/spec/graphql/types/dunning_campaign_thresholds/object_spec.rb b/spec/graphql/types/dunning_campaign_thresholds/object_spec.rb index b5517219278..36ed6bb3915 100644 --- a/spec/graphql/types/dunning_campaign_thresholds/object_spec.rb +++ b/spec/graphql/types/dunning_campaign_thresholds/object_spec.rb @@ -5,6 +5,8 @@ RSpec.describe Types::DunningCampaignThresholds::Object do subject { described_class } + it { is_expected.to have_field(:id).of_type('ID!') } + it { is_expected.to have_field(:amount_cents).of_type("BigInt!") } it { is_expected.to have_field(:currency).of_type("CurrencyEnum!") } end diff --git a/spec/graphql/types/dunning_campaigns/create_input_spec.rb b/spec/graphql/types/dunning_campaigns/create_input_spec.rb index a5dd6d6b083..c4e1e826139 100644 --- a/spec/graphql/types/dunning_campaigns/create_input_spec.rb +++ b/spec/graphql/types/dunning_campaigns/create_input_spec.rb @@ -10,7 +10,7 @@ it { is_expected.to accept_argument(:days_between_attempts).of_type('Int!') } it { is_expected.to accept_argument(:max_attempts).of_type('Int!') } it { is_expected.to accept_argument(:name).of_type('String!') } - it { is_expected.to accept_argument(:thresholds).of_type('[CreateDunningCampaignThresholdInput!]!') } + it { is_expected.to accept_argument(:thresholds).of_type('[DunningCampaignThresholdInput!]!') } it { is_expected.to accept_argument(:description).of_type('String') } end From 91cee8c41b211ff92dd0523848c7a5b0cbe8b0ab Mon Sep 17 00:00:00 2001 From: Ancor Cruz Date: Thu, 21 Nov 2024 13:01:08 +0000 Subject: [PATCH 2/3] Update DunningCampaing Update mutation spec with full payload actual update is not yet implemented, we are focusing on frontend required changes. --- .../dunning_campaigns/update_spec.rb | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/spec/graphql/mutations/dunning_campaigns/update_spec.rb b/spec/graphql/mutations/dunning_campaigns/update_spec.rb index ff7ae6b9839..c9ca2688268 100644 --- a/spec/graphql/mutations/dunning_campaigns/update_spec.rb +++ b/spec/graphql/mutations/dunning_campaigns/update_spec.rb @@ -9,6 +9,9 @@ let(:dunning_campaign) do create(:dunning_campaign, organization:, applied_to_organization: true) end + let(:dunning_campaign_threshold) do + create(:dunning_campaign_threshold, dunning_campaign:) + end let(:mutation) do <<-GQL @@ -23,6 +26,25 @@ GQL end + let(:input) do + { + id: dunning_campaign.id, + name: "Updated Dunning campaign name", + code: "updated-dunning-campaign-code", + description: "Updated Dunning campaign description", + maxAttempts: 99, + daysBetweenAttempts: 7, + appliedToOrganization: false, + thresholds: [ + { + id: dunning_campaign_threshold.id, + amountCents: 999_00, + currency: "USD" + } + ] + } + end + around { |test| lago_premium!(&test) } before do @@ -39,19 +61,15 @@ current_organization: organization, permissions: required_permission, query: mutation, - variables: { - input: { - id: dunning_campaign.id, - appliedToOrganization: false - } - } + variables: {input:} ) + # TODO: update expectation with dunning campaign changes after update service implementation. expect(result["data"]["updateDunningCampaign"]).to include( "id" => String, "name" => dunning_campaign.name, "code" => dunning_campaign.code, - "appliedToOrganization" => false + "appliedToOrganization" => input[:appliedToOrganization] ) end end From d403add8baa50d5a27cec28e78514139acacb88a Mon Sep 17 00:00:00 2001 From: Ancor Cruz Date: Fri, 22 Nov 2024 09:55:18 +0000 Subject: [PATCH 3/3] DunningCampaign UpdateInput type have all arguments not required except ID. This change is a frontend requirement --- .../types/dunning_campaigns/update_input.rb | 10 ++- schema.graphql | 12 +-- schema.json | 88 +++++++------------ .../dunning_campaigns/update_input_spec.rb | 8 +- 4 files changed, 54 insertions(+), 64 deletions(-) diff --git a/app/graphql/types/dunning_campaigns/update_input.rb b/app/graphql/types/dunning_campaigns/update_input.rb index 95cdba24245..fcfb625eb6a 100644 --- a/app/graphql/types/dunning_campaigns/update_input.rb +++ b/app/graphql/types/dunning_campaigns/update_input.rb @@ -2,10 +2,18 @@ module Types module DunningCampaigns - class UpdateInput < Types::DunningCampaigns::CreateInput + class UpdateInput < Types::BaseInputObject graphql_name "UpdateDunningCampaignInput" argument :id, ID, required: true + + argument :applied_to_organization, Boolean, required: false + argument :code, String, required: false + argument :days_between_attempts, Integer, required: false + argument :description, String, required: false + argument :max_attempts, Integer, required: false + argument :name, String, required: false + argument :thresholds, [Types::DunningCampaignThresholds::Input], required: false end end end diff --git a/schema.graphql b/schema.graphql index c4edac83450..4a4109bffd4 100644 --- a/schema.graphql +++ b/schema.graphql @@ -8116,19 +8116,19 @@ input UpdateCustomerWalletInput { Autogenerated input type of UpdateDunningCampaign """ input UpdateDunningCampaignInput { - appliedToOrganization: Boolean! + appliedToOrganization: Boolean """ A unique identifier for the client performing the mutation. """ clientMutationId: String - code: String! - daysBetweenAttempts: Int! + code: String + daysBetweenAttempts: Int description: String id: ID! - maxAttempts: Int! - name: String! - thresholds: [DunningCampaignThresholdInput!]! + maxAttempts: Int + name: String + thresholds: [DunningCampaignThresholdInput!] } """ diff --git a/schema.json b/schema.json index f740b024801..a3e3ecf324b 100644 --- a/schema.json +++ b/schema.json @@ -40178,14 +40178,14 @@ "fields": null, "inputFields": [ { - "name": "appliedToOrganization", + "name": "id", "description": null, "type": { "kind": "NON_NULL", "name": null, "ofType": { "kind": "SCALAR", - "name": "Boolean", + "name": "ID", "ofType": null } }, @@ -40194,95 +40194,67 @@ "deprecationReason": null }, { - "name": "code", + "name": "appliedToOrganization", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "Boolean", + "ofType": null }, "defaultValue": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "daysBetweenAttempts", + "name": "code", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "defaultValue": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "maxAttempts", + "name": "daysBetweenAttempts", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - } + "kind": "SCALAR", + "name": "Int", + "ofType": null }, "defaultValue": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "name", + "name": "description", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } + "kind": "SCALAR", + "name": "String", + "ofType": null }, "defaultValue": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "thresholds", + "name": "maxAttempts", "description": null, "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "INPUT_OBJECT", - "name": "DunningCampaignThresholdInput", - "ofType": null - } - } - } + "kind": "SCALAR", + "name": "Int", + "ofType": null }, "defaultValue": null, "isDeprecated": false, "deprecationReason": null }, { - "name": "description", + "name": "name", "description": null, "type": { "kind": "SCALAR", @@ -40294,15 +40266,19 @@ "deprecationReason": null }, { - "name": "id", + "name": "thresholds", "description": null, "type": { - "kind": "NON_NULL", + "kind": "LIST", "name": null, "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DunningCampaignThresholdInput", + "ofType": null + } } }, "defaultValue": null, diff --git a/spec/graphql/types/dunning_campaigns/update_input_spec.rb b/spec/graphql/types/dunning_campaigns/update_input_spec.rb index 072d3838319..0fde6594fda 100644 --- a/spec/graphql/types/dunning_campaigns/update_input_spec.rb +++ b/spec/graphql/types/dunning_campaigns/update_input_spec.rb @@ -7,5 +7,11 @@ it { is_expected.to accept_argument(:id).of_type('ID!') } - it { is_expected.to accept_argument(:applied_to_organization).of_type('Boolean!') } + it { is_expected.to accept_argument(:applied_to_organization).of_type('Boolean') } + it { is_expected.to accept_argument(:code).of_type('String') } + it { is_expected.to accept_argument(:days_between_attempts).of_type('Int') } + it { is_expected.to accept_argument(:description).of_type('String') } + it { is_expected.to accept_argument(:max_attempts).of_type('Int') } + it { is_expected.to accept_argument(:name).of_type('String') } + it { is_expected.to accept_argument(:thresholds).of_type('[DunningCampaignThresholdInput!]') } end