Jump to content

Fallo al ordenar productos dentro de categoria "Padre"


korsakov14

Recommended Posts

Buenos días a todos,

tengo un problema, que seguramente su solución sea simple, pero por más que estoy probando cosas no doy con la solución buena. Estoy usando el tema warehouse.

Si alguien me pueda recomendar alguna alternativa le estaría muy agradecido.

Tengo el siguiente árbol de categorías en mi web:

image.png.2e69655317c227195062c714f392313f.png

 

Y quiero que en el grid de la categoría padre me muestre el orden de productos que le digo dentro de la categoría (en "Productos--> filtro por categoría --> Posición)

Desde la configuración también tengo puesto que ordene los grids con este criterio.

La página en cuestión sería esta, y como veis me ordena como le da la gana, creo que por producto relevantes. Mi ordenación dentro de turrones de jijona es poner todos los de categoria gourmet delante.

https://www.turronartesano.com/es/turrones-de-jijona

 

La alternativa de crear un grid personalizado en elementor no es válida porque cuando hago eso, pierdo la leftColumn y por lo tanto la búsqueda por facetas,

A alguien se le ocurre alguna solución?

Gracias de antemano!

 

Saludos.

 

 

 

Edited by nadie
Moderación del foro edita título del tema (más descriptivo) (see edit history)
Link to comment
Share on other sites

¿Qué versión exacta de Prestashop 1.7 usas? (Edito mensaje ,veo que usas 1.7.5.2)

Lo digo porque se han corregido errores relacionados: 

Dejo enlaces del repositorio de código:

https://github.com/PrestaShop/PrestaShop/pull/14879 (Tema discusión)

https://github.com/PrestaShop/PrestaShop/issues/14616 (Parche sobre fichero => src/Adapter/Product/AdminProductDataUpdater.php ) (+ añadir línea, - añadir línea)

Dicen de dejar el fichero así:
 

<?php
/**
 * 2007-2018 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:
 * https://opensource.org/licenses/OSL-3.0
 * 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-2018 PrestaShop SA
 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
 * International Registered Trademark & Property of PrestaShop SA
 */

namespace PrestaShop\PrestaShop\Adapter\Product;

use PrestaShopBundle\Service\DataUpdater\Admin\ProductInterface;
use PrestaShopBundle\Exception\UpdateProductException;
use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface;
use Product;
use Validate;
use Shop;
use ShopGroup;
use Category;
use GroupReduction;
use Pack;
use Search;
use Db;
use Configuration;
use Image;

/**
 * This class will update/insert/delete data from DB / ORM about Product, for both Front and Admin interfaces.
 */
class AdminProductDataUpdater implements ProductInterface
{
    /**
     * @var HookDispatcherInterface
     */
    private $hookDispatcher;

    /**
     * Constructor. HookDispatcher is injected by Sf container.
     *
     * @param HookDispatcher $hookDispatcher
     */
    public function __construct(HookDispatcherInterface $hookDispatcher)
    {
        $this->hookDispatcher = $hookDispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function activateProductIdList(array $productListId, $activate = true)
    {
        if (count($productListId) < 1) {
            throw new \Exception('AdminProductDataUpdater->activateProductIdList() should always receive at least one ID. Zero given.', 5003);
        }

        $failedIdList = array();
        foreach ($productListId as $productId) {
            $product = new Product($productId);
            if (!Validate::isLoadedObject($product)) {
                $failedIdList[] = $productId;
                continue;
            }
            $product->active = ($activate ? 1 : 0);
            $product->update();
            $this->hookDispatcher->dispatchWithParameters('actionProductActivation', array('id_product' => (int) $product->id, 'product' => $product, 'activated' => $activate));
        }

        if (count($failedIdList) > 0) {
            throw new UpdateProductException('Cannot change activation state on many requested products', 5004);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteProductIdList(array $productIdList)
    {
        if (count($productIdList) < 1) {
            throw new \Exception('AdminProductDataUpdater->deleteProductIdList() should always receive at least one ID. Zero given.', 5005);
        }

        $failedIdList = $productIdList; // Since we have just one call to delete all, cannot have distinctive fails.
        // Hooks: will trigger actionProductDelete multiple times
        $result = (new Product())->deleteSelection($productIdList);

        if ($result === 0) {
            throw new UpdateProductException('Cannot delete many requested products.', 5006);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function duplicateProductIdList(array $productIdList)
    {
        if (count($productIdList) < 1) {
            throw new \Exception('AdminProductDataUpdater->duplicateProductIdList() should always receive at least one ID. Zero given.', 5005);
        }

        $failedIdList = array();
        foreach ($productIdList as $productId) {
            try {
                $this->duplicateProduct($productId);
            } catch (\Exception $e) {
                $failedIdList[] = $productId;
                continue;
            }
        }

        if (count($failedIdList) > 0) {
            throw new UpdateProductException('Cannot duplicate many requested products', 5004);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteProduct($productId)
    {
        $product = new Product($productId);
        if (!Validate::isLoadedObject($product)) {
            throw new \Exception('AdminProductDataUpdater->deleteProduct() received an unknown ID.', 5005);
        }

        // dumb? no: delete() makes a lot of things, and can reject deletion in specific cases.
        // Hooks: will trigger actionProductDelete
        $result = $product->delete();

        if ($result === 0) {
            throw new UpdateProductException('Cannot delete the requested product.', 5007);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function duplicateProduct($productId, $namePattern = 'copy of %s')
    {
        //TODO : use the $namePattern var to input translated version of 'copy of %s', if translation requested.
        $product = new Product($productId);
        if (!Validate::isLoadedObject($product)) {
            throw new \Exception('AdminProductDataUpdater->duplicateProduct() received an unknown ID.', 5005);
        }

        $id_product_old = $product->id;
        if (empty($product->price) && Shop::getContext() == Shop::CONTEXT_GROUP) {
            $shops = ShopGroup::getShopsFromGroup(Shop::getContextShopGroupID());
            foreach ($shops as $shop) {
                if ($product->isAssociatedToShop($shop['id_shop'])) {
                    $product_price = new Product($id_product_old, false, null, $shop['id_shop']);
                    $product->price = $product_price->price;
                }
            }
        }

        unset($product->id);
        unset($product->id_product);
        $product->indexed = 0;
        $product->active = 0;

        // change product name to prefix it
        foreach ($product->name as $langKey => $oldName) {
            if (!preg_match('/^' . str_replace('%s', '.*', preg_quote($namePattern, '/') . '$/'), $oldName)) {
                $newName = sprintf($namePattern, $oldName);
                if (mb_strlen($newName, 'UTF-8') <= 127) {
                    $product->name[$langKey] = $newName;
                }
            }
        }

        if ($product->add()
            && Category::duplicateProductCategories($id_product_old, $product->id)
            && Product::duplicateSuppliers($id_product_old, $product->id)
            && ($combination_images = Product::duplicateAttributes($id_product_old, $product->id)) !== false
            && GroupReduction::duplicateReduction($id_product_old, $product->id)
            && Product::duplicateAccessories($id_product_old, $product->id)
            && Product::duplicateFeatures($id_product_old, $product->id)
            && Product::duplicateSpecificPrices($id_product_old, $product->id)
            && Pack::duplicate($id_product_old, $product->id)
            && Product::duplicateCustomizationFields($id_product_old, $product->id)
            && Product::duplicateTags($id_product_old, $product->id)
            && Product::duplicateDownload($id_product_old, $product->id)) {
            if ($product->hasAttributes()) {
                Product::updateDefaultAttribute($product->id);
            }

            if (!Image::duplicateProductImages($id_product_old, $product->id, $combination_images)) {
                throw new UpdateProductException('An error occurred while copying images.', 5008);
            } else {
                $this->hookDispatcher->dispatchWithParameters('actionProductAdd', array('id_product' => (int) $product->id, 'product' => $product));
                if (in_array($product->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) {
                    Search::indexation(false, $product->id);
                }

                return $product->id;
            }
        } else {
            throw new \Exception('An error occurred while creating an object.', 5009);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function sortProductIdList(array $productList, $filterParams)
    {
        if (count($productList) < 2) {
            return false;
        }

        if (!isset($filterParams['filter_category'])) {
            throw new \Exception('Cannot sort when filterParams does not contains \'filter_category\'.', 5010);
        }

        foreach ($filterParams as $k => $v) {
            if ($v == '' || strpos($k, 'filter_') !== 0) {
                continue;
            }
            if ($k == 'filter_category') {
                continue;
            }
            throw new \Exception('Cannot sort when filterParams contains other filter than \'filter_category\'.', 5010);
        }

        $categoryId = $filterParams['filter_category'];
		$minPosition = min(array_values($productList));
        $productsIds = implode(',', array_map('intval', array_keys($productList)));
       
	   /* Sorting items on one page only, with ONE SQL UPDATE query,
         * then fixing bugs (duplicates and 0 values) on next pages with more queries, if needed.
         *
         * Most complicated case example:
         * We have to sort items from offset 5, limit 5, on total object count: 14
         * The previous AND the next pages MUST NOT be impacted but fixed if needed.
         * legend:  #<id>|P<position>
         *
         * Before sort:
         * #1|P2 #2|P4 #3|P5 #7|P8 #6|P9   #5|P10 #8|P11 #10|P13 #12|P14 #11|P15   #9|P16 #12|P18 #14|P19 #22|P24
         * (there is holes in positions)
         *
         * Sort request:
         *                                 #5|P?? #10|P?? #12|P?? #8|P?? #11|P??
         *
         * After sort:
         * (previous page unchanged)       (page to sort: sort and no duplicates) (the next pages MUST be shifted to avoid duplicates if any)
         *
         * Request input:
         *                               [#5]P10 [#10]P13 [#12]P14 [#8]P11 [#11]P15
         */
      /*  $maxPosition = max(array_values($productList));
        $sortedPositions = array_values($productList);
        sort($sortedPositions); // new positions to update

        // avoid '0', starts with '1', so shift right (+1)
        if ($sortedPositions[1] === 0) {
            foreach ($sortedPositions as $k => $v) {
                $sortedPositions[$k] = $v + 1;
            }
        }

        // combine old positions with new position in an array
        $combinedOldNewPositions = array_combine(array_values($productList), $sortedPositions);
        ksort($combinedOldNewPositions); // (keys: old positions starting at '1', values: new positions)
        $positionsMatcher = array_replace(array_pad(array(), $maxPosition, 0), $combinedOldNewPositions); // pad holes with 0
        array_shift($positionsMatcher); // shift because [0] is not used in MySQL FIELD()
        $fields = implode(',', $positionsMatcher);

        // update current pages.
        $updatePositions = 'UPDATE `' . _DB_PREFIX_ . 'category_product` cp
            INNER JOIN `' . _DB_PREFIX_ . 'product` p ON (cp.`id_product` = p.`id_product`)
            ' . Shop::addSqlAssociation('product', 'p') . '
            SET cp.`position` = ELT(cp.`position`, ' . $fields . '),
                p.`date_upd` = "' . date('Y-m-d H:i:s') . '",
                product_shop.`date_upd` = "' . date('Y-m-d H:i:s') . '"
            WHERE cp.`id_category` = ' . (int) $categoryId . ' AND cp.`id_product` IN (' . implode(',', array_map('intval', array_keys($productList))) . ')';

        Db::getInstance()->execute($updatePositions);

        // Fixes duplicates on all pages
        Db::getInstance()->query('SET @i := 0');
        $selectPositions = 'UPDATE`' . _DB_PREFIX_ . 'category_product` cp
            SET cp.`position` = (SELECT @i := @i + 1)
            WHERE cp.`id_category` = ' . (int) $categoryId . '
            ORDER BY cp.`id_product` NOT IN (' . implode(',', array_map('intval', array_keys($productList))) . '), cp.`position` ASC';
        Db::getInstance()->execute($selectPositions);
*/

Db::getInstance()->query('SET @i := ' . (((int) $minPosition) - 1));
        $updatePositions = 'UPDATE `' . _DB_PREFIX_ . 'category_product` cp ' .
            'SET cp.`position` = (SELECT @i := @i + 1) ' .
            'WHERE cp.`id_category` = ' . (int) $categoryId . ' AND cp.`id_product` IN (' . $productsIds . ') ' .
            'ORDER BY FIELD(cp.`id_product`, ' . $productsIds . ')';
        Db::getInstance()->query($updatePositions);
        /**
         * Second request to update date_upd because
         * ORDER BY is not working on multi-tables update
         */
        $updateProducts = 'UPDATE `' . _DB_PREFIX_ . 'product` p ' .
            '' . Shop::addSqlAssociation('product', 'p') . ' ' .
            'SET ' .
            '    p.`date_upd` = "' . date('Y-m-d H:i:s') . '", ' .
            '    product_shop.`date_upd` = "' . date('Y-m-d H:i:s') . '" ' .
            'WHERE p.`id_product` IN (' . $productsIds . ') ';
        Db::getInstance()->query($updateProducts);
        return true;
    }
}

Ese fichero  es uno que tengo de la 1.7.5.1, modificando según parámetros que recomiendan en el parche.

******

Inicialmente por lo que veo lo tienes bien configurado. Imagino que has probado (aunque no tenga que seguramente nada que ver) si te ocurre lo mismo con la plantilla por defecto

Una cosa,

Prueba lo siguiente, en el módulo "Navegación por facetas" la opción que dice:  Mostrar productos de las subcategorías (desactívalo y revisa si te ordena bien los productos ahora en el front)

Adjunto Imagen

mfacetasps176.png

Lo digo porque si tienes esa opción configurada al meterte en las categorías X verás directamente listado los productos de todas las subcategorías y quizás eso te esté creando confusión.

Ahora intenta en Catálogo => Productos probar la ordenación de nuevo, pero fijate que estés ordenando productos de la categoría (principal) asociada a los productos en cuestión.

Adjunto capturas

 

opas-1024x261.png

Fijate bien donde dice "Categoría" que concuerden.

Por supuesto, entiendo que en la pestaña Parámetros de la tienda => Configuración de los Productos" tienes configurado Ordenar productos por => Posición dentro de la categoría

Adjunto captura

spacer.png

Me explico:

Si el producto tiene asociada categoría por defecto => tomates y además está metido en chorizos y luego tienes otro producto que tiene chorizos como principal, y tomates como secundaria, ambos productos no se encuentran en la categoría principal tomates. Deja ambos en el raiz de chorizos y luego como secundaria tomates según de donde sea..

Haz esa prueba y dime.

 

AdminProductDataUpdater.php

Edited by nadie (see edit history)
  • Like 1
Link to comment
Share on other sites

hace 52 minutos, nadie dijo:

¿Qué versión exacta de Prestashop 1.7 usas?

Lo digo porque se han corregido errores relacionados: 

Dejo enlaces del repositorio de código:

https://github.com/PrestaShop/PrestaShop/pull/14879 (Tema discusión)

https://github.com/PrestaShop/PrestaShop/issues/14616 (Parche sobre fichero => src/Adapter/Product/AdminProductDataUpdater.php ) (+ añadir línea, - añadir línea)

Dicen de dejar el fichero así:
 


<?php
/**
 * 2007-2018 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:
 * https://opensource.org/licenses/OSL-3.0
 * 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-2018 PrestaShop SA
 * @license   https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
 * International Registered Trademark & Property of PrestaShop SA
 */

namespace PrestaShop\PrestaShop\Adapter\Product;

use PrestaShopBundle\Service\DataUpdater\Admin\ProductInterface;
use PrestaShopBundle\Exception\UpdateProductException;
use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface;
use Product;
use Validate;
use Shop;
use ShopGroup;
use Category;
use GroupReduction;
use Pack;
use Search;
use Db;
use Configuration;
use Image;

/**
 * This class will update/insert/delete data from DB / ORM about Product, for both Front and Admin interfaces.
 */
class AdminProductDataUpdater implements ProductInterface
{
    /**
     * @var HookDispatcherInterface
     */
    private $hookDispatcher;

    /**
     * Constructor. HookDispatcher is injected by Sf container.
     *
     * @param HookDispatcher $hookDispatcher
     */
    public function __construct(HookDispatcherInterface $hookDispatcher)
    {
        $this->hookDispatcher = $hookDispatcher;
    }

    /**
     * {@inheritdoc}
     */
    public function activateProductIdList(array $productListId, $activate = true)
    {
        if (count($productListId) < 1) {
            throw new \Exception('AdminProductDataUpdater->activateProductIdList() should always receive at least one ID. Zero given.', 5003);
        }

        $failedIdList = array();
        foreach ($productListId as $productId) {
            $product = new Product($productId);
            if (!Validate::isLoadedObject($product)) {
                $failedIdList[] = $productId;
                continue;
            }
            $product->active = ($activate ? 1 : 0);
            $product->update();
            $this->hookDispatcher->dispatchWithParameters('actionProductActivation', array('id_product' => (int) $product->id, 'product' => $product, 'activated' => $activate));
        }

        if (count($failedIdList) > 0) {
            throw new UpdateProductException('Cannot change activation state on many requested products', 5004);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteProductIdList(array $productIdList)
    {
        if (count($productIdList) < 1) {
            throw new \Exception('AdminProductDataUpdater->deleteProductIdList() should always receive at least one ID. Zero given.', 5005);
        }

        $failedIdList = $productIdList; // Since we have just one call to delete all, cannot have distinctive fails.
        // Hooks: will trigger actionProductDelete multiple times
        $result = (new Product())->deleteSelection($productIdList);

        if ($result === 0) {
            throw new UpdateProductException('Cannot delete many requested products.', 5006);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function duplicateProductIdList(array $productIdList)
    {
        if (count($productIdList) < 1) {
            throw new \Exception('AdminProductDataUpdater->duplicateProductIdList() should always receive at least one ID. Zero given.', 5005);
        }

        $failedIdList = array();
        foreach ($productIdList as $productId) {
            try {
                $this->duplicateProduct($productId);
            } catch (\Exception $e) {
                $failedIdList[] = $productId;
                continue;
            }
        }

        if (count($failedIdList) > 0) {
            throw new UpdateProductException('Cannot duplicate many requested products', 5004);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function deleteProduct($productId)
    {
        $product = new Product($productId);
        if (!Validate::isLoadedObject($product)) {
            throw new \Exception('AdminProductDataUpdater->deleteProduct() received an unknown ID.', 5005);
        }

        // dumb? no: delete() makes a lot of things, and can reject deletion in specific cases.
        // Hooks: will trigger actionProductDelete
        $result = $product->delete();

        if ($result === 0) {
            throw new UpdateProductException('Cannot delete the requested product.', 5007);
        }

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function duplicateProduct($productId, $namePattern = 'copy of %s')
    {
        //TODO : use the $namePattern var to input translated version of 'copy of %s', if translation requested.
        $product = new Product($productId);
        if (!Validate::isLoadedObject($product)) {
            throw new \Exception('AdminProductDataUpdater->duplicateProduct() received an unknown ID.', 5005);
        }

        $id_product_old = $product->id;
        if (empty($product->price) && Shop::getContext() == Shop::CONTEXT_GROUP) {
            $shops = ShopGroup::getShopsFromGroup(Shop::getContextShopGroupID());
            foreach ($shops as $shop) {
                if ($product->isAssociatedToShop($shop['id_shop'])) {
                    $product_price = new Product($id_product_old, false, null, $shop['id_shop']);
                    $product->price = $product_price->price;
                }
            }
        }

        unset($product->id);
        unset($product->id_product);
        $product->indexed = 0;
        $product->active = 0;

        // change product name to prefix it
        foreach ($product->name as $langKey => $oldName) {
            if (!preg_match('/^' . str_replace('%s', '.*', preg_quote($namePattern, '/') . '$/'), $oldName)) {
                $newName = sprintf($namePattern, $oldName);
                if (mb_strlen($newName, 'UTF-8') <= 127) {
                    $product->name[$langKey] = $newName;
                }
            }
        }

        if ($product->add()
            && Category::duplicateProductCategories($id_product_old, $product->id)
            && Product::duplicateSuppliers($id_product_old, $product->id)
            && ($combination_images = Product::duplicateAttributes($id_product_old, $product->id)) !== false
            && GroupReduction::duplicateReduction($id_product_old, $product->id)
            && Product::duplicateAccessories($id_product_old, $product->id)
            && Product::duplicateFeatures($id_product_old, $product->id)
            && Product::duplicateSpecificPrices($id_product_old, $product->id)
            && Pack::duplicate($id_product_old, $product->id)
            && Product::duplicateCustomizationFields($id_product_old, $product->id)
            && Product::duplicateTags($id_product_old, $product->id)
            && Product::duplicateDownload($id_product_old, $product->id)) {
            if ($product->hasAttributes()) {
                Product::updateDefaultAttribute($product->id);
            }

            if (!Image::duplicateProductImages($id_product_old, $product->id, $combination_images)) {
                throw new UpdateProductException('An error occurred while copying images.', 5008);
            } else {
                $this->hookDispatcher->dispatchWithParameters('actionProductAdd', array('id_product' => (int) $product->id, 'product' => $product));
                if (in_array($product->visibility, array('both', 'search')) && Configuration::get('PS_SEARCH_INDEXATION')) {
                    Search::indexation(false, $product->id);
                }

                return $product->id;
            }
        } else {
            throw new \Exception('An error occurred while creating an object.', 5009);
        }
    }

    /**
     * {@inheritdoc}
     */
    public function sortProductIdList(array $productList, $filterParams)
    {
        if (count($productList) < 2) {
            return false;
        }

        if (!isset($filterParams['filter_category'])) {
            throw new \Exception('Cannot sort when filterParams does not contains \'filter_category\'.', 5010);
        }

        foreach ($filterParams as $k => $v) {
            if ($v == '' || strpos($k, 'filter_') !== 0) {
                continue;
            }
            if ($k == 'filter_category') {
                continue;
            }
            throw new \Exception('Cannot sort when filterParams contains other filter than \'filter_category\'.', 5010);
        }

        $categoryId = $filterParams['filter_category'];
		$minPosition = min(array_values($productList));
        $productsIds = implode(',', array_map('intval', array_keys($productList)));
       
	   /* Sorting items on one page only, with ONE SQL UPDATE query,
         * then fixing bugs (duplicates and 0 values) on next pages with more queries, if needed.
         *
         * Most complicated case example:
         * We have to sort items from offset 5, limit 5, on total object count: 14
         * The previous AND the next pages MUST NOT be impacted but fixed if needed.
         * legend:  #<id>|P<position>
         *
         * Before sort:
         * #1|P2 #2|P4 #3|P5 #7|P8 #6|P9   #5|P10 #8|P11 #10|P13 #12|P14 #11|P15   #9|P16 #12|P18 #14|P19 #22|P24
         * (there is holes in positions)
         *
         * Sort request:
         *                                 #5|P?? #10|P?? #12|P?? #8|P?? #11|P??
         *
         * After sort:
         * (previous page unchanged)       (page to sort: sort and no duplicates) (the next pages MUST be shifted to avoid duplicates if any)
         *
         * Request input:
         *                               [#5]P10 [#10]P13 [#12]P14 [#8]P11 [#11]P15
         */
      /*  $maxPosition = max(array_values($productList));
        $sortedPositions = array_values($productList);
        sort($sortedPositions); // new positions to update

        // avoid '0', starts with '1', so shift right (+1)
        if ($sortedPositions[1] === 0) {
            foreach ($sortedPositions as $k => $v) {
                $sortedPositions[$k] = $v + 1;
            }
        }

        // combine old positions with new position in an array
        $combinedOldNewPositions = array_combine(array_values($productList), $sortedPositions);
        ksort($combinedOldNewPositions); // (keys: old positions starting at '1', values: new positions)
        $positionsMatcher = array_replace(array_pad(array(), $maxPosition, 0), $combinedOldNewPositions); // pad holes with 0
        array_shift($positionsMatcher); // shift because [0] is not used in MySQL FIELD()
        $fields = implode(',', $positionsMatcher);

        // update current pages.
        $updatePositions = 'UPDATE `' . _DB_PREFIX_ . 'category_product` cp
            INNER JOIN `' . _DB_PREFIX_ . 'product` p ON (cp.`id_product` = p.`id_product`)
            ' . Shop::addSqlAssociation('product', 'p') . '
            SET cp.`position` = ELT(cp.`position`, ' . $fields . '),
                p.`date_upd` = "' . date('Y-m-d H:i:s') . '",
                product_shop.`date_upd` = "' . date('Y-m-d H:i:s') . '"
            WHERE cp.`id_category` = ' . (int) $categoryId . ' AND cp.`id_product` IN (' . implode(',', array_map('intval', array_keys($productList))) . ')';

        Db::getInstance()->execute($updatePositions);

        // Fixes duplicates on all pages
        Db::getInstance()->query('SET @i := 0');
        $selectPositions = 'UPDATE`' . _DB_PREFIX_ . 'category_product` cp
            SET cp.`position` = (SELECT @i := @i + 1)
            WHERE cp.`id_category` = ' . (int) $categoryId . '
            ORDER BY cp.`id_product` NOT IN (' . implode(',', array_map('intval', array_keys($productList))) . '), cp.`position` ASC';
        Db::getInstance()->execute($selectPositions);
*/

Db::getInstance()->query('SET @i := ' . (((int) $minPosition) - 1));
        $updatePositions = 'UPDATE `' . _DB_PREFIX_ . 'category_product` cp ' .
            'SET cp.`position` = (SELECT @i := @i + 1) ' .
            'WHERE cp.`id_category` = ' . (int) $categoryId . ' AND cp.`id_product` IN (' . $productsIds . ') ' .
            'ORDER BY FIELD(cp.`id_product`, ' . $productsIds . ')';
        Db::getInstance()->query($updatePositions);
        /**
         * Second request to update date_upd because
         * ORDER BY is not working on multi-tables update
         */
        $updateProducts = 'UPDATE `' . _DB_PREFIX_ . 'product` p ' .
            '' . Shop::addSqlAssociation('product', 'p') . ' ' .
            'SET ' .
            '    p.`date_upd` = "' . date('Y-m-d H:i:s') . '", ' .
            '    product_shop.`date_upd` = "' . date('Y-m-d H:i:s') . '" ' .
            'WHERE p.`id_product` IN (' . $productsIds . ') ';
        Db::getInstance()->query($updateProducts);
        return true;
    }
}

Ese fichero  es uno que tengo de la 1.7.5.1, modificando según parámetros que recomiendan en el parche.

******

Inicialmente por lo que veo lo tienes bien configurado. Imagino que has probado (aunque no tenga que seguramente nada que ver) si te ocurre lo mismo con la plantilla por defecto

Una cosa,

Prueba lo siguiente, en el módulo "Navegación por facetas" la opción que dice:  Mostrar productos de las subcategorías (desactívalo y revisa si te ordena bien los productos ahora en el front)

Adjunto Imagen

mfacetasps176.png

Lo digo porque si tienes esa opción configurada al meterte en las categorías X verás directamente listado los productos de todas las subcategorías y quizás eso te esté creando confusión.

Ahora intenta en Catálogo => Productos probar la ordenación de nuevo, pero fijate que estés ordenando productos de la categoría (principal) asociada a los productos en cuestión.

Adjunto capturas

 

opas-1024x261.png

Fijate bien donde dice "Categoría" que concuerden.

Por supuesto, entiendo que en la pestaña Parámetros de la tienda => Configuración de los Productos" tienes configurado Ordenar productos por => Posición dentro de la categoría

Adjunto captura

spacer.png

Me explico:

Si el producto tiene asociada categoría por defecto => tomates y además está metido en chorizos en chorizos y luego tienes otro producto que tiene chorizos como principal, y tomates como secundaria, ambos productos no se encuentran en la categoría principal tomates. Deja amos en el raiz de chorizos y luego como secundaria tomates.

Haz esa prueba y dime.

 

AdminProductDataUpdater.php 13.46 kB · 0 downloads

👏👏 muchas gracias por la respuesta, he alucinado por el nivel de detalle, no esperaba algo así, vamos a ver si lo resolvemos!

Vamos por partes, para descartar cosas,

1. Versión de prestashop 1.7.5.2

2. Desactivando que me muestre productos de subcategorías SI funciona, esto ya lo había probado antes debería haberlo citado en el post, disculpa. ¿Esto descartaría que sea el bug que comentas?

3.Pensaba que el error podía venir por lo último que has comentado de los chorizos y los tomates 😅 Ya que tenía un producto que tenia de categoría principal chocolate (que no está dentro de turrones de jijona) y también pertenecía a turrones de jijona, pero he quitado este producto de dentro y sigue saliendo lo mismo. 

Con el árbol que tengo ahora sería esto...

image.thumb.png.74582bda3e758b8538e2cfce263a0ff6.png

 

Entonces mi duda es... ¿no puedo ordenar en "turrones de jijona" turrones de la subcategoría "turrón suprema" por ejemplo, que está dentro de turrones de jijona (aunque ese producto tenga como principal turrón suprema en lugar de turrones de jijona). Es decir, ¿aunque tenga productos que solo pertenezcan a la misma rama padre-hijo, no puedo ordenar en el grid padre con un orden personalizado, no?

Gracias por todo, 

Saludos.

 

Edited by korsakov14
imagen duplicada (see edit history)
Link to comment
Share on other sites

  • 2 months later...

Me uno a la duda. 

Tengo una tienda de semillas donde la "macrocategoría" es "semillas"
La categoría es "frutas"
La subcategoría es "tomates", "manzanas"...

 

Mi idea es que una semilla de "manzana" esté dentro de las 3 categorías: semillas>fruta>manzanas
De tal forma que si entra alguien a "semillas" (porque no tiene claro qué quiere) se encuentre entre otras las semillas de manzanas.
Lo mismo si alguien entra dentro de la categoría frutas, allí tb encontrará las semillas de manzanas.
Y finalmente si alguien entra en la categoría manzanas allí va a encontrar todas las semillas específicas de manzana. 

El problema es que cuando miro la categoría "semillas" todo es un cristo, con un orden que no entiendo y nada parecido al listado de productos que me muestra el backend de prestashop filtrando por "semillas". 

 

Así como notas: 

  • La macrocategoría "semillas" tiene más de 700 productos
  • Tengo activa la opción de mostrar productos de subcategorías (para que se muestren los productos en todas las categorías seleccionadas)
  • El orden de la macrocategoría semillas es "aleatorio". Siempre aparecen más o menos las mismas pero en posiciones distintas. Eso me tiene muerto.


Alguna idea?

Edited by gironactiva (see edit history)
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...