prestashop-specs icon indicating copy to clipboard operation
prestashop-specs copied to clipboard

Multiple Orders for a Cart

Open Matt75 opened this issue 5 years ago • 29 comments

Order splitting

Sometime PrestaShop will split a Cart in multiple Order with same Reference after a Payment.

Because this splitting is made by PrestaShop after the Payment, Customer has only paid Shipping Costs for one Order.

So PrestaShop will display a warning on Order view page to notify merchant the total order amount is not equal to total cart amount.

Possible cases

  1. A product of Cart exceeds the price/weight range of carriers
  2. A product of Cart is restricted to one Carrier (case described bellow)
  3. Warehouse management in 1.6, removed in 1.7
  4. Multi-shipping functionnality in 1.5 removed in 1.6
  5. Others cases I don't know

➡️ Find every possible cases will cause Order splitting

How to handle that for PaymentModule

  • Every PaymentModule will only update OrderState of the main Order, on module validation trigger by API (like bank validation return).
  • Every child Order should be manually update by merchant because he needs to choose if additional shipping cost should be paid by Customer or if he take it in charge.

⚠️ This should be confirmed and documented

Related to https://github.com/PrestaShop/docs/issues/508

Matt75 avatar Apr 21 '20 12:04 Matt75

For me, the best and easy way should be to remove order splitting. It's not needed anymore and upset ERP and accountants

jf-viguier avatar Apr 27 '20 10:04 jf-viguier

ping @PrestaShop/prestashop-product-team @MatShir

eternoendless avatar May 14 '20 15:05 eternoendless

Hello @Matt75, thanks for your issue. What do you expect from the @PrestaShop/product-team on this issue, specifications for the multiple orders?

LouiseBonnard avatar Oct 01 '20 16:10 LouiseBonnard

@LouiseBonnard Currently PrestaShop generate multiple Order from a Cart in some cases described in the issue. Module developers don't know how to manage this because we receive only the latest Order id created by PrestaShop. Core developers don't know how this works or should works.

So Product Team, please document how PrestaShop create Order from Cart, cases where PrestaShop create multiple Orders, check if current process is good because there are problems with shipping costs and invoices.

Currently modules developers receive many complaints about this and we don't know what to respond or what to improve. This is a huge pain point.

Matt75 avatar Oct 02 '20 09:10 Matt75

Hi we have a client that the PS is randomly splitting orders by assigning different delivery address to each order.

Some times PS use deleted delivery address but the buyer select only one address during checkout

Same issue decribes here https://www.prestashop.com/forums/topic/1049013-prestashop-is-splitting-orders-using-deleted-delivery-addresses/

PS 1.7.6.9

msaustral avatar Jun 10 '21 19:06 msaustral

Thanks @Matt75 for this, I totally agree with you 👍

jf-viguier avatar Jun 10 '21 21:06 jf-viguier

for us orders with products quantity<=0 got split and the order with the Q<=0 had a totally random address - same addres everytime with every user

shpe11 avatar Jul 28 '21 20:07 shpe11

Hi we have some customers with split orders that have deleted address as a Shipping address, any idea?

msaustral avatar Nov 03 '21 19:11 msaustral

Please, there is any information about this issue? the bad thing about this is that for me its imposible to replicate... i get this error, but copy exactly the same order and destination and every thing work fine i appreciate any method to track this problem

oldlastman avatar Nov 04 '21 19:11 oldlastman

In our case we have not specified a carrier to certain products and this issue still happens. A temporary solution that I've found is to remove the part that does a where clause on id_address_delivery in Cart.php updateAddressId() function. Now when a customer goes through checkout steps and chooses an address, all the products will be updated in cart_product table to have the same id_address_delivery.

Change this:

$sql = 'UPDATE `' . _DB_PREFIX_ . 'cart_product`
        SET `id_address_delivery` = ' . (int) $id_address_new . '
        WHERE  `id_cart` = ' . (int) $this->id . '
            AND `id_address_delivery` = ' . (int) $id_address;
        Db::getInstance()->execute($sql);

        $sql = 'UPDATE `' . _DB_PREFIX_ . 'customization`
            SET `id_address_delivery` = ' . (int) $id_address_new . '
            WHERE  `id_cart` = ' . (int) $this->id . '
                AND `id_address_delivery` = ' . (int) $id_address;
        Db::getInstance()->execute($sql);

To this:

$sql = 'UPDATE `' . _DB_PREFIX_ . 'cart_product`
        SET `id_address_delivery` = ' . (int) $id_address_new . '
        WHERE  `id_cart` = ' . (int) $this->id;
        Db::getInstance()->execute($sql);

        $sql = 'UPDATE `' . _DB_PREFIX_ . 'customization`
            SET `id_address_delivery` = ' . (int) $id_address_new . '
            WHERE  `id_cart` = ' . (int) $this->id;
        Db::getInstance()->execute($sql);

itsvahid avatar Nov 10 '21 15:11 itsvahid

In our case we have not specified a carrier to certain products and this issue still happens. A temporary solution that I've found is to remove the part that does a where clause on id_address_delivery in Cart.php updateAddressId() function. Now when a customer goes through checkout steps and chooses an address, all the products will be updated in cart_product table to have the same id_address_delivery.

Change this:

$sql = 'UPDATE `' . _DB_PREFIX_ . 'cart_product`
        SET `id_address_delivery` = ' . (int) $id_address_new . '
        WHERE  `id_cart` = ' . (int) $this->id . '
            AND `id_address_delivery` = ' . (int) $id_address;
        Db::getInstance()->execute($sql);

        $sql = 'UPDATE `' . _DB_PREFIX_ . 'customization`
            SET `id_address_delivery` = ' . (int) $id_address_new . '
            WHERE  `id_cart` = ' . (int) $this->id . '
                AND `id_address_delivery` = ' . (int) $id_address;
        Db::getInstance()->execute($sql);

To this:

$sql = 'UPDATE `' . _DB_PREFIX_ . 'cart_product`
        SET `id_address_delivery` = ' . (int) $id_address_new . '
        WHERE  `id_cart` = ' . (int) $this->id;
        Db::getInstance()->execute($sql);

        $sql = 'UPDATE `' . _DB_PREFIX_ . 'customization`
            SET `id_address_delivery` = ' . (int) $id_address_new . '
            WHERE  `id_cart` = ' . (int) $this->id;
        Db::getInstance()->execute($sql);

Very good approach, I did some testing. review at car_product table, hope it fix the problem, from now on.

javierrojas10 avatar Dec 13 '21 21:12 javierrojas10

I think the proposed patch by @itsvahid touches code involved by this patch, https://github.com/PrestaShop/PrestaShop/issues/9932 https://github.com/PrestaShop/PrestaShop/pull/15399/commits/87f351e767b0f537fffe42ca484a992eb74b7201

could the two be related? Because started noticing this cart splitting issue after applying the patch for issue 9932 on PrestaShop.

EDIT:another possible reason could be (need more debugging to confirm) if you have a cart discount rule that adds a product to the cart and sets free shipping = false, but you have a main cart rule to offer free shipping at a certain price so:

cart with a total amount 50€ (free shipping main rule matches) free product with free shipping = false =then=> order is split, so we see an order with the product and free shipping and another order with the free product but payed shipping.

drc0 avatar Dec 17 '21 09:12 drc0

Hi @drc0 please confirm on any of the splitted order if they have on ether shipping or billing address an address id that on ps_address has on the field deleted "1"

msaustral avatar Dec 17 '21 12:12 msaustral

@msaustral yes ! in fact I was seeing strange placeholders in the order recap admin page regarding the address.. But the real customer address is in fact correct.. I have to say that I have installed a plugin that previews shipping prices by creating temporary addresses and setting them as deleted, do you see any other possible reason though?

drc0 avatar Dec 17 '21 13:12 drc0

Hi, this is hard to solve, it is random, not because a shipping method or discount.

Prestashop is working on solved but it can not be reproduce.

The issue comes from v.1.6 that allow the customer to have different address by products in his cart.

On V. 1.7 this option is not present but the core still have the code.

msaustral avatar Dec 17 '21 18:12 msaustral

Please find the FINAL solution to split order:

1- modify class/PaymentModule.php line 320 -+ and add a break before the firs closing } like this:

foreach ($package_list as $id_address => $packageByAddress) {
                foreach ($packageByAddress as $id_package => $package) {
                    $orderData = $this->createOrderFromCart(
                        $this->context->cart,
                        $this->context->currency,
                        $package['product_list'],
                        $id_address,
                        $this->context,
                        $reference,
                        $secure_key,
                        $payment_method,
                        $this->name,
                        $dont_touch_amount,
                        $amount_paid,
                        $package_list[$id_address][$id_package]['id_warehouse'],
                        $cart_total_paid,
                        self::DEBUG_MODE,
                        $order_status,
                        $id_order_state,
                        isset($package['id_carrier']) ? $package['id_carrier'] : null
                    );
                    $order = $orderData['order'];
                    $order_list[] = $order;
                    $order_detail_list[] = $orderData['orderDetail'];
                    break; 
                } 
                break; 
            }

This will prevent the split order.

2 - Modify class/Cart.php line 322 and 327 and erase the condition AND id_address_delivery = ' . (int) $id_address; like this:

$sql = 'UPDATE `' . _DB_PREFIX_ . 'cart_product`
SET `id_address_delivery` = ' . (int) $id_address_new . '
WHERE  `id_cart` = ' . (int) $this->id;
Db::getInstance()->execute($sql);

$sql = 'UPDATE `' . _DB_PREFIX_ . 'customization`
SET `id_address_delivery` = ' . (int) $id_address_new . '
WHERE  `id_cart` = ' . (int) $this->id;
Db::getInstance()->execute($sql);

This will force to update the delivery address on the cart.

Hopes it helps!

msaustral avatar Jan 17 '22 15:01 msaustral

Hi, why this solution is not present in latest version, nor in any pull request? We have this issue randomly happens in many shops, seem to be caused when user change/create address in order process.

ComonSoft avatar Jun 21 '22 09:06 ComonSoft

Probably because this solution works if you don't use the multiple package feature but it could breaks this feature if no deeper investigation is done.

Split order is a "normal" behavior when using carriers restrictions, warehouse or multishipping. But it's not documented, nobody know how it works or should works so before consider any code changes, product team have to studies and create specifications. (It's a legacy from PrestaShop 1.5)

@PrestaShop/product-team friendly reminder, I know it's a hard topic but everyone needs more knowledges on this.

Matt75 avatar Jun 21 '22 09:06 Matt75

Ok @Matt75 I understand, but as you explained this feature is not yet implemented! So according to me it will be better for users to have a solution instead of a bug ;-) Sad effect on customers :-( We noticed it's happend when user delete an address used in cart. See sample database ps_cart_product: psbug

The id_address_delivery 41780 is marked deleted in database, and we don't have carrier restrictions.

ComonSoft avatar Jun 21 '22 11:06 ComonSoft

@ComonSoft You misunderstand, the feature was implemented on PrestaShop 1.5, partially removed from Core and reintroduced to modules. Many merchants needs it so to restore it, they can install a module to have Warehouse, multishipping like before etc... So this change can breaks original behavior so it can breaks thoses modules. That's why this must be studied and specified before any code changes on PrestaShop Core.

Matt75 avatar Jun 21 '22 15:06 Matt75

My module relies on the multishipping and split orders functionalities. please do not remove this feature.

immakdas avatar Jan 02 '24 08:01 immakdas

For me order-splitting is a real pain, but I see that it might be needed for some merchants, like if they need different carriers for different products (like a cart with a fox, a chicken, and a sack of corn). Or modules that for different reasons use this.

But for the rest of us: it makes only issues.

  1. We really need to know how, why and when order splitting occurs.
  2. Since it's a feature that not many use, it should be optional. I suggest making it a config Allow order splitting. If disabled, then selecting product-specific carriers should be greyed out (maybe other things as well).

Any update @PrestaShop/product-team? Thank you

madsoliver avatar Jan 09 '24 11:01 madsoliver

Here is my humble opinion:

We really need to know how, why and when order splitting occurs.

=> This happens when there are multiple packages, in other words, multiple carriers shipping distinct products. In my humble opinion, this split order case is not a random case. To be able to reproduce it, just add 2 different products shipped by 2 different carriers. This will lead to a split order. The problem is that the split order case is not correctly handled, meaning there are multiple resulting issues related to:

  • how products and related carriers are displayed in the order page at the delivery step
  • how products and related carriers are displayed in the order page at the summary step (or payment step)
  • how products and chosen carriers are displayed in the order confirmation page
  • how the discount code are handled (in both front office and back office)
  • how the invoices are handled
  • how the total paid amount is updated after each sub order status update
  • etc.

If there is another scenario (other than the one I mentioned) causing the split order, please share the detailed steps to reproduce it.

For me, the best and easy way should be to remove order splitting. It's not needed anymore and upset ERP and accountants

=> In my humble opinion, it should the split order feature should be kept to respond to many use cases, such as:

  • a merchant who is selling light items and heavy items, these items are shipped by 2 different carriers (one for light items and one for heavy items).
  • a merchant who is selling fresh items and normal items, these items are shipped by 2 different carriers (one for fresh items and one for normal items).
  • a merchant who is shipping some items from his own warehouse and some items directly from his suppliers. He will need the use of 2 different carriers, one for each source of shipment.
  • a merchant who is dropshipping items from different suppliers. He will need to define a carrier for each supplier.
  • etc.

These are real use cases I have encountered with merchants who bought the module I developed Multi Shipping / Multiple Carriers Order (also available here - check for better FAQ section readability), in which I handled all the above-mentioned aspects.

In a nutshell, the module enables multi shipping / multi carrier orders in PrestaShop. The order will be split based on the number of the carriers. Here is the demo video.

Here is the module documentation Multi Shipping - Multiple Carriers Order_documentation.pdf where you can find examples and the limitations to be aware of.

Every PaymentModule will only update OrderState of the main Order, on module validation trigger by API (like bank validation return). Every child Order should be manually update by merchant because he needs to choose if additional shipping cost should be paid by Customer or if he take it in charge.

=> This is normal. All the payment and shipping modules are implemented for the classic context, not the split order context. So they do not handle this out of the box. So when setting up a store with split order context, the developer has to adapt each involved payment or shipping module (especially those with pickup locations) to the split order context (please check section "6. Recommendations" in the documentation). For example, I tested the module with Stripe (v3.1.4) and PayPal (v6.0.2) which updated all sub-orders with the status "Payment" accepted, but it was not the case with Revolut.

Hope this helps!

jouino16 avatar Apr 14 '25 19:04 jouino16

Hi @jouino16 the problem is that on those known cases that you mention and slip order is need it, it does not fail

there are some rare cases that we have not able to reproduce where PS add, at the same time, address that are marked as deleted and the right address that the customer select during checkout.

In this case PS slip the order, one with the right selected address and another with the deleted address

This case is a bug.

msaustral avatar Apr 14 '25 20:04 msaustral

Hi @msaustral, thank you for your feedback.

In this case, I would suspect a shipping module that could mess up with the customer delivery address. This would be sufficient to cause an issue.

For example, Mondial Relay module creates a new delivery address when selecting a pickup location. I'm not saying that Mondial Relay is causing an issue. But if some module has the same behavior but with a hidden bug, this might cause the split order issue.

jouino16 avatar Apr 15 '25 07:04 jouino16

Hi @jouino16 it happen with regular shipping method

msaustral avatar Apr 15 '25 14:04 msaustral

Hi @msaustral, I would be curious to have the replication steps. Hope someone posts it some day.

jouino16 avatar Apr 15 '25 14:04 jouino16

Hi @jouino16 , that is the problem, it have not been solved because it can not be reproduce, it happens once a month with one order

msaustral avatar Apr 15 '25 14:04 msaustral

Hi @msaustral, yes that is what I understood, but I hope someday someone will be able to do it.

jouino16 avatar Apr 15 '25 14:04 jouino16