-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Fix order state with customer returns when receiving return items #3483
Fix order state with customer returns when receiving return items #3483
Conversation
backend/spec/controllers/spree/admin/return_items_controller_spec.rb
Outdated
Show resolved
Hide resolved
7a4e792
to
fff7ab7
Compare
@elia thank you for this fix 🎉 I see you added many tests at the controller and integration level, those are very good as they expose the functionality and the application flow in the |
fff7ab7
to
423afdf
Compare
@spaghetticode I've added some model-level specs, let me know if you think there's enough coverage now 🔍 |
423afdf
to
398a581
Compare
core/spec/models/spree/order/outstanding_balance_integration_spec.rb
Outdated
Show resolved
Hide resolved
6228fe9
to
0dd92fd
Compare
@elia failures seem legit here, can you please take a look? |
0dd92fd
to
0e9e70a
Compare
core/app/models/spree/order.rb
Outdated
# Inventory units are transitioned to the return state by ReturnItem | ||
# across a different association path goes through CustomerReturn and | ||
# ReturnItem instead of using Order#inventory_units. That makes any | ||
# the cached association on order stale and require a *reload* before | ||
# checking if they're returned. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you could improve the English here a bit, looks like it has been rewritten a few times and the grammar doesn't make much sense anymore. Same goes for the commit.
@@ -34,7 +34,13 @@ | |||
let(:new_reception_status) { 'received' } | |||
let(:reception_status_event) { 'receive' } | |||
|
|||
before { return_item.update reception_status: 'in_transit'} | |||
before do | |||
allow(Spree::Deprecation).to receive(:warn) do |message| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI you can use a regexp here, but it's up to you:
allow(Spree::Deprecation).to receive(:warn).with(/#process_inventory_unit! will not call/)
expect(message).to match('#process_inventory_unit! will not call') | ||
end | ||
|
||
return_item.update reception_status: 'in_transit' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually I use update!
when setting up a test. That way, if the setup code fails for some reason, it does so loudly instead of making the expectations fail.
0e9e70a
to
ac8eff3
Compare
ac8eff3
to
5f2a546
Compare
5f2a546
to
545e764
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@elia thank you 👍
@aldesantis can you review the PR again after Elia's changes? |
Checking for customer_return is much faster than the other checks and since it's already in #should_restock? we can get rid of the extra check and make the code more linear.
Avoid defining the shared examples globally.
This endpoint is hit from the button that marks return items as received in admin/customer_returns.
This is in preparation to adding more specs and cover more behavior of that part of the admin.
This method is mainly used after inventory items are put in "return" state, and that usually happens through order->customer_returns-> return_item->inventory_unit. This makes the instances of InventoryUnit cached in Order#inventory_units potentially stale. By using reload we avoid the bugs stemming from this discrepancy. See also the comment in the code.
Apparently the state_machines library can halt callback chains without telling anything to anyone. That was happening in some cases when ReturnItem#attempt_accept was failing. In those cases, just to increase confusion, the acceptance state-machine is interacting with the reception state-machine. Additionally, the introduction of the accessor for skip_customer_return_processing was fixing one code path (the one still visible in the original PR) but was disrupting another one, namely marking the order as "returned" after the return-item state-machine was delivered the "receive" event.
Walk back the use of skip_customer_return_processing and restore the call to process_return! within process_inventory_unit!.
545e764
to
cad0a4c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing work @elia, and much needed! Thanks! 🙏
@elia merging. Can you help me writing the changelog entry for this? A comment here is enough, I will take care of moving it into a full changelog entry once we are approaching the release. |
📝 Notes on reviewing: I suggest to review this PR commit by commit, knowing that the core of the fix is in the last commits:
Which fixes the check on the Order state transition toward "returned".
This one contains the feature specs demonstrating the problem along with the changes that make them pass.
Walk back the attempted fix introduced by Allow order with multiple line items to be marked as "Returned" #3199.
Description
Why?
Currently when a customer return transitions from "In transit" toward "Received" doesn't trigger the transition of the Order status to "Returned".
How
The problem is a composite of multiple bugs.
The first one was that
order.inventory_units
was memoized with completely different instances fromReturnItem#inventory_unit
. So the check to see if they were all returned was, at times, ineffective.The second part is that the
state_machines
library can halt callback chains without telling anything to anyone. That was happening in some cases whenReturnItem#attempt_accept
was failing. In those cases, just to increase confusion, the acceptance state-machine was interfering with the reception state-machine.The third part is that the introduction of the accessor for
skip_customer_return_processing
was fixing one code path (the one still visible in the original PR) but was disrupting another one, namely marking the order as returned after the return-item state-machine was getting the "receive" event.Ref #3199
Checklist: