Skip to content

Commit

Permalink
feat(dunning): Filter dunning campaigns by threshold currency (#2719)
Browse files Browse the repository at this point in the history
## Roadmap Task

πŸ‘‰ https://getlago.canny.io/feature-requests/p/set-up-payment-retry-logic
πŸ‘‰
https://getlago.canny.io/feature-requests/p/send-reminders-for-overdue-invoices

 ## Context

We want to automate dunning process so that our users don't have to look
at each customer to maximize their chances of being paid retrying
payments of overdue balances and sending email reminders.

We're first automating the overdue balance payment request, before
looking at individual invoices.

 ## Description

Add filter to dunning campaigns resolver to request campaigns in a give
set of currencies. This will allow to display only relevant campaigns
matching customer currency.
  • Loading branch information
ancorcruz authored Oct 22, 2024
1 parent 09e5693 commit f55a4c6
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 12 deletions.
7 changes: 6 additions & 1 deletion app/graphql/resolvers/dunning_campaigns_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class DunningCampaignsResolver < Resolvers::BaseResolver
REQUIRED_PERMISSION = "dunning_campaigns:view"

argument :applied_to_organization, Boolean, required: false
argument :currency, [Types::CurrencyEnum], required: false
argument :limit, Integer, required: false
argument :order, String, required: false
argument :page, Integer, required: false
Expand All @@ -19,6 +20,7 @@ class DunningCampaignsResolver < Resolvers::BaseResolver

def resolve( # rubocop:disable Metrics/ParameterLists
applied_to_organization: nil,
currency: nil,
order: nil,
page: nil,
limit: nil,
Expand All @@ -29,7 +31,10 @@ def resolve( # rubocop:disable Metrics/ParameterLists
search_term:,
order:,
pagination: {page:, limit:},
filters: {applied_to_organization:}
filters: {
applied_to_organization:,
currency:
}
)

result.dunning_campaigns
Expand Down
8 changes: 8 additions & 0 deletions app/queries/dunning_campaigns_query.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ def call
dunning_campaigns = dunning_campaigns.order(order)

dunning_campaigns = with_applied_to_organization(dunning_campaigns) unless filters.applied_to_organization.nil?
dunning_campaigns = with_currency_threshold(dunning_campaigns) if filters.currency.present?

result.dunning_campaigns = dunning_campaigns
result
Expand Down Expand Up @@ -37,4 +38,11 @@ def order
def with_applied_to_organization(scope)
scope.where(applied_to_organization: filters.applied_to_organization)
end

def with_currency_threshold(scope)
scope
.joins(:thresholds)
.where(dunning_campaign_thresholds: {currency: filters.currency})
.distinct
end
end
2 changes: 1 addition & 1 deletion schema.graphql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions schema.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 38 additions & 1 deletion spec/graphql/resolvers/dunning_campaigns_resolver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,44 @@

dunning_campaigns_response = result["data"]["dunningCampaigns"]

aggregate_failures do
expect(dunning_campaigns_response["collection"].first).to include(
"id" => dunning_campaign.id,
"name" => dunning_campaign.name
)

expect(dunning_campaigns_response["metadata"]).to include(
"currentPage" => 1,
"totalCount" => 1
)
end

context "when filtering by threshold currency" do
let(:query) do
<<~GQL
query {
dunningCampaigns(limit: 5, currency: [EUR]) {
collection { id name }
metadata { currentPage, totalCount }
}
}
GQL
end

before do
create(:dunning_campaign, organization:)
create(:dunning_campaign_threshold, dunning_campaign:, currency: "EUR")
end

it "returns all dunning campaigns with currency threshold" do
result = execute_graphql(
current_user: membership.user,
current_organization: organization,
permissions: required_permission,
query:
)

dunning_campaigns_response = result["data"]["dunningCampaigns"]

expect(dunning_campaigns_response["collection"].first).to include(
"id" => dunning_campaign.id,
"name" => dunning_campaign.name
Expand Down
74 changes: 65 additions & 9 deletions spec/queries/dunning_campaigns_query_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,13 @@
let(:pagination) { {page: 2, limit: 2} }

it "applies the pagination", :aggregate_failures do
aggregate_failures do
expect(result).to be_success
expect(result.dunning_campaigns.count).to eq(1)
expect(result.dunning_campaigns.current_page).to eq(2)
expect(result.dunning_campaigns.prev_page).to eq(1)
expect(result.dunning_campaigns.next_page).to be_nil
expect(result.dunning_campaigns.total_pages).to eq(2)
expect(result.dunning_campaigns.total_count).to eq(3)
end
expect(result).to be_success
expect(result.dunning_campaigns.count).to eq(1)
expect(result.dunning_campaigns.current_page).to eq(2)
expect(result.dunning_campaigns.prev_page).to eq(1)
expect(result.dunning_campaigns.next_page).to be_nil
expect(result.dunning_campaigns.total_pages).to eq(2)
expect(result.dunning_campaigns.total_count).to eq(3)
end
end

Expand Down Expand Up @@ -82,6 +80,64 @@
end
end

context "with currency filter" do
let(:filters) { {currency: "USD"} }

before do
create(
:dunning_campaign_threshold,
dunning_campaign: dunning_campaign_first,
currency: "USD"
)

create(
:dunning_campaign_threshold,
dunning_campaign: dunning_campaign_first,
currency: "GBP"
)

create(
:dunning_campaign_threshold,
dunning_campaign: dunning_campaign_third,
currency: "EUR"
)
end

it "returns only dunning campaigns with a threshold matching the currency" do
expect(result.dunning_campaigns).to eq([dunning_campaign_first])
end

context "with multiple currencies" do
let(:filters) { {currency: ["USD", "EUR"]} }

let(:dunning_campaign_fourth) { create(:dunning_campaign, organization:) }

before do
create(
:dunning_campaign_threshold,
dunning_campaign: dunning_campaign_fourth,
currency: "EUR"
)

create(
:dunning_campaign_threshold,
dunning_campaign: dunning_campaign_fourth,
currency: "USD"
)
end

it "returns only dunning campaigns with a threshold matching the currency" do
expect(result.dunning_campaigns).to eq(
[
dunning_campaign_fourth,
dunning_campaign_first,
dunning_campaign_third
]
)
end
end
end

context "with order on code" do
let(:order) { "code" }

Expand Down

0 comments on commit f55a4c6

Please sign in to comment.