Как сделать скидки от количества товара?
Всем привет. Возникла необходимость сделать у каждого товара индивидуальные скидки от количества товара и когда покупатель кладет товар в корзинку, то в анонсе корзины он должен видеть уже пересчитанную стоимость товара.
Так же, у него должна быть возможность изменить количество товара в корзинке, когда он уже будет оформлять покупку.
Первое что пришло в голову, это установить MIGX и по средством TV параметра, скажем discount выгружать количество товара и скидок от которых они зависят, вот что получилось:
На странице мы видим вот такой список:
5 шт. — 0%
10 шт. — 5%
30 шт. — 10%
100 шт. — 20%
500 шт. — 30%
Нашёл в сообществе решение и решил на его базе сделать то, что мне нужно. Написать плагин с названием cartProcessing и системными событиями msOnAddToCart, msOnChangeInCart и msOnRemoveFromCart:
Так же, у него должна быть возможность изменить количество товара в корзинке, когда он уже будет оформлять покупку.
Первое что пришло в голову, это установить MIGX и по средством TV параметра, скажем discount выгружать количество товара и скидок от которых они зависят, вот что получилось:
<?php
$dis = $modx->resource->getTVValue('discount');
$a = json_decode($dis, true);
foreach ($a as $discount => $value) {
$count = $value["count"];
$price = $value["price"];
echo '<p>'.$count.' шт. - '.$price.'%</p>';
}
На странице мы видим вот такой список:
5 шт. — 0%
10 шт. — 5%
30 шт. — 10%
100 шт. — 20%
500 шт. — 30%
Нашёл в сообществе решение и решил на его базе сделать то, что мне нужно. Написать плагин с названием cartProcessing и системными событиями msOnAddToCart, msOnChangeInCart и msOnRemoveFromCart:
<?php
switch ($modx->event->name) {
case 'msOnChangeInCart': case 'msOnAddToCart': case 'msOnRemoveFromCart':
$miniShop2 = $modx->getService('minishop2','miniShop2',
MODX_CORE_PATH . 'components/minishop2/model/minishop2/', $scriptProperties);
if (!($miniShop2 instanceof miniShop2)) return '';
// Инициализируем класс в текущий контекст
$miniShop2->initialize($modx->context->key, $scriptProperties);
$total_count = $miniShop2->cart->status()['total_count'];
$tmp = $miniShop2->cart->get();
$dis = $modx->resource->getTVValue('discount');
$a = json_decode($dis, true);
foreach ($a as $discount => $value) {
$count = $value["count"];
$price = $value["price"];
echo '<p>'.$count.' - '.$price.'</p>';
if ($total_count > $count) { // если 5 и более товаров
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$tmp[$key1]['price'] = $price;
}
}
}
else {
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$tmp[$key1]['price'] = $realPrice;
}
}
}
}
$miniShop2->cart->set($tmp);
break;
}
Помогите пожалуйста, не умею я писать плагины из-за того, что не до конца понимаю принцип их работы. Комментарии: 13
$dis = $modx->resource->getTVValue('discount');
Проблема как минимум в этой строчке, т.к. вам нужно получить не тв-поле текущего ресурса, а тв-поле товара.У вас есть как минимум 2 способа реализовать данную задачу — через систему плагинов или через расширение класса корзины.
В обоих случаях принцип работы примерно такой:
— при требуемых событиях (добавление товара, изменение количества, удаление товара и тд) для каждого конкретного товара или циклом во всей корзине получаем параметры товаров
— из полученных данных выбираем id и запрашиваем для каждого товара кастомное тв-поле со списком скидок
— если тв-поле присутствует, то в отсортированным по необходимому для скидки количеству массиве, через цикл сверяем значение с количеством товара в корзине. Так получаем соответствующую скидку по количеству для каждого товара.
— умножаем скидку на исходную цену товара
— возвращаем значение
Сделал через систему плагинов, плагин вот такой получился, по ощущениям всё правильно должно быть, но он не считает почему-то:
<?php
switch ($modx->event->name) {
case 'msOnChangeInCart': case 'msOnAddToCart': case 'msOnRemoveFromCart':
$miniShop2 = $modx->getService('minishop2','miniShop2',
MODX_CORE_PATH . 'components/minishop2/model/minishop2/', $scriptProperties);
if (!($miniShop2 instanceof miniShop2)) return '';
// Инициализируем класс в текущий контекст
$miniShop2->initialize($modx->context->key, $scriptProperties);
$total_count = $miniShop2->cart->status()['total_count'];
$tmp = $miniShop2->cart->get();
if ($total_count > 4) { // если 5 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount1 = $product->get('discount1');
$opt = $realPrice*$discount1/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 9) { // если 10 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount2 = $product->get('discount2');
$opt = $realPrice*$discount2/100;
$optPrice = '';
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 29) { // если 30 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount3 = $product->get('discount3');
$opt = $realPrice*$discount3/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 99) { // если 100 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount4 = $product->get('discount4');
$opt = $realPrice*$discount4/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 499) { // если 500 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount5 = $product->get('discount5');
$opt = $realPrice*$discount5/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
else {
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$tmp[$key1]['price'] = $realPrice;
}
}
}
$miniShop2->cart->set($tmp);
break;
}
Рабочий вариант плагина:
<?php
switch ($modx->event->name) {
case 'msOnChangeInCart': case 'msOnAddToCart': case 'msOnRemoveFromCart':
$miniShop2 = $modx->getService('minishop2','miniShop2',
MODX_CORE_PATH . 'components/minishop2/model/minishop2/', $scriptProperties);
if (!($miniShop2 instanceof miniShop2)) return '';
// Инициализируем класс в текущий контекст
$miniShop2->initialize($modx->context->key, $scriptProperties);
$total_count = $miniShop2->cart->status()['total_count'];
$tmp = $miniShop2->cart->get();
if ($total_count > 499) { // если 5 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount5 = $product->get('discount5');
$opt = $realPrice*$discount5/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 99) { // если 10 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount4 = $product->get('discount4');
$opt = $realPrice*$discount4/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 29) { // если 30 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount3 = $product->get('discount3');
$opt = $realPrice*$discount3/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 9) { // если 100 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount2 = $product->get('discount2');
$opt = $realPrice*$discount2/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
elseif ($total_count > 4) { // если 500 и более товаров - оптовые цены, в интернет-магазине оптовые цены забиваются в поле article
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$discount1 = $product->get('discount1');
$opt = $realPrice*$discount1/100;
$optPrice = $realPrice-$opt;
$tmp[$key1]['price'] = $optPrice;
}
}
}
else {
foreach ($tmp as $key1 => $value) {
if ($product = $modx->getObject('msProduct', $value['id'])) {
$realPrice = $product->get('price');
$tmp[$key1]['price'] = $realPrice;
}
}
}
$miniShop2->cart->set($tmp);
break;
}
Осталось теперь придумать как это всё менять на лету, на странице с товаром и в корзине при оформлении заказа, может кто-нибудь в курсе как дописать этот скрипт, чтобы считалось всё на лету?<script type="text/javascript">
$('#msCart input[name="count"]').change(function(){
var count = $(this).val();
var singlePrice = parseInt($(this).closest('.tab_row').children(".tab_sum").text());
$(this).closest('.tab_row').children(".tab_pr").children("span").html(count * singlePrice);
});
</script>
что бы отображаемая цена менялась?
Было бы очень не плохо.
я на странице товара js'ом меняю, а в корзине сделал событие которое при изменении количества подгружает ajax'ом обновленную div с корзиной с другой страницы.
Есть еще такой вариант modx.pro/solutions/3942-dynamic-update-of-the-basic-basket/
но он у меня не пошел, все время что-то отваливается и работает не так.
Есть еще такой вариант modx.pro/solutions/3942-dynamic-update-of-the-basic-basket/
но он у меня не пошел, все время что-то отваливается и работает не так.
Артём а можете подсказать, как вы реализовали динамическую смену цены в корзине. И ещё вопрос как можно делать скидку именно для определённой категории
Этот плагин ещё работает?
У меня плагин ругается при попытке инициализации класса:
В файле minishop2.class.php на этих строчках регистрация клиентского скрипта:
И понятное дело плагин не срабатывает как задумывалось. В чём может быть проблема? Или minishop2 с тех пор настолько изменился что конфликтует?
У меня плагин ругается при попытке инициализации класса:
[2017-03-31 11:34:26] (ERROR @ /home/s7102/www/core/components/minishop2/model/minishop2/minishop2.class.php : 95) Recoverable error: Object of class msCartHandler could not be converted to string
[2017-03-31 11:34:26] (ERROR @ /home/s7102/www/core/components/minishop2/model/minishop2/minishop2.class.php : 104) Recoverable error: Object of class msCartHandler could not be converted to string
В файле minishop2.class.php на этих строчках регистрация клиентского скрипта:
$this->modx->regClientCSS(str_replace($config['pl'], $config['vl'], $css)); // 95 строчка
$this->modx->regClientScript(str_replace($config['pl'], $config['vl'], $js)); // 104 строчка
И понятное дело плагин не срабатывает как задумывалось. В чём может быть проблема? Или minishop2 с тех пор настолько изменился что конфликтует?
Ругается именно на эту строчку в плагине:
$miniShop2->initialize($modx->context->key, $scriptProperties);
уже есть компонент для этого дела: modstore.pro/packages/ecommerce/mssaleprice
Неа, не подходит. У меня своя логика формирования цены должна быть, и она зависит от веса (weight), а не от количества.
Если в коротко, то при достижении например 400 грамм суммарно для всех товаров в корзине должна применяться для всех них скидка в 20% например.
Этот плагин идеально подходил бы к моей задаче, если бы не плевался в логи…
Если в коротко, то при достижении например 400 грамм суммарно для всех товаров в корзине должна применяться для всех них скидка в 20% например.
Этот плагин идеально подходил бы к моей задаче, если бы не плевался в логи…
Ответ в чём была проблема был найден тут.
Уже обсуждали, и не один раз:
modx.pro/work/3953-the-price-of-the-goods-depending-on-the-number/
modx.pro/help/987/
modx.pro/help/3200/
Думаю, можно найти еще.
modx.pro/work/3953-the-price-of-the-goods-depending-on-the-number/
modx.pro/help/987/
modx.pro/help/3200/
Думаю, можно найти еще.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.