Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed: Partial cart rule not creating when using multiple coupons in a single cart #1153

Merged
merged 13 commits into from
Sep 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions classes/Cart.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ class CartCore extends ObjectModel
const ONLY_ROOM_SERVICES_WITH_AUTO_ADD_WITHOUT_CONVENIENCE_FEE = 17;
const ONLY_CONVENIENCE_FEE = 18;

const ONLY_PRODUCTS_WITH_DEMANDS = 19;

public function __construct($id = null, $id_lang = null)
{
parent::__construct($id);
Expand Down Expand Up @@ -366,8 +368,8 @@ public static function getTaxesAverageUsed($id_cart)
*/
public function getAverageProductsTaxRate(&$cart_amount_te = null, &$cart_amount_ti = null)
{
$cart_amount_ti = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS);
$cart_amount_te = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS);
$cart_amount_ti = $this->getOrderTotal(true, Cart::ONLY_PRODUCTS_WITH_DEMANDS);
$cart_amount_te = $this->getOrderTotal(false, Cart::ONLY_PRODUCTS_WITH_DEMANDS);

$cart_vat_amount = $cart_amount_ti - $cart_amount_te;

Expand Down Expand Up @@ -1029,6 +1031,9 @@ public function addCartRule($id_cart_rule)
if ((int)$cartRule->gift_product) {
$this->updateQty(1, $cartRule->gift_product, $cartRule->gift_product_attribute, false, 'up', 0, null, false);
}
// after adding new cart rule, check if any of the appled cart rules are not being used
CartRule::autoRemoveFromCart(Context::getContext());
CartRule::autoAddToCart(Context::getContext());

return true;
}
Expand Down Expand Up @@ -1612,6 +1617,7 @@ public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products
Cart::ONLY_PHYSICAL_PRODUCTS_WITHOUT_SHIPPING,
Cart::ADVANCE_PAYMENT,
Cart::ADVANCE_PAYMENT_ONLY_PRODUCTS,
Cart::ONLY_PRODUCTS_WITH_DEMANDS,
);

// Define virtual context to prevent case where the cart is not the in the global context
Expand Down Expand Up @@ -1875,16 +1881,14 @@ public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products


// price of extra demands on room type in the cart
if ($type == Cart::BOTH || $type == Cart::BOTH_WITHOUT_SHIPPING || $type == Cart::ADVANCE_PAYMENT) {
$totalDemandsPrice += $objCartBookingData->getCartExtraDemands($this->id, $product['id_product'], 0, 0, 0, 1, 0, (int)$with_taxes);
}
$totalDemandsPrice += $objCartBookingData->getCartExtraDemands($this->id, $product['id_product'], 0, 0, 0, 1, 0, (int)$with_taxes);
}

foreach ($products_total as $key => $price) {
$order_total += $price;
}

$order_total_products = $order_total;
$order_total_products = $order_total + $totalDemandsPrice;

if ($type == Cart::ONLY_DISCOUNTS) {
$order_total = 0;
Expand All @@ -1904,7 +1908,11 @@ public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products
}

// price of extra demands on room type in the cart
if ($type == Cart::BOTH || $type == Cart::BOTH_WITHOUT_SHIPPING || $type == Cart::ADVANCE_PAYMENT) {
if ($type == Cart::BOTH
|| $type == Cart::BOTH_WITHOUT_SHIPPING
|| $type == Cart::ADVANCE_PAYMENT
|| $type == Cart::ONLY_PRODUCTS_WITH_DEMANDS
) {
$order_total += $totalDemandsPrice;
}

Expand All @@ -1921,7 +1929,8 @@ public function getOrderTotal($with_taxes = true, $type = Cart::BOTH, $products
Cart::ONLY_CONVENIENCE_FEE,
Cart::ONLY_ROOM_SERVICES_WITHOUT_AUTO_ADD,
Cart::ONLY_ROOM_SERVICES_WITHOUT_CONVENIENCE_FEE,
Cart::ONLY_ROOM_SERVICES_WITH_AUTO_ADD_WITHOUT_CONVENIENCE_FEE)
Cart::ONLY_ROOM_SERVICES_WITH_AUTO_ADD_WITHOUT_CONVENIENCE_FEE,
Cart::ONLY_PRODUCTS_WITH_DEMANDS)
) && CartRule::isFeatureActive()
) {
// First, retrieve the cart rules associated to this "getOrderTotal"
Expand Down Expand Up @@ -3814,10 +3823,6 @@ public function getSummaryDetails($id_lang = null, $refresh = false)

}
}

if (((float)$cart_rule['value_real'] == 0 && (int)$cart_rule['free_shipping'] == 0)) {
unset($cart_rules[$key]);
}
}

$objHotelAdvancedPayment = new HotelAdvancedPayment();
Expand Down
23 changes: 17 additions & 6 deletions classes/CartRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,9 @@ public function checkValidity(Context $context, $alreadyInCart = false, $display
if (strtotime($this->date_to) < time()) {
return (!$display_error) ? false : Tools::displayError('This voucher has expired');
}
if (!$alreadyInCart && $context->cart->getOrderTotal(true, Cart::BOTH) <= 0) {
return (!$display_error) ? false : Tools::displayError('You cannot add more vouchers. Please remove an existing voucher before applying a new one.');
}

if ($context->cart->id_customer) {
$quantityUsed = Db::getInstance()->getValue('
Expand Down Expand Up @@ -970,8 +973,8 @@ public function getContextualValue($use_tax, Context $context = null, $filter =

$all_cart_rules_ids = $context->cart->getOrderedCartRulesIds();

$cart_amount_ti = $context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS);
$cart_amount_te = $context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
$cart_amount_ti = $context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS_WITH_DEMANDS);
$cart_amount_te = $context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS_WITH_DEMANDS);

// Free shipping on selected carriers
if ($this->free_shipping && in_array($filter, array(CartRule::FILTER_ACTION_ALL, CartRule::FILTER_ACTION_ALL_NOCAP, CartRule::FILTER_ACTION_SHIPPING))) {
Expand All @@ -997,7 +1000,7 @@ public function getContextualValue($use_tax, Context $context = null, $filter =
// Discount (%) on the whole order
if ($this->reduction_percent && $this->reduction_product == 0) {
// Do not give a reduction on free products!
$order_total = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package_products);
$order_total = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS_WITH_DEMANDS, $package_products);
foreach ($context->cart->getCartRules(CartRule::FILTER_ACTION_GIFT) as $cart_rule) {
$order_total -= Tools::ps_round($cart_rule['obj']->getContextualValue($use_tax, $context, CartRule::FILTER_ACTION_GIFT, $package), _PS_PRICE_COMPUTE_PRECISION_);
}
Expand Down Expand Up @@ -1070,9 +1073,9 @@ public function getContextualValue($use_tax, Context $context = null, $filter =
if ((float)$this->reduction_amount > 0) {
$prorata = 1;
if (!is_null($package) && count($all_products)) {
$total_products = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS);
$total_products = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS_WITH_DEMANDS);
if ($total_products) {
$prorata = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS, $package['products']) / $total_products;
$prorata = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS_WITH_DEMANDS, $package['products']) / $total_products;
}
}

Expand Down Expand Up @@ -1121,7 +1124,7 @@ public function getContextualValue($use_tax, Context $context = null, $filter =
if ($this->reduction_tax == $use_tax) {
// The reduction cannot exceed the products total, except when we do not want it to be limited (for the partial use calculation)
if ($filter != CartRule::FILTER_ACTION_ALL_NOCAP) {
$cart_amount = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS);
$cart_amount = $context->cart->getOrderTotal($use_tax, Cart::ONLY_PRODUCTS_WITH_DEMANDS);
$reduction_amount = min($reduction_amount, $cart_amount);
}
$reduction_value += $prorata * $reduction_amount;
Expand Down Expand Up @@ -1377,12 +1380,20 @@ public static function autoRemoveFromCart($context = null)
return array();
}

$order_total = $context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS_WITH_DEMANDS, null, null, false);
static $errors = array();
foreach ($context->cart->getCartRules() as $cart_rule) {
if ($error = $cart_rule['obj']->checkValidity($context, true)) {
$context->cart->removeCartRule($cart_rule['obj']->id);
$context->cart->update();
$errors[] = $error;
} else {
if ($order_total <= 0) {
// remove cart rule if cart amount is already reached 0
$context->cart->removeCartRule($cart_rule['obj']->id);
} else {
$order_total = $order_total - $cart_rule['value_real'];
}
}
}
return $errors;
Expand Down
Loading