NIKESLB Posted January 5, 2018 Share Posted January 5, 2018 Hi, I'm using PS 1.6.1.17 and I got a problem with the combinations. I have two multistore. When I select "All stores" and I want to change one product combination, If i change the reference, the weight or the EAN-13, the product combination get a reset and the price become 0. Is it normal? Any solution please? Link to comment Share on other sites More sharing options...
martin.nv Posted January 11, 2018 Share Posted January 11, 2018 Hello, I tryed this at my 1.6.1.17 and there is also problem. I have 2 stores in 2 store categories. They have 1 stock but they are not sharing customers and orders. When I try to change ean13 or reference in "All stores" mode and Save, it delete this combination. Formore when I configure prices for combination, my "increased price" does not show on product page, olny in cart (but only in second shop, in main shop it is ok). I think the multistore does not work properly, but many merchants does not using it, so bugs are not squashed. Link to comment Share on other sites More sharing options...
NIKESLB Posted January 18, 2018 Author Share Posted January 18, 2018 Yes I found multiple bug with multi store, but this one is for me the biggest problem. One of my customers have multistore with almost 10k clients and this funcionality working would be really usefull. Link to comment Share on other sites More sharing options...
NIKESLB Posted January 19, 2018 Author Share Posted January 19, 2018 (edited) So I'm trying to solve this myself and did some progress but it's really hard to fix it. The problem is prestashop save every field from a combination. Instead update just the field where it was modified, it updates everything. In the file adminProductsController at the function "processProductAttribute" and the edit section we can find: $this->isProductFieldUpdated('attribute_weight_impact') ? Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact') : null, So if there is no update at this field then the value is null. All attributes are sent to the file Product.php at updateAttribute function. The first code is: $combination = new Combination($id_product_attribute); At this moment it fetchs every attributes from database where id is equal to id_product_attribute. At this point it's no sense to fetch this data if we going to update over it. Then we get this code: $combination->weight = (float)$weight; The $weight come from the "processProductAttribute" function and if the result is null then the property $combination->weight become null. So when saves to the database the weight will be 0 for this combination in every stores. I tried to unset the property, but null or unset will always save 0 to the database. EDIT: Better fix if (Shop::isFeatureActive() && Shop::getContext() != Shop::CONTEXT_SHOP) { if(get_class($this) == "Combination") { foreach ($this->update_fields as $key => $val) { if($val == null) { unset($fields[$key]); } } } else { foreach ($fields as $key => $val) { if (!array_key_exists($key, $this->update_fields)) { unset($fields[$key]); } } } } Edited January 26, 2018 by NIKESLB (see edit history) Link to comment Share on other sites More sharing options...
NIKESLB Posted January 22, 2018 Author Share Posted January 22, 2018 Well I think I found finally the fix. At ObjectModel.php function update I added those line (At "//START FIX"): foreach ($id_shop_list as $id_shop) { $fields['id_shop'] = (int)$id_shop; $all_fields['id_shop'] = (int)$id_shop; $where = $this->def['primary'].' = '.(int)$this->id.' AND id_shop = '.(int)$id_shop; // A little explanation of what we do here : we want to create multishop entry when update is called, but // only if we are in a shop context (if we are in all context, we just want to update entries that alread exists) $shop_exists = Db::getInstance()->getValue('SELECT '.$this->def['primary'].' FROM '._DB_PREFIX_.$this->def['table'].'_shop WHERE '.$where); if ($shop_exists) { //START FIX if(get_class($this) == "Combination") { foreach ($fields as $key => $val) { if($val == 0) unset($fields[$key]); } } //END FIX $result &= Db::getInstance()->update($this->def['table'].'_shop', $fields, $where, 0, $null_values); } elseif (Shop::getContext() == Shop::CONTEXT_SHOP) { $result &= Db::getInstance()->insert($this->def['table'].'_shop', $all_fields, $null_values); } } I unset all property where value is equal to 0, so it will ignore all fields where there is no modification. I spent some days on it, I'm pretty sure some people have the same as me, because it's happening to me in diferents stores. I really hope this fix will help someone. Link to comment Share on other sites More sharing options...
Bill Dalton Posted March 10, 2019 Share Posted March 10, 2019 Where is this file ObjectModel.php ? Did you fix this for PS 1.7 ? Link to comment Share on other sites More sharing options...
Bill Dalton Posted March 10, 2019 Share Posted March 10, 2019 Ok found the file, but it didn't work for my problem PS 1.7.5.1 Saving Bulk actions combination in multistore context. Only work around is to save in single site context, one for each shop. Thanks for the idea Link to comment Share on other sites More sharing options...
Bill Dalton Posted March 10, 2019 Share Posted March 10, 2019 Found a fix that works for me, Fix for me in PS 1.7.5.1 Table ps_attribute_group rename field "is_color_group" to anything you like > Save > Then rename the field back to "is_color_group" Not sure why this works, I assume it is related to a bad index. Link to comment Share on other sites More sharing options...
rayrodriguezg Posted June 4, 2019 Share Posted June 4, 2019 Hi, I have tried the exposed solutions but they do not work for me, According to my evaluation the problem is given because the allshops parameter is being sent in true without evaluating if we are in an allshops context, what I have done is to verify if we are in the context of allshops and pass that result as a variable to the method productAttributeExists since by default it is always being sent to true, with this it works correctly. the modifications are: Quote $allShops = true; if (Shop::isFeatureActive()) { if(Shop::getContext() != Shop::CONTEXT_ALL) { $allShops = false; } } and Quote if (($id_product_attribute = (int)Tools::getValue('id_product_attribute')) || ($id_product_attribute = $product->productAttributeExists(Tools::getValue('attribute_combination_list'), false, null, $allShops, true))) { and the complety file is: Place this file in /override/controllers/admin/AdminProductsController.php and then delete the file /cache/class_index.php as usual <?php /* * 2007-2017 PrestaShop * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 3.0) * that is bundled with this package in the file LICENSE.txt. * It is also available through the world-wide-web at this URL: * http://opensource.org/licenses/osl-3.0.php * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to [email protected] so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to http://www.prestashop.com for more information. * * @author PrestaShop SA <[email protected]> * @copyright 2007-2017 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ class AdminProductsController extends AdminProductsControllerCore { public function processProductAttribute() { // Don't process if the combination fields have not been submitted if (!Combination::isFeatureActive() || !Tools::getValue('attribute_combination_list')) { return; } if (Validate::isLoadedObject($product = $this->object)) { if ($this->isProductFieldUpdated('attribute_price') && (!Tools::getIsset('attribute_price') || Tools::getIsset('attribute_price') == null)) { $this->errors[] = Tools::displayError('The price attribute is required.'); } if (!Tools::getIsset('attribute_combination_list') || Tools::isEmpty(Tools::getValue('attribute_combination_list'))) { $this->errors[] = Tools::displayError('You must add at least one attribute.'); } $array_checks = array( 'reference' => 'isReference', 'supplier_reference' => 'isReference', 'location' => 'isReference', 'ean13' => 'isEan13', 'upc' => 'isUpc', 'wholesale_price' => 'isPrice', 'price' => 'isPrice', 'ecotax' => 'isPrice', 'quantity' => 'isInt', 'weight' => 'isUnsignedFloat', 'unit_price_impact' => 'isPrice', 'default_on' => 'isBool', 'minimal_quantity' => 'isUnsignedInt', 'available_date' => 'isDateFormat' ); foreach ($array_checks as $property => $check) { if (Tools::getValue('attribute_'.$property) !== false && !call_user_func(array('Validate', $check), Tools::getValue('attribute_'.$property))) { $this->errors[] = sprintf(Tools::displayError('Field %s is not valid'), $property); } } if (!count($this->errors)) { if (!isset($_POST['attribute_wholesale_price'])) { $_POST['attribute_wholesale_price'] = 0; } if (!isset($_POST['attribute_price_impact'])) { $_POST['attribute_price_impact'] = 0; } if (!isset($_POST['attribute_weight_impact'])) { $_POST['attribute_weight_impact'] = 0; } if (!isset($_POST['attribute_ecotax'])) { $_POST['attribute_ecotax'] = 0; } if (Tools::getValue('attribute_default')) { $product->deleteDefaultAttributes(); } $allShops = true; if (Shop::isFeatureActive()) { if(Shop::getContext() != Shop::CONTEXT_ALL) { $allShops = false; } } // Change existing one if (($id_product_attribute = (int)Tools::getValue('id_product_attribute')) || ($id_product_attribute = $product->productAttributeExists(Tools::getValue('attribute_combination_list'), false, null, $allShops, true))) { if ($this->tabAccess['edit'] === '1') { if ($this->isProductFieldUpdated('available_date_attribute') && (Tools::getValue('available_date_attribute') != '' &&!Validate::isDateFormat(Tools::getValue('available_date_attribute')))) { $this->errors[] = Tools::displayError('Invalid date format.'); } else { $product->updateAttribute((int)$id_product_attribute, $this->isProductFieldUpdated('attribute_wholesale_price') ? Tools::getValue('attribute_wholesale_price') : null, $this->isProductFieldUpdated('attribute_price_impact') ? Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact') : null, $this->isProductFieldUpdated('attribute_weight_impact') ? Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact') : null, $this->isProductFieldUpdated('attribute_unit_impact') ? Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact') : null, $this->isProductFieldUpdated('attribute_ecotax') ? Tools::getValue('attribute_ecotax') : null, Tools::getValue('id_image_attr'), Tools::getValue('attribute_reference'), Tools::getValue('attribute_ean13'), $this->isProductFieldUpdated('attribute_default') ? Tools::getValue('attribute_default') : null, Tools::getValue('attribute_location'), Tools::getValue('attribute_upc'), $this->isProductFieldUpdated('attribute_minimal_quantity') ? Tools::getValue('attribute_minimal_quantity') : null, $this->isProductFieldUpdated('available_date_attribute') ? Tools::getValue('available_date_attribute') : null, false); StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute); StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute); } } else { $this->errors[] = Tools::displayError('You do not have permission to add this.'); } } // Add new else { if ($this->tabAccess['add'] === '1') { if ($product->productAttributeExists(Tools::getValue('attribute_combination_list'))) { $this->errors[] = Tools::displayError('This combination already exists.'); } else { $id_product_attribute = $product->addCombinationEntity( Tools::getValue('attribute_wholesale_price'), Tools::getValue('attribute_price') * Tools::getValue('attribute_price_impact'), Tools::getValue('attribute_weight') * Tools::getValue('attribute_weight_impact'), Tools::getValue('attribute_unity') * Tools::getValue('attribute_unit_impact'), Tools::getValue('attribute_ecotax'), 0, Tools::getValue('id_image_attr'), Tools::getValue('attribute_reference'), null, Tools::getValue('attribute_ean13'), Tools::getValue('attribute_default'), Tools::getValue('attribute_location'), Tools::getValue('attribute_upc'), Tools::getValue('attribute_minimal_quantity'), array(), Tools::getValue('available_date_attribute') ); StockAvailable::setProductDependsOnStock((int)$product->id, $product->depends_on_stock, null, (int)$id_product_attribute); StockAvailable::setProductOutOfStock((int)$product->id, $product->out_of_stock, null, (int)$id_product_attribute); } } else { $this->errors[] = Tools::displayError('You do not have permission to').'<hr>'.Tools::displayError('edit here.'); } } if (!count($this->errors)) { $combination = new Combination((int)$id_product_attribute); $combination->setAttributes(Tools::getValue('attribute_combination_list')); // images could be deleted before $id_images = Tools::getValue('id_image_attr'); if (!empty($id_images)) { $combination->setImages($id_images); } $product->checkDefaultAttributes(); if (Tools::getValue('attribute_default')) { Product::updateDefaultAttribute((int)$product->id); if (isset($id_product_attribute)) { $product->cache_default_attribute = (int)$id_product_attribute; } if ($available_date = Tools::getValue('available_date_attribute')) { $product->setAvailableDate($available_date); } else { $product->setAvailableDate(); } } } } } } } Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now