Index: branches/5.2.x/units/orders/orders_event_handler.php =================================================================== diff -u -r14089 -r14099 --- branches/5.2.x/units/orders/orders_event_handler.php (.../orders_event_handler.php) (revision 14089) +++ branches/5.2.x/units/orders/orders_event_handler.php (.../orders_event_handler.php) (revision 14099) @@ -1,6 +1,6 @@ MasterEvent->status == erSUCCESS) ) return false; + if( !($event->MasterEvent->status == kEvent::erSUCCESS) ) return false; $ses_id = $this->Application->RecallVar('front_order_id'); if($ses_id) @@ -245,7 +245,7 @@ */ function OnUserLogin(&$event) { - if( !($event->MasterEvent->status == erSUCCESS) ) { + if( !($event->MasterEvent->status == kEvent::erSUCCESS) ) { return false; } @@ -280,14 +280,20 @@ return $affiliate_user->isLoaded() ? $affiliate_user->GetDBField('AffiliateId') : 0; } + /** + * Charge order + * + * @param OrdersItem $order + * @return Array + */ function ChargeOrder(&$order) { $gw_data = $order->getGatewayData(); $this->Application->registerClass( $gw_data['ClassName'], GW_CLASS_PATH.'/'.$gw_data['ClassFile'] ); $gateway_object =& $this->Application->recallObject( $gw_data['ClassName'] ); - $payment_result = $gateway_object->DirectPayment($order->FieldValues, $gw_data['gw_params']); + $payment_result = $gateway_object->DirectPayment($order->GetFieldValues(), $gw_data['gw_params']); $sql = 'UPDATE %s SET GWResult1 = %s WHERE %s = %s'; $sql = sprintf($sql, $order->TableName, $this->Conn->qstr($gateway_object->getGWResponce()), $order->IDField, $order->GetID() ); $this->Conn->Query($sql); @@ -374,9 +380,9 @@ //$this->Application->StoreVar('gw_error', getArrayValue($charge_result, 'data', 'responce_reason_text') ); $event->redirect = $this->Application->GetVar('failure_template'); - $event->redirect_params['m_cat_id'] = 0; + $event->SetRedirectParam('m_cat_id', 0); if ($event->Special == 'recurring') { // if we set failed status for other than recurring special the redirect will not occur - $event->status = erFAIL; + $event->status = kEvent::erFAIL; } return false; } @@ -420,7 +426,7 @@ $this->Application->StoreVar('last_order_user', $order->GetDBField('Username')); $event->redirect = $this->Application->GetVar('success_template'); - $event->redirect_params['m_cat_id'] = 0; + $event->SetRedirectParam('m_cat_id', 0); } else { @@ -506,7 +512,7 @@ $this->OnUpdateCart($event); if ($event->getEventParam('RecalculateChangedCart')) { - $event->SetRedirectParam('checkout_error', $event->redirect_params['checkout_error']); + $event->SetRedirectParam('checkout_error', $event->getRedirectParam('checkout_error')); } else { @@ -537,7 +543,7 @@ $event->redirect = $this->Application->GetVar('next_step_template'); $order_id = $this->Application->GetVar('order_id'); - if($order_id !== false) $event->redirect_params['ord_id'] = $order_id; + if($order_id !== false) $event->SetRedirectParam('ord_id', $order_id); } } @@ -610,10 +616,10 @@ return true; } else { - $event->redirect_params = Array('opener' => 's'); + $event->setRedirectParams(Array('opener' => 's'), true); } - if ($event->status == erSUCCESS) { + if ($event->status == kEvent::erSUCCESS) { $this->createMissingAddresses($event); } else { @@ -770,14 +776,14 @@ // of orders with items added through admin when approving them $this->AddItemToOrder($event, $item_id, $qty, $this->Application->isAdminUser ? 1 : null); } - if ($event->status == erSUCCESS && !$event->redirect) { - $event->redirect_params['pass'] = 'm'; - $event->redirect_params['pass_category'] = 0; //otherwise mod-rewrite shop-cart URL will include category + if ($event->status == kEvent::erSUCCESS && !$event->redirect) { + $event->SetRedirectParam('pass', 'm'); + $event->SetRedirectParam('pass_category', 0); //otherwise mod-rewrite shop-cart URL will include category $event->redirect = true; } else { if ($this->Application->isAdminUser) { - $event->redirect_params['opener'] = 'u'; + $event->SetRedirectParam('opener', 'u'); } } } @@ -861,11 +867,11 @@ } if ($result) { - $event->status = erSUCCESS; + $event->status = kEvent::erSUCCESS; $event->redirect = $this->Application->isAdminUser ? true : $this->Application->GetVar('shop_cart_template'); } else { - $event->status = erFAIL; + $event->status = kEvent::erFAIL; } return $result; } @@ -902,8 +908,8 @@ $ord_item->SetDBField('OptionsSalt', $this->OptionsSalt($options)); $ord_item->Update(); $event->CallSubEvent('OnRecalculateItems'); - if ($event->status == erSUCCESS && $this->Application->isAdminUser) { - $event->redirect_params['opener'] = 'u'; + if ($event->status == kEvent::erSUCCESS && $this->Application->isAdminUser) { + $event->SetRedirectParam('opener', 'u'); } } @@ -1179,6 +1185,7 @@ function SetStepRequiredFields(&$event) { $order =& $event->getObject(); + /* @var $order OrdersItem */ $cs_helper =& $this->Application->recallObject('CountryStatesHelper'); /* @var $cs_helper kCountryStatesHelper */ @@ -1202,7 +1209,7 @@ $has_tangibles = $order->HasTangibleItems(); $req_fields = array('ShippingTo', 'ShippingAddress1', 'ShippingCity', 'ShippingZip', 'ShippingCountry', 'ShippingPhone'); foreach ($req_fields as $field) { - $order->Fields[$field]['required'] = $has_tangibles; + $order->setRequired($field, $has_tangibles); } $order->setRequired('ShippingState', $cs_helper->CountryHasStates( $field_values['ShippingCountry'] )); @@ -1212,7 +1219,7 @@ if ($this->Application->GetVar('check_billing_address')) { $req_fields = array('BillingTo', 'BillingAddress1', 'BillingCity', 'BillingZip', 'BillingCountry', 'BillingPhone'); foreach ($req_fields as $field) { - $order->Fields[$field]['required'] = true; + $order->setRequired($field, true); } $order->setRequired('BillingState', $cs_helper->CountryHasStates( $field_values['BillingCountry'] )); @@ -1235,7 +1242,7 @@ } foreach ($req_fields as $field) { - $order->Fields[$field]['required'] = true; + $order->setRequired($field, true); } } } @@ -1334,7 +1341,7 @@ $combinations = $this->queryCombinations($order_items); - $event->status = erSUCCESS; + $event->status = kEvent::erSUCCESS; while (!$order_items->EOL()) { $rec = $order_items->getCurrentRecord(); $product_object->Load( $rec['ProductId'] ); @@ -1350,7 +1357,7 @@ // reserve lack or what is available (in case if we need to reserve anything, by Alex) $to_reserve = min($lack, $inv_object->GetDBField('QtyInStock') - $product_object->GetDBField('QtyInStockMin')); - if ($to_reserve < $lack) $event->status = erFAIL; // if we can't reserve the full lack + if ($to_reserve < $lack) $event->status = kEvent::erFAIL; // if we can't reserve the full lack //reserve in order $order_item->SetDBFieldsFromHash($rec); @@ -1366,7 +1373,7 @@ if ($product_object->GetDBField('InventoryStatus') == 2) { // inventory by options, then restore changed combination values back to common $combinations array !!! - $combinations[ $rec['ProductId'].'_'.$rec['OptionsSalt'] ] = $inv_object->FieldValues; + $combinations[ $rec['ProductId'].'_'.$rec['OptionsSalt'] ] = $inv_object->GetFieldValues(); } } $order_items->GoNext(); @@ -1376,7 +1383,7 @@ function OnOrderPrint(&$event) { - $event->redirect_params = Array('opener'=>'s'); + $event->setRedirectParams(Array('opener'=>'s'), true); } /** @@ -1440,7 +1447,7 @@ $this->DoPlaceOrder($event); } } - $event->status = erSUCCESS; + $event->status = kEvent::erSUCCESS; } @@ -1563,7 +1570,7 @@ if ($product_object->GetDBField('InventoryStatus') == 2) { // inventory by options, then restore changed combination values back to common $combinations array !!! - $combinations[ $rec['ProductId'].'_'.$rec['OptionsSalt'] ] = $inv_object->FieldValues; + $combinations[ $rec['ProductId'].'_'.$rec['OptionsSalt'] ] = $inv_object->GetFieldValues(); } $order_items->GoNext(); @@ -1609,7 +1616,7 @@ $product_h =& $this->Application->recallObject('p_EventHandler'); if ($product_object->GetDBField('InventoryStatus') == 2) { // inventory by options, then restore changed combination values back to common $combinations array !!! - $combinations[ $rec['ProductId'].'_'.$rec['OptionsSalt'] ] = $inv_object->FieldValues; + $combinations[ $rec['ProductId'].'_'.$rec['OptionsSalt'] ] = $inv_object->GetFieldValues(); // using freed qty to fullfill possible backorders $product_h->FullfillBackOrders($product_object, $inv_object->GetID()); @@ -1637,7 +1644,7 @@ function MassInventoryAction(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - $event->status = erFAIL; + $event->status = kEvent::erFAIL; return; } @@ -1659,7 +1666,7 @@ function InventoryAction(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { - $event->status = erFAIL; + $event->status = kEvent::erFAIL; return; } @@ -1692,7 +1699,7 @@ $object->SetDBField('Status', $event_status_map[$event->Name]); $set_new_status = false; - $event->status = erSUCCESS; + $event->status = kEvent::erSUCCESS; $email_params = $this->OrderEmailParams($object); @@ -1719,7 +1726,7 @@ $this->Application->registerClass( $gw_data['ClassName'], GW_CLASS_PATH.'/'.$gw_data['ClassFile'] ); $gateway_object =& $this->Application->recallObject( $gw_data['ClassName'] ); - $charge_result = $gateway_object->Charge($object->FieldValues, $gw_data['gw_params']); + $charge_result = $gateway_object->Charge($object->GetFieldValues(), $gw_data['gw_params']); $sql = 'UPDATE %s SET GWResult2 = %s WHERE %s = %s'; $sql = sprintf($sql, $object->TableName, $this->Conn->qstr($gateway_object->getGWResponce()), $object->IDField, $object->GetID() ); $this->Conn->Query($sql); @@ -1779,7 +1786,7 @@ $this->Application->registerClass( $gw_data['ClassName'], GW_CLASS_PATH.'/'.$gw_data['ClassFile'] ); $gateway_object =& $this->Application->recallObject( $gw_data['ClassName'] ); - $gateway_object->OrderDeclined($object->FieldValues, $gw_data['gw_params']); + $gateway_object->OrderDeclined($object->GetFieldValues(), $gw_data['gw_params']); } // !!! LOOK HERE !!! @@ -1832,7 +1839,7 @@ $this->Application->registerClass( $gw_data['ClassName'], GW_CLASS_PATH.'/'.$gw_data['ClassFile'] ); $gateway_object =& $this->Application->recallObject( $gw_data['ClassName'] ); - $gateway_object->OrderShipped($object->FieldValues, $gw_data['gw_params']); + $gateway_object->OrderShipped($object->GetFieldValues(), $gw_data['gw_params']); } else { $sqe_errors = $this->Application->RecallVar('sqe_errors'); @@ -1847,10 +1854,10 @@ case 'OnOrderProcess': if ($this->ReadyToProcess($object->GetID())) { $event->CallSubEvent('OnReserveItems'); - if ($event->status == erSUCCESS) $set_new_status = true; + if ($event->status == kEvent::erSUCCESS) $set_new_status = true; $email_event_user =& $this->Application->EmailEventUser('BACKORDER.PROCESS', $object->GetDBField('PortalUserId'), $email_params); } else { - $event->status = erFAIL; + $event->status = kEvent::erFAIL; } break; } @@ -1930,8 +1937,8 @@ foreach($search_filter as $filter_name => $filter_params) { - $filter_type = $filter_params['type'] == 'where' ? WHERE_FILTER : HAVING_FILTER; - $object->addFilter($filter_name, $filter_params['value'], $filter_type, FLT_VIEW); + $filter_type = $filter_params['type'] == 'where' ? kDBList::WHERE_FILTER : kDBList::HAVING_FILTER; + $object->addFilter($filter_name, $filter_params['value'], $filter_type, kDBList::FLT_VIEW); } } @@ -2391,7 +2398,7 @@ if ($this->UseTempTables($event) && $next_sub_number == 0) { $sub_order =& $order; } - $sub_order->SetDBFieldsFromHash($order->FieldValues); + $sub_order->SetDBFieldsFromHash($order->GetFieldValues()); $sub_order->SetDBField('SubNumber', $next_sub_number); $sub_order->SetDBField('SubTotal', $sub_order_data['TotalAmount']); @@ -2559,121 +2566,6 @@ } } - /** - * Updates product info in shopping cart - * - * @param kEvent $event - * @param unknown_type $prod_id - * @param unknown_type $back_order - * @param unknown_type $qty - * @param unknown_type $price - * @param unknown_type $discounted_price - * @param unknown_type $discount_type - * @param unknown_type $discount_id - * @param unknown_type $order_item_id - * @param unknown_type $options_salt - * @param unknown_type $passed_item_data - * @param unknown_type $cost - * @return unknown - */ - function UpdateOrderItem(&$event, $prod_id, $back_order, $qty, $price, $discounted_price, $discount_type, $discount_id, $order_item_id = 0, $options_salt = 0, $passed_item_data=null, $cost=0) - { - $price = (float) $price; - $discounted_price = (float) $discounted_price; - $qty = (int) $qty; - - $ord_id = $this->getPassedId($event); - - $table_prefix = $this->TablePrefix($event); - - if($order_item_id) - { - $query = ' SELECT OrderItemId, Quantity, FlatPrice, Price, BackOrderFlag, ItemData FROM '.$table_prefix.'OrderItems - WHERE OrderItemId = '.$order_item_id; - } - else - { - // try to load specified Product by its Id and BackOrderFlag in the order - $query = 'SELECT OrderItemId, Quantity, FlatPrice, Price, BackOrderFlag, ItemData FROM '.$table_prefix.'OrderItems - WHERE - OrderId = '.$ord_id.' - AND - ProductId = '.$prod_id.' - AND - BackOrderFlag '.($back_order ? ' >= 1' : ' = 0').' - AND - OptionsSalt = '.$options_salt; - } - $item_row = $this->Conn->GetRow($query); - $item_id = $item_row['OrderItemId']; - - $object =& $this->Application->recallObject('orditems.-item', null, Array('skip_autoload' => true)); - $item_data = $item_row['ItemData']; - if($item_data) - { - $item_data = unserialize($item_data); - } - $orig_discount_type = (int)getArrayValue($item_data, 'DiscountType'); - $orig_discount_id = (int)getArrayValue($item_data, 'DiscountId'); - - if ($item_id) { // if Product already exists in the order - if ($qty > 0 && - $item_row['Quantity'] == $qty && - round($item_row['FlatPrice'], 3) == round($price, 3) && - round($item_row['Price'], 3) == round($discounted_price, 3) && - $orig_discount_type == $discount_type && - $orig_discount_id == $discount_id) - { - return false; - } - $object->Load($item_id); - if ($qty > 0) { // Update Price by _TOTAL_ qty - $object->SetDBField('Quantity', $qty); - $object->SetDBField('FlatPrice', $price ); - $object->SetDBField('Price', $discounted_price ); - $object->SetDBField('Cost', $cost); - if($item_data = $object->GetDBField('ItemData')) - { - $item_data = unserialize($item_data); - } - else - { - $item_data = Array(); - } - $item_data['DiscountType'] = $discount_type; - $item_data['DiscountId'] = $discount_id; - $object->SetDBField('ItemData', serialize($item_data)); - $object->Update(); - } - else { // delete products with 0 qty - $object->Delete(); - } - } - elseif ($qty > 0) { // if we are adding product - $product =& $this->Application->recallObject('p', null, Array ('skip_autoload' => true)); - $product->Load($prod_id); - $object->SetDBField('ProductId', $prod_id); - $object->SetDBField('ProductName', $product->GetField('Name')); - $object->SetDBField('Quantity', $qty); - $object->SetDBField('FlatPrice', $price ); - $object->SetDBField('Price', $discounted_price ); - $object->SetDBField('Cost', $cost); - $object->SetDBField('OrderId', $ord_id); - $object->SetDBField('BackOrderFlag', $back_order); - if ($passed_item_data && !is_array($passed_item_data)) { - $passed_item_data = unserialize($passed_item_data); - } -// $item_data = Array('DiscountType' => $discount_type, 'DiscountId' => $discount_id); - $item_data = $passed_item_data; - $object->SetDBField('ItemData', serialize($item_data)); - $object->Create(); - } - else { - return false; // item requiring to set qty to 0, meaning already does not exist - } - return true; - } - function OptionsSalt($options, $comb_only=false) { $helper =& $this->Application->recallObject('kProductOptionsHelper'); @@ -2716,111 +2608,16 @@ return false; } - $ord_id = $order->GetID(); + $manager =& $this->Application->recallObject('OrderManager'); + /* @var $manager OrderManager */ - if ($item_data = $event->getEventParam('ItemData')) { - $item_data = unserialize($item_data); - } - else { - $item_data = Array (); - } + $manager->setOrder($order); + $manager->addProduct($product, $event->getEventParam('ItemData'), $qty, $package_num); - $options = getArrayValue($item_data, 'Options'); - if (!$this->CheckOptions($event, $options, $item_id, $qty, $product->GetDBField('OptionsSelectionMode'))) return; - - // Checking if such product already exists in the cart - $keys['OrderId'] = $ord_id; - $keys['ProductId'] = $product->GetId(); - - if (isset($item_data['Options'])) { - $options_salt = $this->OptionsSalt($item_data['Options']); - $keys['OptionsSalt'] = $options_salt; - } - else { - $options_salt = null; - } - - $exists = $object->Load($keys); - - $object->SetDBField('ProductId', $product->GetId()); - $object->SetDBField('ProductName', $product->GetField('l'.$this->Application->GetDefaultLanguageId().'_Name')); - $object->SetDBField('Weight', $product->GetDBField('Weight')); - if (isset($item_data['Options'])) { - $object->SetDBField('OptionsSalt', $options_salt); - } - - if (isset($package_num)) { - $object->SetDBField('PackageNum', $package_num); - } - - if($product->GetDBField('Type') == PRODUCT_TYPE_TANGIBLE || $product->GetDBField('Type') == 6) - { - $object->SetDBField('Quantity', $object->GetDBField('Quantity') + $qty); - } - else // Types: 2,3,4 - { - $object->SetDBField('Quantity', $qty); // 1 - $exists = false; - } - - if (isset($item_data['ForcePrice'])) { - $price = $item_data['ForcePrice']; - } - else { - $price = $this->GetPlainProductPrice($product->GetId(), $object->GetDBField('Quantity'), $product->GetDBField('Type'), $order, $options_salt, $item_data); - } - - $cost = $this->GetProductCost($product->GetId(), $object->GetDBField('Quantity'), $product->GetDBField('Type'), $options_salt, $item_data); - $object->SetDBField('FlatPrice', $price); - $couponed_price = $this->GetCouponDiscountedPrice($order->GetDBField('CouponId'), $product->GetId(), $price); - $discounted_price = $this->GetDiscountedProductPrice($product->GetId(), $price, $discount_id, $order); - if( $couponed_price < $discounted_price ) - { - $discounted_price = $couponed_price; - $discount_type = 'coupon'; - $discount_id = $order->GetDBField('CouponId'); - } - else - { - $discount_type = 'discount'; - $discount_id = $discount_id; - } - - $item_data['DiscountType'] = $discount_type; - $item_data['DiscountId'] = $discount_id; - $item_data['IsRecurringBilling'] = $product->GetDBField('IsRecurringBilling'); - - // it item is processed in order using new style, then put such mark in orderitem record - $processing_data = $product->GetDBField('ProcessingData'); - if ($processing_data) { - $processing_data = unserialize($processing_data); - if (getArrayValue($processing_data, 'HasNewProcessing')) { - $item_data['HasNewProcessing'] = 1; - } - } - $object->SetDBField('ItemData', serialize($item_data)); - - $object->SetDBField('Price', $discounted_price); // will be retrieved later - $object->SetDBField('Cost', $cost); - - $object->SetDBField('BackOrderFlag', 0); // it will be updated in OnRecalculateItems later if needed - $object->SetDBField('OrderId', $ord_id); - - if ($exists) { - if ($qty > 0) { - $object->Update(); - } - else { - $object->Delete(); - } - } - else { - $object->Create(); - } - $this->Application->HandleEvent($ord_event, 'ord:OnRecalculateItems'); + /*if ($ord_event->getEventParam('RecalculateChangedCart') && !$this->Application->isAdmin) { - $event->SetRedirectParam('checkout_error', $ord_event->redirect_params['checkout_error']); + $event->SetRedirectParam('checkout_error', $ord_event->getRedirectParam('checkout_error')); }*/ } @@ -2872,7 +2669,7 @@ */ function OnRecalculateItems(&$event) { - if (is_object($event->MasterEvent) && ($event->MasterEvent->status != erSUCCESS)) { + if (is_object($event->MasterEvent) && ($event->MasterEvent->status != kEvent::erSUCCESS)) { // e.g. master order update failed, don't recalculate order products return ; } @@ -2898,235 +2695,42 @@ return; } - $table_prefix = $this->TablePrefix($event); + $manager =& $this->Application->recallObject('OrderManager'); + /* @var $manager OrderManager */ - // process only tangible products here - $poc_table = $this->Application->getUnitOption('poc', 'TableName'); - $query = ' SELECT oi.ProductId, oi.OptionsSalt, oi.ItemData, SUM(oi.Quantity) AS Quantity, - IF(p.InventoryStatus = 2, poc.QtyInStock, p.QtyInStock) AS QtyInStock, - p.QtyInStockMin, p.BackOrder, p.InventoryStatus - FROM '.$table_prefix.'OrderItems AS oi - LEFT JOIN '.TABLE_PREFIX.'Products AS p ON oi.ProductId = p.ProductId - LEFT JOIN '.$poc_table.' poc ON (poc.CombinationCRC = oi.OptionsSalt) AND (oi.ProductId = poc.ProductId) - WHERE (oi.OrderId = '.$ord_id.') AND (p.Type = 1) - GROUP BY oi.ProductId, OptionsSalt'; - $items = $this->Conn->Query($query); + $manager->setOrder($order); + $result = $manager->calculate(); - $result = false; - $cost_total = 0; - $sub_total = 0; - $sub_total_flat = 0; - $coupon_discount = 0; - $pending_operations = Array(); - - $backordering = $this->Application->ConfigValue('Comm_Enable_Backordering'); - $coupon_id = $order->GetDBField('CouponId'); - - foreach ($items as $row) { - $a_item_data = isset($row['ItemData']) ? unserialize($row['ItemData']) : Array(); - - $min_qty = $this->GetMinQty($row['ProductId']); - if ($row['Quantity'] > 0 && $row['Quantity'] < $min_qty) { - $row['Quantity'] = $min_qty; - $event->SetRedirectParam('checkout_error', 6); - } - - $back_order = 0; - $to_order = 0; - if (!$row['InventoryStatus']) { - $available = $row['Quantity']*2; // always available; - } - else { - // if there are not enough qty AND backorder is auto or backorder is always - $available = $row['QtyInStock'] - $row['QtyInStockMin']; - $available = max(0, $available); // just in case - } - if ( - $backordering && // backordering generally enabled - ( - ($row['Quantity'] > $available) - && - ($row['BackOrder'] == 2) //auto - ) - || - $row['BackOrder'] == 1 // always - ) - { // split order into order & backorder - if ($row['BackOrder'] == 1) { //Always backorder - $available = 0; - $to_order = 0; - $back_order = $row['Quantity']; - } - else { //Auto - $to_order = $available; - $back_order = $row['Quantity'] - $available; - } - - if (isset($a_item_data['ForcePrice'])) { - $price = $a_item_data['ForcePrice']; - } - else { - $price = $this->GetPlainProductPrice( $row['ProductId'], $to_order + $back_order, 1, $order, $row['OptionsSalt'], $row['ItemData'] ); - } - $cost = $this->GetProductCost( $row['ProductId'], $to_order + $back_order, 1, $row['OptionsSalt'], $row['ItemData'] ); - $discounted_price = $this->GetDiscountedProductPrice( $row['ProductId'], $price, $discount_id, $order ); - $couponed_price = $this->GetCouponDiscountedPrice( $coupon_id, $row['ProductId'], $price ); - if($couponed_price < $discounted_price) - { - $discounted_price = $couponed_price; - $coupon_discount += ($price - $couponed_price) * ($to_order + $back_order); - $discount_type = 'coupon'; - $discount_id = $coupon_id; - } - else - { - $discount_type = 'discount'; - } - $pending_operations[] = Array( $row['ProductId'], 0, $to_order, $price, $discounted_price, $discount_type, $discount_id, 0, $row['OptionsSalt'], $row['ItemData'], $cost ); - $pending_operations[] = Array( $row['ProductId'], 1, $back_order, $price, $discounted_price, $discount_type, $discount_id, 0, $row['OptionsSalt'], $row['ItemData'], $cost); - } - else { // store as normal order (and remove backorder) - // we could get here with backorder=never then we should order only what's available - $to_order = min($row['Quantity'], $available); - if (isset($a_item_data['ForcePrice'])) { - $price = $a_item_data['ForcePrice']; - } - else { - $price = $this->GetPlainProductPrice( $row['ProductId'], $to_order + $back_order, 1, $order, $row['OptionsSalt'], $row['ItemData'] ); - } - $cost = $this->GetProductCost( $row['ProductId'], $to_order + $back_order, 1, $row['OptionsSalt'], $row['ItemData'] ); - $discounted_price = $this->GetDiscountedProductPrice( $row['ProductId'], $price, $discount_id, $order ); - $couponed_price = $this->GetCouponDiscountedPrice( $coupon_id, $row['ProductId'], $price ); - if($couponed_price < $discounted_price) - { - $discounted_price = $couponed_price; - $coupon_discount += ($price - $couponed_price) * ($to_order + $back_order); - $discount_type = 'coupon'; - $discount_id = $coupon_id; - } - else - { - $discount_type = 'discount'; - } - $pending_operations[] = Array( $row['ProductId'], 0, $to_order, $price, $discounted_price, $discount_type, $discount_id, 0, $row['OptionsSalt'], $row['ItemData'], $cost ); - $pending_operations[] = Array( $row['ProductId'], 1, 0, $price, $discounted_price, $discount_type, $discount_id, 0, $row['OptionsSalt'], $row['ItemData'], $cost ); // this removes backorders - if ($to_order < $row['Quantity']) { // has changed - if ($to_order > 0) { - $event->SetRedirectParam('checkout_error', 2); - } - else { - $event->SetRedirectParam('checkout_error', 3); - } - $result = true; - } - } - $sub_total_flat += ($to_order + $back_order) * $price; - $sub_total += ($to_order + $back_order) * $discounted_price; - $cost_total += ($to_order + $back_order) * $cost; + if ( $manager->getError() ) { + $event->SetRedirectParam('checkout_error', $manager->getError()); } - // process subscriptions, services and downloadable: begin - $poc_table = $this->Application->getUnitOption('poc', 'TableName'); - $query = ' SELECT oi.OrderItemId, oi.ProductId, oi.Quantity, oi.OptionsSalt, oi.ItemData, - IF(p.InventoryStatus = 2, poc.QtyInStock, p.QtyInStock) AS QtyInStock, - p.QtyInStockMin, p.BackOrder, p.InventoryStatus, p.Type - FROM '.$table_prefix.'OrderItems AS oi - LEFT JOIN '.TABLE_PREFIX.'Products AS p ON oi.ProductId = p.ProductId - LEFT JOIN '.$poc_table.' poc ON (poc.CombinationCRC = oi.OptionsSalt) AND (oi.ProductId = poc.ProductId) - WHERE (oi.OrderId = '.$ord_id.') AND (p.Type IN (2,3,4,5,6))'; - $items = $this->Conn->Query($query); - - foreach ($items as $row) - { - $a_item_data = isset($row['ItemData']) ? unserialize($row['ItemData']) : Array(); - if (isset($a_item_data['ForcePrice'])) { - $price = $a_item_data['ForcePrice']; - } - else { - $price = $this->GetPlainProductPrice( $row['ProductId'], $row['Quantity'], $row['Type'], $order, $row['OptionsSalt'], $row['ItemData'] ); - } - $cost = $this->GetProductCost( $row['ProductId'], $row['Quantity'], $row['Type'], $row['OptionsSalt'], $row['ItemData'] ); - $discounted_price = $this->GetDiscountedProductPrice( $row['ProductId'], $price, $discount_id, $order ); - $couponed_price = $this->GetCouponDiscountedPrice( $coupon_id, $row['ProductId'], $price ); - if($couponed_price < $discounted_price) - { - $discounted_price = $couponed_price; - $coupon_discount += ($price - $couponed_price); - $discount_type = 'coupon'; - $discount_id = $coupon_id; - } - else - { - $discount_type = 'discount'; - } - $pending_operations[] = Array( $row['ProductId'], 0, $row['Quantity'], $price, $discounted_price, $discount_type, $discount_id, $row['OrderItemId'], 0, $row['ItemData'], $cost ); - - $sub_total_flat += $price * $row['Quantity']; - $sub_total += $discounted_price * $row['Quantity']; - $cost_total += $cost * $row['Quantity']; - } - // process subscriptions, services and downloadable: end - - $flat_discount = $this->GetWholeOrderPlainDiscount($global_discount_id, $order); - $flat_discount = ($flat_discount < $sub_total_flat) ? $flat_discount : $sub_total_flat; - $coupon_flat_discount = $this->GetWholeOrderCouponDiscount($coupon_id); - $coupon_flat_discount = ($coupon_flat_discount < $sub_total_flat) ? $coupon_flat_discount : $sub_total_flat; - if($coupon_flat_discount && $coupon_flat_discount > $flat_discount) - { - $flat_discount = $coupon_flat_discount; - $global_discount_type = 'coupon'; - $global_discount_id = $coupon_id; - } - else - { - $global_discount_type = 'discount'; - } - if($sub_total_flat - $sub_total < $flat_discount) - { - $coupon_discount = ($flat_discount == $coupon_flat_discount) ? $flat_discount : 0; - $sub_total = $sub_total_flat - $flat_discount; - foreach ($pending_operations as $operation_row) - { - list($product_id, $backorder, $qty, $price, $discounted_price, $dummy, $dummy, $order_item_id, $options_salt, $item_data, $cost) = $operation_row; - $new_price = ($price / $sub_total_flat) * $sub_total; - $result = $this->UpdateOrderItem($event, $product_id, $backorder, $qty, $price, $new_price, $global_discount_type, $global_discount_id, $order_item_id, $options_salt, $item_data, $cost) || $result; - } - } - else - { - foreach ($pending_operations as $operation_row) - { - list($product_id, $backorder, $qty, $price, $discounted_price, $discount_type, $discount_id, $order_item_id, $options_salt, $item_data, $cost) = $operation_row; - $result = $this->UpdateOrderItem($event, $product_id, $backorder, $qty, $price, $discounted_price, $discount_type, $discount_id, $order_item_id, $options_salt, $item_data, $cost) || $result; - } - } - - $order->SetDBField('SubTotal', $sub_total); - $order->SetDBField('CostTotal', $cost_total); - // $this->CalculateDiscount($event); - $order->SetDBField('DiscountTotal', $sub_total_flat - $sub_total); - - if($coupon_id && $coupon_discount == 0) - { + if ($order->GetDBField('CouponId') && $order->GetDBField('CouponDiscount') == 0) { $this->RemoveCoupon($order); $event->SetRedirectParam('checkout_error', 8); } - $order->SetDBField('CouponDiscount', $coupon_discount); - if ($result) $this->UpdateShippingOption($event); + if ($result) { + $this->UpdateShippingOption($event); + } + $this->UpdateShippingTotal($event); $this->RecalculateProcessingFee($event); $this->RecalculateTax($event); $this->RecalculateGift($event); - if ($event->Name != 'OnAfterItemUpdate') $order->Update(); + if ($event->Name != 'OnAfterItemUpdate') { + $order->Update(); + } + $event->setEventParam('RecalculateChangedCart', $result); + if (is_object($event->MasterEvent)) { $event->MasterEvent->setEventParam('RecalculateChangedCart', $result); } - if ($result && !getArrayValue($event->redirect_params, 'checkout_error')) { + if ($result && ($event->getEventParam('checkout_error') === false)) { $event->SetRedirectParam('checkout_error', 1); } @@ -3152,301 +2756,7 @@ return $cost['TotalCost']; }*/ - function GetMinQty($p_id) - { - $query = 'SELECT - MIN(pp.MinQty) - FROM '.TABLE_PREFIX.'ProductsPricing AS pp - WHERE pp.ProductId = '.$p_id; - $min_qty = $this->Conn->GetOne($query); - if (!$min_qty) return 1; - return $min_qty; - } - /** - * Return product cost for given qty, taking no discounts into account - * - * @param int $p_id ProductId - * @param int $qty Quantity - * @return float - */ - function GetProductCost($p_id, $qty, $product_type, $options_salt=null, $item_data=null) - { - $user_groups = $this->Application->RecallVar('UserGroups'); - if($product_type == 1) - { - // $where_clause = 'pp.ProductId = '.$p_id.' AND pp.MinQty <= '.$qty; - // $orderby_clause = 'ORDER BY ('.$qty.' - pp.MinQty) ASC'; - $where_clause = 'GroupId IN ('.$user_groups.') AND pp.ProductId = '.$p_id.' AND pp.MinQty <= '.$qty.' AND ('.$qty.' < pp.MaxQty OR pp.MaxQty=-1)'; - $orderby_clause = 'ORDER BY pp.Price ASC'; - } - else - { - $price_id = $this->GetPricingId($p_id, $item_data); - $where_clause = 'pp.ProductId = '.$p_id.' AND pp.PriceId = '.$price_id; - $orderby_clause = ''; - } - - $sql = 'SELECT Cost - FROM '.TABLE_PREFIX.'ProductsPricing AS pp - LEFT JOIN '.TABLE_PREFIX.'Products AS p - ON p.ProductId = pp.ProductId - WHERE '.$where_clause.' - '.$orderby_clause; - - // GROUP BY pp.ProductId - removed, this it qty pricing is caclucated incorrectly !!! - - $cost = $this->Conn->GetOne($sql); - if (!$cost) $price = 0; - - return $cost; - } - - /** - * Return product price for given qty, taking no discounts into account - * - * @param int $p_id ProductId - * @param int $qty Quantity - * @return float - */ - function GetPlainProductPrice($p_id, $qty, $product_type, &$order_object, $options_salt=null, $item_data=null) - { - $user_id = $order_object->GetDBField('PortalUserId'); - $user_groups = $this->Application->getUserGroups($user_id); - - if($product_type == 1) - { - // $where_clause = 'pp.ProductId = '.$p_id.' AND pp.MinQty <= '.$qty; - // $orderby_clause = 'ORDER BY ('.$qty.' - pp.MinQty) ASC'; - $where_clause = 'GroupId IN ('.$user_groups.') AND pp.ProductId = '.$p_id.' AND pp.MinQty <= '.$qty.' AND ('.$qty.' < pp.MaxQty OR pp.MaxQty=-1)'; - - // if we have to stick ti primary group this order by clause force its pricing to go first, - // but if there is no pricing for primary group it will take next optimal - if ($this->Application->ConfigValue('Comm_PriceBracketCalculation') == 1){ - if ($user_id <= 0) { - $primary_group = $this->Application->ConfigValue('User_LoggedInGroup'); // actually this is Everyone - } - else { - $primary_group = $this->Conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'UserGroup WHERE PortalUserId='.$user_id.' AND PrimaryGroup=1'); - } - $orderby_clause = 'ORDER BY (IF(GroupId='.$primary_group.',1,2)) ASC, pp.Price ASC'; - } - else { - $orderby_clause = 'ORDER BY pp.Price ASC'; - } - - } - else - { - $price_id = $this->GetPricingId($p_id, $item_data); - $where_clause = 'pp.ProductId = '.$p_id.' AND pp.PriceId = '.$price_id; - $orderby_clause = ''; - } - - $sql = 'SELECT Price - FROM '.TABLE_PREFIX.'ProductsPricing AS pp - LEFT JOIN '.TABLE_PREFIX.'Products AS p - ON p.ProductId = pp.ProductId - WHERE '.$where_clause.' - '.$orderby_clause; - - // GROUP BY pp.ProductId - removed, this it qty pricing is caclucated incorrectly !!! - - $price = $this->Conn->GetOne($sql); - if (!$price) $price = 0; - - if (isset($item_data) && !is_array($item_data)) { - $item_data = unserialize($item_data); - } - - if (isset($item_data['Options'])) { - $addtion = 0; - $opt_helper =& $this->Application->recallObject('kProductOptionsHelper'); - foreach ($item_data['Options'] as $opt => $val) { - $data = $this->Conn->GetRow('SELECT * FROM '.TABLE_PREFIX.'ProductOptions WHERE ProductOptionId = '.$opt); - - $parsed = $opt_helper->ExplodeOptionValues($data); - if (!$parsed) continue; - $conv_prices = $parsed['Prices']; - $conv_price_types = $parsed['PriceTypes']; - - if (is_array($val)) { - foreach ($val as $a_val) { - if (isset($conv_prices[unhtmlentities($a_val)]) && $conv_prices[unhtmlentities($a_val)]) { - if ($conv_price_types[unhtmlentities($a_val)] == '$') { - $addtion += $conv_prices[unhtmlentities($a_val)]; - } - elseif ($conv_price_types[unhtmlentities($a_val)] == '%') { - $addtion += $price * $conv_prices[unhtmlentities($a_val)] / 100; - } - } - } - } - else { - if (isset($conv_prices[unhtmlentities($val)]) && $conv_prices[unhtmlentities($val)]) { - if ($conv_price_types[unhtmlentities($val)] == '$') { - $addtion += $conv_prices[unhtmlentities($val)]; - } - elseif ($conv_price_types[unhtmlentities($val)] == '%') { - $addtion += $price * $conv_prices[unhtmlentities($val)] / 100; - } - } - } - } - $price += $addtion; - } - - $comb_salt = $this->OptionsSalt( getArrayValue($item_data, 'Options'), 1); - if ($comb_salt) { - $query = 'SELECT * FROM '.TABLE_PREFIX.'ProductOptionCombinations WHERE CombinationCRC = '.$comb_salt; - $comb = $this->Conn->GetRow($query); - if ($comb) { - switch ($comb['PriceType']) { - case 1: // = override - $price = $comb['Price']; - break; - case 2: // flat - $price = $price + $comb['Price']; - break; - case 3: // percent - $price = $price * (1 + $comb['Price'] / 100); - break; - } - } - } - - return max($price, 0); - } - - /** - * Return product price for given qty, taking possible discounts into account - * - * @param int $p_id ProductId - * @param int $qty Quantity - * @return float - */ - function GetDiscountedProductPrice($p_id, $price, &$discount_id, &$order_object) - { - $discount_id = 0; - $user_id = $order_object->GetDBField('PortalUserId'); - $user_groups = $this->Application->getUserGroups($user_id); - $sql = ' - SELECT - IF(pd.Type = 1, - '.$price.' - pd.Amount, - IF(pd.Type = 2, - ('.$price.' * (1-pd.Amount/100)), - '.$price.' - ) - ) AS DiscountedPrice, - pd.DiscountId - FROM '.TABLE_PREFIX.'Products AS p - LEFT JOIN '.TABLE_PREFIX.'ProductsDiscountItems AS pdi ON - pdi.ItemResourceId = p.ResourceId OR pdi.ItemType = 0 - LEFT JOIN '.TABLE_PREFIX.'ProductsDiscounts AS pd ON - pd.DiscountId = pdi.DiscountId - AND - (pdi.ItemType = 1 OR (pdi.ItemType = 0 AND pd.Type = 2)) - AND - pd.Status = 1 - AND - ( pd.GroupId IN ('.$user_groups.') AND - ( (pd.Start IS NULL OR pd.Start < UNIX_TIMESTAMP()) - AND - (pd.End IS NULL OR pd.End > UNIX_TIMESTAMP()) - ) - ) - WHERE p.ProductId = '.$p_id.' AND pd.DiscountId IS NOT NULL - '; - - $pricing = $this->Conn->GetCol($sql, 'DiscountId'); - if (!$pricing) return $price; - - $discounted_price = min($pricing); - $pricing = array_flip($pricing); - $discount_id = $pricing[$discounted_price]; - - $discounted_price = min($discounted_price, $price); - return max($discounted_price, 0); - } - - function GetCouponDiscountedPrice($coupon_id, $p_id, $price) - { - if(!$coupon_id) return $price; - - $sql = ' - SELECT - '.$price.' AS Price, - MIN(IF(pc.Type = 1, - '.$price.' - pc.Amount, - IF(pc.Type = 2, - ('.$price.' * (1-pc.Amount/100)), - '.$price.' - ) - )) AS DiscountedPrice - FROM '.TABLE_PREFIX.'Products AS p - LEFT JOIN '.TABLE_PREFIX.'ProductsCouponItems AS pci ON - pci.ItemResourceId = p.ResourceId OR pci.ItemType = 0 - LEFT JOIN '.TABLE_PREFIX.'ProductsCoupons AS pc ON - pc.CouponId = pci.CouponId - AND - (pci.ItemType = 1 OR (pci.ItemType = 0 AND pc.Type = 2)) - WHERE p.ProductId = '.$p_id.' AND pci.CouponId = '.$coupon_id.' - GROUP BY p.ProductId - '; - - $pricing = $this->Conn->GetRow($sql); - if ($pricing === false) return $price; - $price = min($pricing['Price'], $pricing['DiscountedPrice']); - return max($price, 0); - } - - function GetWholeOrderPlainDiscount(&$discount_id, &$order_object) - { - $user_id = $order_object->GetDBField('PortalUserId'); - $user_groups = $this->Application->getUserGroups($user_id); - $sql = ' - SELECT pd.Amount AS Discount, pd.DiscountId - FROM '.TABLE_PREFIX.'ProductsDiscountItems AS pdi - LEFT JOIN '.TABLE_PREFIX.'ProductsDiscounts AS pd - ON - pd.DiscountId = pdi.DiscountId - AND - pdi.ItemType = 0 AND pd.Type = 1 - AND - pd.Status = 1 - AND - ( pd.GroupId IN ('.$user_groups.') AND - ( (pd.Start IS NULL OR pd.Start < '.$order_object->GetDBField('OrderDate').') - AND - (pd.End IS NULL OR pd.End > '.$order_object->GetDBField('OrderDate').') - ) - ) - WHERE pd.DiscountId IS NOT NULL - '; - $pricing = $this->Conn->GetCol($sql, 'DiscountId'); - if (!$pricing) return 0; - - $discounted_price = max($pricing); - $pricing = array_flip($pricing); - $discount_id = $pricing[$discounted_price]; - - return max($discounted_price, 0); - } - - function GetWholeOrderCouponDiscount($coupon_id) - { - if (!$coupon_id) return 0; - - $sql = 'SELECT Amount - FROM '.TABLE_PREFIX.'ProductsCouponItems AS pci - LEFT JOIN '.TABLE_PREFIX.'ProductsCoupons AS pc - ON pc.CouponId = pci.CouponId - WHERE pci.CouponId = '.$coupon_id.' AND pci.ItemType = 0 AND pc.Type = 1'; - return $this->Conn->GetOne($sql); - } - - /** * Return product pricing id for given product, if not passed - return primary pricing ID * * @param int $product_id ProductId @@ -3579,7 +2889,12 @@ function RecalculateTax(&$event) { $object =& $event->getObject(); - if ($object->GetDBField('Status') > ORDER_STATUS_PENDING) return; + /* @var $object OrdersItem */ + + if ($object->GetDBField('Status') > ORDER_STATUS_PENDING) { + return; + } + $object->RecalculateTax(); } @@ -3600,10 +2915,12 @@ function UpdateTotals(&$event) { $object =& $event->getObject(); + /* @var $object OrdersItem */ + $object->UpdateTotals(); } - function CalculateDiscount(&$event) + /*function CalculateDiscount(&$event) { $object =& $event->getObject(); @@ -3645,7 +2962,7 @@ $object->SetDBField('CouponDiscount', $discount_amount); return $discount_amount; - } + }*/ /** * Jumps to selected order in order's list from search tab @@ -3698,11 +3015,11 @@ $object->SetDBField('Status', ORDER_STATUS_PENDING); if( $object->Update() ) { - $event->status=erSUCCESS; + $event->status=kEvent::erSUCCESS; } else { - $event->status=erFAIL; + $event->status=kEvent::erFAIL; $event->redirect=false; break; } @@ -3772,7 +3089,7 @@ $order->Load($order_id); $this->Application->HandleEvent($complete_event, $event->Prefix.'.recurring:OnCompleteOrder' ); - if ($complete_event->status == erSUCCESS) { + if ($complete_event->status == kEvent::erSUCCESS) { //send recurring ok email $email_event_user =& $this->Application->EmailEventUser('ORDER.RECURRING.PROCESSED', $order->GetDBField('PortalUserId'), $this->OrderEmailParams($order)); $email_event_admin =& $this->Application->EmailEventAdmin('ORDER.RECURRING.PROCESSED'); @@ -3992,13 +3309,14 @@ '__VIRTUAL__SubtotalWithoutDiscount' => 'SubtotalWithoutDiscount', '__VIRTUAL__OrderNumber' => 'OrderNumber', ); - return array_merge_recursive2($columns, $new_columns); + + return array_merge($columns, $new_columns); } function OnSave(&$event) { $res = parent::OnSave($event); - if ($event->status == erSUCCESS) { + if ($event->status == kEvent::erSUCCESS) { $copied_ids = unserialize($this->Application->RecallVar($event->Prefix.'_copied_ids'.$this->Application->GetVar('wid'), serialize(array()))); foreach ($copied_ids as $id) { $an_event = new kEvent($this->Prefix.':Dummy'); @@ -4089,7 +3407,7 @@ */ function OnDownloadLabel(&$event) { - $event->status = erSTOP; + $event->status = kEvent::erSTOP; ini_set('memory_limit', '300M'); ini_set('max_execution_time', '0');