[Решено] Запрет заказывать больше чем есть в наличии

Тема в разделе "OpenCart", создана пользователем skiv14, 9 янв 2016.

  1. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    1.5.5.2 ocstore на манимэйкере

    Очередной вопрос, на который не нашёл ответа.
    Состоит из 2 частей.

    Допустим, у нас есть товар мячик в количестве 1 штука.

    1) при нажатии на заказать в корзину летит 1 единица товара. Если нажать на кнопку купить ещё раз, то в корзине уже будет 2 мячика и т.д. до бесконечности. А у нас только 1 мячик в наличии.

    2) если выбрать в карточке товара 10 мячиков и нажать на купить, то все 10 мячиков окажутся в корзине. А у нас только один.

    В обоих случаях в корзине появится ошибка с ***, которая не даёт понять сколько же мячиков по максимуму можно заказать. Покупателю остаётся уменьшать и уменьшать количество пока не дойдёт до нужного числа мячиков.
    Это совсем не юзер френдли (простите за похабные слова).

    Говорят, что в джумле такой проблемы нету. А как у нас решается ?
     
    Последнее редактирование: 9 янв 2016
  2. MGT1

    MGT1

    Регистрация:
    5 янв 2013
    Сообщения:
    900
    Симпатии:
    218
    Настройки-Опции
    МАГАЗИН
    Показывать остаток на складе:
    Показывать остаток товаров на складе на странице товара.
     
    Lasted edited by : 9 янв 2016
  3. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    MGT1, не поможет. Суть вопроса в том, чтоб не дать положить в корзину больше. чем есть на складе, а не чтоб покупатель увидел сколько на складе и сам не положил в корзину ещё единицу.

    Надо в корзине при добавлении товара делать проверку остатка и дальше либо добавлять в корзину, либо что-то сообщать покупателю о нехватке и невозможности добавить в корзину ещё.
    skiv14, какая версия/сборка?

    P.S. @MGT1, следи за стилями при копировании откуда-то, здесь слепых нет (но есть правило про увеличенный шрифт).
     
    skiv14 нравится это.
  4. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    MGT1, в карточке остаток показывается и в корзине самой срабатывает ошибка заказа если на остатке меньше чем заказывают.
    Но гораздо лучше если это дело пресекать ещё при заказе в карточке товара.

    Dotrox, не указал версию cms, т.к. ни для одной не нашёл решения. А если мне подскажут хотя бы для какой версии - дальше буду пробовать прикрутить к своей или найти аналог.
    1.5.5.2 ocstore на манимэйкере.

    Надо ещё до корзины, ещё в карточке товара при клике на купить проверять остатки и выводить подсказку, что товара всего "1" и заказать больше "1" нельзя.
    Модулем бы конечно найти, может кто сталкивался с таким.
     
  5. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Ну, так моё решение будет для конкретной, а не для любой.

    Я говорил не о странице корзины, а о классе корзины, который обрабатывает добавление в корзину.
    Но есть маленький нюанс, который всё очень усложняет - остаток в базе включает и то, что уже есть в корзине (оно не вычитается со склада до завершения оформления заказа).

    Итак, файл /system/library/cart.php, добавляем это:
    PHP:
    public function checkStock($product_id$qty){
       
    $canAdd true;
       
    $cartProducts $this->getProducts();

       if(!empty(
    $cartProducts)){
         
    $products_ids = array();

         foreach (
    $cartProducts as $pData) {
           if(isset(
    $products_ids[$pData['product_id']])){
             
    $products_ids[$pData['product_id']]++;
           } else {
             
    $products_ids[$pData['product_id']] = 1;
           }
         }

         foreach (
    $products_ids as $p_id => $count) {
           if(
    $product_id == $p_id){
             
    $stock $this->db->query("SELECT quantity FROM " DB_PREFIX "product p
               WHERE p.product_id = '" 
    . (int)$product_id "'
               AND p.date_available <= NOW() AND p.status = '1'"
    )->row();

             if(
    $stock $count $qty <= 0){
               
    $canAdd false;
             }

             break;
           }
         }
       }

       return 
    $canAdd;
    }
    Файл /catalog/controller/checkout/cart.php, метод add, перед
    PHP:
    if (!$json) {
                    
    $this->cart->add($this->request->post['product_id'], $quantity$option);
    Добавляем это:
    PHP:
    $canAdd $this->cart->checkStock($this->request->post['product_id'], $quantity);
    if(!
    $canAdd){
        
    $json['error']['stock'] = 'Error message';
    }
    А дальше просто выводим сообщение из $json['error']['stock'] через js в функции добавления товара в корзину (это будет раздельно в common.js и на странице товара + зависит от шаблона).

    P.S. Это решение учитывает, что один товар может быть в корзине несколько раз из-за разных выбранных опций. Все такие товары просуммируются перед рассчётом остатка.
     
    skiv14 нравится это.
  6. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    Заценил.

    Работает, но не как задумано, причём и на установленном шаблоне и на стандартном.

    Работает так:
    - даёт добавить в корзину сколько угодно единиц товара, т.е. по теме проблемы не решилось
    - если закинул в корзину хотя бы 1 единицу товара, то кнопка становится неактивной. Даже если на остатке ещё 100 штук лежат. Кнопка неактивна ни с карточки товара ни с категорий, ни с доп.модулей
    - другой товар даёт добавлять в корзину, но тоже только один раз. Т.е. работает функция проверки на аналогичность товара, который уже лежит в корзине
    - с опциями не тестил

    Да, вопрос кажущийся простым, а на деле...

    @Dotrox, в любом случае спасибо.
     
  7. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Судя по этой ошибке, проблема на стороне js. Мой код никак не влияет и не может влиять на кнопки. Он должен работать так: покупатель кликает на кнопку купить, а дальше товар либо добавляется в корзину, либо выдаётся сообщение, что остаток на складе недостаточен (за эту часть отвечает js, который я не приводил). Сама кнопка при этом активна даже если товара изначально было 0 (при условии, что используется дефолтный ОК без каких-либо модулей, которые что-то делают с кнопкой).

    Дай адрес сайта.
     
    skiv14 нравится это.
  8. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    Готово.

    То о чём я писал также работает. 1 раз добавляешь, второй раз не даёт.
     
    Последнее редактирование: 11 янв 2016
  9. MGT1

    MGT1

    Регистрация:
    5 янв 2013
    Сообщения:
    900
    Симпатии:
    218
    наличие 6 - купил без проблем 7?

    ТОчнее добавил в корзину 7
     
    Lasted edited by : 11 янв 2016
    skiv14 нравится это.
  10. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    При втором добавлении - ошибка 500, потому и не добавляется.
    Сделай это: https://wmasteru.org/threads/Настройки-оптимизации-фичи-статьи-для-opencart.2219/page-7#post-151032

    А потом смотри журнал ошибок.

    Я ж этот код из головы писал и не тестировал, там, конечно, могут быть какие-то ошибки, которые нужно отловить.
     
    skiv14 нравится это.
  11. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    @MGT1, я писал об этом. Нужно не давать купить больше чем есть в наличии.
    А сейчас сработало так, что если покупаешь хоть сколько, то второй раз не купишь нисколько. Кнопка перестаёт быть активной.

    Dotrox, сделал, сейчас гляну ошибки.
     
  12. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    А вот это уже логическая недоработка. Я не учёл, что в пустую корзину могут сразу добавить больше, чем есть на складе. Сейчас допишу.
     
    skiv14 нравится это.
  13. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    Я про это писал
    Но так изначально и было, от этого и нужно уйти.

    Кстати, если получится, сделай модуль, сможешь на продажу выставить без проблем. Это реально полезная штука.

    Ошибка
    2016-01-11 1:21:49 - PHP Fatal Error: Call to undefined method stdClass::row() in /public_html/vqmod/vqcache/vq2-system_library_cart.php on line 576

    Там
    AND p.date_available <= NOW() AND p.status = '1'")->row();

    Этих ошибок куча, все с таким текстом. Появляются как раз когда кликаешь по неактивной кнопке "Купить".
     
    Последнее редактирование: 11 янв 2016
  14. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Ошибка примитивнейшая. Вот, что бывает, когда начинаешь писать код на автомате - там просто скобки лишние, ибо row это не метод, а поле.

    Обнови метод checkStock:
    PHP:
    public function checkStock($product_id$qty){
        
    $canAdd true;
        
    $count 0;
        
    $cartProducts $this->getProducts();
      
        if(!empty(
    $cartProducts)){
            
    $products_ids = array();

            foreach (
    $cartProducts as $pData) {
                if(isset(
    $products_ids[$pData['product_id']])){
                    
    $products_ids[$pData['product_id']]++;
                } else {
                    
    $products_ids[$pData['product_id']] = 1;
                }
            }

            if(isset(
    $products_ids[$product_id])){
                
    $count $products_ids[$product_id];
            }
        }

        
    $stock $this->db->query("SELECT quantity FROM " DB_PREFIX "product p
                        WHERE p.product_id = '" 
    . (int)$product_id "'
                        AND p.date_available <= NOW() AND p.status = '1'"
    )->row;

        if(
    $stock $count $qty <= 0){
            
    $canAdd false;
        }

        return 
    $canAdd;
    }
    Здесь и эта ошибка исправлена и проблема с добавлением в корзину сразу большего количества, чем есть на складе.

    Я принципиально не использую vQmod, а здесь без него не обойтись, если оформлять в виде модуля.
     
    Lasted edited by : 11 янв 2016
    skiv14 нравится это.
  15. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    Сделал.

    Теперь не даёт добавить в корзину вообще. Кнопка купить неактивна.

    Ошибка другая
    2016-01-11 1:52:41 - PHP Fatal Error: Unsupported operand types in vqmod/vqcache/vq2-system_library_cart.php on line 584

    Там
    if($stock - $count - $qty <= 0){

    Почитал, пишут, что несовместимые переменные.
     
    Последнее редактирование: 11 янв 2016
  16. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Вот окончательный вариант:
    PHP:
    public function checkStock($product_id$qty){
        
    $canAdd true;
        
    $count 0;
        
    $cartProducts $this->getProducts();
       
        if(!empty(
    $cartProducts)){
            
    $products_ids = array();

            foreach (
    $cartProducts as $pData) {
                if(isset(
    $products_ids[$pData['product_id']])){
                    
    $products_ids[$pData['product_id']] += (int)$pData['quantity'];
                } else {
                    
    $products_ids[$pData['product_id']] = (int)$pData['quantity'];
                }
            }

            if(isset(
    $products_ids[$product_id])){
                
    $count $products_ids[$product_id];
            }
        }

        
    $stock $this->db->query("SELECT quantity FROM " DB_PREFIX "product p
                        WHERE p.product_id = '" 
    . (int)$product_id "'
                        AND p.date_available <= NOW() AND p.status = '1'"
    )->row;

        if(
    $stock['quantity'] - $count $qty 0){
            
    $canAdd false;
        }

        return 
    $canAdd;
    }
    Вроде, уже всё учёл.
     
    skiv14 нравится это.
  17. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    Сделал.

    Ты только отпиши если правок не будет ))))

    Вроде всё чётко
     
  18. Dotrox

    Dotrox Команда форума

    Регистрация:
    27 ноя 2012
    Сообщения:
    3.198
    Симпатии:
    1.306
    Да, на сервере всё работает, как надо. Но надо ж ещё для покупателя сообщение выводить, а то оно просто не добавляется, будто это баг.
     
    skiv14 нравится это.
  19. skiv14

    skiv14

    Регистрация:
    9 июн 2015
    Сообщения:
    437
    Симпатии:
    180
    Dotrox, это я сам попробую решить, мне стыдно, что ты для меня столько работы проводишь. Спасибо тебе :Smile:
    Если будешь удалять последние посты, скопируй, плиз, верный код в свой первый пост. Может ещё кому пригодится.

    Пойду спать, а то завтра на работу. Начальство не поймёт если я через 6 часов не встану )) Давай, удачи :Smile:

    ps без уведомления покупателя гораздо лучше чем давать ему ошибочно заказывать, а потом разбираться в корзине что к чему.
     
  20. Krikona

    Krikona

    Регистрация:
    31 мар 2017
    Сообщения:
    3
    Симпатии:
    0
    Всё сделала по вашим инструкциям и просто великолепно работает. Спасибо огромное! :Good: Хотелось бы еще сообщение об ошибке выводить, самой не получилось сделать толково, если сможете, то сообщите, пожалуйста, как вывести значение $json['error']['stock'] на странице товара.