Array ('subitem' => true), 'OnSaveItems' => Array ('subitem' => 'add|edit'), ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Processes item selection from popup item selector * * @param kEvent $event */ function OnProcessSelected($event) { $object = $event->getObject( Array('skip_autoload' => true) ); $selected_ids = $this->Application->GetVar('selected_ids'); $product_ids = $selected_ids['p']; if ($product_ids) { //after adding Options Selection during adding products to order in admin, selector is in single mode // = allows selecting one item at a time, but we leave this code just in case :) $product_ids = explode(',', $product_ids); $product_object = $this->Application->recallObject('p.-item', null, array('skip_autoload' => true)); /* @var $product_object ProductsItem */ foreach ($product_ids as $product_id) { $product_object->Load($product_id); $sql = 'SELECT COUNT(*) FROM ' . $this->Application->getUnitOption('po', 'TableName') . ' WHERE (Required = 1) AND (ProductId = ' . $product_id . ')'; if ( $this->Conn->GetOne($sql) ) { $url_params = Array ( $event->Prefix . '_event' => 'OnNew', 'p_id' => $product_id, 'm_opener' => 's', 'pass' => 'm,ord,p', ); $this->Application->EventManager->openerStackPush('in-commerce/orders/order_product_edit', $url_params); } else { $orders_h = $this->Application->recallObject('ord_EventHandler'); /* @var $orders_h OrdersEventHandler */ // 1 for PacakgeNum - temporary solution to overcome splitting into separate sub-orders // of orders with items added through admin when approving them $orders_h->AddItemToOrder($event, $product_id, null, 1); } } } $event->SetRedirectParam('opener', 'u'); } /** * Updates subtotal field in order record. * Only for "Items" tab in "Orders -> Order Edit" in Admin * * @param kEvent $event * @return void * @access protected */ protected function OnUpdate(kEvent $event) { $items_info = $this->Application->GetVar($event->getPrefixSpecial(true)); if ( !$items_info ) { return; } $object = $event->getObject(Array ('skip_autoload' => true)); /* @var $object kDBItem */ $table_info = $object->getLinkedInfo(); $main_object = $this->Application->recallObject($table_info['ParentPrefix']); /* @var $main_object OrdersItem */ foreach ($items_info as $id => $field_values) { $object->Clear(); // otherwise validation errors will be passed to next object $object->Load($id); $object->SetFieldsFromHash($field_values); $event->setEventParam('form_data', $field_values); $this->customProcessing($event, 'before'); if ( $object->Update($id) ) { $this->customProcessing($event, 'after'); $event->status = kEvent::erSUCCESS; } else { $oi_string = $object->GetDBField('ProductId') . ':' . $object->GetDBField('OptionsSalt') . ':' . $object->GetDBField('BackOrderFlag'); $field_errors = $object->GetFieldErrors(); foreach ($field_errors as $field => $error_params) { $error_msg = $object->GetErrorMsg($field); if ( $error_msg ) { $main_object->setCheckoutError(OrderCheckoutErrorType::PRODUCT, OrderCheckoutError::FIELD_UPDATE_ERROR, $oi_string . ':' . $field); } } $event->status = kEvent::erFAIL; $event->redirect = false; // break; } } if ( $this->Application->GetVar('t') != 'in-commerce/orders/orders_edit_items' ) { return; } $sub_total = $this->getSubTotal($items_info); if ( $sub_total !== false ) { $main_object->SetDBField('SubTotal', $sub_total); } $main_object->SetDBField('ReturnTotal', $this->getReturnTotal($items_info)); $main_object->Update(); } /** * Remembers what fields were changed * * @param kEvent $event * @return void * @access protected */ protected function OnAfterItemUpdate(kEvent $event) { parent::OnAfterItemUpdate($event); if ( $this->Application->isAdmin ) { return; } $object = $event->getObject(); /* @var $object kDBItem */ $changed_fields = $object->GetChangedFields(); if ( $changed_fields ) { $table_info = $object->getLinkedInfo(); $main_object = $this->Application->recallObject($table_info['ParentPrefix']); /* @var $main_object OrdersItem */ $oi_string = $object->GetDBField('ProductId') . ':' . $object->GetDBField('OptionsSalt') . ':' . $object->GetDBField('BackOrderFlag'); foreach ($changed_fields as $changed_field => $change_info) { $error_code = OrderCheckoutError::FIELD_UPDATE_SUCCESS; if ( $changed_field == 'ItemData' ) { $item_data_old = unserialize($change_info['old']); $item_data_new = unserialize($change_info['new']); if ( $item_data_old['DiscountId'] != $item_data_new['DiscountId'] || $item_data_old['DiscountType'] != $item_data_new['DiscountType'] ) { if ( $item_data_new['DiscountId'] > 0 ) { $error_code = $item_data_new['DiscountType'] == 'discount' ? OrderCheckoutError::DISCOUNT_APPLIED : OrderCheckoutError::COUPON_APPLIED; } else { $error_code = $item_data_old['DiscountType'] == 'discount' ? OrderCheckoutError::DISCOUNT_REMOVED : OrderCheckoutError::COUPON_REMOVED; } } if ( $error_code == OrderCheckoutError::DISCOUNT_APPLIED || $error_code == OrderCheckoutError::DISCOUNT_REMOVED ) { // set general error too $main_object->setCheckoutError(OrderCheckoutErrorType::DISCOUNT, $error_code); } } elseif ( $changed_field == 'Quantity' && $this->Application->isDebugMode() ) { // here is how qty is changed: // OLD QTY -> NEW QTY // RECALCULATE // NEW QTY = IN_STOCK_QTY // NEW ORDER ITEM with LEFTOVER QTY $this->Application->Debugger->appendTrace(); $this->Application->Debugger->appendHTML('QTY_CHANGE (' . $oi_string . '): ' . $change_info['old'] . ' => ' . $change_info['new']); } $main_object->setCheckoutError(OrderCheckoutErrorType::PRODUCT, $error_code, $oi_string . ':' . $changed_field); } } } /** * Returns subtotal * * @param Array $items_info * @return float */ function getSubTotal($items_info) { $sub_total = 0; foreach ($items_info as $id => $field_values) { if (!array_key_exists('Price', $field_values)) { return false; } $sub_total += $field_values['Quantity'] * $field_values['Price']; } return $sub_total; } /** * Returns total returned amount (refund) * * @param Array $items_info * @return float */ function getReturnTotal($items_info) { $return_total = 0; foreach ($items_info as $id => $field_values) { $return_total += $field_values['ReturnAmount']; } return $return_total; } /** * Saves selected items * * @param kEvent $event */ function OnSaveItems($event) { $event->CallSubEvent('OnUpdate'); $event->redirect = false; $event->SetRedirectParam('opener', 's'); $event->SetRedirectParam('pass', 'all'); } /** * Occurs after an item has been cloned * Id of newly created item is passed as event' 'id' param * * @param kEvent $event * @return void * @access protected */ protected function OnAfterClone(kEvent $event) { parent::OnAfterClone($event); $id = $event->getEventParam('id'); $table = $this->Application->getUnitOption($event->Prefix, 'TableName'); $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); $sql = 'UPDATE ' . $table . ' SET QuantityReserved = NULL WHERE ' . $id_field . ' = ' . $id; $this->Conn->Query($sql); } /** * Occurs after loading item, 'id' parameter * allows to get id of item that was loaded * * @param kEvent $event * @return void * @access protected */ protected function OnAfterItemLoad(kEvent $event) { parent::OnAfterItemLoad($event); $object = $event->getObject(); /* @var $object kDBItem */ $item_info = $object->GetDBField('ItemData'); if ( $item_info ) { $item_info = unserialize($item_info); $object->SetDBField('DiscountType', getArrayValue($item_info, 'DiscountType')); $object->SetDBField('DiscountId', getArrayValue($item_info, 'DiscountId')); } } /** * Apply any custom changes to list's sql query * * @param kEvent $event * @return void * @access protected * @see kDBEventHandler::OnListBuild() */ protected function SetCustomQuery(kEvent $event) { parent::SetCustomQuery($event); $object = $event->getObject(); /* @var $object kDBList */ $package_num = $event->getEventParam('package_num'); if ( $package_num ) { $object->addFilter('package_num', 'PackageNum = ' . $package_num); } $type = $event->getEventParam('product_type'); if ( $type ) { $object->addFilter('product_type', 'p.Type =' . $type); } } /** * Checks, that currently loaded item is allowed for viewing (non permission-based) * * @param kEvent $event * @return bool * @access protected */ protected function checkItemStatus(kEvent $event) { if ( $this->Application->isAdmin ) { return true; } $object = $event->getObject(); /* @var $object kDBItem */ if ( !$object->isLoaded() ) { return true; } $order = $this->Application->recallObject('ord'); /* @var $order kDBItem */ if ( $order->isLoaded() && ($order->GetID() == $object->GetDBField('OrderId')) ) { return $order->GetDBField('PortalUserId') == $this->Application->RecallVar('user_id'); } return false; } }