Вывод модификаций msOptionsPrice2 в окне заказа minishop2, при добавлении товара.
Всем привет, столкнулся с задачей сделать выбор модификаций компонента msOptionsPrice2, при добавлении товара в заказ минишопа, в админке. Корректность моего кода не гарантирую, поэтому, если будут какие-то замечания или советы буду только рад. За помощь в некоторых моментах, спасибо Павлу Зарубину.
Для начала нам нужно вывести комбобокс в окне добавления товара. Для этого нам нужно подключить свой js для админки.
Создаем плагин с любым названием и пишем в нем этот код:
Ставим ему событие msOnManagerCustomCssJs.
Далее по пути assets/components/ создаем папку customJs и в этой папке создаем файл default.js.
Открываем файл default.js и вставляем в него этот код
Теперь нам нужно сделать процессор, который будет загружать в комбобокс модификации текущего товара.
Для начала нужно создать коннектор, который будет посылать данные в процессор.
Создаем файл connector.php по пути assets/components/helpers/ и помещаем в него следующий код:
Теперь процессор.
В директории core/elements/processors/order создаем файл addproduct.class.php
и помещаем в него код:
Теперь в окне редактирования товара появился наш селект и если у товара будут модификации, то они попадут в комбобокс.
Далее мы создадим плагин, назовем его customOrderRemains и назначим ему такие события:
При добавлении товара в заказ, в админке, в окне редактирования товара появляется селект, который подгружает к себе в значения модификации товаров. Перед сохранением, редактированием или удалением, плагин проверяет наличие остатков у этой модификации и если их нет, то выводит ошибку, а если они есть, то вычитает количество товара из остатков модификации и сохраняет товар в заказ. Так же, в зависимости от типа модификации (+ к цене, = цене), плагин подставляет стоимость товара.
Ну вот и все, надеюсь будет кому-нибудь полезно, спасибо :)
Вывод нового поля в заказе
Для начала нам нужно вывести комбобокс в окне добавления товара. Для этого нам нужно подключить свой js для админки.
Создаем плагин с любым названием и пишем в нем этот код:
switch ($modx->event->name) {
case 'msOnManagerCustomCssJs':
if ($page != 'orders') return;
$modx->controller->addLastJavascript(MODX_ASSETS_URL.'components/customJs/default.js');
break;
}
Ставим ему событие msOnManagerCustomCssJs.
Далее по пути assets/components/ создаем папку customJs и в этой папке создаем файл default.js.
Открываем файл default.js и вставляем в него этот код
//создаем переменную с нашим будущим классом
Ext.ComponentMgr.onAvailable('minishop2-window-orderproduct-update', function(){
let id = 0;
if (!this.record.product_id) {
id = this.record.id;
} else {
id = this.record.product_id;
}
let addProduct = function (config) {
config = config || {};
//Устанавливаем свойства этого класса
Ext.applyIf(config, {
name: 'modlist',
fieldLabel: config.name || 'Модификации',
hiddenName: config.name || 'modlist',
displayField: 'name',
valueField: 'id',
anchor: '99%',
fields: ['name','id'],
pageSize: 20,
typeAhead: false,
editable: true,
allowBlank: false,
url: '/assets/components/helpers/connector.php',
baseParams: {
action: 'order/addproduct',
combo: false,
id: id
},
tpl: new Ext.XTemplate('\
<tpl for=".">\
<div class="x-combo-list-item">\
<span>\
<b>{name}</b>\
</span>\
</div>\
</tpl>',
{compiled: true}
),
});
//Инициализируем класс
addProduct.superclass.constructor.call(this, config);
};
//Говорим ExtJs'у что мы будем расширять нашим классом класс MODx.combo.ComboBox
Ext.extend(addProduct, MODx.combo.ComboBox);
//Регистрируем наш класс как xtype
Ext.reg('addProduct-xtype', addProduct);
var options = this.record;
var modifications = {
border: false,
layout: 'column',
items: [
{
border: false,
columnWidth: 0.5,
autoHeight: true,
layout: 'form',
items: {
xtype: 'addProduct-xtype',
}
}
]
};
this.fields.push(modifications); // Добавляем наше поле в окно товара
});
Теперь нам нужно сделать процессор, который будет загружать в комбобокс модификации текущего товара.
Для начала нужно создать коннектор, который будет посылать данные в процессор.
Создаем файл connector.php по пути assets/components/helpers/ и помещаем в него следующий код:
<?php
/** @noinspection PhpIncludeInspection */
require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/config.core.php';
/** @noinspection PhpIncludeInspection */
require_once MODX_CORE_PATH . 'config/' . MODX_CONFIG_KEY . '.inc.php';
/** @noinspection PhpIncludeInspection */
require_once MODX_CONNECTORS_PATH . 'index.php';
$scriptProperties = $_REQUEST;
$path = MODX_CORE_PATH . 'elements/processors/';
$path = $modx->getOption('processorsPath', $scriptProperties, $path);
/** @var modConnectorRequest $request */
$request = $modx->request;
$request->handleRequest(array(
'processors_path' => $path,
'location' => '',
));
Теперь процессор.
В директории core/elements/processors/order создаем файл addproduct.class.php
и помещаем в него код:
<?php
// Расширяем класс
class GetModification extends modProcessor
{
public $msop;
public $mod;
public $id;
public $ms2;
public function initialize()
{
// Иициализируем компонент msoptionprice
$this->msop = $this->modx->getService('msoptionsprice');
$this->msop->initialize($this->getProperty('context', $this->modx->context->key));
// Получаем id товара
$this->id = $this->getProperty('id');
return parent::initialize();
}
public function process()
{
// Получаем модификации этого товара
$q = ['rid' => $this->id];
$mod = $this->modx->getCollection('msopModification', $q);
if ($mod){
foreach ($mod as $v){
$qi = ['mid' => $v->get('id')];
$opt = $this->modx->getObject('msopModificationOption', $qi);
$val = '';
if ($opt){
$val .= $v->get('name').'-'.$opt->get('value');
}
$arr[] = $mod = [
'id' => $v->get('id'),
'name' => $val,
];
};
return $this->outputArray($arr);
}
}
}
return 'GetModification';
Теперь в окне редактирования товара появился наш селект и если у товара будут модификации, то они попадут в комбобокс.
Далее мы создадим плагин, назовем его customOrderRemains и назначим ему такие события:
- msOnBeforeCreateOrderProduct
- msOnBeforeUpdateOrderProduct
- msOnBeforeRemoveOrderProduct
<?php
switch ($modx->event->name) {
case "msOnBeforeCreateOrderProduct":
$mid = $object->get('modlist');
$prod_id = $object->get('product_id');
$prod_cost = $object->get('cost');
$order_id = $object->get('order_id');
$prod_price = $object->get('price');
$prod_count = $object->get('count');
$modpar = array(
'rid' => $prod_id
);
$par = array(
'mid' => $mid
);
$mods = $modx->getCollection('msopModification', $modpar);
foreach ($mods as $item) {
if ($item->get('id') == $mid) {
$count = $item->get('count');
$modprice = $item->get('price');
$type = $item->get('type');
if ($count < 1) {
$modx->event->output("Нет доступного количества");
break;
}
$newCount = $count - $prod_count;
$item->set('count', $newCount);
if ($type == 1) {
$prod_sum = $prod_price = $modprice;
};
if ($type == 2) {
$prod_sum = $prod_price + $prod_price;
}
$item->save();
$opt = $modx->getObject('msopModificationOption', $par);
$options = [
$opt->get('key') => $opt->get('value')
];
$prod_newcost = $prod_sum * $prod_count;
$object->set('options', $options);
$object->set('price', $prod_sum);
$object->set('cost', $prod_newcost);
$object->save();
}
};
break;
case "msOnBeforeUpdateOrderProduct" :
$mid = $object->get('modlist');
$prod_id = $object->get('product_id');
$order_id = $object->get('order_id');
$prod_price = $object->get('price');
$prod_count = $object->get('count');
$prod_cost = $object->get('cost');
$modpar = array(
'rid' => $prod_id
);
$par = array(
'mid' => $mid
);
$mods = $modx->getCollection('msopModification', $modpar);
$order = $modx->getObject('msOrder', $order_id);
$opt = $modx->getObject('msopModificationOption', $par);
$option = $object->get('options');
foreach ($mods as $item) {
foreach ($option as $k => $v) {
if ($k == $opt->get('key') && $v == $opt->get('value')) {
return false;
break;
}
}
if ($item->get('id') == $mid) {
$count = $item->get('count');
$modprice = $item->get('price');
$type = $item->get('type');
if ($count < 1) {
$modx->event->output("Нет доступного количества");
break;
}
$newCount = $count - $prod_count;
$item->set('count', $newCount);
if ($type == 1) {
$prod_sum = $prod_price = $modprice;
};
if ($type == 2) {
$prod_sum = $prod_price + $prod_price;
}
$item->save();
$options = [
$opt->get('key') => $opt->get('value')
];
$prod_newcost = $prod_sum * $prod_count;
$object->set('options', $options);
$object->set('price', $prod_sum);
$object->set('cost', $prod_newcost);
$object->save();
}
};
break;
case "msOnBeforeRemoveOrderProduct" :
$prod_id = $object->get('product_id');
$order_id = $object->get('order_id');
$prod_price = $object->get('price');
$prod_count = $object->get('count');
$option = $object->get('options');
foreach ($option as $k => $v) {
if ($i <= 1){
$par[] = array(
'rid' => $prod_id,
'key' => $k,
'value' => $v
);
}
}
$opt = $modx->getObject('msopModificationOption', $par[0]);
$modpar = array(
'rid' => $prod_id
);
$mods = $modx->getObject('msopModification', $modpar);
if ($mods->get('id') == $opt->get('mid')) {
$count = $mods->get('count');
$newCount = $count + $prod_count;
$mods->set('count', $newCount);
$mods->save();
}
break;
}
Как это работает
При добавлении товара в заказ, в админке, в окне редактирования товара появляется селект, который подгружает к себе в значения модификации товаров. Перед сохранением, редактированием или удалением, плагин проверяет наличие остатков у этой модификации и если их нет, то выводит ошибку, а если они есть, то вычитает количество товара из остатков модификации и сохраняет товар в заказ. Так же, в зависимости от типа модификации (+ к цене, = цене), плагин подставляет стоимость товара.
Ну вот и все, надеюсь будет кому-нибудь полезно, спасибо :)
Поблагодарить автора
Отправить деньги
Комментарии: 10
А при обновлении товара в заказе, тот модификатор, который ранее был применён, получает обратно свои остатки или происходит только вычитание? Грубо говоря:
1) Юзер оформил заказ с неправильным модификатором товара, кол-во в наличии у модификатора уменьшилось,
2) Менеджер уже на стороне бекэнда при помощи вашего решения изменил неверный модификатор на верный, кол-во в наличии у «верного» модификатора уменьшилось.
Итого мы получаем двойное вычитание кол-ва.
P.S.: Решение хорошее. Было бы вообще круто, если бы вы название компонента, для которого решение пилилось, корректно написали. Не «msOptionPrice2» а «msOptionsPrice2». =)
1) Юзер оформил заказ с неправильным модификатором товара, кол-во в наличии у модификатора уменьшилось,
2) Менеджер уже на стороне бекэнда при помощи вашего решения изменил неверный модификатор на верный, кол-во в наличии у «верного» модификатора уменьшилось.
Итого мы получаем двойное вычитание кол-ва.
P.S.: Решение хорошее. Было бы вообще круто, если бы вы название компонента, для которого решение пилилось, корректно написали. Не «msOptionPrice2» а «msOptionsPrice2». =)
Да, этот момент я упустил, спасибо за комментарий, я допилю эту функцию. А про название дополнения, я постоянно забываю про эту S, даже при разработке, моя невнимательность :)
А кто-нибудь в курсе множественные значение для одной опции можно задавать?
у меня вот лестницы и много вариантов длины у каждой, одну задаю, а вторая почему то не создается, материться, что с таким полем есть уже значение…
у меня вот лестницы и много вариантов длины у каждой, одну задаю, а вторая почему то не создается, материться, что с таким полем есть уже значение…
А этот код работает вообще? У меня процессор отдает ошибку с текстом GetModification
.class не прописал наверное
Классное решение! Спасибо
Есть два вопроса:
1. При добавлении модификации все равно пишет is.gd/KDtOnO
2. Как то можно из плагина убрать проверку остатков? просто на сайте стоит msProductRemains компонент и с ним ваше решение не работает
Есть два вопроса:
1. При добавлении модификации все равно пишет is.gd/KDtOnO
2. Как то можно из плагина убрать проверку остатков? просто на сайте стоит msProductRemains компонент и с ним ваше решение не работает
Спасибо большое. По поводу скрина не понял, у меня нет никаких фасовок, скорее всего у вас другой компонент еще стоит.
Проверку остатков можно отключить в системных настройках дополнения, в плагин лезть не надо.
Проверку остатков можно отключить в системных настройках дополнения, в плагин лезть не надо.
Да, стоит msProductRemains
ну я рассчитывал только на работу с msOptionsPrice, с остальными компонентами работать попросту не может. Тут помочь не могу
А можете подсказать какой там параметр?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.