Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Checkout] Shipping fees update, remove order callback #13023

Merged
4 changes: 0 additions & 4 deletions app/models/spree/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -673,10 +673,6 @@ def process_each_payment
break if payment_total >= total

yield payment

if payment.completed?
self.payment_total += payment.amount
end
Comment on lines -677 to -680
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit weird to take a payment without updating the total. But I guess that we are just moving the responsibility of updating the total out of the callback. And at some point, we may not want payments in a callback either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was cause for me to look it up to make sure I understood. I found that four controllers update the order.payment_total (via OrderManagement::Order::Updater#update_totals_and_states):
checkout_controller.rb, voucher_adjustments_controller.rb, api/v0/shipments_controller.rb, admin/adjustments_controller.rb

It is updated by counting up all payments. That seems like a much safer method than the incrementing above.

https://github.com/openfoodfoundation/openfoodnetwork/blob/master/engines/order_management/app/services/order_management/order/updater.rb#L60

        order.payment_total = payments.completed.sum(:amount)

Very good!

Copy link
Collaborator Author

@rioug rioug Jan 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue was actually caused by this :

def update_order
OrderManagement::Order::Updater.new(order).after_payment_update(self)
end

which is triggered by an after_save callback.
So by the time the code reach these deleted lines the payment was already added to order.payment_total. It was hidden by the fact OrderManagement::Order::Updater#update_totals_and_states was triggered further down the line, which now does not always happen.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I can see that this triggers the same code (order.payment_total = payments.completed.sum(:amount))

If we can be sure that update_totals_and_states is always triggered down the line (by a controller), then perhaps we can remove this model callback also! But I'm afraid to suggest it in this PR..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would need more investigation. I believe the payment callback is there to ensure the order.payment_total is updated when a payment is completed outside the checkout. Ie, capturing a cash payment in the backoffice. There might be other scenarios as well, It's not something I would want to do here.

end
end

Expand Down
2 changes: 1 addition & 1 deletion app/views/spree/orders/_totals_footer.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
%td.text-right{colspan: "3"}
%strong
= t :order_amount_paid
%td.text-right.total
%td.text-right.total{id: "amount-paid"}
%strong
= order.display_payment_total.to_html
- if order.outstanding_balance.positive?
Expand Down
6 changes: 1 addition & 5 deletions spec/controllers/admin/customers_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,9 @@ module Admin
let!(:variant) { create(:variant, price: 10.0) }

before do
allow_any_instance_of(Spree::Payment).to receive(:completed?).and_return(true)

order.contents.add(variant)
order.payments << create(:payment, order:, amount: order.total)
order.reload
order.payments << create(:payment, :completed, order:, amount: order.total)

order.process_payments!
order.update_attribute(:state, 'canceled')
end

Expand Down
6 changes: 3 additions & 3 deletions spec/models/spree/order/payment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ module Spree
create(:credit_card)
}
let(:payment1) {
create(:payment, amount: 50, payment_method:, source:, response_code: "12345")
create(:payment, order:, amount: 50, payment_method:, source:, response_code: "12345")
}
let(:payment2) {
create(:payment, amount: 50, payment_method:, source:, response_code: "12345")
create(:payment, order:, amount: 50, payment_method:, source:, response_code: "12345")
}
let(:payment3) {
create(:payment, amount: 50, payment_method:, source:, response_code: "12345")
create(:payment, order:, amount: 50, payment_method:, source:, response_code: "12345")
}
let(:failed_payment) {
create(:payment, amount: 50, state: 'failed', payment_method:, source:,
Expand Down
22 changes: 6 additions & 16 deletions spec/models/spree/order_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -280,40 +280,31 @@
end
end

context "#process_payments!" do
describe "#process_payments!" do
let(:payment) { build(:payment) }
before { allow(order).to receive_messages pending_payments: [payment], total: 10 }

it "should return false if no pending_payments available" do
it "returns false if no pending_payments available" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tidying these 👍

allow(order).to receive_messages pending_payments: []
expect(order.process_payments!).to be_falsy
end

context "when the processing is sucessful" do
it "should process the payments" do
it "processes the payments" do
expect(payment).to receive(:process!)
expect(order.process_payments!).to be_truthy
end

it "stores the payment total on the order" do
allow(payment).to receive(:process!)
allow(payment).to receive(:completed?).and_return(true)

order.process_payments!

expect(order.payment_total).to eq(payment.amount)
end
end

context "when a payment raises a GatewayError" do
before { expect(payment).to receive(:process!).and_raise(Spree::Core::GatewayError) }

it "should return true when configured to allow checkout on gateway failures" do
it "returns true when configured to allow checkout on gateway failures" do
Spree::Config.set allow_checkout_on_gateway_error: true
expect(order.process_payments!).to be_truthy
end

it "should return false when not configured to allow checkout on gateway failures" do
it "returns false when not configured to allow checkout on gateway failures" do
Spree::Config.set allow_checkout_on_gateway_error: false
expect(order.process_payments!).to be_falsy
end
Expand Down Expand Up @@ -1247,8 +1238,7 @@

order.update_shipping_fees!

item_num = order.line_items.sum(&:quantity)
expect(order.reload.adjustment_total).to eq(item_num * shipping_fee)
expect(order.reload.adjustment_total).to eq(15) # 3 items * 5
end
end
end
Expand Down
1 change: 1 addition & 0 deletions spec/system/consumer/shopping/checkout_paypal_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@

click_on "Complete order"
expect(page).to have_content "Your order has been processed successfully"
expect(page.find("#amount-paid").text).to have_content "$19.99"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using an ID, can we test for the associated label instead? (also below)

Suggested change
expect(page.find("#amount-paid").text).to have_content "$19.99"
expect(page).to have_content "Amount Paid\n$19.99"


expect(order.reload.state).to eq "complete"
expect(order.payments.count).to eq 1
Expand Down
2 changes: 2 additions & 0 deletions spec/system/consumer/shopping/checkout_stripe_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@
checkout_with_stripe

expect(page).to have_content "Confirmed"
expect(page.find("#amount-paid").text).to have_content "$19.99"

expect(order.reload.completed?).to eq true
expect(order.payments.first.state).to eq "completed"
end
Expand Down
Loading