From 572aa0f4a96a56b3fd65dfaf2857d8c8985d024c Mon Sep 17 00:00:00 2001 From: Blake Erickson Date: Tue, 16 Jul 2024 11:54:56 -0600 Subject: [PATCH] FIX: Exception with campaign refresh data job (#222) Depending on the invoices in stripe there could be some nil values for things so we need to account for those in this job or an exception will be thrown causing the job to fail. --- .../discourse_subscriptions/campaign.rb | 38 ++++++++++--------- spec/services/campaign_spec.rb | 18 +++++++++ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/app/services/discourse_subscriptions/campaign.rb b/app/services/discourse_subscriptions/campaign.rb index 16aec62..365a9d9 100644 --- a/app/services/discourse_subscriptions/campaign.rb +++ b/app/services/discourse_subscriptions/campaign.rb @@ -154,26 +154,30 @@ module DiscourseSubscriptions all_invoices = ::Stripe::Invoice.list(limit: 100, starting_after: current_set[:last_record]) - current_set[:last_record] = all_invoices[:data].last[:id] if all_invoices[:data].present? - current_set[:has_more] = all_invoices[:has_more] + if all_invoices[:data].present? + current_set[:last_record] = all_invoices[:data].last[:id] + current_set[:has_more] = all_invoices[:has_more] - all_invoices[:data].each do |invoice| - customer_id = invoice[:customer] - next if invoice[:paid] != true - line_item = invoice[:lines][:data][0] if invoice[:lines] && invoice[:lines][:data] # Discourse only makes single-line item charges - # check if non-subscription and that the plan is active - if line_item[:plan] == nil && line_item[:price] && - line_item[:price][:recurring] == nil && line_item[:price][:active] == true - product_id = line_item[:price][:product] - if product_ids.include? product_id - line_data = { - customer_id: customer_id, - product_id: product_id, - price: line_item[:price][:unit_amount], - } - one_time_payments << line_data + all_invoices[:data].each do |invoice| + customer_id = invoice[:customer] + next if invoice[:paid] != true + line_item = invoice[:lines][:data][0] if invoice[:lines] && invoice[:lines][:data] # Discourse only makes single-line item charges + # check if non-subscription and that the plan is active + if line_item && line_item[:plan] == nil && line_item[:price] && + line_item[:price][:recurring] == nil && line_item[:price][:active] == true + product_id = line_item[:price][:product] + if product_ids.include? product_id + line_data = { + customer_id: customer_id, + product_id: product_id, + price: line_item[:price][:unit_amount], + } + one_time_payments << line_data + end end end + else + current_set[:has_more] = false end end end diff --git a/spec/services/campaign_spec.rb b/spec/services/campaign_spec.rb index 116439a..241d9ae 100644 --- a/spec/services/campaign_spec.rb +++ b/spec/services/campaign_spec.rb @@ -62,6 +62,10 @@ describe DiscourseSubscriptions::Campaign do }, } end + let(:invoice_with_nil_lines) { { id: "in_1236", paid: true, lines: nil } } + let(:invoice_with_nil_price) do + { id: "in_1237", paid: true, lines: { data: [{ plan: nil, price: nil }] } } + end before do Fabricate(:product, external_id: "prodct_23456") @@ -104,6 +108,20 @@ describe DiscourseSubscriptions::Campaign do DiscourseSubscriptions::Campaign.new.refresh_data expect(Discourse.redis.get("subscriptions_goal_met_date")).to be_blank end + + it "handles invoices with nil lines gracefully" do + ::Stripe::Subscription.expects(:list).returns(data: [subscription], has_more: false) + ::Stripe::Invoice.expects(:list).returns(data: [invoice_with_nil_lines], has_more: false) + + expect { DiscourseSubscriptions::Campaign.new.refresh_data }.not_to raise_error + end + + it "handles invoices with nil price gracefully" do + ::Stripe::Subscription.expects(:list).returns(data: [subscription], has_more: false) + ::Stripe::Invoice.expects(:list).returns(data: [invoice_with_nil_price], has_more: false) + + expect { DiscourseSubscriptions::Campaign.new.refresh_data }.not_to raise_error + end end context "with a campaign product set" do