Как сделать сортировку одновременно по цене и наличию?

Тема в разделе "PrestaShop", создана пользователем kotan, 22 сен 2014.

Информация :
Приветствую гость, обрати внимание! Темы которые закреплены в разделах, в скором времени будут откреплены. Правила раздела PrestaShop

(Не актуальные темы) Каталоги:Модули PrestaShop 1.7Модули PrestaShop 1.5 - 1.6Шаблоны PrestaShop 1.7Шаблоны PrestaShop 1.5 - 1.6
(Не актуальные темы) Поиск / Запросы:Модули PrestaShop 1.7Модули PrestaShop 1.5 - 1.6Шаблоны PrestaShop 1.7Шаблоны PrestaShop 1.5 - 1.6
Полезная информация:Поддержка и помощь c PrestaShopУбираем ПрестаТраст, стучалки и прочую рекламуСовместные покупки модулей и шаблоновПеревод Prestashop и модулей
Модераторы: trace
  1. andrew.irpin

    andrew.irpin

    Регистр.:
    24 авг 2013
    Сообщения:
    342
    Симпатии:
    320
    Есть решение для prestashop 1.6 + blocklayered модуля версии 2.1.3, товары которых нет в наличии сортируются в конце списка по выбранному в категории способу сортировки. В итоге на странице категории с включенным фильтром многоуровневой навигации - работают все способы сортировки в категории: по цене, наличию, от А до Я и т.д., а также товары которых нет в наличии таким же способом отсортированы в самом конце списка после основного перечня товаров.
    Работает отлично на Blocklayered Module 2.1.3 , для более поздних версий Престашоп /Блока многоуровневой навигации можно сделать по аналогии.
    Также есть решение для Престашоп 1.6 + Вархаус последней версии.
    Кому нужно - пишите в личку.
     
    evgenij.sobolev нравится это.
  2. _sashok

    _sashok PrestaShop Expert

    Регистр.:
    15 июл 2011
    Сообщения:
    2.029
    Симпатии:
    3.355

    та выкладывай сюда - пусть гуглится всем кто ищет :)
     
    evgenij.sobolev нравится это.
  3. Ph48

    Ph48 Писатель

    Регистр.:
    17 июл 2014
    Сообщения:
    6
    Симпатии:
    0
    подскажите пожалуйста как можно сделать, что бы в конце списка всегда были товары "не доступные" к заказу. а товары с "0" остатком, но доступные к заказу в конец списка не переносились?

    Версия Prestashop 1.6.0.14
    Блок многоуровневой навигации - v2.1.3

    Спасибо
     
  4. cyzme

    cyzme Писатель

    Регистр.:
    11 июл 2016
    Сообщения:
    4
    Симпатии:
    0
    Для этого нужно наследовать модель Category, и переписать под себя метод getProducts()
     
  5. Jame

    Jame

    Регистр.:
    16 июл 2012
    Сообщения:
    376
    Симпатии:
    191
    Есть у кого-то готовое решение для 1.6 + Warehouse + AS4 ? Нужно товары с 0 остатком отправлять в конец при любом виде сортировке.
     
    evgenij.sobolev нравится это.
  6. andrew.irpin

    andrew.irpin

    Регистр.:
    24 авг 2013
    Сообщения:
    342
    Симпатии:
    320
    evgenij.sobolev, omega80, Jame и ещё 1-му нравится это.
  7. Staut82

    Staut82 Создатель

    Регистр.:
    15 июл 2013
    Сообщения:
    18
    Симпатии:
    11
    Не могу найти ваш пост, можете в ЛС скинуть?
     
    evgenij.sobolev нравится это.
  8. evgenij.sobolev

    evgenij.sobolev

    Регистр.:
    8 дек 2015
    Сообщения:
    209
    Симпатии:
    212
    Лучше тут продублировать.
    Думаю, для многих актуальна эта тема.
     
  9. dsdscdscde

    dsdscdscde RD Нарушитель

    Заблокирован
    Регистр.:
    7 окт 2016
    Сообщения:
    270
    Симпатии:
    240
    а подскажите как сделать чтобы по unit price была сортировка (сначала те что дешевле). + стоит adv search.

    спасибо
     
    evgenij.sobolev нравится это.
  10. Quant

    Quant Создатель

    Регистр.:
    22 май 2013
    Сообщения:
    24
    Симпатии:
    39
    Одно из решений, если надо выводить товары с 0 остатком в конце списка для категорий.
    (без использования blocklayered и as4)

    Делаем override Category.php (или добавляем)

    PHP:
    <?php
    class Category extends CategoryCore
    {
        
    /*
         * Исправление сортировки по цене (для товаров с комбинацией и базовой ценой 0)
         * см. $sql - "IFNULL(product_attribute_shop.price, product_shop.price) AS orderprice"
         *
         * Изм. порядка сортировки - товары с 0 qty в конце при любом виде сортировки
         *
         */
        
    public function getProducts($id_lang$p$n$order_by null$order_way null$get_total false$active true$random false$random_number_products 1$check_access trueContext $context null)
        {
            if (!
    $context) {
                
    $context Context::getContext();
            }

            if (
    $check_access && !$this->checkAccess($context->customer->id)) {
                return 
    false;
            }

            
    $front in_array($context->controller->controller_type, array('front''modulefront'));
            
    $id_supplier = (int)Tools::getValue('id_supplier');

            
    /** Return only the number of products */
            
    if ($get_total) {
                
    $sql 'SELECT COUNT(cp.`id_product`) AS total
                        FROM `'
    ._DB_PREFIX_.'product` p
                        '
    .Shop::addSqlAssociation('product''p').'
                        LEFT JOIN `'
    ._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`
                        WHERE cp.`id_category` = '
    .(int)$this->id.
                    (
    $front ' AND product_shop.`visibility` IN ("both", "catalog")' '').
                    (
    $active ' AND product_shop.`active` = 1' '').
                    (
    $id_supplier 'AND p.id_supplier = '.(int)$id_supplier '');

                return (int)
    Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
            }

            if (
    $p 1) {
                
    $p 1;
            }

            
    /** Tools::strtolower is a fix for all modules which are now using lowercase values for 'orderBy' parameter */
            
    $order_by  Validate::isOrderBy($order_by)   ? Tools::strtolower($order_by)  : 'position';
            
    $order_way Validate::isOrderWay($order_way) ? Tools::strtoupper($order_way) : 'ASC';

            
    $order_by_prefix false;
            if (
    $order_by == 'id_product' || $order_by == 'date_add' || $order_by == 'date_upd') {
                
    $order_by_prefix 'p';
            } elseif (
    $order_by == 'name') {
                
    $order_by_prefix 'pl';
            } elseif (
    $order_by == 'manufacturer' || $order_by == 'manufacturer_name') {
                
    $order_by_prefix 'm';
                
    $order_by 'name';
            } elseif (
    $order_by == 'position') {
                
    $order_by_prefix 'cp';
            }

            if (
    $order_by == 'price') {
                
    $order_by 'orderprice';
            }

            
    $nb_days_new_product Configuration::get('PS_NB_DAYS_NEW_PRODUCT');
            if (!
    Validate::isUnsignedInt($nb_days_new_product)) {
                
    $nb_days_new_product 20;
            }

            
    $sql 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) AS quantity'.(Combination::isFeatureActive() ? ', IFNULL(product_attribute_shop.id_product_attribute, 0) AS id_product_attribute,
                        product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity' 
    '').', pl.`description`, pl.`description_short`, pl.`available_now`,
                        pl.`available_later`, pl.`link_rewrite`, pl.`meta_description`, pl.`meta_keywords`, pl.`meta_title`, pl.`name`, image_shop.`id_image` id_image,
                        il.`legend` as legend, m.`name` AS manufacturer_name, cl.`name` AS category_default,
                        DATEDIFF(product_shop.`date_add`, DATE_SUB("'
    .date('Y-m-d').' 00:00:00",
                        INTERVAL '
    .(int)$nb_days_new_product.' DAY)) > 0 AS new, IFNULL(product_attribute_shop.price, product_shop.price) AS orderprice,
                        IF(stock.quantity = 0, 0, 1) AS qty_as_availability
                    FROM `'
    ._DB_PREFIX_.'category_product` cp
                    LEFT JOIN `'
    ._DB_PREFIX_.'product` p
                        ON p.`id_product` = cp.`id_product`
                    '
    .Shop::addSqlAssociation('product''p').
                (
    Combination::isFeatureActive() ? ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop
                    ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='
    .(int)$context->shop->id.')':'').'
                    '
    .Product::sqlStock('p'0).'
                    LEFT JOIN `'
    ._DB_PREFIX_.'category_lang` cl
                        ON (product_shop.`id_category_default` = cl.`id_category`
                        AND cl.`id_lang` = '
    .(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')
                    LEFT JOIN `'
    ._DB_PREFIX_.'product_lang` pl
                        ON (p.`id_product` = pl.`id_product`
                        AND pl.`id_lang` = '
    .(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').')
                    LEFT JOIN `'
    ._DB_PREFIX_.'image_shop` image_shop
                        ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='
    .(int)$context->shop->id.')
                    LEFT JOIN `'
    ._DB_PREFIX_.'image_lang` il
                        ON (image_shop.`id_image` = il.`id_image`
                        AND il.`id_lang` = '
    .(int)$id_lang.')
                    LEFT JOIN `'
    ._DB_PREFIX_.'manufacturer` m
                        ON m.`id_manufacturer` = p.`id_manufacturer`
                    WHERE product_shop.`id_shop` = '
    .(int)$context->shop->id.'
                        AND cp.`id_category` = '
    .(int)$this->id
                
    .($active ' AND product_shop.`active` = 1' '')
                .(
    $front ' AND product_shop.`visibility` IN ("both", "catalog")' '')
                .(
    $id_supplier ' AND p.id_supplier = '.(int)$id_supplier '');

            if (
    $random === true) {
                
    $sql .= ' ORDER BY RAND() LIMIT '.(int)$random_number_products;
            } else {
                
    $sql .= ' ORDER BY qty_as_availability DESC, '.(!empty($order_by_prefix) ? $order_by_prefix.'.' '').'`'.bqSQL($order_by).'` '.pSQL($order_way).'
                LIMIT '
    .(((int)$p 1) * (int)$n).','.(int)$n;
            }

            
    $result Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sqltruefalse);

            if (!
    $result) {
                return array();
            }
            
    //Если в магазине не так много товаров со скидками и не используются правила цен для груп польз,
            //етот блок IF можно закоментировать (применяется для сортировки по вычисленной цене к выборке из БД)
            
    if ($order_by == 'orderprice') {
                
    Tools::orderbyPriceAndAvailability($result$order_way);
            }

            
    /** Modify SQL result */
            
    return Product::getProductsProperties($id_lang$result);
        }
    }
    Делаем override Tools.php (или добавляем, функции сравнения за скобки класса)

    PHP:
    <?php
    class Tools extends ToolsCore
    {
        
    /*
         * Изменены названия функций сортировки (см Tools::orderbyPrice)
         */
        
    public static function orderbyPriceAndAvailability(&$array$order_way)
        {
            foreach (
    $array as &$row) {
                
    $row['price_tmp'] = Product::getPriceStatic($row['id_product'], true, ((isset($row['id_product_attribute']) && !empty($row['id_product_attribute'])) ? (int)$row['id_product_attribute'] : null), 2);
            }

            unset(
    $row);

            if (
    Tools::strtolower($order_way) == 'desc') {
                
    uasort($array'cmpPriceDescAndAvailability');
            } else {
                
    uasort($array'cmpPriceAscAndAvailability');
            }
            foreach (
    $array as &$row) {
                unset(
    $row['price_tmp']);
            }
        }
    }

    function 
    cmpPriceAscAndAvailability($a$b)
    {
        if (
    $a['qty_as_availability'] == $b['qty_as_availability']) {
            if ((float)
    $a['price_tmp'] < (float)$b['price_tmp']) {
                return -
    1;
            } elseif ((float)
    $a['price_tmp'] > (float)$b['price_tmp']) {
                return 
    1;
            }
            return 
    0;
        }
        return (
    $a['qty_as_availability'] < $b['qty_as_availability']) ? : -1;
    }

    function 
    cmpPriceDescAndAvailability($a$b)
    {
        if (
    $a['qty_as_availability'] == $b['qty_as_availability']) {
            if ((float)
    $a['price_tmp'] < (float)$b['price_tmp']) {
                return 
    1;
            } elseif ((float)
    $a['price_tmp'] > (float)$b['price_tmp']) {
                return -
    1;
            }
            return 
    0;
        }
        return (
    $a['qty_as_availability'] < $b['qty_as_availability']) ? : -1;
    }
    Работает на ps 1.6.1.20
     
    DaoKakao, cepera_007, fortuner и ещё 1-му нравится это.