diff --git a/admin-dev/themes/default/template/controllers/cart_rules/actions.tpl b/admin-dev/themes/default/template/controllers/cart_rules/actions.tpl index 2621310ec..bc0264172 100644 --- a/admin-dev/themes/default/template/controllers/cart_rules/actions.tpl +++ b/admin-dev/themes/default/template/controllers/cart_rules/actions.tpl @@ -28,7 +28,7 @@
- +
getFieldValue($currentObject, 'gift_product')|intval}checked="checked"{/if} />    - getFieldValue($currentObject, 'gift_product')|intval}checked="checked"{/if} /> + getFieldValue($currentObject, 'gift_product')|intval}checked="checked"{/if} />
- +
- - +
-
\ No newline at end of file +
+
+ + +
+
 
+
+ +
+ {$gift_product_attribute_select} +
+
+
 
+
+ +
diff --git a/admin-dev/themes/default/template/controllers/cart_rules/form.js b/admin-dev/themes/default/template/controllers/cart_rules/form.js index 8ab9d0170..15db30784 100644 --- a/admin-dev/themes/default/template/controllers/cart_rules/form.js +++ b/admin-dev/themes/default/template/controllers/cart_rules/form.js @@ -228,36 +228,6 @@ $('#cart_rule_form').submit(function() { $(this).attr('selected', 'selected'); }); }); - -$('#giftProductFilter') - .autocomplete( - 'ajax-tab.php', { - minChars: 2, - max: 50, - width: 500, - selectFirst: false, - scroll: false, - dataType: 'json', - formatItem: function(data, i, max, value, term) { - return value; - }, - parse: function(data) { - var mytab = new Array(); - for (var i = 0; i < data.length; i++) - mytab[mytab.length] = { data: data[i], value: (data[i].reference + ' ' + data[i].name).trim() }; - return mytab; - }, - extraParams: { - controller: 'AdminCartRules', - token: currentToken, - giftProductFilter: 1 - } - } - ) - .result(function(event, data, formatted) { - $('#gift_product').val(data.id_product); - $('#giftProductFilter').val((data.reference + ' ' + data.name).trim()); - }); $('#reductionProductFilter') .autocomplete( @@ -347,4 +317,75 @@ $('.datepicker').datepicker({ prevText: '', nextText: '', dateFormat: 'yy-mm-dd ' + hours + ':' + mins + ':' + secs -}); \ No newline at end of file +}); + +$('#giftProductFilter').typeWatch({ + captureLength: 2, + highlight: false, + wait: 100, + callback: function(){ searchProducts(); } +}); + +var gift_product_search = $('#giftProductFilter').val(); +function searchProducts() +{ + if ($('#giftProductFilter').val() == gift_product_search) + return; + gift_product_search = $('#giftProductFilter').val(); + + $.ajax({ + type: 'POST', + url: 'ajax-tab.php', + async: true, + dataType: 'json', + data: { + controller: 'AdminCartRules', + token: currentToken, + action: 'searchProducts', + product_search: $('#giftProductFilter').val() + }, + success : function(res) + { + var products_found = ''; + var attributes_html = ''; + stock = {}; + + if (res.found) + { + $('#gift_products_err').hide(); + $('#gift_products_found').show(); + $.each(res.products, function() { + products_found += ''; + + attributes_html += ''; + }); + + $('#gift_product_list #gift_product').html(products_found); + $('#gift_attributes_list #gift_attributes_list_select').html(attributes_html); + displayProductAttributes(); + } + else + { + $('#products_found').hide(); + $('#products_err').html(res.notfound); + $('#products_err').show(); + } + } + }); +} + +function displayProductAttributes() +{ + if ($('#ipa_' + $('#gift_product option:selected').val() + ' option').length === 0) + $('#gift_attributes_list').hide(); + else + { + $('#gift_attributes_list').show(); + $('.id_product_attribute').hide(); + $('#ipa_' + $('#gift_product option:selected').val()).show(); + } +} \ No newline at end of file diff --git a/classes/Cart.php b/classes/Cart.php index c43efbd2f..1957292fc 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -705,7 +705,7 @@ class CartCore extends ObjectModel Cache::clean('Cart::getCartRules'.$this->id); if ((int)$cartRule->gift_product) - return $this->updateQty(1, $cartRule->gift_product); + $this->updateQty(1, $cartRule->gift_product, $cartRule->gift_product_attribute); return true; } @@ -751,8 +751,8 @@ class CartCore extends ObjectModel { if ($id_address_delivery == 0) // The $id_address_delivery is null, get the default customer address $id_address_delivery = (int)Address::getFirstCustomerAddressId((int)Context::getContext()->customer->id); - else if (!Customer::customerHasAddress(Context::getContext()->customer->id, $id_address_delivery)) // The $id_address_delivery must be linked with customer - $id_address_delivery = 0; + elseif (!Customer::customerHasAddress(Context::getContext()->customer->id, $id_address_delivery)) // The $id_address_delivery must be linked with customer + $id_address_delivery = 0; } $quantity = (int)$quantity; @@ -1019,11 +1019,18 @@ class CartCore extends ObjectModel public function removeCartRule($id_cart_rule) { Cache::clean('Cart::getCartRules'.$this->id); - return Db::getInstance()->Execute( - 'DELETE FROM `'._DB_PREFIX_.'cart_cart_rule` - WHERE `id_cart_rule` = '.(int)$id_cart_rule.' - AND `id_cart` = '.(int)$this->id.' LIMIT 1' - ); + + $result = Db::getInstance()->Execute(' + DELETE FROM `'._DB_PREFIX_.'cart_cart_rule` + WHERE `id_cart_rule` = '.(int)$id_cart_rule.' + AND `id_cart` = '.(int)$this->id.' + LIMIT 1'); + + $cart_rule = new CartRule($id_cart_rule, Configuration::get('PS_LANG_DEFAULT')); + if ((int)$cart_rule->gift_product) + $this->updateQty(1, $cart_rule->gift_product, $cart_rule->gift_product_attribute, null, null, 'down'); + + return $result; } /** @@ -1051,14 +1058,13 @@ class CartCore extends ObjectModel AND `id_product_attribute` = '.(int)$id_product_attribute ); - $customization_quantity = (int)Db::getInstance()->getValue( - 'SELECT `quantity` - FROM `'._DB_PREFIX_.'customization` - WHERE `id_cart` = '.(int)$this->id.' - AND `id_product` = '.(int)$id_product.' - AND `id_product_attribute` = '.(int)$id_product_attribute.' - AND `id_address_delivery` = '.(int)$id_address_delivery - ); + $customization_quantity = (int)Db::getInstance()->getValue(' + SELECT `quantity` + FROM `'._DB_PREFIX_.'customization` + WHERE `id_cart` = '.(int)$this->id.' + AND `id_product` = '.(int)$id_product.' + AND `id_product_attribute` = '.(int)$id_product_attribute.' + '.((int)$id_address_delivery ? 'AND `id_address_delivery` = '.(int)$id_address_delivery : '')); if (!$this->_deleteCustomization((int)$id_customization, (int)$id_product, (int)$id_product_attribute)) return false; @@ -1091,13 +1097,12 @@ class CartCore extends ObjectModel ); /* Product deletion */ - $result = Db::getInstance()->execute( - 'DELETE FROM `'._DB_PREFIX_.'cart_product` - WHERE `id_product` = '.(int)$id_product. - (!is_null($id_product_attribute) ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' - AND `id_cart` = '.(int)$this->id.' - AND `id_address_delivery` = '.(int)$id_address_delivery - ); + $result = Db::getInstance()->execute(' + DELETE FROM `'._DB_PREFIX_.'cart_product` + WHERE `id_product` = '.(int)$id_product.' + '.(!is_null($id_product_attribute) ? ' AND `id_product_attribute` = '.(int)$id_product_attribute : '').' + AND `id_cart` = '.(int)$this->id.' + '.((int)$id_address_delivery ? 'AND `id_address_delivery` = '.(int)$id_address_delivery : '')); if ($result) { diff --git a/classes/CartRule.php b/classes/CartRule.php index 6118deda4..4fcf5ff9e 100644 --- a/classes/CartRule.php +++ b/classes/CartRule.php @@ -55,6 +55,7 @@ class CartRuleCore extends ObjectModel public $reduction_currency; public $reduction_product; public $gift_product; + public $gift_product_attribute; public $active = 1; public $date_add; public $date_upd; @@ -93,6 +94,7 @@ class CartRuleCore extends ObjectModel 'reduction_currency' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'reduction_product' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), 'gift_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'gift_product_attribute' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'), 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), @@ -463,24 +465,31 @@ class CartRuleCore extends ObjectModel // If a product is given for free in this rule and already in the cart, the price is subtracted if ($this->gift_product) { - $in_cart = (bool)Db::getInstance()->getValue('SELECT id_product FROM '._DB_PREFIX_.'cart_product WHERE id_product = '.(int)$this->gift_product.' AND id_cart = '.(int)$context->cart->id); + $in_cart = (bool)Db::getInstance()->getValue(' + SELECT id_product + FROM '._DB_PREFIX_.'cart_product + WHERE id_product = '.(int)$this->gift_product.' + AND id_product_attribute = '.(int)$this->gift_product_attribute.' + AND id_cart = '.(int)$context->cart->id); if ($in_cart) { $ref = false; $product_price = Product::getPriceStatic( $this->gift_product, $this->minimum_amount_tax, - null, null, null, null, null, null, null, + $this->gift_product_attribute, + null, null, null, null, null, null, $context->cart->id_customer ? $context->cart->id_customer : null, $context->cart->id, (int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} ? (int)$context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')} : null, $ref, null, null, $context, null ); + $cartTotal -= $product_price; } } - + if ($cartTotal < $minimum_amount) return Tools::displayError('You do not reach the minimum amount required to use this voucher'); } @@ -762,10 +771,10 @@ class CartRuleCore extends ObjectModel } // Free gift - if ($this->gift_product) + if ((int)$this->gift_product) { foreach ($context->cart->getProducts() as $product) - if ($product['id_product'] == $this->gift_product) + if ($product['id_product'] == $this->gift_product && $product['id_product_attribute'] == $this->gift_product_attribute) $reduction_value += ($useTax ? $product['price_wt'] : $product['price']); } diff --git a/controllers/admin/AdminCartRulesController.php b/controllers/admin/AdminCartRulesController.php index 58ccb1d08..17108e45e 100644 --- a/controllers/admin/AdminCartRulesController.php +++ b/controllers/admin/AdminCartRulesController.php @@ -57,6 +57,10 @@ class AdminCartRulesControllerCore extends AdminController foreach (array('country', 'carrier', 'group', 'cart_rule', 'product', 'shop') as $type) if (!Tools::getValue($type.'_restriction')) $_POST[$type.'_restriction'] = 0; + + // Retrieve the product attribute id of the gift (if available) + if ($id_product = (int)Tools::getValue('gift_product')) + $_POST['gift_product_attribute'] = (int)Tools::getValue('ipa_'.$id_product); // Idiot-proof control if (strtotime(Tools::getValue('date_from')) > strtotime(Tools::getValue('date_to'))) @@ -330,6 +334,51 @@ class AdminCartRulesControllerCore extends AdminController die(Tools::jsonEncode($products)); } } + + protected function searchProducts($search) + { + if ($products = Product::searchByName((int)$this->context->language->id, $search)) + { + foreach ($products as &$product) + { + // Formatted price + $combinations = array(); + $productObj = new Product((int)$product['id_product'], false, (int)$this->context->language->id); + $attributes = $productObj->getAttributesGroups((int)$this->context->language->id); + $product['formatted_price'] = Tools::displayPrice(Tools::convertPrice($product['price_tax_incl'], $this->context->currency), $this->context->currency); + + foreach ($attributes as $attribute) + { + if (!isset($combinations[$attribute['id_product_attribute']]['attributes'])) + $combinations[$attribute['id_product_attribute']]['attributes'] = ''; + $combinations[$attribute['id_product_attribute']]['attributes'] .= $attribute['attribute_name'].' - '; + $combinations[$attribute['id_product_attribute']]['id_product_attribute'] = $attribute['id_product_attribute']; + $combinations[$attribute['id_product_attribute']]['default_on'] = $attribute['default_on']; + if (!isset($combinations[$attribute['id_product_attribute']]['price'])) + { + $price_tax_incl = Product::getPriceStatic((int)$product['id_product'], true, $attribute['id_product_attribute']); + $combinations[$attribute['id_product_attribute']]['formatted_price'] = Tools::displayPrice(Tools::convertPrice($price_tax_incl, $this->context->currency), $this->context->currency); + } + } + + foreach ($combinations as &$combination) + $combination['attributes'] = rtrim($combination['attributes'], ' - '); + $product['combinations'] = $combinations; + } + return array( + 'products' => $products, + 'found' => true + ); + } + else + return array('found' => false, 'notfound' => Tools::displayError('No product found')); + } + + public function ajaxProcessSearchProducts() + { + $array = $this->searchProducts(Tools::getValue('product_search')); + $this->content = trim(Tools::jsonEncode($array)); + } public function renderForm() { @@ -343,6 +392,7 @@ class AdminCartRulesControllerCore extends AdminController ); // Todo: change for "Media" version + $this->addJs(_PS_JS_DIR_.'jquery/plugins/jquery.typewatch.js'); $this->addJs(_PS_JS_DIR_.'jquery/plugins/fancybox/jquery.fancybox.js'); $this->addJs(_PS_JS_DIR_.'jquery/plugins/autocomplete/jquery.autocomplete.js'); $this->addCss(_PS_JS_DIR_.'jquery/plugins/fancybox/jquery.fancybox.css'); @@ -359,19 +409,19 @@ class AdminCartRulesControllerCore extends AdminController $gift_product_filter = ''; if (Validate::isUnsignedId($current_object->gift_product) && - ($product = new Product($current_object->gift_product, false, Context::getContext()->language->id)) && + ($product = new Product($current_object->gift_product, false, $this->context->language->id)) && Validate::isLoadedObject($product)) $gift_product_filter = trim($product->reference.' '.$product->name); $reduction_product_filter = ''; if (Validate::isUnsignedId($current_object->reduction_product) && - ($product = new Product($current_object->reduction_product, false, Context::getContext()->language->id)) && + ($product = new Product($current_object->reduction_product, false, $this->context->language->id)) && Validate::isLoadedObject($product)) $reduction_product_filter = trim($product->reference.' '.$product->name); $product_rule_groups = $this->getProductRuleGroupsDisplay($current_object); - $attribute_groups = AttributeGroup::getAttributesGroups(Context::getContext()->language->id); + $attribute_groups = AttributeGroup::getAttributesGroups($this->context->language->id); $currencies = Currency::getCurrencies(); $languages = Language::getLanguages(); $countries = $current_object->getAssociatedRestrictions('country', true, true); @@ -384,8 +434,35 @@ class AdminCartRulesControllerCore extends AdminController foreach ($carrier as $field => &$value) if ($field == 'name' && $value == '0') $value = Configuration::get('PS_SHOP_NAME'); + + $gift_product_select = ''; + $gift_product_attribute_select = ''; + if ((int)$current_object->gift_product) + { + $search_products = $this->searchProducts($gift_product_filter); + foreach ($search_products['products'] as $product) + { + $gift_product_select .= ' + '; + + if (count($product['combinations'])) + { + $gift_product_attribute_select .= ''; + } + } + } - Context::getContext()->smarty->assign( + $this->context->smarty->assign( array( 'show_toolbar' => true, 'toolbar_btn' => $this->toolbar_btn, @@ -395,6 +472,8 @@ class AdminCartRulesControllerCore extends AdminController 'defaultDateTo' => date('Y-m-d H:00:00', strtotime('+1 month')), 'customerFilter' => $customer_filter, 'giftProductFilter' => $gift_product_filter, + 'gift_product_select' => $gift_product_select, + 'gift_product_attribute_select' => $gift_product_attribute_select, 'reductionProductFilter' => $reduction_product_filter, 'defaultCurrency' => Configuration::get('PS_CURRENCY_DEFAULT'), 'defaultLanguage' => Configuration::get('PS_LANG_DEFAULT'), @@ -424,7 +503,7 @@ class AdminCartRulesControllerCore extends AdminController public function displayAjaxSearchCartRuleVouchers() { $found = false; - if ($vouchers = CartRule::getCartsRuleByCode(Tools::getValue('q'), (int)Context::getContext()->cookie->id_lang)) + if ($vouchers = CartRule::getCartsRuleByCode(Tools::getValue('q'), (int)$this->context->language->id)) $found = true; echo Tools::jsonEncode(array('found' => $found, 'vouchers' => $vouchers)); } diff --git a/install-dev/data/db_structure.sql b/install-dev/data/db_structure.sql index ce4226bd1..b769977bd 100644 --- a/install-dev/data/db_structure.sql +++ b/install-dev/data/db_structure.sql @@ -224,6 +224,7 @@ CREATE TABLE `PREFIX_cart_rule` ( `reduction_currency` int(10) unsigned NOT NULL default 0, `reduction_product` int(10) NOT NULL default 0, `gift_product` int(10) unsigned NOT NULL default 0, + `gift_product_attribute` int(10) unsigned NOT NULL default 0, `active` tinyint(1) unsigned NOT NULL default 0, `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, diff --git a/install-dev/upgrade/sql/1.5.0.6.sql b/install-dev/upgrade/sql/1.5.0.6.sql index 2b7bbc3ff..8a019a79b 100644 --- a/install-dev/upgrade/sql/1.5.0.6.sql +++ b/install-dev/upgrade/sql/1.5.0.6.sql @@ -9,4 +9,6 @@ SET o.`current_state` = ( LIMIT 1 ); +ALTER TABLE `PREFIX_cart_rule` ADD `gift_product_attribute` int(10) unsigned NOT NULL default 0 AFTER `gift_product`; + UPDATE `PREFIX_product` set is_virtual = 1 WHERE id_product IN (SELECT id_product FROM `PREFIX_product_download` WHERE active = 1); diff --git a/translations/fr/admin.php b/translations/fr/admin.php index 17e9bb1be..8d293aafb 100644 --- a/translations/fr/admin.php +++ b/translations/fr/admin.php @@ -3032,7 +3032,9 @@ $_LANGADM['AdminCartRules00d23a76e43b46dae9ec7aa9dcbebb32'] = 'Activé'; $_LANGADM['AdminCartRulesb9f5c797ebbf55adccdd8539a65a0241'] = 'Désactivé'; $_LANGADM['AdminCartRulesfc6341fa76fe93b837d748563e0a60c1'] = 'Appliquer une réduction'; $_LANGADM['AdminCartRulesda73ea07f51049046d527dabd85170e1'] = 'En pourcent (%)'; +$_LANGADM['AdminCartRulesb2f40690858b404ed10e62bdf422c704'] = 'Montant'; $_LANGADM['AdminCartRules6adf97f83acf6453d4a6a4b1070f3754'] = 'Aucune'; +$_LANGADM['AdminCartRules689202409e48743b914713f96d93947c'] = 'Valeur'; $_LANGADM['AdminCartRulesde11e2e4296bb20487b6430508866e06'] = 'Ne s\'applique pas aux frais de ports'; $_LANGADM['AdminCartRulesbefcac0f9644a7abee43e69f49252ac4'] = 'HT'; $_LANGADM['AdminCartRulesf4a0d7cb0cd45214c8ca5912c970de13'] = 'TTC'; @@ -3043,6 +3045,9 @@ $_LANGADM['AdminCartRules8bab8ac32605948e59399033c7606222'] = 'Le produit le moi $_LANGADM['AdminCartRules8cfdac16c15c9b130f26ca1d275035a0'] = 'Le(s) produit(s) sélectionné(s)'; $_LANGADM['AdminCartRulesdeb10517653c255364175796ace3553f'] = 'Produit'; $_LANGADM['AdminCartRules2f73d13f0a878086ce1f9933aed3ac80'] = 'Offrir un cadeau'; +$_LANGADM['AdminCartRulesc5f17f7ca53d9225478fdbfd0a5583ac'] = 'Rechercher un produit'; +$_LANGADM['AdminCartRules635c8dcb5a9c7f405ebf10ee3351a158'] = 'Produits'; +$_LANGADM['AdminCartRules34b9126c1ba9f3b131875a8da7b426c4'] = 'Déclinaisons'; $_LANGADM['AdminCartRules8f36b08eb9ebba13ef930c9dd719ff7c'] = 'Limiter à un seul client'; $_LANGADM['AdminCartRules5e60b472b57279a00a961e1e93fa0802'] = 'Facultatif : la règle panier sera disponible pour tout le monde si vous laissez ce champ vide.'; $_LANGADM['AdminCartRulesb07cc2801693b2e722906a3db3d9c447'] = 'Validité'; diff --git a/translations/fr/errors.php b/translations/fr/errors.php index 3ddadd1f6..ce161484e 100644 --- a/translations/fr/errors.php +++ b/translations/fr/errors.php @@ -267,6 +267,7 @@ $_ERRORS['eedef2c356c6598d1c1c35c30459ba3c'] = 'Le bon de réduction ne peut ter $_ERRORS['9eafdd415e82973f24b7af6580ff15de'] = 'Le montant minimum ne peut être inférieur à 0'; $_ERRORS['ed6f33d6a5ac4b1e0f37e9ccd6e6a96e'] = 'Le pourcentage de réduction doit être entre 0% et 100%'; $_ERRORS['8c9b12ce6c7cf8bc520d01e89b358c60'] = 'Le montant de la réduction ne peut être inférieur à 0'; +$_ERRORS['44fb451a35a1c382da79166dc8c78e43'] = 'Aucun produit trouvé'; $_ERRORS['c1a4c1b929c4f5c81f80ece2d7b196aa'] = 'Produit non valable'; $_ERRORS['e5b55dc69d10c8673f9d5db587591526'] = 'Combinaison invalide'; $_ERRORS['b59e4337db2c711a88aa5756f86c682e'] = 'Une commande a déjà été passée avec ce panier';