783 lines
33 KiB
PHP
783 lines
33 KiB
PHP
<?php
|
|
class CartRule extends CartRuleCore
|
|
{
|
|
|
|
|
|
/**
|
|
* Check if this cart rule can be applied
|
|
*
|
|
* @param Context $context
|
|
* @param bool $alreadyInCart Check if the voucher is already on the cart
|
|
* @param bool $display_error Display error
|
|
* @return bool|mixed|string
|
|
*/
|
|
public function checkValidity(Context $context, $alreadyInCart = false, $display_error = true)
|
|
{
|
|
#10762 -> Bon de bienvenue
|
|
if ($this->id == 50084) {
|
|
$date_add = $context->customer->date_add;
|
|
$date_to_available = date('Y-m-d', strtotime("+1 month", strtotime($date_add)));
|
|
$date_now = date('Y-m-d H:i:s');
|
|
if ($date_now > $date_to_available) {
|
|
return $display_error ?
|
|
Tools::displayError('Ce bon est utilisable uniquement pour les nouveaux utilisateurs (< 1 mois)') : false;
|
|
}
|
|
}
|
|
$res = Parent::checkValidity($context, $alreadyInCart, $display_error);
|
|
$success = Parent::checkValidity($context, $alreadyInCart, false);
|
|
|
|
if (!$success)
|
|
return (!$display_error) ? false : $res;
|
|
|
|
if ($this->getCategoryRestriction()){
|
|
$r = $this->checkCategoryRestriction($context, $display_error, $alreadyInCart);
|
|
if ($r !== false && $display_error)
|
|
return $r;
|
|
elseif (!$r && !$display_error)
|
|
return false;
|
|
}
|
|
|
|
// Check pour compatibilité Bon LIVRAISON15 et bons générés en masse
|
|
/*$step = (int)(Tools::getValue('step'));
|
|
if ($step == 0 && ($context->cart->id_customer == 94202 || $context->cart->id_customer == 221)) {
|
|
$cartRulesAlreadyInCart = $context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING);
|
|
if ($cartRulesAlreadyInCart){
|
|
|
|
$totalWithoutShipping = floatval($context->cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING));
|
|
$totalWithoutShippingAndTax = floatval($context->cart->getOrderTotal(false, Cart::BOTH_WITHOUT_SHIPPING));
|
|
|
|
foreach ($cartRulesAlreadyInCart as $key => $cartrule) {
|
|
|
|
$totalPrice = 0;
|
|
$minimum = 0;
|
|
if ($this->minimum_amount_tax && $cartrule['minimum_amount_tax'] && $cartrule['minimum_amount']>0) {
|
|
$totalPrice = $totalWithoutShipping - $this->minimum_amount;
|
|
$minimum = $cartrule['minimum_amount'];
|
|
} elseif (!$this->minimum_amount_tax && !$cartrule['minimum_amount_tax'] && $cartrule['minimum_amount']>0) {
|
|
$totalPrice = $totalWithoutShippingAndTax - $this->minimum_amount;
|
|
$minimum = $cartrule['minimum_amount'];
|
|
}
|
|
|
|
$remaining = $totalPrice - $this->reduction_amount;
|
|
if ($remaining < $cartrule['minimum_amount']) {
|
|
return (!$display_error) ? false : Tools::displayError('Le montant minimum requis (bons inclus) pour la livraison gratuite doit être de '.Tools::displayPrice($cartrule['minimum_amount']).'. Avec le bon cumulé, le montant serait de '.Tools::displayPrice($remaining));
|
|
}
|
|
}
|
|
}
|
|
}*/
|
|
|
|
return (!$display_error) ? true : false;
|
|
}
|
|
|
|
/**
|
|
* Check if this cart rule can be applied
|
|
*
|
|
* @param Context $context
|
|
* @param bool $alreadyInCart Check if the voucher is already on the cart
|
|
* @param bool $display_error Display error
|
|
* @return bool|mixed|string
|
|
*/
|
|
public function checkValidityWithoutAmount(Context $context, $alreadyInCart = false, $display_error = true)
|
|
{
|
|
if (!CartRule::isFeatureActive())
|
|
return false;
|
|
|
|
if (!$this->active)
|
|
return (!$display_error) ? false : Tools::displayError('This voucher is disabled');
|
|
if (!$this->quantity)
|
|
return (!$display_error) ? false : Tools::displayError('This voucher has already been used');
|
|
if (strtotime($this->date_from) > time())
|
|
return (!$display_error) ? false : Tools::displayError('This voucher is not valid yet');
|
|
if (strtotime($this->date_to) < time())
|
|
return (!$display_error) ? false : Tools::displayError('This voucher has expired');
|
|
|
|
if ($context->cart->id_customer)
|
|
{
|
|
$quantityUsed = Db::getInstance()->getValue('
|
|
SELECT count(*)
|
|
FROM '._DB_PREFIX_.'orders o
|
|
LEFT JOIN '._DB_PREFIX_.'order_cart_rule od ON o.id_order = od.id_order
|
|
WHERE o.id_customer = '.$context->cart->id_customer.'
|
|
AND od.id_cart_rule = '.(int)$this->id.'
|
|
AND '.(int)Configuration::get('PS_OS_ERROR').' != o.current_state
|
|
');
|
|
if ($quantityUsed + 1 > $this->quantity_per_user)
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher anymore (usage limit reached)');
|
|
}
|
|
|
|
// Get an intersection of the customer groups and the cart rule groups (if the customer is not logged in, the default group is 1)
|
|
if ($this->group_restriction)
|
|
{
|
|
$id_cart_rule = (int)Db::getInstance()->getValue('
|
|
SELECT crg.id_cart_rule
|
|
FROM '._DB_PREFIX_.'cart_rule_group crg
|
|
WHERE crg.id_cart_rule = '.(int)$this->id.'
|
|
AND crg.id_group '.($context->cart->id_customer ? 'IN (SELECT cg.id_group FROM '._DB_PREFIX_.'customer_group cg WHERE cg.id_customer = '.(int)$context->cart->id_customer.')' : '= 1'));
|
|
if (!$id_cart_rule)
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
|
|
}
|
|
|
|
// Check if the customer delivery address is usable with the cart rule
|
|
if ($this->country_restriction)
|
|
{
|
|
if (!$context->cart->id_address_delivery)
|
|
return (!$display_error) ? false : Tools::displayError('You must choose a delivery address before applying this voucher to your order');
|
|
$id_cart_rule = (int)Db::getInstance()->getValue('
|
|
SELECT crc.id_cart_rule
|
|
FROM '._DB_PREFIX_.'cart_rule_country crc
|
|
WHERE crc.id_cart_rule = '.(int)$this->id.'
|
|
AND crc.id_country = (SELECT a.id_country FROM '._DB_PREFIX_.'address a WHERE a.id_address = '.(int)$context->cart->id_address_delivery.' LIMIT 1)');
|
|
if (!$id_cart_rule)
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in your country of delivery');
|
|
}
|
|
|
|
// Check if the cart rules appliy to the shop browsed by the customer
|
|
if ($this->shop_restriction && $context->shop->id && Shop::isFeatureActive())
|
|
{
|
|
$id_cart_rule = (int)Db::getInstance()->getValue('
|
|
SELECT crs.id_cart_rule
|
|
FROM '._DB_PREFIX_.'cart_rule_shop crs
|
|
WHERE crs.id_cart_rule = '.(int)$this->id.'
|
|
AND crs.id_shop = '.(int)$context->shop->id);
|
|
if (!$id_cart_rule)
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
|
|
}
|
|
|
|
// Check if the products chosen by the customer are usable with the cart rule
|
|
if ($this->product_restriction)
|
|
{
|
|
$r = $this->checkProductRestrictions($context, false, $display_error, $alreadyInCart);
|
|
if ($r !== false && $display_error)
|
|
return $r;
|
|
elseif (!$r && !$display_error)
|
|
return false;
|
|
}
|
|
|
|
// Check if the cart rule is only usable by a specific customer, and if the current customer is the right one
|
|
if ($this->id_customer && $context->cart->id_customer != $this->id_customer)
|
|
{
|
|
if (!Context::getContext()->customer->isLogged())
|
|
return (!$display_error) ? false : (Tools::displayError('You cannot use this voucher').' - '.Tools::displayError('Please log in'));
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher');
|
|
}
|
|
|
|
|
|
/* This loop checks:
|
|
- if the voucher is already in the cart
|
|
- if a non compatible voucher is in the cart
|
|
- if there are products in the cart (gifts excluded)
|
|
Important note: this MUST be the last check, because if the tested cart rule has priority over a non combinable one in the cart, we will switch them
|
|
*/
|
|
$nb_products = Cart::getNbProducts($context->cart->id);
|
|
$otherCartRules = $context->cart->getCartRules();
|
|
if (count($otherCartRules)) {
|
|
|
|
// check cart_rules restriction
|
|
if (!$this->cart_rule_restriction){
|
|
return (!$display_error) ? false : Tools::displayError('Ce bon de réduction n\'est pas compatible avec d\'autres bons de réduction.');
|
|
}
|
|
|
|
foreach ($otherCartRules as $otherCartRule)
|
|
{
|
|
if ($otherCartRule['id_cart_rule'] == $this->id && !$alreadyInCart)
|
|
return (!$display_error) ? false : Tools::displayError('This voucher is already in your cart');
|
|
if ($otherCartRule['gift_product'])
|
|
--$nb_products;
|
|
|
|
// ANTADIS FIX : if any restriction from one cart rule or the other, check it !!!
|
|
//if ($this->cart_rule_restriction && $otherCartRule['cart_rule_restriction'] && $otherCartRule['id_cart_rule'] != $this->id)
|
|
if (($this->cart_rule_restriction || $otherCartRule['cart_rule_restriction']) && $otherCartRule['id_cart_rule'] != $this->id)
|
|
{
|
|
$combinable = Db::getInstance()->getValue('
|
|
SELECT id_cart_rule_1
|
|
FROM '._DB_PREFIX_.'cart_rule_combination
|
|
WHERE (id_cart_rule_1 = '.(int)$this->id.' AND id_cart_rule_2 = '.(int)$otherCartRule['id_cart_rule'].')
|
|
OR (id_cart_rule_2 = '.(int)$this->id.' AND id_cart_rule_1 = '.(int)$otherCartRule['id_cart_rule'].')');
|
|
if (!$combinable)
|
|
{
|
|
$cart_rule = new CartRule((int)$otherCartRule['id_cart_rule'], $context->cart->id_lang);
|
|
// The cart rules are not combinable and the cart rule currently in the cart has priority over the one tested
|
|
if ($cart_rule->priority <= $this->priority)
|
|
return (!$display_error) ? false : Tools::displayError('This voucher is not combinable with an other voucher already in your cart:').' '.$cart_rule->name;
|
|
// But if the cart rule that is tested has priority over the one in the cart, we remove the one in the cart and keep this new one
|
|
else
|
|
$context->cart->removeCartRule($cart_rule->id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$nb_products)
|
|
return (!$display_error) ? false : Tools::displayError('Cart is empty');
|
|
|
|
if ($this->getCategoryRestriction()){
|
|
$r = $this->checkCategoryRestriction($context, $display_error, $alreadyInCart);
|
|
if ($r !== false && $display_error)
|
|
return $r;
|
|
elseif (!$r && !$display_error)
|
|
return false;
|
|
}
|
|
|
|
return (!$display_error) ? true : false;
|
|
}
|
|
|
|
protected function checkCategoryRestriction(Context $context, $display_error = true, $alreadyInCart = false){
|
|
|
|
if (!isset($context->cart) || !is_object($context->cart) || !is_array($products = $context->cart->getProducts()))
|
|
return (!$display_error) ? false : Tools::displayError('Cart is empty');
|
|
|
|
foreach ($products as $product)
|
|
if (in_array($product['id_category_default'], $this->getCategoryRestriction()))
|
|
return (!$display_error) ? false : Tools::displayError('Ce bon de réduction n\'est pas valable pour l\'un des produits du panier');
|
|
return (!$display_error) ? true : false;
|
|
}
|
|
|
|
|
|
public function getAssociatedRestrictions($type, $active_only, $i18n)
|
|
{
|
|
if (!in_array($type, array('category')))
|
|
return parent::getAssociatedRestrictions($type, $active_only, $i18n);
|
|
|
|
$array = array('selected' => array(), 'unselected' => array());
|
|
|
|
$shop_list = '';
|
|
if (!Validate::isLoadedObject($this))
|
|
{
|
|
$array['unselected'] = Db::getInstance()->executeS('
|
|
SELECT t.*'.($i18n ? ', tl.*' : '').', 1 as selected
|
|
FROM `'._DB_PREFIX_.$type.'` t
|
|
'.($i18n ? 'LEFT JOIN `'._DB_PREFIX_.$type.'_lang` tl ON (t.id_'.$type.' = tl.id_'.$type.' AND tl.id_lang = '.(int)Context::getContext()->language->id.')' : '').'
|
|
WHERE 1
|
|
'.($active_only ? 'AND t.active = 1' : '').
|
|
$shop_list.
|
|
' ORDER BY name ASC');
|
|
}
|
|
else
|
|
{
|
|
$resource = Db::getInstance()->query('
|
|
SELECT t.*'.($i18n ? ', tl.*' : '').', IF(crt.id_'.$type.' IS NULL, 0, 1) as selected
|
|
FROM `'._DB_PREFIX_.$type.'` t
|
|
'.($i18n ? 'LEFT JOIN `'._DB_PREFIX_.$type.'_lang` tl ON (t.id_'.$type.' = tl.id_'.$type.' AND tl.id_lang = '.(int)Context::getContext()->language->id.')' : '').'
|
|
LEFT JOIN (SELECT id_'.$type.' FROM `'._DB_PREFIX_.'cart_rule_'.$type.'` WHERE id_cart_rule = '.(int)$this->id.') crt ON t.id_'.($type == 'carrier' ? 'reference' : $type).' = crt.id_'.$type.'
|
|
WHERE 1 '.($active_only ? ' AND t.active = 1' : '').
|
|
$shop_list.
|
|
' ORDER BY name ASC',
|
|
false);
|
|
while ($row = Db::getInstance()->nextRow($resource))
|
|
$array[($row['selected']) ? 'selected' : 'unselected'][] = $row;
|
|
}
|
|
return $array;
|
|
}
|
|
|
|
public function getCategoryRestriction(){
|
|
$category_restriction = array();
|
|
$restrictions = Db::getInstance()->executeS('SELECT `id_category` FROM `'._DB_PREFIX_.'cart_rule_category` WHERE `id_cart_rule` = '.(int)$this->id);
|
|
if (!$restrictions)
|
|
return false;
|
|
foreach ($restrictions as $row)
|
|
$category_restriction[] = (int)$row['id_category'];
|
|
return $category_restriction;
|
|
}
|
|
|
|
protected function checkProductRestrictions(Context $context, $return_products = false, $display_error = true, $alreadyInCart = false)
|
|
{
|
|
$selectedProducts = array();
|
|
|
|
// Check if the products chosen by the customer are usable with the cart rule
|
|
if ($this->product_restriction)
|
|
{
|
|
$productRuleGroups = $this->getProductRuleGroups();
|
|
foreach ($productRuleGroups as $id_product_rule_group => $productRuleGroup)
|
|
{
|
|
$eligibleProductsList = array();
|
|
if (isset($context->cart) && is_object($context->cart) && is_array($products = $context->cart->getProducts()))
|
|
foreach ($products as $product)
|
|
$eligibleProductsList[] = (int)$product['id_product'].'-'.(int)$product['id_product_attribute'];
|
|
if (!count($eligibleProductsList))
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in an empty cart');
|
|
|
|
$productRules = $this->getProductRules($id_product_rule_group);
|
|
foreach ($productRules as $productRule)
|
|
{
|
|
switch ($productRule['type'])
|
|
{
|
|
case 'attributes':
|
|
$cartAttributes = Db::getInstance()->executeS('
|
|
SELECT cp.quantity, cp.`id_product`, pac.`id_attribute`, cp.`id_product_attribute`
|
|
FROM `'._DB_PREFIX_.'cart_product` cp
|
|
LEFT JOIN `'._DB_PREFIX_.'product_attribute_combination` pac ON cp.id_product_attribute = pac.id_product_attribute
|
|
WHERE cp.`id_cart` = '.(int)$context->cart->id.'
|
|
AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligibleProductsList)).')
|
|
AND cp.id_product_attribute > 0');
|
|
$countMatchingProducts = 0;
|
|
$matchingProductsList = array();
|
|
foreach ($cartAttributes as $cartAttribute)
|
|
if (in_array($cartAttribute['id_attribute'], $productRule['values']))
|
|
{
|
|
$countMatchingProducts += $cartAttribute['quantity'];
|
|
if ($alreadyInCart && $this->gift_product == $cartAttribute['id_product'] && $this->gift_product_attribute == $cartAttribute['id_product_attribute'])
|
|
--$countMatchingProducts;
|
|
$matchingProductsList[] = $cartAttribute['id_product'].'-'.$cartAttribute['id_product_attribute'];
|
|
}
|
|
if ($countMatchingProducts < $productRuleGroup['quantity'])
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
$eligibleProductsList = CartRule::array_uintersect($eligibleProductsList, $matchingProductsList);
|
|
break;
|
|
case 'products':
|
|
$cartProducts = Db::getInstance()->executeS('
|
|
SELECT cp.quantity, cp.`id_product`
|
|
FROM `'._DB_PREFIX_.'cart_product` cp
|
|
WHERE cp.`id_cart` = '.(int)$context->cart->id.'
|
|
AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligibleProductsList)).')');
|
|
$countMatchingProducts = 0;
|
|
$matchingProductsList = array();
|
|
foreach ($cartProducts as $cartProduct)
|
|
if (in_array($cartProduct['id_product'], $productRule['values']))
|
|
{
|
|
$countMatchingProducts += $cartProduct['quantity'];
|
|
if ($alreadyInCart && $this->gift_product == $cartProduct['id_product'])
|
|
--$countMatchingProducts;
|
|
$matchingProductsList[] = $cartProduct['id_product'].'-0';
|
|
}
|
|
if ($countMatchingProducts < $productRuleGroup['quantity'])
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
$eligibleProductsList = CartRule::array_uintersect($eligibleProductsList, $matchingProductsList);
|
|
break;
|
|
case 'categories':
|
|
/** @Override */
|
|
$rootCategory = Category::getRootCategory();
|
|
if (in_array((int)$rootCategory->id, $productRule['values'])) {
|
|
$result = Db::getInstance()->ExecuteS('SELECT id_category FROM '._DB_PREFIX_.'category');
|
|
$productRule['values'] = array();
|
|
foreach ($result as $row)
|
|
$productRule['values'][] = $row['id_category'];
|
|
}
|
|
/** end @Override */
|
|
$cartCategories = Db::getInstance()->executeS('
|
|
SELECT cp.quantity, cp.`id_product`, cp.`id_product_attribute`, catp.`id_category`
|
|
FROM `'._DB_PREFIX_.'cart_product` cp
|
|
LEFT JOIN `'._DB_PREFIX_.'category_product` catp ON cp.id_product = catp.id_product
|
|
WHERE cp.`id_cart` = '.(int)$context->cart->id.'
|
|
AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligibleProductsList)).')
|
|
AND cp.`id_product` <> '.(int)$this->gift_product);
|
|
$countMatchingProducts = 0;
|
|
$matchingProductsList = array();
|
|
foreach ($cartCategories as $cartCategory)
|
|
if (in_array($cartCategory['id_category'], $productRule['values'])
|
|
// We also check that the product is not already in the matching product list, because there are doubles in the query results (when the product is in multiple categories)
|
|
&& !in_array($cartCategory['id_product'].'-'.$cartCategory['id_product_attribute'], $matchingProductsList))
|
|
{
|
|
$countMatchingProducts += $cartCategory['quantity'];
|
|
$matchingProductsList[] = $cartCategory['id_product'].'-'.$cartCategory['id_product_attribute'];
|
|
}
|
|
if ($countMatchingProducts < $productRuleGroup['quantity'])
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
// Attribute id is not important for this filter in the global list, so the ids are replaced by 0
|
|
foreach ($matchingProductsList as &$matchingProduct)
|
|
$matchingProduct = preg_replace('/^([0-9]+)-[0-9]+$/', '$1-0', $matchingProduct);
|
|
$eligibleProductsList = CartRule::array_uintersect($eligibleProductsList, $matchingProductsList);
|
|
break;
|
|
case 'manufacturers':
|
|
$cartManufacturers = Db::getInstance()->executeS('
|
|
SELECT cp.quantity, cp.`id_product`, p.`id_manufacturer`
|
|
FROM `'._DB_PREFIX_.'cart_product` cp
|
|
LEFT JOIN `'._DB_PREFIX_.'product` p ON cp.id_product = p.id_product
|
|
WHERE cp.`id_cart` = '.(int)$context->cart->id.'
|
|
AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligibleProductsList)).')');
|
|
$countMatchingProducts = 0;
|
|
$matchingProductsList = array();
|
|
foreach ($cartManufacturers as $cartManufacturer)
|
|
if (in_array($cartManufacturer['id_manufacturer'], $productRule['values']))
|
|
{
|
|
$countMatchingProducts += $cartManufacturer['quantity'];
|
|
$matchingProductsList[] = $cartManufacturer['id_product'].'-0';
|
|
}
|
|
if ($countMatchingProducts < $productRuleGroup['quantity'])
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
$eligibleProductsList = CartRule::array_uintersect($eligibleProductsList, $matchingProductsList);
|
|
break;
|
|
case 'suppliers':
|
|
$cartSuppliers = Db::getInstance()->executeS('
|
|
SELECT cp.quantity, cp.`id_product`, p.`id_supplier`
|
|
FROM `'._DB_PREFIX_.'cart_product` cp
|
|
LEFT JOIN `'._DB_PREFIX_.'product` p ON cp.id_product = p.id_product
|
|
WHERE cp.`id_cart` = '.(int)$context->cart->id.'
|
|
AND cp.`id_product` IN ('.implode(',', array_map('intval', $eligibleProductsList)).')');
|
|
$countMatchingProducts = 0;
|
|
$matchingProductsList = array();
|
|
foreach ($cartSuppliers as $cartSupplier)
|
|
if (in_array($cartSupplier['id_supplier'], $productRule['values']))
|
|
{
|
|
$countMatchingProducts += $cartSupplier['quantity'];
|
|
$matchingProductsList[] = $cartSupplier['id_product'].'-0';
|
|
}
|
|
if ($countMatchingProducts < $productRuleGroup['quantity'])
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
$eligibleProductsList = CartRule::array_uintersect($eligibleProductsList, $matchingProductsList);
|
|
break;
|
|
}
|
|
|
|
if (!count($eligibleProductsList))
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
}
|
|
$selectedProducts = array_merge($selectedProducts, $eligibleProductsList);
|
|
}
|
|
}
|
|
|
|
if ($return_products)
|
|
return $selectedProducts;
|
|
return (!$display_error) ? true : false;
|
|
}
|
|
|
|
public function isEligibleProduct(Context $context, $display_error = true, $id_product){
|
|
|
|
if (!is_numeric($id_product)) {
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher in an unknown product');
|
|
}
|
|
$product = new Product((int)$id_product);
|
|
$sql = 'SELECT cp.`id_category` FROM `'._DB_PREFIX_.'category_product` cp WHERE cp.`id_product` = '.(int)$id_product;
|
|
$productCategories = Db::getInstance()->executeS($sql);
|
|
|
|
if ($this->product_restriction ){
|
|
$productRuleGroups = $this->getProductRuleGroups();
|
|
foreach ($productRuleGroups as $id_product_rule_group => $productRuleGroup)
|
|
{
|
|
$productRules = $this->getProductRules($id_product_rule_group);
|
|
foreach ($productRules as $productRule)
|
|
{
|
|
switch ($productRule['type'])
|
|
{
|
|
case 'products':
|
|
if (!in_array($product->id, $productRule['values'])) {
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with these products');
|
|
}
|
|
break;
|
|
case 'categories':
|
|
$rootCategory = Category::getRootCategory();
|
|
if (in_array((int)$rootCategory->id, $productRule['values'])) {
|
|
$result = Db::getInstance()->ExecuteS('SELECT id_category FROM '._DB_PREFIX_.'category');
|
|
$productRule['values'] = array();
|
|
foreach ($result as $row) {
|
|
$productRule['values'][] = $row['id_category'];
|
|
}
|
|
}
|
|
foreach ($productCategories as $productCategorie) {
|
|
if (!in_array($productCategorie['id_category'], $productRule['values'])) {
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this product');
|
|
}
|
|
}
|
|
break;
|
|
/*case 'attributes':
|
|
$productAttributes = array():
|
|
foreach ($productAttributes as $productAttribute) {
|
|
if (in_array($productAttribute['id_attribute'], $productRule['values'])) {
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this product attribute');
|
|
}
|
|
}
|
|
break;*/
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$cat_restriction = $this->getCategoryRestriction();
|
|
|
|
if (is_array($productCategories) && is_array($cat_restriction)) {
|
|
foreach ($productCategories as $productCategorie) {
|
|
if (in_array($productCategorie['id_category'], $cat_restriction)) {
|
|
return (!$display_error) ? false : Tools::displayError('You cannot use this voucher with this product');
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
protected function getCartRuleCombinations()
|
|
{
|
|
$date_max = new DateTime('last month');
|
|
|
|
$array = array();
|
|
$array['selected'] = Db::getInstance()->executeS('
|
|
SELECT cr.*, crl.*, 1 as selected
|
|
FROM '._DB_PREFIX_.'cart_rule cr
|
|
LEFT JOIN '._DB_PREFIX_.'cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = '.(int)Context::getContext()->language->id.')
|
|
WHERE cr.id_cart_rule != '.(int)$this->id.'
|
|
AND (
|
|
cr.cart_rule_restriction = 0
|
|
OR cr.id_cart_rule IN (
|
|
SELECT IF(id_cart_rule_1 = '.(int)$this->id.', id_cart_rule_2, id_cart_rule_1)
|
|
FROM '._DB_PREFIX_.'cart_rule_combination
|
|
WHERE '.(int)$this->id.' = id_cart_rule_1
|
|
OR '.(int)$this->id.' = id_cart_rule_2
|
|
)
|
|
)
|
|
AND (
|
|
cr.id_cart_rule NOT IN (
|
|
SELECT cr.`id_cart_rule`
|
|
FROM `'._DB_PREFIX_.'cart_rule` cr
|
|
JOIN `'._DB_PREFIX_.'cart_rule_lang` crl ON crl.`id_cart_rule` = cr.`id_cart_rule`
|
|
WHERE
|
|
(crl.`name` LIKE \'%panier abandon%\' OR crl.`name` LIKE \'%parrainage%\')
|
|
AND cr.`date_to` < \''.$date_max->format('Y-m-d').'\'
|
|
ORDER BY cr.`date_to` DESC
|
|
)
|
|
)
|
|
');
|
|
|
|
$array['unselected'] = Db::getInstance()->executeS('
|
|
SELECT cr.*, crl.*, 1 as selected
|
|
FROM '._DB_PREFIX_.'cart_rule cr
|
|
INNER JOIN '._DB_PREFIX_.'cart_rule_lang crl ON (cr.id_cart_rule = crl.id_cart_rule AND crl.id_lang = '.(int)Context::getContext()->language->id.')
|
|
LEFT JOIN '._DB_PREFIX_.'cart_rule_combination crc1 ON (cr.id_cart_rule = crc1.id_cart_rule_1 AND crc1.id_cart_rule_2 = '.(int)$this->id.')
|
|
LEFT JOIN '._DB_PREFIX_.'cart_rule_combination crc2 ON (cr.id_cart_rule = crc2.id_cart_rule_2 AND crc2.id_cart_rule_1 = '.(int)$this->id.')
|
|
WHERE cr.cart_rule_restriction = 1
|
|
AND cr.id_cart_rule != '.(int)$this->id.'
|
|
AND crc1.id_cart_rule_1 IS NULL
|
|
AND crc2.id_cart_rule_1 IS NULL');
|
|
return $array;
|
|
}
|
|
|
|
|
|
public function addFollowupRestrictions()
|
|
{
|
|
if (in_array($this->code, array('WELCOME', 'WELCOMEPDM'))) {
|
|
|
|
$sql = 'DELETE FROM `'._DB_PREFIX_.'cart_rule_combination` WHERE
|
|
`id_cart_rule_1` = '.(int)$this->id.'
|
|
AND `id_cart_rule_2` IN (
|
|
SELECT `id_cart_rule`
|
|
FROM `'._DB_PREFIX_.'cart_rule`
|
|
WHERE `code` LIKE \'PRIVILEGE%\' OR `code` LIKE \'FLW-%\'
|
|
)';
|
|
Db::getInstance()->execute($sql);
|
|
|
|
$sql = 'DELETE FROM `'._DB_PREFIX_.'cart_rule_combination` WHERE
|
|
`id_cart_rule_2` = '.(int)$this->id.'
|
|
AND `id_cart_rule_1` IN (
|
|
SELECT `id_cart_rule`
|
|
FROM `'._DB_PREFIX_.'cart_rule`
|
|
WHERE `code` LIKE \'PRIVILEGE%\' OR `code` LIKE \'FLW-%\'
|
|
)';
|
|
Db::getInstance()->execute($sql);
|
|
}
|
|
else if (preg_match('/^PRIVILEGE/i', $this->code)===1
|
|
|| preg_match('/^FLW\-/i', $this->code)===1) {
|
|
|
|
$sql = 'DELETE FROM `'._DB_PREFIX_.'cart_rule_combination` WHERE
|
|
`id_cart_rule_1` = '.(int)$this->id.'
|
|
AND `id_cart_rule_2` IN (
|
|
SELECT `id_cart_rule`
|
|
FROM `'._DB_PREFIX_.'cart_rule`
|
|
WHERE `code` LIKE \'WELCOME\' OR `code` LIKE \'WELCOMEPDM\'
|
|
)';
|
|
Db::getInstance()->execute($sql);
|
|
|
|
$sql = 'DELETE FROM `'._DB_PREFIX_.'cart_rule_combination` WHERE
|
|
`id_cart_rule_2` = '.(int)$this->id.'
|
|
AND `id_cart_rule_1` IN (
|
|
SELECT `id_cart_rule`
|
|
FROM `'._DB_PREFIX_.'cart_rule`
|
|
WHERE `code` LIKE \'WELCOME%\' OR `code` LIKE \'WELCOMEPDM\'
|
|
)';
|
|
Db::getInstance()->execute($sql);
|
|
}
|
|
}
|
|
|
|
public function isAnyCartProductInRestrictionlist(Context $context)
|
|
{
|
|
if (!$this->product_restriction) {
|
|
return true;
|
|
}
|
|
|
|
return parent::checkProductRestrictions($context, false, false, false);
|
|
}
|
|
|
|
|
|
//
|
|
// @Override [ticket 12906]
|
|
// same as getCustomerCartRules but ordered by priority (if same priority, ordered by id)
|
|
//
|
|
public static function getCustomerCartRulesByPriority($id_lang, $id_customer, $active = false, $includeGeneric = true, $inStock = false, Cart $cart = null, $exclude_with_voucher=false)
|
|
{
|
|
if (!CartRule::isFeatureActive())
|
|
return array();
|
|
|
|
// override antadis : add sorted by priority
|
|
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS('
|
|
SELECT *
|
|
FROM `'._DB_PREFIX_.'cart_rule` cr
|
|
LEFT JOIN `'._DB_PREFIX_.'cart_rule_lang` crl ON (cr.`id_cart_rule` = crl.`id_cart_rule` AND crl.`id_lang` = '.(int)$id_lang.')
|
|
WHERE (
|
|
cr.`id_customer` = '.(int)$id_customer.' OR cr.group_restriction = 1
|
|
'.($includeGeneric ? 'OR cr.`id_customer` = 0' : '').'
|
|
)
|
|
AND cr.date_from < "'.date('Y-m-d H:i:s').'"
|
|
AND cr.date_to > "'.date('Y-m-d H:i:s').'"
|
|
'.($active ? 'AND cr.`active` = 1' : '').'
|
|
'.($inStock ? 'AND cr.`quantity` > 0' : '').'
|
|
'.($exclude_with_voucher ? ' AND TRIM(cr.`code`) = \'\'' : '')."
|
|
ORDER BY cr.`priority`, cr.`id_cart_rule`"
|
|
);
|
|
|
|
// Remove cart rule that does not match the customer groups
|
|
$customerGroups = Customer::getGroupsStatic($id_customer);
|
|
|
|
foreach ($result as $key => $cart_rule)
|
|
if ($cart_rule['group_restriction'])
|
|
{
|
|
$cartRuleGroups = Db::getInstance()->executeS('SELECT id_group FROM '._DB_PREFIX_.'cart_rule_group WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']);
|
|
foreach ($cartRuleGroups as $cartRuleGroup)
|
|
if (in_array($cartRuleGroup['id_group'], $customerGroups))
|
|
continue 2;
|
|
unset($result[$key]);
|
|
}
|
|
|
|
foreach ($result as &$cart_rule)
|
|
if ($cart_rule['quantity_per_user'])
|
|
{
|
|
$quantity_used = Order::getDiscountsCustomer((int)$id_customer, (int)$cart_rule['id_cart_rule']);
|
|
if (isset($cart) && isset($cart->id))
|
|
$quantity_used += $cart->getDiscountsCustomer((int)$cart_rule['id_cart_rule']);
|
|
$cart_rule['quantity_for_user'] = $cart_rule['quantity_per_user'] - $quantity_used;
|
|
}
|
|
else
|
|
$cart_rule['quantity_for_user'] = 0;
|
|
unset($cart_rule);
|
|
|
|
foreach ($result as $key => $cart_rule)
|
|
if ($cart_rule['shop_restriction'])
|
|
{
|
|
$cartRuleShops = Db::getInstance()->executeS('SELECT id_shop FROM '._DB_PREFIX_.'cart_rule_shop WHERE id_cart_rule = '.(int)$cart_rule['id_cart_rule']);
|
|
foreach ($cartRuleShops as $cartRuleShop)
|
|
if (Shop::isFeatureActive() && ($cartRuleShop['id_shop'] == Context::getContext()->shop->id))
|
|
continue 2;
|
|
unset($result[$key]);
|
|
}
|
|
|
|
if (isset($cart) && isset($cart->id))
|
|
foreach ($result as $key => $cart_rule)
|
|
if ($cart_rule['product_restriction'])
|
|
{
|
|
$cr = new CartRule((int)$cart_rule['id_cart_rule']);
|
|
$r = $cr->checkProductRestrictions(Context::getContext(), false, false);
|
|
if ($r !== false)
|
|
continue;
|
|
unset($result[$key]);
|
|
}
|
|
|
|
foreach ($result as $key => $cart_rule)
|
|
if ($cart_rule['country_restriction'])
|
|
{
|
|
$countries = Db::getInstance()->ExecuteS('
|
|
SELECT `id_country`
|
|
FROM `'._DB_PREFIX_.'address`
|
|
WHERE `id_customer` = '.(int)$id_customer.'
|
|
AND `deleted` = 0'
|
|
);
|
|
|
|
if (is_array($countries) && count($countries))
|
|
foreach($countries as $country)
|
|
{
|
|
$id_cart_rule = (bool)Db::getInstance()->getValue('
|
|
SELECT crc.id_cart_rule
|
|
FROM '._DB_PREFIX_.'cart_rule_country crc
|
|
WHERE crc.id_cart_rule = '.(int)$cart_rule['id_cart_rule'].'
|
|
AND crc.id_country = '.(int)$country['id_country']);
|
|
if (!$id_cart_rule)
|
|
unset($result[$key]);
|
|
}
|
|
}
|
|
|
|
// Retrocompatibility with 1.4 discounts
|
|
foreach ($result as &$cart_rule)
|
|
{
|
|
$cart_rule['value'] = 0;
|
|
$cart_rule['minimal'] = Tools::convertPriceFull($cart_rule['minimum_amount'], new Currency($cart_rule['minimum_amount_currency']), Context::getContext()->currency);
|
|
$cart_rule['cumulable'] = !$cart_rule['cart_rule_restriction'];
|
|
$cart_rule['id_discount_type'] = false;
|
|
if ($cart_rule['free_shipping'])
|
|
$cart_rule['id_discount_type'] = Discount::FREE_SHIPPING;
|
|
elseif ($cart_rule['reduction_percent'] > 0)
|
|
{
|
|
$cart_rule['id_discount_type'] = Discount::PERCENT;
|
|
$cart_rule['value'] = $cart_rule['reduction_percent'];
|
|
}
|
|
elseif ($cart_rule['reduction_amount'] > 0)
|
|
{
|
|
$cart_rule['id_discount_type'] = Discount::AMOUNT;
|
|
$cart_rule['value'] = $cart_rule['reduction_amount'];
|
|
}
|
|
}
|
|
unset($cart_rule);
|
|
|
|
return $result;
|
|
}
|
|
|
|
|
|
// @Override [ticket 7902]
|
|
// @Override [ticket 12906]
|
|
//
|
|
// Previous override : understand business rule :
|
|
// If the cart contains any product not eligible for free shipping (in case there is any rule with free shipping)
|
|
// then the cart is not eligible.
|
|
//
|
|
// ticket 12906 - Addition to this business rule :
|
|
// The carts rules are ordered by priority
|
|
// the highest priority cart rules (minimal number) overrides other cart rules with products restricted (in case
|
|
// there no product in the restriction list)
|
|
//
|
|
static function getEligibilityAndMinimumAmount(Context $context)
|
|
{
|
|
$all_cart_rules = CartRule::getCustomerCartRulesByPriority($context->language->id, $context->customer->id, true, true, true, null, true);
|
|
$notEligible = false;
|
|
$previous_priority = 1;
|
|
|
|
$cartRulesAlreadyInCart = $context->cart->getCartRules(CartRule::FILTER_ACTION_SHIPPING);
|
|
|
|
if($all_cart_rules) {
|
|
$is_cart_valid = false;
|
|
foreach ($all_cart_rules as $key => $cart_rule) {
|
|
if($cart_rule['id_discount_type'] == Discount::FREE_SHIPPING){
|
|
$cr = new CartRule((int)$cart_rule['id_cart_rule']);
|
|
|
|
// if this cart rule restrict to only N products and no cart product is in this restriction list,
|
|
// check if there was a previous eligible free shipping cart rule.
|
|
// if it is the case : skip this one.
|
|
// if not, it is not eligible
|
|
if (!$cr->isAnyCartProductInRestrictionlist($context)) {
|
|
if ($is_cart_valid && $cr->priority > $previous_priority ) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
$previous_priority = $cr->priority;
|
|
|
|
$is_cart_valid = $cr->checkValidityWithoutAmount($context,false,false);
|
|
if($is_cart_valid && $cart_rule['minimal']>0){
|
|
if(!isset($minimum_amount)) {
|
|
$minimum_amount = $cart_rule['minimal'];
|
|
}
|
|
if($minimum_amount < $cart_rule['minimal']) {
|
|
continue;
|
|
}
|
|
$minimum_amount = ($minimum_amount < $cart_rule['minimal'])?$minimum_amount:$cart_rule['minimal'];
|
|
$minimum_amount_tax = (int)$cart_rule['minimum_amount_tax'] ;
|
|
} elseif (!$is_cart_valid && empty($cartRulesAlreadyInCart)) {
|
|
$notEligible = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return array(
|
|
'cartRulesAlreadyInCart' => $cartRulesAlreadyInCart,
|
|
'notEligible' => $notEligible,
|
|
'minimum_amount' => isset($minimum_amount) ? $minimum_amount : 0,
|
|
'minimum_amount_tax' => isset($minimum_amount_tax) ? $minimum_amount_tax : 0
|
|
);
|
|
}
|
|
|
|
}
|