miniShop2 - скидка или наценка к сумме заказа

Добрый день!

Такой вопрос… нужно реализовать логику: наценка 5%, если в корзине 1 или 2 товара, скидка 2%, если в корзине 8 товаров или больше. Как это делать?

Пока идея: переопределить msCartHandler, в методе get реализовать мою логику:

public function get() {
	$cart['skidka'] = array('id' => 'skidka', 'price' => -100, 'weight' => 0, 'options' ),
	return $this->cart;
}

… но… есть еще

public function status($data = array()) {

… окей, и там можно реализовать эту логику. И еще немного надо будет поправить js файлы, хорошо… хотя уже что-то много правок намечается… я верно пытаюсь сделать? или нужно по другому реализовывать? Василий, как бы ты поступил? Общие мысли интересуют, реализовать — справлюсь :)

Естественно, мне нужно, что бы все заработало и в маленькой корзине в шапке сайта, и в большой корзине.
Наумов Алексей
05 мая 2014, 13:58
modx.pro
10
4 668
0

Комментарии: 17

Алексей Ерохин
24 июля 2014, 17:40
0
Простите, а Вы добились чего-нибудь в этом направлении?
    Наумов Алексей
    25 июля 2014, 09:37
    1
    +2
    Да, сделал!

    1. Переопределяем msCartHahdler. В частности функцию status:
    public function status($data = array()) {
            $status = parent::status($data);
    
            // margin && discount
            $status['margin'] = $this->getCartMargin();
            $status['discount'] = $this->getCartDiscount();
            $status['total_cost'] = $this->calcTotalCostEx($status['total_cost'], $status['margin'], $status['discount']);
    
            return $status;
        }
    
    public function calcTotalCostEx($total_cost, $margin, $discount){
            $result = $total_cost;
            if(!empty($margin)){
                $result = $total_cost + $margin;
            }
            if(!empty($discount)){
                $result = $total_cost - $discount;
            }
            return $result;
        }
    getCartMargin, getCartDiscount — считайте скидку и наценку как хотите в них, для этого у вас есть $this->cart — корзина с товарами.

    2. Копируем файл minishop2.js, указываем в настройках новый путь к нему, добавляем логику:

    2.1 Метод miniShop2.Cart… setup
    miniShop2.Cart.margin = '.ms2_margin';
    miniShop2.Cart.discount = '.ms2_discount';
    2.2. Метод status:
    if(status['margin'] > 0){
                        $(miniShop2.Cart.margin).show();
                        $(miniShop2.Cart.margin + ' .ms2_margin_price').text(status['margin']);
                    }
                    else{
                        $(miniShop2.Cart.margin).hide();
                    }
                    if(status['discount'] > 0){
                        $(miniShop2.Cart.discount).show();
                        $(miniShop2.Cart.discount + ' .ms2_discount_price').text(status['discount']);
                    }
                    else{
                        $(miniShop2.Cart.discount).hide();
                    }
    3. Ну и добавляем в чанк cart.Outer строчки с наценкой и скидкой:
    <div class="ms2_discount">Скидка: <span class="ms2_discount_price"></span></div>
    
    <div class="ms2_margin">Наценка: <span class="ms2_margin_price"></span></div>
      Алексей Ерохин
      25 июля 2014, 11:29
      1
      0
      Спасибо.
        Алексей Ерохин
        25 июля 2014, 13:28
        0
        Подскажите, возможно я что-то упускаю.
        При загрузке страницы корзины значения скидки/наценки не проставляются, только после каких-либо изменений в корзине.
        Что нужно сделать, чтоб они показывались сразу после обновления страницы,
          Наумов Алексей
          25 июля 2014, 13:39
          0
          А, немного упустил этот момент, писал по памяти.

          Пункт 3 из моего комментария переделываем:
          <div class="ms2_discount [[+hide_discount]]">Скидка: <span class="ms2_discount_price">[[+discount]]</span></div>
          <div class="ms2_margin [[+hide_margin]]">Наценка: <span class="ms2_margin_price">[[+margin]]</span></div>
          
          а в конце чанка еще и так:
          <!--minishop2_hide_margin style="display:none;"-->
          <!--minishop2_hide_discount style="display:none;"-->
          Сниппет msCart копируем в msCartEx и вызываем на странице его.
          в нем (в конце, после цикла foreach ($cart as $k => $v) ) добавляем примерно это:
          $outer['hide_margin'] = !$outer['margin'] = $miniShop2->cart->getCartMargin();
          $outer['hide_discount'] = !$outer['discount'] = $miniShop2->cart->getCartDiscount();
          $outer['total_cost'] = $miniShop2->cart->calcTotalCostEx($outer['total_cost'], $outer['margin'], $outer['discount']);
          Вообще вещь индивидуальная для каждого сайта, поэтому подгоняйте для себя.

          т.е. тут у нас 2 действия:
          1. проставляем margin и discount
          2. скрываем или показываем строчку со скидкой.
        Купчинский Михаил
        08 апреля 2015, 18:33
        0
        Алексей, подскажите а как может быть реализована скидка в 15% при достижении 3 товаров в корзине, по Вашему способу. Что-то уже всю голову сломал). Пытаюсь сам переопределить класс корзины
          Наумов Алексей
          09 апреля 2015, 08:52
          0
          Ну в принципе в комментарии все написано. Переопределите класс и выведите в нем $this->cart, посмотрите, что там внтури, 3 товара найдете и в зависимости от этого условие делайте свое.
            Купчинский Михаил
            09 апреля 2015, 09:41
            0
            Правильно ли я понимаю, что должно быть написано, что-то типа этого?

            // margin && discount
                    $status['margin'] = $this->getCartMargin();
                    $status['discount'] = $this->getCartDiscount({
            		$cart = $this->ms2->cart->status();
            		$count = $with_cart
            			? $cart['total_count']
            			: 0;
            			$total_cost = $cart['total_cost'];
            
            		        if($count > 2 ) {
            
                        			$total_cost =  $cart['total_cost'] * 0.85;
                    		}
                                    else {
            			return $total_cost;
                                    }
            );
                    $status['total_cost'] = $this->calcTotalCostEx($status['total_cost'], $status['margin'], $status['discount']);
            
                    return $status;
            Увы я не силен в программировании. И такая простая вещь иногда ставит в тупик)

            PS Попробовал — такая конструкция дает ошибку
              Наумов Алексей
              09 апреля 2015, 09:50
              1
              +1
              Даю полный код своей расширенной корзины:

              <?php
              class myCartHandler extends msCartHandler{
              
                  private $marginPercent = 5.0;
                  private $discountPercent = 2.0;
              
                  public function getMarginPercent(){
                      return $this->marginPercent;
                  }
                  public function getDiscountPercent(){
                      return $this->discountPercent;
                  }
              
                  /* @inheritdoc} */
                  public function status($data = array()) {
                      $status = parent::status($data);
              
                      // margin && discount
                      $status['margin'] = $this->getCartMargin();
                      $status['discount'] = $this->getCartDiscount();
                      //$status['total_cost_ex'] = $this->calcTotalCostEx($status['total_cost'], $status['margin'], $status['discount']);
                      $status['total_cost'] = $this->calcTotalCostEx($status['total_cost'], $status['margin'], $status['discount']);
              
                      return $status;
                  }
              
                  public function calcTotalCostEx($total_cost, $margin, $discount){
                      $result = $total_cost;
                      if(!empty($margin)){
                          //$result = $this->roundCost($total_cost + $margin);
                          $result = $total_cost + $margin;
                      }
                      if(!empty($discount)){
                          //$result = $this->roundCost($total_cost - $discount);
                          $result = $total_cost - $discount;
                      }
                      return $result;
                  }
              
                  public function getCartMargin(){
                      $count = 0;
                      $totalCount = 0;
                      $totalCost = 0;
                      $tmpPrice = 0;
                      foreach ($this->cart as $item) {
                          if (empty($item['ctx']) || $item['ctx'] == $this->modx->context->key){
                              $count++;
                              $totalCount += $item['count'];
                              $tmpPrice = $item['price'];
                              $totalCost += $item['price'] * $item['count'];
                          }
                      }
              
                      // наценка, если в корзине 1 товарная позиция, с кол-вом 2 шт и ценой менее 4000 рублей
                      if($count == 1 && $totalCount <= 2 && $tmpPrice < 4000){
                          return $this->roundCost($totalCost * ($this->marginPercent / 100.0));
                      }
                      return 0;
                  }
              
                  public function getCartDiscount(){
                      $countSet = 0;
                      $totalCost = 0;
                      foreach ($this->cart as $item) {
                          if (empty($item['ctx']) || $item['ctx'] == $this->modx->context->key){
                              if($item['count'] >= 4){
                                  $countSet ++;
                              }
                              $totalCost += $item['price'] * $item['count'];
                          }
                      }
              
                      // скидка, если в корзине 2 комплекта
                      if($countSet >= 2){
                          return $this->roundCost($totalCost * ($this->discountPercent / 100.0));
                      }
                      return 0;
                  }
              
                  public function roundCost($cost){
                      return round($cost / 50) * 50;
                  }
              }
              Она делает скидку 2%, если в корзине есть как минимум 2 разных товара по 4 штуки (это магазин шин и дисков, т.е. имеется ввиду что в корзине минимум 2 набора по 4 колеса или диска). Так е есть наценка 5% если в корзине всего 1 товарная позиция с кол-вом меньшим или раным 2 штук (например 1 или 2 покрышки) и общей суммой заказа меньше 4 тысяч рублей…

              + тут еще есть округление скидки или наценки до 50 рублей функцией roundCost
                Купчинский Михаил
                09 апреля 2015, 09:59
                0
                Спасибо! Попробую разобраться.
                  Купчинский Михаил
                  09 апреля 2015, 12:12
                  0
                  Спасибо Алексей, с корзиной все получилось. И с правкой скриптового файла тоже.
                  Единственное — встал вопрос, как эту скидку указать в письме, отправляемом клиенту?
                  Или изменить цену товара на цену со скидкой.
                  А то получается вот такая картина joxi.ru/YmEkaaytapoBA6
                  Три товара по 570 руб. стоят 1460 руб. вместо 1710 руб.
                    Наумов Алексей
                    09 апреля 2015, 13:54
                    0
                    Я брал сниппет msOrder, который получает заказ, делал его копию, в нем получал эту скидку и в чанках во всех выводил ее… точнее сейчас сказать уже не смогу
                      Купчинский Михаил
                      09 апреля 2015, 14:19
                      0
                      Ну вроде я тоже попытался так сделать:
                      Судя по вызову в чанке tpl.msOrder.success сниппета [[!msGetOrder?id=`[[+id]]`]], в нем и надо делать правки.
                      Попробовал добавить в нем:
                      $outer['hide_margin'] = !$outer['margin'] = $miniShop2->cart->getCartMargin();
                      $outer['hide_discount'] = !$outer['discount'] = $miniShop2->cart->getCartDiscount();
                      $outer['total_cost'] = $miniShop2->cart->calcTotalCostEx($outer['total_cost'], $outer['margin'], $outer['discount']);
                      Но результата не добился)

                      а в скриптовом файле не надо правки вносить?
                        Наумов Алексей
                        09 апреля 2015, 14:29
                        0
                        Отвлекаете меня прям)
                        но раз взялся помочь, залез и дальше.

                        Алгоритм следующий:

                        1. Делаем копию сниппета msGetOrder, что бы при обновлении все не затерлось
                        2. В этом сниппете есть цикл
                        foreach ($rows as $row) {
                        в котором мы «пробегаемся» по покупкам.

                        Так давайте посчитаем в цикле стоимость покупок:
                        $rowsCost += $row['cost'];
                        3. И еще у нас есть $outer['cart_cost'], она где то в вверху сниппета фигурирует — это стоимость корзины.

                        Так вот, если была скидка или наценка, то стоимость покупок и стоимость корзины не совпадают)) Значит можно и посчитать скидку или наценку простым вычитанием. При этом вызывать $miniShop2->cart->getCartMargin(); не нужно из этого снипеета!
                          Купчинский Михаил
                          09 апреля 2015, 21:11
                          0
                          Алексей, простите что отвлек) Ведь когда задаешь вопрос, не знаешь занят человек или нет)
                          Сейчас пробую реализовать по этой инструкции.

                          Вроде все понятно, но получаю какие-то результаты не те.
                          Добавил $rowsCost += $row['cost']; в блок с foreach ($rows as $row) {.
                          Ниже цикла, перед конструкцией:
                          if (empty($tplOuter)) {
                          	$modx->toPlaceholders($outer);
                          }
                          Пытаюсь вставить код:
                          $outer['discount'] = $rowsCost - $outer['cart_cost'];
                          Результат получается сумма всех товаров -1. (1709 руб.)
                          Причем если вывожу так:
                          $outer['discount'] = $rowsCost
                          То выводится правильная сумма всех товаров без скидки. (1710 руб.)
                          Если вывожу вот так:
                          $outer['discount'] =  $outer['cart_cost'];
                          То выводится стоимость корзины (сумма товаров со скидкой 1460 руб.)

                          Не могу въехать почему не работает конструкция $rowsCost — $outer['cart_cost'];

                          Купчинский Михаил
                          09 апреля 2015, 23:09
                          0
                          Вроде разобрался! Проблема была с $miniShop2->formatPrice()
                          Алексей, спасибо большое за помощь!
      Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
      17