From 2968e50f38396bb99eaa1ad1d0a537b13af39349 Mon Sep 17 00:00:00 2001 From: Graeme Porteous Date: Mon, 29 Jul 2024 15:18:28 +0100 Subject: [PATCH 1/4] Add missing specs for invoice wrapper --- spec/models/alaveteli_pro/invoice_spec.rb | 74 +++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 spec/models/alaveteli_pro/invoice_spec.rb diff --git a/spec/models/alaveteli_pro/invoice_spec.rb b/spec/models/alaveteli_pro/invoice_spec.rb new file mode 100644 index 0000000000..ecbde6f709 --- /dev/null +++ b/spec/models/alaveteli_pro/invoice_spec.rb @@ -0,0 +1,74 @@ +require 'spec_helper' + +RSpec.describe AlaveteliPro::Invoice, type: :model do + let(:invoice) { AlaveteliPro::Invoice.new(stripe_invoice) } + + let(:stripe_invoice) do + double('Stripe::Invoice', + status: 'open', charge: 'ch_123', date: 1722211200) + end + + let(:stripe_charge) do + double('Stripe::Charge', receipt_url: 'http://example.com/receipt') + end + + before do + allow(Stripe::Charge). + to receive(:retrieve).with('ch_123').and_return(stripe_charge) + end + + describe '#open?' do + it 'returns true when the status is open' do + expect(invoice).to be_open + end + + it 'returns false when the status is not open' do + allow(stripe_invoice).to receive(:status).and_return('paid') + expect(invoice).not_to be_open + end + end + + describe '#paid?' do + it 'returns true when the status is paid' do + allow(stripe_invoice).to receive(:status).and_return('paid') + expect(invoice).to be_paid + end + + it 'returns false when the status is not paid' do + expect(invoice).not_to be_paid + end + end + + describe '#date' do + it 'returns a date object for the invoice' do + with_env_tz 'UTC' do + expect(invoice.date).to eq(Date.new(2024, 7, 29)) + end + end + end + + describe '#charge' do + it 'returns a Stripe::Charge object' do + expect(invoice.charge).to eq(stripe_charge) + end + + it 'memoizes the Stripe::Charge object' do + expect(Stripe::Charge).to receive(:retrieve).once.with('ch_123') + 2.times { invoice.charge } + end + end + + describe '#receipt_url' do + it 'delegates receipt_url to the charge' do + expect(invoice.receipt_url).to eq('http://example.com/receipt') + end + end + + describe '#method_missing' do + it 'forwards missing methods to the original object' do + allow(stripe_invoice). + to receive(:some_missing_method).and_return('result') + expect(invoice.some_missing_method).to eq('result') + end + end +end From 7bb9a7544d00e9f2784a66eebd99951f95236955 Mon Sep 17 00:00:00 2001 From: Graeme Porteous Date: Mon, 29 Jul 2024 15:23:13 +0100 Subject: [PATCH 2/4] Update AlaveteiPro::Invoice#receipt_url Return nil if there is no Stripe charge. This happens when the invoice has been 100% discounted. --- app/models/alaveteli_pro/invoice.rb | 5 +++-- spec/models/alaveteli_pro/invoice_spec.rb | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/models/alaveteli_pro/invoice.rb b/app/models/alaveteli_pro/invoice.rb index b982ba10e8..5fa5b3cbe5 100644 --- a/app/models/alaveteli_pro/invoice.rb +++ b/app/models/alaveteli_pro/invoice.rb @@ -20,10 +20,11 @@ def date # charge def charge - @charge ||= Stripe::Charge.retrieve(__getobj__.charge) + charge_id = __getobj__.charge + @charge ||= Stripe::Charge.retrieve(charge_id) if charge_id end - delegate :receipt_url, to: :charge + delegate :receipt_url, to: :charge, allow_nil: true private diff --git a/spec/models/alaveteli_pro/invoice_spec.rb b/spec/models/alaveteli_pro/invoice_spec.rb index ecbde6f709..48fe17d0e3 100644 --- a/spec/models/alaveteli_pro/invoice_spec.rb +++ b/spec/models/alaveteli_pro/invoice_spec.rb @@ -62,6 +62,11 @@ it 'delegates receipt_url to the charge' do expect(invoice.receipt_url).to eq('http://example.com/receipt') end + + it 'returns nil when there is no charge' do + allow(stripe_invoice).to receive(:charge).and_return(nil) + expect(invoice.receipt_url).to be_nil + end end describe '#method_missing' do From ca930ce5183e3695653fef4edd7923b009fd57b1 Mon Sep 17 00:00:00 2001 From: Graeme Porteous Date: Mon, 29 Jul 2024 15:24:12 +0100 Subject: [PATCH 3/4] Update AlaveteliPro::Invoice#paid? Return false if the invoice has been 100% discounted. This will prevent the "View Receipt" link being rendered when there is no payment receipt. --- app/models/alaveteli_pro/invoice.rb | 2 +- spec/models/alaveteli_pro/invoice_spec.rb | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/models/alaveteli_pro/invoice.rb b/app/models/alaveteli_pro/invoice.rb index 5fa5b3cbe5..750fb0827c 100644 --- a/app/models/alaveteli_pro/invoice.rb +++ b/app/models/alaveteli_pro/invoice.rb @@ -10,7 +10,7 @@ def open? end def paid? - status == 'paid' + status == 'paid' && amount_paid > 0 end # attributes diff --git a/spec/models/alaveteli_pro/invoice_spec.rb b/spec/models/alaveteli_pro/invoice_spec.rb index 48fe17d0e3..ce0ef784ee 100644 --- a/spec/models/alaveteli_pro/invoice_spec.rb +++ b/spec/models/alaveteli_pro/invoice_spec.rb @@ -5,7 +5,7 @@ let(:stripe_invoice) do double('Stripe::Invoice', - status: 'open', charge: 'ch_123', date: 1722211200) + status: 'open', charge: 'ch_123', date: 1722211200, amount_paid: 0) end let(:stripe_charge) do @@ -29,12 +29,19 @@ end describe '#paid?' do - it 'returns true when the status is paid' do + it 'returns true when the status is paid and an amount has been paid' do allow(stripe_invoice).to receive(:status).and_return('paid') + allow(stripe_invoice).to receive(:amount_paid).and_return(1000) expect(invoice).to be_paid end + it 'returns false when 100% discounted' do + allow(stripe_invoice).to receive(:status).and_return('paid') + expect(invoice).not_to be_paid + end + it 'returns false when the status is not paid' do + allow(stripe_invoice).to receive(:amount_paid).and_return(1000) expect(invoice).not_to be_paid end end From db3ea764e3d52ee3babd15c0fe722d5f8efd07bf Mon Sep 17 00:00:00 2001 From: Graeme Porteous Date: Mon, 29 Jul 2024 15:28:08 +0100 Subject: [PATCH 4/4] Update changelog --- doc/CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/CHANGES.md b/doc/CHANGES.md index 5a0822f0a9..2f26951658 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -2,6 +2,8 @@ ## Highlighted Features +* Fix rendering invoices page when there are discounted Pro subscription (Graeme + Porteous) * Drop support for Ruby 3.0 (Graeme Porteous) * Allow projects owners to publish datasets (Graeme Porteous) * Add comment deletion (Helen Cross, Graeme Porteous, Gareth Rees)