mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Fix #1902: ensure correct payment state when failed payments are present
Problem: order payments didn't seem to be loaded in any particular order, and OrderUpdater#update_payment_state was relying on payment order to de- termine payment state. Strategy: Adapt a version of this method from a future version of Spree. I tried to select a version where I would have to make the absolute mini- mum number of changes to get it to work. See comments in code for justif- ications of the changes that I did make.
This commit is contained in:
41
app/models/spree/order_updater_decorator.rb
Normal file
41
app/models/spree/order_updater_decorator.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
module Spree
|
||||
OrderUpdater.class_eval do
|
||||
# TODO: This logic adapted from Spree 2.4, remove when we get there
|
||||
# Handles state updating in a much more logical way than < 2.4
|
||||
# Specifically, doesn't depend on payments.last to determine payment state
|
||||
# Also swapped: == 0 for .zero?, .size == 0 for empty? and .size > 0 for !empty?
|
||||
# See:
|
||||
# https://github.com/spree/spree/commit/38b8456183d11fc1e00e395e7c9154c76ef65b85
|
||||
# https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
|
||||
def update_payment_state
|
||||
last_state = order.payment_state
|
||||
if payments.present? && payments.valid.empty?
|
||||
order.payment_state = 'failed'
|
||||
elsif order.state == 'canceled' && order.payment_total.zero?
|
||||
order.payment_state = 'void'
|
||||
else
|
||||
# This part added so that we don't need to override order.outstanding_balance
|
||||
balance = order.outstanding_balance
|
||||
balance = -1 * order.payment_total if canceled_and_paid_for?
|
||||
order.payment_state = 'balance_due' if balance > 0
|
||||
order.payment_state = 'credit_owed' if balance < 0
|
||||
order.payment_state = 'paid' if balance.zero?
|
||||
|
||||
# Original logic
|
||||
# order.payment_state = 'balance_due' if order.outstanding_balance > 0
|
||||
# order.payment_state = 'credit_owed' if order.outstanding_balance < 0
|
||||
# order.payment_state = 'paid' if !order.outstanding_balance?
|
||||
end
|
||||
order.state_changed('payment') if last_state != order.payment_state
|
||||
order.payment_state
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Taken from order.outstanding_balance in Spree 2.4
|
||||
# See: https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
|
||||
def canceled_and_paid_for?
|
||||
order.canceled? && order.payments.present? && !order.payments.completed.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
91
spec/models/spree/order_updater_spec.rb
Normal file
91
spec/models/spree/order_updater_spec.rb
Normal file
@@ -0,0 +1,91 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::OrderUpdater do
|
||||
# Copied pretty much verbatim from Spree 2.4. Remove this file once we get there,
|
||||
# assuming the unchanged 2.4 logic still works for us.
|
||||
# Only changes are stubs of :empty? instead of :size
|
||||
context "updating payment state" do
|
||||
let(:order) { Spree::Order.new }
|
||||
let(:updater) { order.updater }
|
||||
|
||||
it "is failed if no valid payments" do
|
||||
order.stub_chain(:payments, :valid, :empty?).and_return(true)
|
||||
|
||||
updater.update_payment_state
|
||||
order.payment_state.should == 'failed'
|
||||
end
|
||||
|
||||
context "payment total is greater than order total" do
|
||||
it "is credit_owed" do
|
||||
order.payment_total = 2
|
||||
order.total = 1
|
||||
|
||||
expect {
|
||||
updater.update_payment_state
|
||||
}.to change { order.payment_state }.to 'credit_owed'
|
||||
end
|
||||
end
|
||||
|
||||
context "order total is greater than payment total" do
|
||||
it "is credit_owed" do
|
||||
order.payment_total = 1
|
||||
order.total = 2
|
||||
|
||||
expect {
|
||||
updater.update_payment_state
|
||||
}.to change { order.payment_state }.to 'balance_due'
|
||||
end
|
||||
end
|
||||
|
||||
context "order total equals payment total" do
|
||||
it "is paid" do
|
||||
order.payment_total = 30
|
||||
order.total = 30
|
||||
|
||||
expect {
|
||||
updater.update_payment_state
|
||||
}.to change { order.payment_state }.to 'paid'
|
||||
end
|
||||
end
|
||||
|
||||
context "order is canceled" do
|
||||
before do
|
||||
order.state = 'canceled'
|
||||
end
|
||||
|
||||
context "and is still unpaid" do
|
||||
it "is void" do
|
||||
order.payment_total = 0
|
||||
order.total = 30
|
||||
expect {
|
||||
updater.update_payment_state
|
||||
}.to change { order.payment_state }.to 'void'
|
||||
end
|
||||
end
|
||||
|
||||
context "and is paid" do
|
||||
it "is credit_owed" do
|
||||
order.payment_total = 30
|
||||
order.total = 30
|
||||
order.stub_chain(:payments, :valid, :empty?).and_return(false)
|
||||
order.stub_chain(:payments, :completed, :empty?).and_return(false)
|
||||
expect {
|
||||
updater.update_payment_state
|
||||
}.to change { order.payment_state }.to 'credit_owed'
|
||||
end
|
||||
end
|
||||
|
||||
context "and payment is refunded" do
|
||||
it "is void" do
|
||||
order.payment_total = 0
|
||||
order.total = 30
|
||||
order.stub_chain(:payments, :valid, :empty?).and_return(false)
|
||||
order.stub_chain(:payments, :completed, :empty?).and_return(false)
|
||||
expect {
|
||||
updater.update_payment_state
|
||||
}.to change { order.payment_state }.to 'void'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user