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

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


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

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

Спасибо
 
Для этого нужно наследовать модель Category, и переписать под себя метод getProducts()
 
Есть у кого-то готовое решение для 1.6 + Warehouse + AS4 ? Нужно товары с 0 остатком отправлять в конец при любом виде сортировке.
 
  • Заблокирован
  • #49
а подскажите как сделать чтобы по unit price была сортировка (сначала те что дешевле). + стоит adv search.

спасибо
 
Одно из решений, если надо выводить товары с 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 = true, Context $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($sql, true, false);

        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 : -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 : -1;
}

Работает на ps 1.6.1.20
 
Назад
Сверху