-
-
Notifications
You must be signed in to change notification settings - Fork 725
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
filter available shipping methods based on tags #6039
filter available shipping methods based on tags #6039
Conversation
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.
Great catch Andy!
I think we must find a way to remove the copied logic from enterprise_helper. Otherwise we are making what's already badly structured a bit worse.
engines/order_management/app/services/order_management/stock/package.rb
Outdated
Show resolved
Hide resolved
I am moving to in dev until feedback is addressed 👍 |
69d3ad3
to
7f17ab5
Compare
@luisramos0 this now uses DistributorShippingMethod service and the tests are back to green. I have a few things left on the todo list since there's a lot of potential for cleanup/refactoring here per the Boy Scout rule:
|
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.
nice, looking good.
- display_on_checkout is needed there, it's an option in the methods to hide them from the checkout page. you can leave it as is. looks good to me.
- I think shipping_categories can be removed and that sepc (the build will also tell us if it's ok to remove it 👍 )
I think we need to extend the testing notes of the PR to include tests validating the changes in package.rb - I'd say we need to test everything related to shipping methods in the checkout process as well as shipping methods in the admin edit order page ... for example, checkout ship methods of different zones and categories. and change ship method in admin edit order page and verify the list of ship methods is correct.
ff1a3f1
to
f0752bf
Compare
That one spec that's failing is passing locally for me, I think rebuilding will get it back to green :) |
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.
Nice 😄
Hey @andrewpbrett , great catch indeed. Thanks for reproducing this error. I've done this as well in two different ways:
Editing the order in the backoffice shows that the hidden (and only) payment method was indeed being used for processing the order:
In this situation, and despite the methods being set to backofice, it does not seem possible to select one. Trying to ship this order leads to an error: This also happens for orders placed in the backoffice: in summary, setting all shipping methods as backoffice only seems to hide all of them, from the backoffice as well. Maybe this was introduced by #5392. If one enters customer details first and then chooses the product, then the shipping methods appear. This was quite tricky to track down, but it's indeed the current behavior. After staging your PR, both these scenarios (1, and 2) were checked and a general sanity test around shipping methods functionality (3).
All good here - awesome! 🎉
But again: skipping the "Order Details" and filling out "Customer Details" first, allows to access all payment methods set to "Backoffice" only.
ii) checkout shipping methods of different zones and categories - found no changes, I think we are good here. The category of the product can differ from the shipping category; the zone of the shipment can differ as well from the zone of delivery. iii) change ship method in admin edit order page and verify the list of ship methods is correct If it is in fact intended, then maybe we would need to change this wording, as it currently only refers to "checkout": The PR is good to go, moving to Ready to Go. For documentations sake and as a summary, I'm adding further notes, as there are issues which should to be opened, from this testing. I point out that these are not introduced by this PR:
|
yes Filipe, I didnt think about that case, with the change in Package done here: The admin order edit page will not allow the manager to add ship methods that the customer doesn't have access to through tags... this is a loss of functionality... and I think it's a bug. Even if there are tags hiding the ship method from checkout, the ship method should appear on admin order edit page so that the manager, if they want, can override the tag rules... It's a product decision to accept this as is or to prevent this PR from being merged as is. I am not sure where to move this PR to but I want to move it away from ready to go to avoid someone accidentally just merging it... let's keep it in Test Ready until this decision is made? I think @RachL or @lin-d-hop would be able to make a call here? In terms of solution for it, the view in admin orders uses order.shipment.shipping_rates.backend, but with this PR this is now getting the tag rules filters. The code that builds the ship rates is the Package code that is inside the Order workflow and that is the same code used in the checkout part that we just fixed by adding the tag rules... we need to split this and make it work differently for frontoffice and backoffice. It's not obvious but there must be an easy way out of it. |
I guess the workaround is for the admin to tag themselves? Correct? |
Oof this is a tough one. Very impressed by the whole team on this issue! 😍 To be sure I understand: Will the instance manager (super admin) be able to add the shipping method? Or no? I'm trying to consider support load in thinking about this. The case that we are resolving is reasonably rare and essentially protecting against user error (if the user sets up no shipping methods that are available by default). I estimate that the case that we are creating will create a bigger support load than we are solving if users lose flexibility over shipping methods. For that reason I would lean towards NOT merging as is. I don't feel strongly about this and would accept if others did feel this should be merged. I hate to throw a spanner in the works - but would a more appropriate solution to this issue to be a check when adding tags that warns the hub if they create tag conditions that result in no shipping/payment methods available by default? I haven't thought this through yet. It might be terribly complex 🤔 |
@lin-d-hop your understanding is correct. Even a superadmin would be not be able to add the shipping method (I'm pretty sure). I also think your point about the frequency of these cases is a really good one. I'd also lean toward not merging as it is. I have a potential solution in the works that would make all the shipping methods available to the backend and still apply the filters correctly on the frontend. Not sure exactly when it'll be ready to push up and have others take a look, but I'd say we can pause more discussion until it's there. PS I did think about adding a validation or warning the admin when they're adding tags that they should/must have one shipping method that has no tag rules on it, but it seemed fairly complicated (and potentially confusing/annoying to people) so I wrote it as a "potential further enhancement" wayyy back up there in the original PR description. It would be really nice to do this but we might want some design thinking/inception around it. |
Hrm, I may have messed that up, it's now showing all the commits from master as part of this PR.... uno momento. Edit: all good now. Sorry about the force push :) |
d4e817f
to
84b38e4
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.
This is a good try but:
- I think it's too complicated, I dont think we need so much flexibility in so many methods (see comment about the possiblity to remove args from refresh_rates).
- I think it's incorrect in some details (see comment about some default values).
I must confess this is not straight forward and I did burn a few neurons processing this PR :-)
So, well done Andy for taking care of this!
engines/order_management/spec/services/order_management/stock/estimator_spec.rb
Outdated
Show resolved
Hide resolved
packages = OrderManagement::Stock::Coordinator.new(self).packages | ||
packages = OrderManagement::Stock::Coordinator.new(self).packages( | ||
checkout: true, apply_tags: true | ||
) |
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 dont think this is correct, this step is also executed when you create an order in the backoffice and so we would want these checkout/tags args to be false in that case...
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.
Ah okay that makes sense - I think I was focused on the case where we wanted to be able to change the shipping method on an existing order in the backend and have all methods available... forgot about creating one. I think we can still make it work, but definitely trickier.
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 this commit a36c2bf should address this.
engines/order_management/app/services/order_management/stock/estimator.rb
Show resolved
Hide resolved
dc3c2c4
to
660be31
Compare
engines/order_management/app/services/order_management/stock/estimator.rb
Show resolved
Hide resolved
engines/order_management/app/services/order_management/stock/estimator.rb
Show resolved
Hide resolved
660be31
to
a36c2bf
Compare
).filter!(shipping_methods) | ||
end | ||
|
||
shipping_methods.uniq |
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.
At this point the shipping_methods
is already an Array
because the ActiveRecord::Relation
fired a DB query on line 9 due to to_a
. I'd be much better if we asked to remove duplicates to PostgreSQL which is much faster than asking Ruby to do it (and instantiate a bunch of bloated ActiveModel objects that are meant to be discarded). We could do that by using #distinct
.
That, unfortunately, will only work when apply_tags == false
when true
shipping_methods
will be an array at this point (making TagRuleApplication rely on AR relation is totally different topic) so we'll need to nest it within an else
branch. I think it's worth it.
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'm really sorry to delay this further but I think that it still contains a regression, see below. I'm moving it to in-dev until the questions are resolved.
@@ -594,7 +594,7 @@ def create_proposed_shipments | |||
shipments.destroy_all | |||
|
|||
packages = OrderManagement::Stock::Coordinator.new(self).packages( | |||
checkout: true, apply_tags: true | |||
checkout: true, apply_tags: !created_by&.admin? |
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'm not sure that this is correct. If I'm a super admin I see all shipping methods in the admin interface and in the checkout even if I shouldn't based on my current tags, right? That makes it impossible to test tags as admin user. It's also not good if you can't tell which methods another enterprise wants you to use. So this is a problem when a super admin account is also used for shopping.
This also doesn't allow enterprise users to add any shipping method of their own enterprise to orders created in the backoffice. I think that's what @lin-d-hop was after.
I would say:
- The front-office always applies filters to shipping methods.
- The back-office does not apply filters to shipping methods.
So this logic needs to be triggered by the controller. The model is not the right place for this logic. Spree's design decision to include all checkout logic in a state machine is making it very difficult here. It's not pretty but we can move this out of the model into the OrderWorkflow service. It already contains logic concerning shipping method selection and it would make sense to have it in one place. It can then be called with different options from the frontend and backend.
What do you think?
DistributorShippingMethods.shipping_methods( | ||
distributor: self, checkout: true, apply_tags: false | ||
).any? && payment_methods.available.any? |
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.
Really minor but I thought it might be worth sharing that I would found this easier to read like this:
DistributorShippingMethods.shipping_methods( | |
distributor: self, checkout: true, apply_tags: false | |
).any? && payment_methods.available.any? | |
checkout_shipping_methods = DistributorShippingMethods.shipping_methods( | |
distributor: self, checkout: true, apply_tags: false | |
) | |
checkout_shipping_methods.any? && payment_methods.available.any? |
@andrewpbrett do you still plan on finishing this PR? Otherwise I would close it and move the issue to all the things. It doesn't look like a bug prioritised? |
What? Why?
Closes #5950
I was able to reproduce the issue by setting up a single shipping method for a shop and then tagging it "member". When checking out as a guest, the checkout screen showed no available shipping methods and the red error that @emilyjeanrogers circled in the issue's screenshot. Despite not selecting a shipping method, you can complete the checkout.
I stepped through the state machine transitions on checkout and noticed that after the transition to
delivery
, a shipping method was added to the order. I believe it was happening in thecreate_proposed_shipments
method; that method calls thepackages
method which (eventually) uses theshipping methods
method on each package.Currently that method returns all the shipping methods for a distributor, even if there are tag rules that should apply. I looked at the
available_shipping_methods
method in EnterprisesHelper and used a similar approach to apply the appropriate tags.With this PR, checkout now (correctly) fails with the error message: "We are unable to calculate shipping rates for the selected items." if a shipping method has not been selected.
While this first commit (93c1ea6) fixes the issue on the backend; there are a couple of additional improvements to consider:
Separately, in diving into this issue I found two other potential issues:
A similar thing can happen with payment methods - if there are rules that exclude all payment methods from showing up, a user can load the checkout page without knowing anything is wrong... they cannot actually checkout, however, so this would be a front-end improvement.
Deleting the last available shipping method for an enterprise doesn't warn you that it didn't work.
What should we test?
Checking out as a customer (guest or otherwise) at a shop where no shipping methods are available to you based on tag rules.
This PR also cleans up some code in Stock::Package and so we need to do some additional testing around that area. From Luis: We need to test everything related to shipping methods in the checkout process as well as shipping methods in the admin edit order page ... for example, checkout ship methods of different zones and categories. and change ship method in admin edit order page and verify the list of ship methods is correct.
Release notes
Fixed a bug where customers were assigned an incorrect shipping method at checkout if there were no shipping methods available based on tag rules.
Changelog Category: Fixed
Discourse thread
Dependencies
Documentation updates