Списание со складов — различия между версиями
Stexe (обсуждение | вклад) |
Stexe (обсуждение | вклад) |
||
| Строка 9: | Строка 9: | ||
</ol> | </ol> | ||
<br> | <br> | ||
| − | '''Реализация:''' Напишем обработчик события для точки вызова systemModifyObject, которое вызывается при сохранении объекта в административной панели. Вся логика списания или возврата будет находиться в обработчике события. Списание происходит, если статус заказа был изменен на "Готов" (статус 'ready'); возврат товара со склада, если статус заказа был изменен на "Отменен" (статус 'canceled').<br> | + | '''Реализация:''' Напишем обработчик события для точки вызова systemModifyObject, которое вызывается при сохранении объекта в административной панели. Вся логика списания или возврата будет находиться в обработчике события. Списание происходит, если статус заказа был изменен на "Готов" (статус 'ready'); возврат товара со склада, если статус заказа был изменен на "Отменен" (статус 'canceled').<br><br> |
| − | В директорию classes\modules\emarket | + | В директорию classes\modules\emarket добавим файл с названием custom_events.php и содержанием: |
<source lang="php"> | <source lang="php"> | ||
<?php | <?php | ||
new umiEventListener("systemModifyObject", "emarket", "storesReact"); | new umiEventListener("systemModifyObject", "emarket", "storesReact"); | ||
</source> | </source> | ||
| + | |||
| + | В файл classes\modules\emarket\__custom_adm.php добавим код обработчика события: | ||
| + | <source lang="php"> | ||
| + | public function storesReact($event){ | ||
| + | $mode = $event->getMode(); | ||
| + | |||
| + | if ($mode == 'after'){ | ||
| + | $subject = $event->getRef('object'); | ||
| + | $typesCollection = umiObjectTypesCollection::getInstance(); | ||
| + | $umiHierarchy = umiHierarchy::getInstance(); | ||
| + | $subjectTypeId = $subject->getTypeId(); | ||
| + | $subjectType = $typesCollection->getType($subjectTypeId); | ||
| + | $subjectModule = $subjectType->getModule(); | ||
| + | $subjectMethod = $subjectType->getMethod(); | ||
| + | $subjectOrder = order::get($subject->id); | ||
| + | |||
| + | if ($subjectModule == 'emarket' && $subjectMethod == 'order'){ | ||
| + | $orderStatusId = $subject->getValue('status_id'); | ||
| + | $orderStatus = order::getCodeByStatus($orderStatusId); | ||
| + | $currentSwitchMode = $subject->getValue('current_mode'); | ||
| + | |||
| + | if (is_null($currentSwitchMode)) | ||
| + | $currentSwitchMode = false; | ||
| + | |||
| + | $itemsArray = $subjectOrder->getItems(); | ||
| + | |||
| + | $data = array(); | ||
| + | |||
| + | foreach($itemsArray as $item){ | ||
| + | $catalogObject = $item->getItemElement(); | ||
| + | $catalogObjectId = $catalogObject->id; | ||
| + | $itemAmount = $item->getAmount(); | ||
| + | $data[$catalogObjectId] = $itemAmount; | ||
| + | } | ||
| + | |||
| + | if ($orderStatus == 'ready'){ | ||
| + | |||
| + | if (!$currentSwitchMode){ | ||
| + | $changed = self::changeAllAmounts('w', $data); | ||
| + | |||
| + | if ($changed) | ||
| + | $subject->setValue('current_mode', 1); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | if ($orderStatus == 'canceled'){ | ||
| + | |||
| + | if ($currentSwitchMode){ | ||
| + | $changed = self::changeAllAmounts('b', $data); | ||
| + | |||
| + | if ($changed) | ||
| + | $subject->setValue('current_mode', 0); | ||
| + | } | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | protected function changeAmount($mode = 'w', $itemId, $storeId, $amount = 1){ | ||
| + | // mode 'w' - write off | ||
| + | // mode 'b' - get back | ||
| + | $amount = intval($amount); | ||
| + | |||
| + | $umiHierarchy = umiHierarchy::getInstance(); | ||
| + | $item = $umiHierarchy->getElement($itemId); | ||
| + | |||
| + | $data = array(); | ||
| + | |||
| + | if ($item instanceof umiHierarchyElement){ | ||
| + | $stores = $item->getValue('stores_state'); | ||
| + | |||
| + | foreach ($stores as $key => $store){ | ||
| + | |||
| + | if (in_array($storeId, $store)){ | ||
| + | $currentIndex = $key; | ||
| + | $currentValue = $store['int']; | ||
| + | } | ||
| + | } | ||
| + | |||
| + | if (!isset($currentValue) || !isset($key)) | ||
| + | return false; | ||
| + | |||
| + | $amountNow = $currentValue; | ||
| + | |||
| + | if ($mode == 'w') | ||
| + | $amountNow = $currentValue - $amount; | ||
| + | else | ||
| + | $amountNow = $currentValue + $amount; | ||
| + | |||
| + | $storesNow = array(); | ||
| + | $stores[$currentIndex]['int'] = $amountNow; | ||
| + | |||
| + | foreach ($stores as $store){ | ||
| + | $storesNow[] = array('int' => $store['int'], 'rel' => $store['rel']); | ||
| + | } | ||
| + | |||
| + | $item->setValue('stores_state', $storesNow); | ||
| + | return true; | ||
| + | } | ||
| + | |||
| + | |||
| + | } | ||
| + | protected function changeAllAmounts($mode='w', $data){ | ||
| + | $umiHierarchy = umiHierarchy::getInstance(); | ||
| + | |||
| + | foreach ($data as $id => $amount){ | ||
| + | $catalogItem = $umiHierarchy->getElement($id); | ||
| + | $stores = $catalogItem->getValue('stores_state'); | ||
| + | |||
| + | $storeId = self::getStoreId($stores); | ||
| + | $changed = self::changeAmount($mode, $id, $storeId, $amount); | ||
| + | } | ||
| + | |||
| + | if ($changed) | ||
| + | return true; | ||
| + | } | ||
| + | |||
| + | protected function getStoreId($stores){ | ||
| + | if (!is_array($stores)) | ||
| + | return false; | ||
| + | |||
| + | // Insert Your store id choosing logic | ||
| + | |||
| + | $currentKey = 0; | ||
| + | foreach ($stores as $key => $store){ | ||
| + | if (intval($store['int']) > 0){ | ||
| + | $currentKey = $key; | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | if (is_numeric($stores[$currentKey]['rel'])) | ||
| + | return $stores[$currentKey]['rel']; | ||
| + | } | ||
| + | </source> | ||
| + | |||
| + | В метод getStoreId() Вы можете добавить свой код для определения id склада. По умолчанию списывание происходит с первого склада, товаров на котором больше нуля. | ||
Версия 12:29, 21 августа 2013
Актуально для версии 2.9.1
В системе UMI.CMS склады введены в основном для наглядности и для удобства менеджерам, обрабатывающим заказ. В этой статье мы добавим данным параметрам функциональности и организуем списание со склада.
Задача: Реализовать функционал автоматического списания или возврата товара со склада.
Условия работы макроса:
- В модуле "Шаблоны данных" в типе данных "Заказ" должно присутствовать невидимое поле типа "Кнопка-флажок" с идентификатором current_mode
- В модуле "Шаблоны данных" в типе данных "Объекты каталога" должно присутствовать поле типа "Составное" с идентификатором stores_state ("Состояние на складах")
Реализация: Напишем обработчик события для точки вызова systemModifyObject, которое вызывается при сохранении объекта в административной панели. Вся логика списания или возврата будет находиться в обработчике события. Списание происходит, если статус заказа был изменен на "Готов" (статус 'ready'); возврат товара со склада, если статус заказа был изменен на "Отменен" (статус 'canceled').
В директорию classes\modules\emarket добавим файл с названием custom_events.php и содержанием:
<?php
new umiEventListener("systemModifyObject", "emarket", "storesReact");
В файл classes\modules\emarket\__custom_adm.php добавим код обработчика события:
public function storesReact($event){
$mode = $event->getMode();
if ($mode == 'after'){
$subject = $event->getRef('object');
$typesCollection = umiObjectTypesCollection::getInstance();
$umiHierarchy = umiHierarchy::getInstance();
$subjectTypeId = $subject->getTypeId();
$subjectType = $typesCollection->getType($subjectTypeId);
$subjectModule = $subjectType->getModule();
$subjectMethod = $subjectType->getMethod();
$subjectOrder = order::get($subject->id);
if ($subjectModule == 'emarket' && $subjectMethod == 'order'){
$orderStatusId = $subject->getValue('status_id');
$orderStatus = order::getCodeByStatus($orderStatusId);
$currentSwitchMode = $subject->getValue('current_mode');
if (is_null($currentSwitchMode))
$currentSwitchMode = false;
$itemsArray = $subjectOrder->getItems();
$data = array();
foreach($itemsArray as $item){
$catalogObject = $item->getItemElement();
$catalogObjectId = $catalogObject->id;
$itemAmount = $item->getAmount();
$data[$catalogObjectId] = $itemAmount;
}
if ($orderStatus == 'ready'){
if (!$currentSwitchMode){
$changed = self::changeAllAmounts('w', $data);
if ($changed)
$subject->setValue('current_mode', 1);
}
}
if ($orderStatus == 'canceled'){
if ($currentSwitchMode){
$changed = self::changeAllAmounts('b', $data);
if ($changed)
$subject->setValue('current_mode', 0);
}
}
}
}
}
protected function changeAmount($mode = 'w', $itemId, $storeId, $amount = 1){
// mode 'w' - write off
// mode 'b' - get back
$amount = intval($amount);
$umiHierarchy = umiHierarchy::getInstance();
$item = $umiHierarchy->getElement($itemId);
$data = array();
if ($item instanceof umiHierarchyElement){
$stores = $item->getValue('stores_state');
foreach ($stores as $key => $store){
if (in_array($storeId, $store)){
$currentIndex = $key;
$currentValue = $store['int'];
}
}
if (!isset($currentValue) || !isset($key))
return false;
$amountNow = $currentValue;
if ($mode == 'w')
$amountNow = $currentValue - $amount;
else
$amountNow = $currentValue + $amount;
$storesNow = array();
$stores[$currentIndex]['int'] = $amountNow;
foreach ($stores as $store){
$storesNow[] = array('int' => $store['int'], 'rel' => $store['rel']);
}
$item->setValue('stores_state', $storesNow);
return true;
}
}
protected function changeAllAmounts($mode='w', $data){
$umiHierarchy = umiHierarchy::getInstance();
foreach ($data as $id => $amount){
$catalogItem = $umiHierarchy->getElement($id);
$stores = $catalogItem->getValue('stores_state');
$storeId = self::getStoreId($stores);
$changed = self::changeAmount($mode, $id, $storeId, $amount);
}
if ($changed)
return true;
}
protected function getStoreId($stores){
if (!is_array($stores))
return false;
// Insert Your store id choosing logic
$currentKey = 0;
foreach ($stores as $key => $store){
if (intval($store['int']) > 0){
$currentKey = $key;
break;
}
}
if (is_numeric($stores[$currentKey]['rel']))
return $stores[$currentKey]['rel'];
}
В метод getStoreId() Вы можете добавить свой код для определения id склада. По умолчанию списывание происходит с первого склада, товаров на котором больше нуля.