Списание со складов — различия между версиями
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 склада. По умолчанию списывание происходит с первого склада, товаров на котором больше нуля.