Closed (fixed)
Project:
Commerce Shipping
Version:
8.x-2.x-dev
Component:
User interface
Priority:
Major
Category:
Feature request
Assigned:
Unassigned
Reporter:
Created:
19 Feb 2017 at 21:55 UTC
Updated:
14 Feb 2019 at 23:53 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
jsacksick commentedIt's far away from being done, but sending my work in progress (See https://cl.ly/3y2u1L271Z06), the patch contains the initial ShipmentListBuilder with the delete operation.
Comment #3
rgpublicJust wondering: Is there, coincidentally, any progress in the mean time on this (e.g. a new patch)? If not, I'd need to quickly patch in some temporary solution for a current project.
Comment #4
bojanz commentedNo progress, it would have been on the issue.
Comment #5
ctrladelTook another pass at this. Changes in the patch
- Setup a canonical url for shipments at '/admin/commerce/orders/{commerce_order}/shipments/{commerce_shipment}'

- Created a view on the collection path '/admin/commerce/orders/{commerce_order}/shipments' that overrides the listbuilder , this mimics what is currently done for orders at '/admin/commerce/orders'
- Changed the default shipment view mode to display a lot more fields
- Created a field formatter that formats 'commerce_shipment_item' fields as a table
Comment #6
ctrladelRemoving the image I put in the issue summary by accident.
Comment #7
zerolab commentedComment #8
ericchew commentedAdded:
I only tested using Commerce_FedEx and FlatRates. Commerce_FedEx was set to package items individually, right now it errors out when its set to anything else. I have a fix for it but right now FedEx's test site is down so its hard to work on. I'll post an updated patch when I can.
Comment #9
ericchew commentedA couple more things:
Comment #10
ericchew commentedAdded the ability to select the PackageType for the shipment. Made sure that any changes to the shipping profile address were being used when recalculating shipping.
Known Issues:
- In FedEx shipping method, you can configure whether shipments should be packaged all in one, individually, or calculated. This makes sense for the Checkout pane, because you want to display all of the shipments as one rate to the customer. However, that configuration setting also changes rate calculations when creating a shipment through the admin UI. If you have 3 shipment items in the shipment through the Admin UI, and FedEx is set to package items individually, the rate request is sent as if that shipment is 3 boxes. It's my opinion that when creating a shipment manually, shipment = one package, and you are specifying what items are in that package, so it should always calculate as "all in one box" when being created manually.
Comment #11
ericchew commentedJust noticed that you get "Illegal choice has been detected" message if no rates are available when calculating shipping. Patch sets shipping methods #access to false if no options are available.
Comment #12
sweetchuckI think we should create a new field widget plugin for the "package_type" base field instead of define a form element in the
\Drupal\commerce_shipping\Form\ShipmentForm::form.Similar to the
\Drupal\content_moderation\Plugin\Field\FieldWidget\ModerationStateWidget.It is not sure there is a package_type saved to the shipment.
Only modification in this patch compared to the #11 is that checks that the package_type is empty or not.
Comment #13
josephdpurcell commentedMoving priority to Major. Being able to create a shipment from the admin interface is a key feature of Commerce.
Confirmed that patch #12 works. I did not complete thorough testing or code review on it.
Attached is a small modification to #12 by adding a "Shipments" entity operation similar to what Payments does. See interdiff.
Comment #14
Juterpillar commentedThanks everyone for you work on this. Patch #13 seems to be working as expected for me.
Comment #15
josephdpurcell commentedReroll on latest 8.x-2.x.
Comment #16
josephdpurcell commentedAttempt to split out permissions on viewing shipment entities. This is completely untested! I copy / pasted from what I saw in orders.
Next step: test this and see if you can correctly control permission to CRUD operations on the Shipment entity, similar to how you can with Orders.
Comment #17
ericchew commentedI'm adding a related issue because it will most certainly impact the Admin UI. I advise anyone following this issue to take a look at https://www.drupal.org/project/commerce_shipping/issues/2953483 and check out the repo and video I posted. I have made significant changes to the Admin UI there.
Comment #18
josephdpurcell commentedEveryone can ignore this patch unless you're using beta 4. Since we are using beta 4, I needed to get a patch for it. It will match my follow up comment for latest 8.x-2.x.
Comment #19
josephdpurcell commentedAttached is a minor change to #16 to ensure the permission is grouped correctly. Consider this the most recent patch on this ticket.
Attached are also 2 screenshots showing the difference in permissions between 13 and 19. Here, you can see that there are now granular permissions on the Shipments. There is also a "View own shipments" permission, which could probably be removed? I'm 80% confident this patch isn't totally right, so if I need to revise I'll follow up.
To clarify: the problem I'm trying to solve with the permissions is to allow someone with Administer Shipments to be able to add a shipment to an order without also needing to have Administer Shipment Types permission.
Comment #20
finex commentedProbably https://www.drupal.org/project/commerce_shipping/issues/2981945 is a duplicate of this issue.
Comment #21
alexpottI've re-rolled the patch on top of 8.x-2.x - just a small conflict in commerce_shipping.module's use statements.
Comment #24
bojanz commentedComment #25
alexpottCoding standards clean-up.
Comment #26
alexpottFixing the tests
Comment #27
andyg5000I like where this is headed. The two pieces that I noticed are :
1) Shipping adjustment is not automatically added to order. Should there be a flag on the shipment to force this?
2) The entity reference on the order is not populated so the order is unaware of the shipment (e.g. doesn't show shipping address)
3) Variations that do no extend the shippable trait are included in the shipment UI
Comment #28
andyg5000Updates to #26 to fix issues found in #27 attached
Comment #30
andyg5000Comment #32
andyg5000Comment #33
andyg5000Ok, here's a patch with all of the improvements mentioned in #27 + test coverage. I think this is pretty close to ready, but would like some extra eyes on it.
The remaining non-blocking (imo) things that should be addressed once this is settled are as follows.
1) Lock adjustments on order edit form when they are tied to a shipment
2) Provide ability to override shipment amount
Comment #34
jsacksick commentedI've been doing some manual testing today and expanded the patch a little:
First of all, IMO the shipments tab should only appear if the order type has the "shipping enabled".
Also, on my local installation, I didn't have any package types configured, and clicking on "Recalculate shipping" would eventually return a 500 (Because we're trying to instantiate a package type with an empty string).
I fixed these 2 things and I'm now wondering if we shouldn't add tests coverage for the shipments admin (although this would require more time...)
Comment #35
jsacksick commentedBtw, shouldn't commerce_shipping_entity_operation() check the "administer commerce_shipment" permission instead of "adminster commerce_shipment_type"?
Comment #36
alexpott@jsacksick we definitely need to add test coverage here. Adding features without test coverage makes them liable to break.
Comment #37
jsacksick commentedI started writing a functional test for the ShipmentAdmin but it still needs to be expanded, posting my work in progress.
Comment #38
jsacksick commentedI expanded the ShipmentAdminTest and found 2 bugs while doing that:
1) There was a bug with the views caching (In the tests, we navigate to the shipments tab, add a shipment then save, then we get redirected to the shipments page again and the page was empty after adding a new shipment), so I configured the caching to "none" (I don't think there's a point in caching that view anyway)....
2) The logic in ShipmentForm wasn't actually adding existing shipment items to the
$shipment_item_optionsarray, that was done from the $order_items loop, the problem with that is that the order item label was used instead of the actual shipment item title that we get by calling$shipment_item->getTitle(), that could probably be confusing.Besides that, I think we can commit the patch as is, and probably work on the remaining things that @andyg5000 mentioned in comment #33 after this is committed (in follow-up issues, because the patch is already big enough).
Comment #39
jsacksick commentedOk, actually, I realized we forgot "2) Perform state transitions on the created shipments.", the attached patch is taking care of that (we now output the transition form instead of the state label, see screenshot below):
Comment #40
jsacksick commentedOk, sorry for the noise :p, but realized we don't need all these changes in the routing.yml and we were directly calling in several places the entity class for creating/loading entities (i.e Profile::create or OrderItem::load).
I made some changes to the ShipmentRouteProvider, as well as the ShipmentController which now extends the EntityController, I'm implementing a different method for the "add-page" though since we have to pass the order ID to the shipment add form.
Additionally ShipmentForm was still passing the entity manager, which we were still using in many places although it's deprecated...
I hope we're good to go this time!
Comment #41
alexpottThese change does not look right - has the view been hand edited?
Comment #42
jsacksick commentedMinor changes to the view:
Comment #43
jsacksick commentedAttaching the right interdiff between #40 & 42.
Comment #44
alexpottI think a comment explaining this if would be great. Also do we have test coverage?
I don't think the if (!$order)... is necessary - with no order this route will not check access. It'll 404.
I think this won't result in the right cacheability and is not as clear as it could be. Something like:
Also is there test coverage for the case where the order type does not have a shipment type?
Is there test coverage of this logic? Either where there is one of more shipment types?
exists - also given we know this is boolean then if (!$adjustment_exists) is fine - the empty() makes you ponder why.
in_array() - let's make it type safe using the third param - set it to TRUE.
exist
Won't it be clearer to check if shipments is empty? Is the reason for this code tested?
Comment #45
jsacksick commented@alexpott: Thanks a lot for this review! It turns out some more changes were actually required to make it right.
I had some discussions with @bojanz today and made the following changes:
I'm just posting my progress here, but the patch is actually still incomplete... There's an issue with the Access checker which doesn't seem to be called for some reason (I remember it working which is kind of driving me crazy...).
Also, we're still missing test coverage to make sure the "Shipments" tab / operation isn't shown for cart orders...
Comment #47
jsacksick commentedI've continued working on this today and made once again several changes:
PathPluginBase::alterRoutes(), so I had to implement a route subscriber to put back the route requirement that makes sure the shipments tab isn't shown for cart orders & non shippable orders.ShipmentController::addShipmentPage()because I realized that there's no point in showing a "shipment types" list since there's an order type setting that lets you configure the shipment type per order type, so the logic now redirects to the add shipment page for the configured shipment type.I'm wondering if we need to prevent updating shipments that are "owned_by_packer" (that flag is added by the packer), because a modification to a shipment that's owned by the packer could be blown away (We might have to just forbid updating the "shipment items" field in that case).
The problem with doing that is that could make this entire UI useless (Although you might want to perform updates to shipments that are owned by the packer once the order is placed).
At least we're forbidding access to the shipments tab for cart orders, which is probably sufficient.
Comment #48
alexpottI've moved the unrelated code style changes to #3013669: Update phpcs to 3.x so people don't have to ponder why they are here. Also fixed the typehints in #47 which had some duplication.
Comment #49
alexpottGiven this is access related I think it is better to split this out into separate ifs. It's much clearer as to what is going on and helps lessen the cognitive load of working out what's happening.
This is very readable. Nice. It really helps when access related stuff is easy to grok.
Is there a core issue for this?
Comment #50
alexpottActually point #49.5 appears to be wrong. We've no test with views installed as far as I can see.
Comment #51
alexpottLol actually #49.5 was correct. The Views module is required by the Commerce module. Here's a test to prove the listing works with and without the view.
Comment #53
alexpottHmmm some unrelated change crept in :(
Comment #54
alexpottSmall coding standards fix.
Comment #55
alexpott@smccabe review this and suggest the UI needed a little polish but that it could be done in a follow-up - so I've created #3015345: Improve shipment admin UI look and feel
Comment #56
bojanz commentedReview, part 1:
1.
Not using $this->t(). Weird case (should be "Shipment items"). Is there a friendlier label we could use in general?
2.
This is odd, we never break up a parents array per-row like this. Let's just declare $parents on the preceding line.
3.
This feels like logic that should live on the shipment entity itself. Esp since we're already doing the same in Shipment::delete().
4.
We generally prefix plugins with just commerce_, so this would be "commerce_shipment_item_table".
5.
Unexpected camelCase.
6.
Permission added but never used. Shipments don't even have a uid field, so this doesn't make sense.
7. The "Shipments" operation is shown in the list builder even if the page is not available (cause the order is still a cart). So I click it and get a 403. Look at how we fixed this in the ProductListBuilder.
8. ShipmentListBuilder injects the deprecated numberFormatter, instead of using the newer currencyFormatter. Plus, the numberFormatter property is never declared.
9. There's a tracking code column in the table, but no tracking code field on the edit form. We either need to fix the field or remove the column.
Comment #57
alexpottshipment itemin the UI. See\Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\FlatRatePerItem::buildConfigurationForm()I guess we should add a follow-up to discuss how to rename that if you want to do that.Comment #58
jsacksick commentedI agree with @alexpott on 3) I didn't want to put the order refresh logic in a postSave() as I think this could potentially be very problematic. Let's say you have custom code that adds multiple shipments to the order, you'll most probably save the order yourself and you wouldn't want the order to be saved each time a shipment is saved (from within a loop for instance).
ShipmentOrderProcessoritself loops on the shipments that are returned by the packer and save them in case changes were detected (so multiple shipments are returned, the same order would be saved many times).Furthermore, the order processors are called from
OrderRefresh::refresh()which is itself called fromdoOrderPresave()on the order storage so I'm sure we'd like to prevent the order to be saved inside a presave.Comment #59
alexpottDiscussed the tracking code on the list builder with @bojanz in Slack. His recommendation was to remove it. I then convinced him to keep it and make it displayed by setting display options in \Drupal\commerce_shipping\Entity\Shipment().
This turns out to be complex. Shipping methods only support tracking codes if they implement
\Drupal\commerce_shipping\Plugin\Commerce\ShippingMethod\SupportsTrackingInterface. However as @bojanz pointed out in slack, there's nothing to stop a userTherefore the patch attached sets the dispaly options for the tracking code so users can edit it. Given that this is all standard field API stuff I've not added any test coverage.
We need a follow-up to make the
commerce_tracking_linkformatter support cases where the shipping method does not haveSupportsTrackingInterfaceand then we can make the listbuilder and view use it for enhanced usability. I'll create the issue.Comment #60
alexpottCreated #3016633: Use TrackingLinkFormatter in Shipments admin UI and allow it to work when SupportsTrackingInterface is not implemented
Comment #62
bojanz commentedThanks everyone. Time to commit this issue and continue in followups.
I've made the following visual tweaks pre-commit:
1) Moved the title to the top of the form. It's odd to have it in the middle of the form, after the profile, Drupal never does that.
2) Added a fieldset around the profile, to group the address and related fields.
3) Moved the tracking code field to the bottom, to provide a buffer between "Recalculate shipping" and the main action buttons.
Ultimately the recalculation will need to be made automatic, but this at least makes it look less ugly.
4) Cleaned up the code a bit (made the elements on the form defined in the order of their weights).
See attached screenshot.
Comment #63
melpers commentedI've run into some issues with this fix when used in conjunction with Commerce UPS and the checkout flow is setup for the customer to pick a shipping option during checkout.
1) When editing the shipment after checkout it will allow you change boxes and remove items, and then recalculate the shipping cost. However, saving the shipment and then going back into edit again none of the changes are reflected (The new shipping total is correct though). Making the same changes a second time and saving it again seems to resolve this.
2) If a customer gets to the review order page (i.e. post-shipping selection) and then edits the cart to add/remove/update items and/or quantities resulting in a new shipment total the next time they go through checkout then when viewing the order's Shipments tab it lists all of the shipments that had been on the order at some point. The last one selected has Send & Cancel options under State, and the others will have Finalize & Cancel options.
3) There is no way to split an item with more than 1 quantity across shipments.
4) If you update a shipment's cost it will be reflected in the order's totals. This does not seem to be a desired behavior after the customer has already paid.
I don't know if any of this might be an issue for the UPS Module to address, but it all felt like core shipping issues.
Comment #65
alexpott@MElpers thanks for the comment.
Comment #66
melpers commented@Alexpott thanks for the two new issues. I'll follow those and comment on #4 shortly.
For the first two, hopefully this will help. First, I ran all of these on fresh install with none of our customer's custom code. I just setup 2 products with a single variation each. The modules I'm testing with are:
I can provide the patch list too if you need it.
Issue #1:
I can also recreate this when there are multiple items in the cart and 1 or more of the item checkboxes are unchecked & then the shipping is recalculated.
Running through the same steps a second time to get the same new shipping totals & saving it again will then allow the new values to show up if the shipment is edited a third time.
Issue #2:
Let me know if you need any additional info.
Comment #67
alexpott@MElpers can you confirm what version of commerce_shipping you are on? Are you on a beta version with the patch applied or have you checkout the commit? Because the first problem sounds a lot like #2920242: Shipment always using last shipping method's package type
Comment #68
melpers commentedComposer tells me it is 2.x-dev 7f02042. I am applying patches for
Multiple destination shipping: https://www.drupal.org/files/issues/2018-10-11/2961463-29.patch
Auto-recalculate shipping when the address changes: https://www.drupal.org/files/issues/2018-10-11/2849756-83.patch
Commerce_profile_select reusable profiles: https://www.drupal.org/files/issues/2018-10-05/2948954-35.patch
Comment #69
alexpottYay I've managed to recreate #1 there appears to be some random-ness but if you change packages and recalculate shipping enough times eventually it will go wrong - I'm investigating the bug.
Comment #70
alexpottI've opened #3028227: Package type not saved when changed in admin UI to address #66 issue 1.
Comment #71
alexpottI'm addressing #66.2 in #2994345: Remove shipping when cart is emptied - this issue has kind of been reported before.
Comment #72
alexpott@MElpers I might be wrong in #71. I'm struggling to reproduce the issue but via reading the code I've come up with #3033195: Need to repack when number of items changes