Hello,
SHORT INTRODUCTION
I was never satisfied with the native behaviour of "delayed shipping" feature in PS 1.6 - it's very helpful but it just doesn't work properly and I wanted to improve it. I have managed to add JSON support and changed its behaviour a little bit. Previously I have modified the behaviour of AVAILABILITY column (which I also described here) in shopping-cart-product-line.tpl, so it now shows 'STOCK quantity' and 'BACKORDER quantity' (or ON REQUEST in my case, since I'm using module which disables COD payment for orders with BACKORDER products and leaves only pre-payment methods).
Now, we have a several cases regarding the "delayed shipping" feature, which we have to investigate:
1) All products in cart have no stock (stock quantity <= 0) in the cart -> delayed shipping not appearing (in native PS it was appearing which was wrong - there is nothing to split here) = works OK -> https://streamable.com/guvfv
2) All products in cart have positive stock (stock quantity > 0) -> delayed shipping appears when the cart quantity exceeds stock quantity - works OK -> https://streamable.com/3v7kh
3) Products in cart have both positive stock (stock quantity > 0) and no stock (stock quantity <= 0).
- I'm deleting out_of_stock products form the cart - works OK -> https://streamable.com/r3ipf
- I'm deleting in_stock products form the cart - works OK -> https://streamable.com/j3fdf
CODE MODIFICATIONS
File: \classes\Cart.php -> I have added 2 functions, which are counting in_stock nad out_of_stock (backorder) products in the cart
public function countOOSProducts() { $product_out_of_stock = 0; foreach ($this->getProducts() as $product) { if ((int)$product['quantity_available'] <= 0 && (!$ignore_virtual || !$product['is_virtual'])) { $product_out_of_stock++; } } return $product_out_of_stock; } public function countISProducts() { $product_in_stock = 0; foreach ($this->getProducts() as $product) { if ((int)$product['quantity_available'] > 0 && (!$ignore_virtual || !$product['is_virtual'])) { $product_in_stock++; } } return $product_in_stock; }
I have added new variables returned by these functions to summary array() to pass them into front files, so the new array() looks like this:
$summary = array( 'delivery' => $delivery, 'delivery_state' => State::getNameById($delivery->id_state), 'invoice' => $invoice, 'invoice_state' => State::getNameById($invoice->id_state), 'formattedAddresses' => $formatted_addresses, 'products' => array_values($products), 'gift_products' => $gift_products, 'discounts' => array_values($cart_rules), 'is_virtual_cart' => (int)$this->isVirtualCart(), // adding 2 new variables 'product_in_stock' => $this->countISProducts();, 'product_out_of_stock' => $this->countOOSProducts();, 'total_discounts' => $total_discounts, 'total_discounts_tax_exc' => $total_discounts_tax_exc, 'total_wrapping' => $this->getOrderTotal(true, Cart::ONLY_WRAPPING), 'total_wrapping_tax_exc' => $this->getOrderTotal(false, Cart::ONLY_WRAPPING), 'total_shipping' => $total_shipping, 'total_shipping_tax_exc' => $total_shipping_tax_exc, 'total_products_wt' => $total_products_wt, 'total_products' => $total_products, 'total_price' => $base_total_tax_inc, 'total_tax' => $total_tax, 'total_price_without_tax' => $base_total_tax_exc, 'is_multi_address_delivery' => $this->isMultiAddressDelivery() || ((int)Tools::getValue('multi-shipping') == 1), 'free_ship' =>!$total_shipping && !count($this->getDeliveryAddressesWithoutCarriers(true, $errors)), 'carrier' => new Carrier($this->id_carrier, $id_lang), );
File: \themes\your_theme\js\cart-summary.js -> I have modified function updateCartSummary(json) a little bit by adding following code:
// Definition of variable storing the each line 'backorder quantity' in shopping cart 886: var OosProducts = 0; // Definition of variable storing the total 'backorder quantity' in shopping cart 887: var OosProductsTotal = 0; // Definition of the variable storing 'available_later' text 921: var available_later = product_list[i].available_later; // JSON support for AVAILABILITY column 0991: OosProducts = parseInt(product_list[i].quantity) - parseInt(product_list[i].quantity_available); 0992: if (OosProducts > 0) { 0993: $('#outofstock_availability_' + key_for_blockcart).html(available_later + ' (' + quantity + ': ' + OosProducts + ')'); 0994: $('#outofstock_availability_' + key_for_blockcart).show(); 0995: } 0996: else { 0997: $('#outofstock_availability_' + key_for_blockcart).hide(); 0998: } 0999: nbrProducts += parseInt(product_list[i].quantity); 1000: OosProductsTotal += OosProducts; 1001: } // JSON support for "delayed shipping" block 1004: if (json.product_out_of_stock == 0 && json.product_in_stock > 0) { 1005: if ((OosProducts-OosProductsTotal == 0 && OosProducts > 0) || (OosProducts-OosProductsTotal < 0 && OosProducts >= 0) || (OosProducts-OosProductsTotal < 0 && OosProducts < 0) || (OosProducts-OosProductsTotal > 0 && OosProducts > 0)) { 1006: $('.allow_seperated_package').show(); 1007: $('.allow_seperated_package').css({'color':'white', 'background-color':'orange', 'padding':'10px', 'display':'inline-block'}); 1008: } else { 1009: $('.allow_seperated_package').hide(); 1010: } 1011: } else if(json.product_out_of_stock > 0 && json.product_in_stock == 0) { 1012: $('.allow_seperated_package').hide(); 1013: } else { 1014: $('.allow_seperated_package').show(); 1015: }
File: \themes\your_theme\shopping-cart.tpl -> I have modified the native "delayed shipping" code:
638: <p class="allow_seperated_package" {if ($show_option_allow_separate_package && {$product_in_stock} > 0)}style="background: orange; padding: 10px; display: inline-block;"{else}style="display: none;"{/if}> 639: <input type="checkbox" name="allow_seperated_package" id="allow_seperated_package" {if $cart->allow_seperated_package}checked="checked"{/if} autocomplete="off"/ > 640: <label for="allow_seperated_package" class="checkbox inline"> 641: {l s='Send available products first'} 642: </label> 643: </p>
File: \themes\your_theme\shopping-cart-product-line.tpl - I have changed a behaviour in shopping cart AVAILIBILITY column here by modifying the native code as following:
25: {if $product.quantity_available <= 0} 26: {if isset($product.allow_oosp) && $product.allow_oosp} 27: {if isset($product.available_later) && $product.available_later} 28: {$product.available_later}{else}{l s='In Stock'} 29: {/if} 30: {else} 31: {l s='Out of stock'} 32: {/if} 33: {else} 34: {if isset($product.available_now) && $product.available_now} 35: {if $product.cart_quantity-$product.quantity_available <= 0} 36: {$product.available_now} ({l s='Quantity'}: {$product.quantity_available}) <br /><br /> 37: <span id="outofstock_availability_{$product.id_product}_{$product.id_product_attribute}_{if $quantityDisplayed > 0}_nocustom{/if}_{$product.id_address_delivery|intval}{if !empty($product.gift)}_gift{/if}" class="label-warning"> </span> 38: {else} 39: {$product.available_now} ({l s='Quantity'}: {$product.quantity_available}) <br /><br /> 40: <span id="outofstock_availability_{$product.id_product}_{$product.id_product_attribute}{if $quantityDisplayed > 0}_nocustom{/if}_{$product.id_address_delivery|intval}{if !empty($product.gift)}_gift{/if}" class="label-warning">{$product.available_later} ({l s='Quantity'}: {$product.cart_quantity-$product.quantity_available})</span> 41: {/if} 42: {else} 43: {if $product.cart_quantity-$product.quantity_available <= 0} 44: {l s='In Stock'} ({l s='Quantity'}: {$product.quantity_available}) <br /><br /> 45: <span id="outofstock_availability_{$product.id_product}_{$product.id_product_attribute}{if $quantityDisplayed > 0}_nocustom{/if}_{$product.id_address_delivery|intval}{if !empty($product.gift)}_gift{/if}" class="label-warning"> </span> 46: {else} 47: {l s='In Stock'} ({l s='Quantity'}: {$product.quantity_available}) <br /><br /> 48: <span id="outofstock_availability_{$product.id_product}_{$product.id_product_attribute}{if $quantityDisplayed > 0}_nocustom{/if}_{$product.id_address_delivery|intval}{if !empty($product.gift)}_gift{/if}" class="label-warning">{$product.available_later} ({l s='Quantity'}: {$product.cart_quantity-$product.quantity_available})</span> 49: {/if} 50: {/if} 51: {/if}
CONCLUSIONS
If you use modules displaying products in cart summary (shopping-cart.tpl) hooks (like crossseling) there is also a need to force page refresh after product "add to cart" action to make it work properly, since PS 1.6 does not support ajax for this action on cart summary page.
And basically that's it. Maybe someone finds it helpful in his adventure with PrestaShop. If anyone has any suggestions I would bevery grateful.
Best regards,
Radoslaw