diff --git a/app/models/spree/gateway.rb b/app/models/spree/gateway.rb index 1ab4e8808f..e08a4e0ca0 100644 --- a/app/models/spree/gateway.rb +++ b/app/models/spree/gateway.rb @@ -17,6 +17,31 @@ 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 f8aef25daa..7953d71a3c 100644 --- a/app/models/spree/payment.rb +++ b/app/models/spree/payment.rb @@ -11,13 +11,6 @@ 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 @@ -159,33 +152,11 @@ module Spree end def actions - supported = ACTIONS & payment_method.actions.to_a - supported.select { public_send("can_#{it}?") } - end + return [] unless payment_method.respond_to?(:actions) - # 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? + payment_method.actions.select do |action| + payment_method.__send__("can_#{action}?", self) + end end def resend_authorization_email! diff --git a/app/models/spree/payment_method/check.rb b/app/models/spree/payment_method/check.rb index 0a931f9f17..839698bebc 100644 --- a/app/models/spree/payment_method/check.rb +++ b/app/models/spree/payment_method/check.rb @@ -7,6 +7,16 @@ 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 2ee18757e6..fb89e42a1d 100644 --- a/app/models/spree/payment_method/taler.rb +++ b/app/models/spree/payment_method/taler.rb @@ -25,6 +25,17 @@ module Spree %w[credit void] end + def can_void?(payment) + payment.state == "completed" + end + + def can_credit?(payment) + return false unless payment.completed? + return false unless payment.order.payment_state == 'credit_owed' + + payment.credit_allowed.positive? + 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 41f81bdd84..3ff9dc0741 100644 --- a/spec/models/spree/gateway_spec.rb +++ b/spec/models/spree/gateway_spec.rb @@ -23,4 +23,51 @@ 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 48dd75df95..a59243096a 100644 --- a/spec/models/spree/payment_spec.rb +++ b/spec/models/spree/payment_spec.rb @@ -873,53 +873,6 @@ 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