Какая логика формирование цены на товар в OpenCart и зачем её менять?

Отвечу на первый вопрос…, логика очень простая, к товару вы добавляете различные опции, будь то select (выбор), image (выбор с картинкой), checkbox (флажок), radio (радио кнопка). К каждой опции вы можете добавить её стоимость, например для опции “Комплектация” типа checkbox, я добавил стоимость к каждой опции: 10, 20 и 25 рублей:

option price 1

 

Это означает, если покупатель выберет данную опцию, то к стоимости товара прибавляется стоимость данной опции. В панели адмнистратора, вы можете выбрать вместо “+” знак “-“, тогда при выборе опции от стоимости товара будет отниматься стоимость опции. В интернете существует модули для OpenCart, позволяющие добавить знак “*” и “/”, т.е. результирующая стоимость будет получается путем умножением или делением стоимости товара к стоимости опции.

 

Если есть такие возможности, то зачем что-то менять?

Я тоже так думал, но однажды, выполняя заказ на мебельный интернет-магазин для OpenCart. Заказчик попросил меня сделать следующие: “Я хочу, что-бы у каждого товара, был выбор комплектации, выбор габарита и выбор материала.”

Поясню для наглядности с помощью картинки:

example new option

Синия  стрелка – это выбор габаритов, т.е. опция radio, красная стрелка – это выбор материалов, т.е. опция image и зеленая – это выбор комплектации, т.е. checkbox.

При выборе габаритов устанавливается  стилизованная зеленая галка, при выборе комплектации устанавливается стандартный флажок в квадрат. При выбореОсновной материал” снизу выдвигался каталог материалов, т.е. просто показываются опции image, аналогично при выборе “Материал компаньон”. Все просто и сделать это не трудно, достаточно немного по колдовать с CSS.

Теперь как формируется цена. При выборе габарита, к цене товара прибавлялась надбавка, с этим справляется стандартная логика формирования цены OpenCart, просто указываем напротив каждой опции его стоимость как на первом рисунке. Также и с комплектацией, при выборе “вешалок” и “штанга для вещей” к стоимости товара прибавлялась стоимость данных опций, тут все стандартно и просто.

Проблемы возникли, когда заказчик захотел: “пусть при выборе материалов к стоимости товара прибавляется не каждый а максимальный по стоимости“. Т.е. если пользователь выбрал материал из “Основных материалов” за 200 рублей, а из “Материалов компаньонавыбрал материал за 500 рублей, то к стоимости товара должно прибавится не +700 рублей как обычно,  а +500 рублей (т.е. прибавляется максимальная выбранная опция).

Это стандартный механизм формирование стоимости OpenCart сделать не мог, а заказ нужно было выполнять…

Как бы просто это не казалось, ответ не лежит на поверхности.

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

Как изменить логику формирования стоимости товара?

Стоимость товара формируется в системной файле движка

\system\library\cart.php

За прибавление к стоимости товара стоимость выбранных опций на странице отвечает большой цикл:

 

foreach ($options as $product_option_id => $option_value) {
 ...
 ...
 ...
}

 

 

В нем находятся IF-ы, для каждого типа опций, т.е. для selectimagecheckbox и т.д. В каждом IF-е, есть кусок кода, отвечающий как раз логику формирование цены, т.е. если мы выбрали “+” в настройках опции (см. первый рисунок) то к текущей стоимости прибавится стоимость опции, если минус, то от текущей отнимется:

 

if ($option_value_query->row['price_prefix'] == '+') {
  $option_price += $option_value_query->row['price'];
} elseif ($option_value_query->row['price_prefix'] == '-') {
  $option_price -= $option_value_query->row['price'];
}

 

Вот эту логику можно изменять, для каждого типа опции.

Например для нашего случая, нам нужно изменить логику формирования цены для опций типа “image” (выбор материалов). Нужно сделать так, что-бы цена копилась в неком массиве, а после “большого цикла” foreach добавить к стоимости товара максимум из этого массива.

Реализуется это так, перед “большим циклом”  foreach ($options as $product_option_id => $option_value) { 

добавляем объявление массива и переменную счетчик, т.е должно получится так:

 

$count=0;              /* счетчик индекса массива */
$option_temp= array(); /* массив куда быдем класть стоимость выбранных опций-image (выбранных материалов) */
foreach ($options as $product_option_id => $option_value) {
  ...
  ...
  ...
}

 

А в IF отвечающий за тип image  

if ($option_query->row['type'] == ‘select’ || $option_query->row['type'] == ‘radio’ || $option_query->row['type'] == ‘image’) {

нужно вместо стандартного if-а

написать модернезированный для нашего случая

 

if ($option_value_query->row['price_prefix'] == '+') {
   if($option_query->row['type'] == 'image') { /* если тип image, стоимость выбранных опций кладем в массив */
     $option_temp[$count]=$option_value_query->row['price']; /* кладем в массив стоимость выбранных опций image */
     $count++;                                               /* прибавляем к счетчику */
   } else {
   /* если иной другой тип (т.е. select,radio) то поступаем стандартно, суммируем */
     $option_price += $option_value_query->row['price']; 
   }
} elseif ($option_value_query->row['price_prefix'] == '-') {
  $option_price -= $option_value_query->row['price'];
}

 

 

Добавим после “большого цикла” foreach ($options as $product_option_id => $option_value) {

следующий код:

 

$option_price+=max($option_temp); /* к текущей стоимости прибавляем максимум от выбранных опций - image (материалы) */

 

 

 Что в итоге?

В итоге я показал вам, где мы можем изменять логику формирования стоимости товара. Например как для моего случая, все опции просто прибавляются к стоимости товара как и раньше, кроме image, в нем прибавляется лишь максимальная из выбранных.

К сожалению есть и минусы, измененный системный файл “\system\library\cart.php” при обновление OpenCart скорее всего будут заменены более свежими, поэтому данные изменения придется делать заново. Но для данной CMS это единственный способ.