Problem/Motivation

How to handle multi-package shipments all to the same address? This is about the shipping system being able to figure out how many boxes a particular order would take to ship.

Proposed resolution

Investigate possible solutions.

Remaining tasks

TBD

User interface changes

API changes

n/a

Data model changes

n/a

Original report

I'm working on the fedex modules for commerce shipping, and I had a couple thoughts/questions regarding the shipments and the packer. I wanted to get some clarification on what jobs the packer and shipping method are supposed to do.

In my head, the packer was going to take the shipable line items, decide what type/how many packages would be needed based on item size and weight, and package type size, and place the items into packages that could be used by shipping methods for quotes, getting tracking codes, etc. There's a ton of ways someone might want this done, so the packer was easily overridable.

It seems the packer is actually only responsible for copying shippable line items over into the shipment entity. It seems that shipment items (Which I thought were packages) are a list of the shippable line items only and require a line item id, so each one can only reference one order line item.

So, all this is fine, I can create my own shipment type that includes packages, manage my own packing and so forth, or store package data elsewhere, but it seems like a lot of functionality that might be common to lots of shipping modules.

I also see that shipments are assigned a single package type as well, but I think it is possible for a shipment to have several packages of different types.

To me, a shipment is one or more packages going from a common point of origin to a common recipient address at the same time, I'm just trying to match that flow to the data structures that we have. I'm happy to do the work, either here or in my module, I'm just trying to figure out the appropriate place to do it. Any thoughts?

CommentFileSizeAuthor
#6 Mulitship Wireframe.pdf34.05 KBheddn
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

mikeNCM created an issue. See original summary.

bojanz’s picture

The shipment is the package. 1-1. Multiple packages == multiple shipments.
This is the structure followed by all systems I've evaluated.
So there's nothing we can fix/change (without rewriting the module), you'll have to adjust your design.
Happy to discuss it on IRC or Slack.

mikelutz’s picture

Actually, reframing it in that context, This may be workable. I'll need my own packer, but that's fine. The data structures make sense on the backend, though I'm not sure how the UI will come out, with multiple shipping quotes for a multi-box shipment. I'll code for the data and worry about the UI later. I joined IRC, I may bounce some thoughts off of you as I dig deeper into this.

Thanks!

bojanz’s picture

The UI assumes you want a quote per shipment, so you'd need to write a custom checkout pane that adds the quotes together before displaying them to the user.

steveoliver’s picture

Adding somewhat related issue.

heddn’s picture

FileSize
34.05 KB

This seems like the closest issue to what we are starting to wireframe. Attached is some thoughts on how this might look. Does it make sense? Are there suggested improvements or things in the wireframe that simply won't work? For example, splitting up 10 widgets of the same type into 8 different shipments.

Here's a link to the pdf wireframe.

heddn’s picture

Issue summary: View changes
mikelutz’s picture

@heddn, This issue is about multi-package shipments, and is a rather different beast than multi-address shipping. This was more about the shipping system being able to figure out how many boxes a particular order would take to ship and then getting a 3rd party quote for that many boxes, and is an issue I'm still working on.

Multi address shipping should be reasonably doable through an overridden shipping pane, either as a contrib module or a PR for commerce_shipping. I looked into it myself at one point, but decided that it would make sense to wait for https://www.drupal.org/project/commerce/issues/2844920 to be finished first.

Ultimately, both scenarios and the administration ui at https://www.drupal.org/project/commerce_shipping/issues/2854035 will all need to play well together, but if you are looking to build multi-address shipping as a PR for commerce_shipping, I would recommend starting your own issue for it so people have the opportunity to comment and contribute.

heddn’s picture

Issue summary: View changes

Discussed in slack with @mlutz and reverting the IS.

andyg5000’s picture

I'm running into this now and would like to come up with a way that USPS, UPS, and FedEx all respect. The simplest thing I can think of is to add an integer field to the shipment entity. The packer plugins could then set the package type and number of packages when proposing shipments.

If the value of this field is > 1, the the rating modules will split the volume and weight of shipment items across that number of packages to make the rate request.

It means that 1 shipment can only have 1 package type, but can have multiple packages of that type. If you need multiple package types per shipment, I think you're in custom code land.

@mikelutz, do you have any thoughts on this?

We could standardize on a field, or have the shipping method config page load fields that match to use for # of packages.

mikelutz’s picture

So, there is really two parts to this. The first is in the rate request itself, made during checkout. Essentially you are describing a system where the checkout pane is deciding that this order needs to be split up into n packages based on the default package and shipment order_items, and then passing the number n to the shipping plugin, which at the end of the day, the shipping plugin is free to use or not use in determining which rates to send back. I would make the argument that the shipping plugin has everything it needs to calculate n if it wants and needs to, and might even have some additional information that might allow it to calculate a more appropriate estimation of n for its purposes.

Currently for the purposes of creating rate requests, the fedex module ships with three strategies for calculating n, and distributing the weight through n packages (selectable globally in the shipping method settings form)

1) Assume all products ship in one box, get a rate request for one box of the combined product weight of the entire order. (generally fine if you ship small products and small quantities)
2) Ship each item in it's own box (safest, but can inflate the shipping cost to the customer more than necessary)
3) Estimate a number of boxes (do a rough calculation of n based on dividing the total volume of products by the volume of one box, then getting a rate request for n boxes each with a weight of (Total Shipment Weight / n)

In addition to those three, some people have has success with patching a fourth option in to use a packing library which actually figures out which items could physically fit in which box. Strategy #3 above would happily assume you can fit 10 10cm x 10cmx 100cm items in a 50cm x 50cm x 40cm box.

You are describing #3 with the calculation of n being removed from the shipping plugin and instead having it included with the weight request, and if this benefits other shipping plugins, then I have no specific objection. I would refactor fedex to continue to allow the three options, but use the passed in n value for option #3 rather than calculating it. It wouldn't have any real benefit to fedex, but I'm all for moving any logic useful to more than one shipping plugin into shipping core.

The other thing to note is that currently, the value of n is of no use outside of the immediate rate calculation done in the checkout form, or when adding a shipment through the admin UI (And I will confess I have not spent much time looking at the changes to the admin UI for shipments done in the last year, so I do need to look through that). While there may be limited value in letting the administrator know the number of boxes the rate calculator assumed when doing it's calculation, that number really has no bearing at all on how many boxes of what type the administrator actually chooses to use to physically ship the order. When they go to physically shipping the order, they are going to use common sense, putting things in the most efficient size of envelop or boxes for that particular order.

So this leads to the second part of this, and the reason why I filed the issue, and would love to have some way to store more specific package information on a shipment (specifically an array of packages listing package size, specific order items and quantities in that box, and tracking information in that box) was to be able to integrate end-to-end fulfillment in the admin interface. So after an order, the admin can go in, start with the best-guess packing strategy that the rate request used, or a blank slate, then add packages of various sizes to the shipment, and add items to the packages, and then with one button print out a packing slip and shipping label for each actual package, so they can just slap them on and be ready to go. Again, this could be built completely in FedEx for FedEx through custom storage and alters, but I would rather try and keep the packing logic separate and reduce the actual fedex module down to just a wrapper around the FedEx api calls.

That all having been said, having full fulfillment is something I've been talking about for two years now, but it's a lot of work and I haven't been in a position where I had a client or sponsorship to do it. There's a lot of BC concerns around modifying the shipping api to the extent that would be needed. Maybe a base 'commerce_shipping_fulfillment' module that shipping methods could all use to get the additional apis and alters to the shipping entity would be a good way to go to avoid the BC concerns and prove everything out with a goal of including it in a future major version update of Centarro Shipping. Anyway, all of this is probably beyond what you are needing right now, so I'll jump down from my soapbox, but I hope this tome of a comment helps a little bit.