1 Отредактировано Ярослав (15.03.2015 21:25:13)

Тема: Скидка от суммы и подытога корзины

Заказчик дал следующее ТЗ:
"Здравствуйте! Необходимо реализовать смену типа цены товаров и пересчет суммы корзины для текущей сессии аналогично sotomore.ru
1. Тип цены текущего пользователя зависит от подытога текущей корзины.
Например:
0-10 000 = тип цены розничная с ID=2
10001-50000 = тип цены опт1 с ID=3
50001-100000 = тип цены опт2 с ID=23"

Немного изменил cost.api, чтобы тип цены по-умолчанию брался из сессии.

Далее написал обработчик события:

<?php

namespace Opt\Config;

class Handlers extends \RS\Event\HandlerAbstract
{
    function init()
    {
        $this->bind('cart.addproduct.after1')
            ->bind('cart.update.after');
    }    
    
   public static function checkprice($info)
    {
         //\Catalog\Model\CostApi::setSessionDefaultCost(2); 
          if (!$_SESSION['user_cost_id']) {
                $_SESSION['user_default_cost_id']=\Catalog\Model\CostApi::getDefaultCostId();
                $cost_id=\Catalog\Model\CostApi::getDefaultCostId() ;
         }  
           else   $cost_id=$_SESSION['user_cost_id'];
                                                    
         $cart=$info['cart'];      
         $cartinfo = $cart->getCartData(false,false);
         flog($cost_id);    //вывод в консоль firebug                          
         flog( $cartinfo['total']);   
          
         if ((  $cartinfo['total']<50000) &&( $cost_id!=1)) 
         {       
             flog('yes');
             $_SESSION['user_cost_id']=1;  
             //здесь необходимо обновить корзину            
             
        }
         elseif ((  $cartinfo['total']>=50000)&&( $cost_id!=2)) 
         {       
              flog('yes2');
              $_SESSION['user_cost_id']=2; 
              //здесь необходимо обновить корзину   
            
         };
 
     return $info;    
    }
  public static function cartUpdateAfter ($info)
    {  
    
       $result=self::checkprice($info);           
       return $result;     
           
    }
      
                           
   public static function cartAddproductAfter ($info)
    {  
           $result=self::checkprice($info);           
          return $result;
    }
    
}

====

но не ясно как перерасчитать корзину после смены ID типа цены в сессии $_SESSION['user_cost_id'] .

Пробовал разные методы модели корзины, но  итог меняется только при следующем изменении корзины.

Например:
Товар с ценой 1=12000 и ценой2 = 10000. Цена1 меняется на цену2 после 50 000 руб.
при количестве 4 в корзине Итог= 48 000 руб
при количестве 5 в корзине Итог= 60 000 руб (меняется тип цены=цена2=10000)
при количестве 6 в корзине Итог= 60 000 руб
уменьшаем
при количестве 5 в корзине Итог= 50 000 руб
при количестве 4 в корзине Итог= 40 000 руб(тип цены меняется цена=цена1=12000)


Подскажите, пожалуйста, как же пересчитать элементы корзины и итог при изменении типа цены?

p.s. Так же не хватает событий на удаление из корзины в стандартной поставке.

2

Re: Скидка от суммы и подытога корзины

Внутри объекта товара $product - сохраняется идентификатор цены cost_id в поле _current_cost_id.
Именно закешированное значение _current_cost_id используется при вызове метода получения цены у товара $product->getCost(null), без явного указания id цены. Необходимо подменить значение _current_cost_id в кэш-поле товара.

Попробуйте выполнить следующий код для пересчета -

//Заменим закешированный _current_cost_id у объекта товара
foreach($cart->getProductItems() as $cartdata) {
    $cartdata['product']['_current_cost_id'] = ID новой цены;
}

//Очистим сведения для блока корзины
$cart->cleanInfoCache();

Насчет события для удаления элемента из корзины. Добавим в ближайшем обновлении.
Функция removeItem($uniq) будет выглядеть так: (можете заменить её прямо в файле cart.inc.php)

    function removeItem($uniq)
    {
        $eresult = \RS\Event\Manager::fire('cart.removeitem.before', array(
            'cart' => $this,
            'uniq' => $uniq
        ));    
        if ($eresult->getEvent()->isStopped()) return false;
                
        if (isset($this->items[$uniq])) {
            if ($this->mode == self::MODE_SESSION) {
                \RS\Orm\Request::make()
                    ->delete()
                    ->from($this->cartitem)
                    ->where($this->select_expression)
                    ->where(array(
                        'uniq' => $uniq
                    ))->exec();
            }
            
            $deleted_item = $this->items[$uniq];
            unset($this->items[$uniq]);
            unset($this->order_items[$uniq]);
            unset($this->cache_products[$uniq]);
            unset($this->cache_coupons[$uniq]);

            \RS\Event\Manager::fire('cart.removeitem.after', array(
                'cart' => $this,
                'uniq' => $uniq,
                'item' => $deleted_item
            ));            
        }
        return true;
    }

Повысить оценку Понизить оценку

Re: Скидка от суммы и подытога корзины

Спасибо большое! Заработало как надо!

А есть ли возможность принудительно устанавливать текущий CostId без модификации costapi?
Это метод \Catalog\Model\CostApi::setSessionDefaultCost()?

4

Re: Скидка от суммы и подытога корзины

Да, если у пользователя в настройках установлен - тип цен: "по-умолчанию",
то можно воспользоваться этим методом - \Catalog\Model\CostApi::setSessionDefaultCost()

Повысить оценку Понизить оценку

Re: Скидка от суммы и подытога корзины

Пользователь должен быть авторизирован или это для текущей сессии любого пользователя?

6

Re: Скидка от суммы и подытога корзины

Если пользователь не авторизован, то у него всегда - тип цен "по-умолчанию".
Т.е. это будет работать и для не авторизованных.

Повысить оценку Понизить оценку

7

Re: Скидка от суммы и подытога корзины

Я не учел, что вы выставляете тип цен только во время события - cart.addproduct.
Вам тогда нужно в обработчике события cart.addproduct писать цену пользователя в $_SESSION['КАКАЯ_НИБУДЬ_ПЕРЕМЕННАЯ']

А потом сделать еще один обработчик события start и уже в нем вызывать:

if (  $_SESSION['КАКАЯ_НИБУДЬ_ПЕРЕМЕННАЯ'] ) {
\Catalog\Model\CostApi::setSessionDefaultCost( $_SESSION['КАКАЯ_НИБУДЬ_ПЕРЕМЕННАЯ'] );
}

------

\Catalog\Model\CostApi::setSessionDefaultCost() - устанавливает текущую цену на одну сессию выполнения PHP (не путать с SESSION).  Т.е. её нужно вызывать её каждый раз.

Повысить оценку Понизить оценку

Re: Скидка от суммы и подытога корзины

Благодарю за помощь!
После OpenCart одно удовольствие расширять систему. Никаких VQMod