diff --git a/app/models/spree/gateway.rb b/app/models/spree/gateway.rb index e08a4e0ca0..1ab4e8808f 100644 --- a/app/models/spree/gateway.rb +++ b/app/models/spree/gateway.rb @@ -17,31 +17,6 @@ module Spree %w{capture_and_complete_order void credit resend_authorization_email} end - # Indicates whether its possible to capture the payment - def can_capture_and_complete_order?(payment) - return false if payment.requires_authorization? - - payment.pending? || payment.checkout? - end - - # Indicates whether its possible to void the payment. - def can_void?(payment) - !payment.void? - end - - # Indicates whether its possible to credit the payment. Note that most gateways require that the - # payment be settled first which generally happens within 12-24 hours of the transaction. - def can_credit?(payment) - return false unless payment.completed? - return false unless payment.order.payment_state == 'credit_owed' - - payment.credit_allowed.positive? - end - - def can_resend_authorization_email?(payment) - payment.requires_authorization? - end - def payment_source_class CreditCard end diff --git a/app/models/spree/payment.rb b/app/models/spree/payment.rb index 7953d71a3c..f8aef25daa 100644 --- a/app/models/spree/payment.rb +++ b/app/models/spree/payment.rb @@ -11,6 +11,13 @@ module Spree localize_number :amount + # All possible actions offered to shop owners. + ACTIONS = %w[ + capture_and_complete_order + void + credit + resend_authorization_email + ].freeze IDENTIFIER_CHARS = (('A'..'Z').to_a + ('0'..'9').to_a - %w(0 1 I O)).freeze delegate :line_items, to: :order @@ -152,11 +159,33 @@ module Spree end def actions - return [] unless payment_method.respond_to?(:actions) + supported = ACTIONS & payment_method.actions.to_a + supported.select { public_send("can_#{it}?") } + end - payment_method.actions.select do |action| - payment_method.__send__("can_#{action}?", self) - end + # Indicates whether its possible to capture the payment + def can_capture_and_complete_order? + return false if requires_authorization? + + pending? || checkout? + end + + # Indicates whether its possible to void the payment. + def can_void? + !void? + end + + # Indicates whether its possible to credit the payment. Note that most gateways require that the + # payment be settled first which generally happens within 12-24 hours of the transaction. + def can_credit? + return false unless completed? + return false unless order.payment_state == "credit_owed" + + credit_allowed.positive? + end + + def can_resend_authorization_email? + requires_authorization? end def resend_authorization_email! diff --git a/app/models/spree/payment_method/check.rb b/app/models/spree/payment_method/check.rb index 839698bebc..0a931f9f17 100644 --- a/app/models/spree/payment_method/check.rb +++ b/app/models/spree/payment_method/check.rb @@ -7,16 +7,6 @@ module Spree %w{capture_and_complete_order void} end - # Indicates whether its possible to capture the payment - def can_capture_and_complete_order?(payment) - ['checkout', 'pending'].include?(payment.state) - end - - # Indicates whether its possible to void the payment. - def can_void?(payment) - payment.state != 'void' - end - def capture(*_args) ActiveMerchant::Billing::Response.new(true, "", {}, {}) end diff --git a/app/models/spree/payment_method/taler.rb b/app/models/spree/payment_method/taler.rb index 479f06811e..9fa8d00caf 100644 --- a/app/models/spree/payment_method/taler.rb +++ b/app/models/spree/payment_method/taler.rb @@ -25,10 +25,6 @@ module Spree %w{void} end - def can_void?(payment) - payment.state == "completed" - end - # Name of the view to display during checkout def method_type "check" # empty view diff --git a/spec/models/spree/gateway_spec.rb b/spec/models/spree/gateway_spec.rb index 3ff9dc0741..41f81bdd84 100644 --- a/spec/models/spree/gateway_spec.rb +++ b/spec/models/spree/gateway_spec.rb @@ -23,51 +23,4 @@ RSpec.describe Spree::Gateway do it "raises an error in test env" do expect { gateway.imaginary_method('foo') }.to raise_error StandardError end - - describe "#can_capture?" do - it "should be true if payment is pending" do - payment = build_stubbed(:payment, created_at: Time.zone.now) - allow(payment).to receive(:pending?) { true } - expect(gateway.can_capture_and_complete_order?(payment)).to be_truthy - end - - it "should be true if payment is checkout" do - payment = build_stubbed(:payment, created_at: Time.zone.now) - allow(payment).to receive_messages pending?: false, - checkout?: true - expect(gateway.can_capture_and_complete_order?(payment)).to be_truthy - end - end - - describe "#can_void?" do - it "should be true if payment is not void" do - payment = build_stubbed(:payment) - allow(payment).to receive(:void?) { false } - expect(gateway.can_void?(payment)).to be_truthy - end - end - - describe "#can_credit?" do - it "should be false if payment is not completed" do - payment = build_stubbed(:payment) - allow(payment).to receive(:completed?) { false } - expect(gateway.can_credit?(payment)).to be_falsy - end - - it "should be false when order payment_state is not 'credit_owed'" do - payment = build_stubbed(:payment, - order: create(:order, payment_state: 'paid')) - allow(payment).to receive(:completed?) { true } - expect(gateway.can_credit?(payment)).to be_falsy - end - - it "should be false when credit_allowed is zero" do - payment = build_stubbed(:payment, - order: create(:order, payment_state: 'credit_owed')) - allow(payment).to receive_messages completed?: true, - credit_allowed: 0 - - expect(gateway.can_credit?(payment)).to be_falsy - end - end end diff --git a/spec/models/spree/payment_spec.rb b/spec/models/spree/payment_spec.rb index cc6e8b029c..48dd75df95 100644 --- a/spec/models/spree/payment_spec.rb +++ b/spec/models/spree/payment_spec.rb @@ -855,7 +855,8 @@ RSpec.describe Spree::Payment do describe "available actions" do context "for most gateways" do - let(:payment) { build_stubbed(:payment, source: build_stubbed(:credit_card)) } + let(:payment) { build_stubbed(:payment, payment_method:) } + let(:payment_method) { Spree::Gateway::StripeSCA.new } it "can capture and void" do expect(payment.actions).to match_array %w(capture_and_complete_order void) @@ -872,6 +873,53 @@ RSpec.describe Spree::Payment do end end end + + describe "#can_capture_and_complete_order?" do + it "should be true if payment is pending" do + payment = build_stubbed(:payment, created_at: Time.zone.now) + allow(payment).to receive(:pending?) { true } + expect(payment.can_capture_and_complete_order?).to be_truthy + end + + it "should be true if payment is checkout" do + payment = build_stubbed(:payment, created_at: Time.zone.now) + allow(payment).to receive_messages pending?: false, + checkout?: true + expect(payment.can_capture_and_complete_order?).to be_truthy + end + end + + describe "#can_void?" do + it "should be true if payment is not void" do + payment = build_stubbed(:payment) + allow(payment).to receive(:void?) { false } + expect(payment.can_void?).to be_truthy + end + end + + describe "#can_credit?" do + it "should be false if payment is not completed" do + payment = build_stubbed(:payment) + allow(payment).to receive(:completed?) { false } + expect(payment.can_credit?).to be_falsy + end + + it "should be false when order payment_state is not 'credit_owed'" do + payment = build_stubbed(:payment, + order: create(:order, payment_state: 'paid')) + allow(payment).to receive(:completed?) { true } + expect(payment.can_credit?).to be_falsy + end + + it "should be false when credit_allowed is zero" do + payment = build_stubbed(:payment, + order: create(:order, payment_state: 'credit_owed')) + allow(payment).to receive_messages completed?: true, + credit_allowed: 0 + + expect(payment.can_credit?).to be_falsy + end + end end describe "refund!" do