Shipping rates are destroyed after selecting a shipping method in admin
In the default admin experience provided by the Solidus backend, it looks like whenever I select a shipping method for a shipment, all other shipping rates are destroyed. This means that until you go through some experience to refresh the available rates, making a choice here is irreversible.
Solidus Version: 3.0.1
To Reproduce
- Create an order in admin by adding items to your cart.
- Enter customer details as needed.
- Look at the shipment generated
- Notice that there are multiple shipping rates available.
- Select one of the rates.
- Notice that this is now the only rate available.
Current behavior The existing Solidus backend/api solution is displaying shipping rates, but then selecting a shipping method. In https://github.com/solidusio/solidus/blob/master/core/app/models/spree/shipment.rb#L170, selecting a shipping method destroys any rate that is not the selected one, leaving only that selected rate to choose from.
Expected behavior It would seem like destroying the rates is undesirable, since an admin user might misclick on a rate and need to make an alternate selection at some point. So preserving the rates would seem desirable.
Additionally, it feels odd to use a list of rates to select a method. Wouldn't it be cleaner and more in line with the abstraction to select a rate directly?
Screenshots
Initial options for shipping rates:

After selecting a shipping method:

I believe this is intentional behaviour introduced in https://github.com/solidusio/solidus/pull/2499 to better support admin-only shipping rates. It could certainly be worthwhile investigating updating the admin to re-run the estimatedRates call after selecting a rate to refresh the list of possible rates for admins.
As a temporary workaround, you can navigate to the "Customer" tab and click the "Update" button at the bottom of the page to trigger the backend to recreate the proposed shipments. (Which would result in the rates being recreated.)
That makes sense as a use case - thanks for clarifying that! As a separate point, though, it really does feel like this should be selecting a rate rather than a method. That makes the very strong assumption that rates and methods are always one-to-one, which I'm not sure will be universally true.
I think there may be a bit of misunderstanding here caused by the label on that form field. It is selecting a rate. (And shipping methods are only ever associated to a shipment through rates.)
In the base implementation, I don't believe it's possible to have multiple rates for a single shipping method on an order. It's always a one-to-one mapping. Personally, I like to think of the associations between rates, methods and shipments as being similar to that of line items, variants, and orders. The rate is just a snapshot of how much a method would cost for a shipment at a specific point in time.
I was just trying to reproduce this against a sandbox app with only the bare minimum installed and couldn't get the behaviour you describe. It looks like it's re-fetching the rates every time I click the "edit" icon next to the shipping rate, which leads to the list being re-populated with everything.
https://user-images.githubusercontent.com/876067/130874164-04a2e9c7-a1ca-4886-803f-e4f49b96fbf4.mov
Is there maybe an extension that's causing some issues on this page? Or maybe I step I missed somewhere?
Hmm - it's possible I've misinterpreted the code, but from what I can see, what's happening in the backend gem here is that we're loading rates, and then using the rate to select a shipping method ID which is then passed back to the API.
You can see this here in the view - it retrieves a shipping_rate and fetches the ID of the shipping_method from it. It then passes that into a function to select a shipping method given an ID. In turn, that ends up invoking Shipment#select_shipping_method which produces the behavior I'm describing.
In our particular installation, we were seeing this as a problem because we've allowed multiple shipping rates to exist for a single shipping method - which may not be a long term good idea, but doesn't seem like an illegitimate possibility. That's why selecting a shipping rate by selecting its method was not working for us.
Do you know how the sample app is refetching the rates when you click edit? I wonder if that was the problem for us - maybe we have a setup that is not correctly fetching our rates in all various scenarios. That could definitely explain why this behavior doesn't impact other users!
The rates are fetched through the Backbone model when the edit button is clicked. And estimatedRates is what makes the API call.
The controller action for fetching the rates does the same estimator lookup that Shipment#select_shipping_method does. If your particular setup has allowed multiple rates for a single shipping method I could definitely see that causing some issues with all of this code. As I do think there's an implicit 1-to-1 mapping between the two throughout the system.
Thanks, @adammathys - much appreciated. I'll dig a little more on my side of things, but it sounds like this isn't really an issue for most other users. Maybe we have some customization/patch somewhere that is making the estimation not work correctly. I'm happy to close this one for now unless you think there's something actionable here.
I will say that it does seem like the admin UI could be slightly improved by passing a rate ID instead of a method ID, just to make it more explicit what is being selected. That would help decouple the assumptions that rate and methods rely on a little more completely in the future.
Yeah, it's a weird bit of the domain where I think most people think you're selecting a shipping method (which you'd then infer the rate from), despite that not being how that data is actually modeled.