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

Allow orders with different shipping categories #3130

Merged
merged 2 commits into from
Oct 17, 2019

Conversation

aitbw
Copy link
Contributor

@aitbw aitbw commented Mar 4, 2019

Description

This PR allows users to submit orders with items that belong to different shipping categories.

This issue is present from Solidus v2.6 through v2.8, as well as in master

Once merged:

See also:

Checklist:

  • I have followed Pull Request guidelines
  • I have added a detailed description into each commit message
  • I have updated Guides and README accordingly to this change (if needed)
  • I have added tests to cover this change (if needed)

Copy link
Contributor

@jacobherrington jacobherrington left a comment

Choose a reason for hiding this comment

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

Nice specs. I think this is a good idea! Thanks @aitbw 👍

Copy link
Member

@kennyadsl kennyadsl left a comment

Choose a reason for hiding this comment

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

Just left a question.

@@ -41,7 +41,7 @@ class ShippingMethod < Spree::Base

scope :available_to_store, ->(store) do
raise ArgumentError, "You must provide a store" if store.nil?
store.shipping_methods.empty? ? all : where(id: store.shipping_method_ids)
store.shipping_methods.empty? ? all : where(id: store.shipping_methods.ids)
Copy link
Member

Choose a reason for hiding this comment

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

What's the difference here? Shouldn't they return the same thing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

They should; I checked the generated SQL on the sandbox and the output was the same for both calls, but somehow, the result is not the same. (at least, not in this scenario.)

I will investigate further to understand what's going on here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@kennyadsl I added this:

puts store.shipping_method_ids.inspect

to the scope and found that store.shipping_method_ids is returning just one shipping method ID, whereas store.shipping_methods.ids is returning all the IDs for the shipping methods associated to the store.

Can't understand why this is happening, as the generated SQL is exactly the same for both, and some unit tests I created for this work as expected with either. Maybe there's a bug present in Rails (as mentioned first by @afdev82 in here) or something else we're missing out.

Copy link
Member

Choose a reason for hiding this comment

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

Trying this out and it returns just one shipping method ID also for:

ActiveRecord::Base.uncached { store.shipping_method_ids } # => [3]

in the test you wrote.

Also, the query seems a bit too much for what it should do:

(0.6ms)
SELECT DISTINCT "spree_shipping_methods"."id"
FROM "spree_shipping_methods"
LEFT OUTER JOIN "spree_shipping_method_stock_locations" ON "spree_shipping_methods"."id" = "spree_shipping_method_stock_locations"."shipping_method_id"
INNER JOIN "spree_store_shipping_methods" ON "spree_shipping_methods"."id" = "spree_store_shipping_methods"."shipping_method_id"
WHERE "spree_shipping_methods"."deleted_at" IS NULL
  AND "spree_shipping_methods"."id" IN
    (SELECT "spree_shipping_methods"."id"
     FROM "spree_shipping_methods"
     INNER JOIN "spree_shipping_method_categories" ON "spree_shipping_method_categories"."shipping_method_id" = "spree_shipping_methods"."id"
     WHERE "spree_shipping_methods"."deleted_at" IS NULL
       AND "spree_shipping_method_categories"."shipping_category_id" = ?
     GROUP BY spree_shipping_methods.id
     HAVING COUNT(DISTINCT "spree_shipping_method_categories"."id") = 1)
  AND ("spree_shipping_methods"."available_to_all" = 1
       OR "spree_shipping_method_stock_locations"."stock_location_id" = 1)
  AND "spree_store_shipping_methods"."store_id" = ? [["shipping_category_id", 2],
      ["store_id", 1]]

There are some suspect join with categories, which I'm not sure why are there and if they are needed here. Can you please investigate a little bit more?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah sure, let me have a further look at it

@spaghetticode
Copy link
Member

@aitbw 👋hi Angel, did you have any chance to continue working on this?

@aitbw
Copy link
Contributor Author

aitbw commented Jun 20, 2019

@spaghetticode, hello Andrea! I've been trying to find out why my proposed change works, but with no avail so far 😓

@cedum
Copy link
Contributor

cedum commented Oct 1, 2019

This seems to be fixed in Rails 6 with this commit:
rails/rails@17f2f30#diff-c47e1c26ae8a3d486119e0cc91f40a30
By applying this patch to Rails 5.2 store.shipping_method_ids starts to behave as expected.

In a scenario with two products with different shipping categories, we get two calls to this scope for each product: the first one seems correct, the second one instead returns the cached result from the previous one.
I'm quite ignorant about ActiveRecord internals, also the scope chaining here is extreme to be able to understand the behavior easily, however, it should be safe accepting the solution in this PR.

@kennyadsl
Copy link
Member

@cedum nice finding!

@aitbw 👋👋👋can you please give us (@cedum or me) access to your solidus fork so we can rebase this PR against master? Or if you prefer and/or have time, please do that by yourself.

@aitbw
Copy link
Contributor Author

aitbw commented Oct 1, 2019

@kennyadsl, hi Alberto! 👋 Done! ✔️

Removed the first commit based on @cedum's comment, but I can add it again if necessary.

@cedum
Copy link
Contributor

cedum commented Oct 1, 2019

hey @aitbw ! Thank you 🙏
It would be nice to have also the second commit since it fixes this scope for Rails 5.2 (the commit from the rails repo I linked has been merged only in rails 6 unfortunately)

@aitbw
Copy link
Contributor Author

aitbw commented Oct 1, 2019

Ooooh ok ok, got it! @cedum, sorry about that 😅

EDIT: Done! ✔️

@ericsaupe
Copy link
Contributor

Sounds like this fixes #3315 as well if you wanted to put that in the description

Copy link
Member

@kennyadsl kennyadsl left a comment

Choose a reason for hiding this comment

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

The fix for this does not seem to have been backported on Rails 5.2, so I suppose we have no other solutions than merge this PR. Thanks @aitbw and @cedum!

@kennyadsl kennyadsl added Need Backport type:bug Error, flaw or fault and removed Needs Work labels Oct 17, 2019
@kennyadsl kennyadsl merged commit e48a6b4 into solidusio:master Oct 17, 2019
@aitbw aitbw deleted the aitbw/fix-2998 branch October 19, 2019 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:bug Error, flaw or fault
Projects
None yet
6 participants