Skip to content

Releases: dbltoe/multiship-3

v3.0.2 — Checkbox attributes no longer stop the cart; shipping titles escaped

Choose a tag to compare

@dbltoe dbltoe released this 04 Oct 23:37

Zen Cart 2.0.0 – 2.3.0, PHP 8. Upload zc_plugins/MultiShip/v3.0.2/ and upgrade from Admin → Modules → Plugin Manager; no core or template files change, and nothing in your settings or database changes.

Fixed

  • A product with a ticked checkbox attribute in the cart stopped the shopping cart page with FATAL MySQL error 1054: Unknown column '13_chk36' in 'where clause'. Zen Cart stores a ticked checkbox under a combined key (<option>_chk<value>), and the plugin's check for downloadable attributes read that key as if it were a plain option number. It now reads both halves of the key, so checkbox, text and every other attribute type are checked the same way. Present since 3.0.0, on every Zen Cart and PHP version the plugin supports.
  • A multiship order couldn't be placed if the chosen shipping method's title contained an apostrophe (Bob's Courier, for example). The title was written into the order unescaped and broke the query; it's now escaped.

Multiple Ship-To Addresses Pro works with 3.0.2 unchanged.

Full history in the Read Me. Support: Zen Cart forum thread.

v3.0.1 — Companion-plugin seams and four split-order fixes

Choose a tag to compare

@dbltoe dbltoe released this 08 Sep 10:23

Zen Cart 2.0.0 – 2.3.0, PHP 8. Upload zc_plugins/MultiShip/v3.0.1/ and upgrade from Admin → Modules → Plugin Manager; no core or template files change.

Fixed

  • Choosing an address that no shipping module serves, in any row but the first, emptied every row. The offer test counted shipping modules whose enabled state reflected whichever address had been validated last; it now asks whether the store has shipping modules installed, which is what it meant.
  • The payment and confirmation pages of a split order showed shipping as $0.00 — and a total without it — whenever the whole order cleared the Shipping order total's free-shipping threshold but the individual addresses did not, while the order was then stored, and charged, with shipping on every address. The Shipping module was judging the parent order against the whole cart after its parts had already been decided. The parent now reports the sum of its sub-orders.
  • A sub-order that earned free shipping on its own under that threshold still showed the carrier's charge on its shipping line, while its total and the order's shipping total disagreed with it. The order-total modules now have the last word on every sub-order.
  • An order that came to nothing — free products, free shipping — raised a PHP warning while its confirmation email was built.

Changed

  • The per-recipient items table heads its last column Item Total rather than Total, which sat a few lines beneath the recipient's own total and read as a contradiction. Its number columns are centered, scoped to these tables only.

Added

  • Seams for companion plugins. NOTIFY_MULTISHIP_QUOTE_ADDRESS and NOTIFY_MULTISHIP_VALIDATE_ADDRESS fire before each address is quoted with the quote passed by reference; NOTIFY_MULTISHIP_INITIALIZE_END fires once every address is priced with the per-address and order-level totals by reference; NOTIFY_HEADER_END_CHECKOUT_MULTISHIP carries two variables that let an observer hide the shipping-method choice and put a note in its place. They exist for Multiple Ship-To Addresses Pro, which picks the cheapest carrier for every address and judges free shipping on the whole order. With no observer attached, nothing about this plugin's behavior changes.

Full history in the Read Me. Support: Zen Cart forum thread.

v3.0.0 — Encapsulated plugin for Zen Cart 2.0.0–2.3.0

Choose a tag to compare

@dbltoe dbltoe released this 26 Aug 20:07

Multiple Ship-To Addresses v3.0.0 is a rewrite of the plugin as a fully encapsulated
zc_plugin. It changes no core file and no template file, installs and uninstalls from
Plugin Manager, and supports Zen Cart 2.0.0 through 2.3.0 on PHP 8.

Built on the plugin created by lat9 of Vinos de Frutas Tropicales, whose original work
provides the order splitting, the per-address shipping costs and the destination-based tax
handling this version still relies on.

Upgrading from 2.x — read this first

The old plugin shipped files into your core and template directories. Those files must be
deleted, not overwritten.
They still execute if left in place, and several of them
duplicate work this version now does elsewhere — one of them auto-submits the shipping form
on checkout_shipping. Remove the old plugin's files under includes/modules/pages/,
includes/templates/YOUR_TEMPLATE/ and includes/classes/ before installing, then upload
zc_plugins/MultiShip/v3.0.0/ and install from Plugin Manager.

Uninstalling drops the orders_multiship table and the orders_multiship_id column from
orders. Per-address data on historical orders is not recoverable afterwards.

What is new

Three steps instead of five. The shipping method is now chosen on the address grid
itself, so a customer goes cart → addresses → payment → confirmation without being asked to
confirm a method they already picked.

Every item is addressable individually. Each unit gets its own row rather than a
quantity box, and nothing is assigned by default — a row with no address chosen blocks
checkout instead of silently shipping to the customer's own address.

The per-address breakdown reaches every page that should show it — confirmation, order
success, the customer's order history, and the admin's order detail, invoice and packing
slip. The admin gets a packing slip per destination.

Quantity discounts survive the split. A cart qualifying for a quantity discount kept it
after being divided between addresses; previously the discount was recalculated per
consignment and lost.

Unshippable addresses are marked, not merely rejected. If the chosen shipping method
cannot serve an address, that row is flagged with a warning icon, the reason is stated above
the grid, and checkout is blocked until it is resolved.

Compatibility handled for you

One Page Checkout, guest and PayPal Express checkout, discount coupons and group pricing are
all handled — see the Read Me for what happens in each case. Payment modules that cannot cope
with a split order can be named in the plugin's configuration.

Known limitations

Edit Orders cannot be used on a multiship order. Opening one returns the admin to the
order's normal detail page with a message explaining why: editing it there would destroy the
record of which items went to which address. Orders that are not multiship are unaffected.

What is blocked is restructuring the line items, not editing the order. The order's own
Details page works as it always has — status changes, comments and customer notifications
are all still there — and this plugin adds per-address status updates to that page, so each
parcel can be advanced independently.

Free shipping does not survive a split. Both kinds behave badly: the Free Options and
Free Shipping shipping modules decide at quote time, so a split order that no longer clears
the threshold produces no quote and checkout is blocked; the Shipping order-total module's
"Allow Free Shipping" decides after the quote, so the order completes with shipping charged
on every address after the cart page said it was free. If you offer free shipping over a
threshold, say so in your shipping policy or set the threshold low enough that a split order
still clears it.

One shipping method for the whole order. Every consignment uses the method the customer
picked; a cheaper carrier for one destination is not offered.

Order emails use Zen Cart's stock banner unless you have replaced /email/header.jpg
with your own. This plugin sends one email per parcel rather than one per order, so an
unreplaced banner is seen more often than before.

Security

Contains no dynamic code execution, no obfuscated or minified-beyond-reading script, no
innerHTML, and no off-site asset — the documentation loads only its own files. The
per-address breakdown reaches the storefront as an inert <template> cloned into place rather
than as HTML parsed from a string, customer-supplied names are escaped on output, every
request value is cast or passed through zen_db_prepare_input before reaching a query, and
included admin files carry the same IS_ADMIN_FLAG guard core uses on its own.

Credits and support

Original plugin © 2014-2019 Vinos de Frutas Tropicales (lat9). v3.0.0 © 2026 My Zen Cart
Host (dbltoe). GPL v2.