Index: branches/5.2.x/units/orders/orders_event_handler.php =================================================================== diff -u -N -r14618 -r14641 --- branches/5.2.x/units/orders/orders_event_handler.php (.../orders_event_handler.php) (revision 14618) +++ branches/5.2.x/units/orders/orders_event_handler.php (.../orders_event_handler.php) (revision 14641) @@ -1,6 +1,6 @@ Array('self' => true), 'OnRemoveFromCart' => Array('self' => true), 'OnUpdateCart' => Array('self' => true), + 'OnUpdateCartJSON' => Array('self' => true), 'OnUpdateItemOptions' => Array('self' => true), 'OnCleanupCart' => Array('self' => true), 'OnContinueShopping' => Array('self' => true), @@ -120,6 +121,7 @@ 'OnProceedToBilling' => Array('self' => true), 'OnProceedToPreview' => Array('self' => true), 'OnCompleteOrder' => Array('self' => true), + 'OnCombinedPlaceOrder' => Array('self' => true), 'OnRemoveCoupon' => Array('self' => true), 'OnRemoveGiftCertificate' => Array('self' => true), @@ -161,6 +163,8 @@ function OnQuietPreSave(&$event) { $object =& $event->getObject(); + /* @var $object kDBItem */ + $object->IgnoreValidation = true; $event->CallSubEvent('OnPreSave'); $object->IgnoreValidation = false; @@ -178,6 +182,7 @@ } $object =& $event->getObject(); + /* @var $object kDBItem */ $shipping_address_id = $this->Application->GetVar('shipping_address_id'); $billing_address_id = $this->Application->GetVar('billing_address_id'); @@ -294,6 +299,7 @@ $this->Application->registerClass( $gw_data['ClassName'], GW_CLASS_PATH.'/'.$gw_data['ClassFile'] ); $gateway_object =& $this->Application->recallObject( $gw_data['ClassName'] ); + /* @var $gateway_object kGWBase */ $payment_result = $gateway_object->DirectPayment($order->GetFieldValues(), $gw_data['gw_params']); $sql = 'UPDATE %s SET GWResult1 = %s WHERE %s = %s'; @@ -319,6 +325,8 @@ function PrepareCoupons(&$event, &$order) { $order_items =& $this->Application->recallObject('orditems.-inv','orditems_List',Array('skip_counting'=>true,'per_page'=>-1) ); + /* @var $order_items kDBList */ + $order_items->linkToParent($order->Special); $order_items->Query(); $order_items->GoFirst(); @@ -512,15 +520,11 @@ function OnCheckout(&$event) { $this->OnUpdateCart($event); - if ($event->getEventParam('RecalculateChangedCart')) - { - $event->SetRedirectParam('checkout_error', $event->getRedirectParam('checkout_error')); - } - else - { + if ( !$event->getEventParam('RecalculateChangedCart') ) { $object =& $event->getObject(); - if(!$object->HasTangibleItems()) - { + /* @var $object OrdersItem */ + + if ( !$object->HasTangibleItems() ) { $object->SetDBField('ShippingTo', ''); $object->SetDBField('ShippingCompany', ''); $object->SetDBField('ShippingPhone', ''); @@ -545,7 +549,10 @@ $event->redirect = $this->Application->GetVar('next_step_template'); $order_id = $this->Application->GetVar('order_id'); - if($order_id !== false) $event->SetRedirectParam('ord_id', $order_id); + + if ( $order_id !== false ) { + $event->SetRedirectParam('ord_id', $order_id); + } } } @@ -596,10 +603,16 @@ */ function OnAfterItemUpdate(&$event) { + parent::OnAfterItemUpdate($event); + $object =& $event->getObject(); + /* @var $object OrdersItem */ $cvv2 = $object->GetDBField('PaymentCVV2'); - if($cvv2 !== false) $this->Application->StoreVar('CVV2Code', $cvv2); + + if ( $cvv2 !== false ) { + $this->Application->StoreVar('CVV2Code', $cvv2); + } } @@ -684,6 +697,57 @@ } /** + * Updates cart and returns various info in JSON format + * + * @param kEvent $event + */ + function OnUpdateCartJSON(&$event) + { + if ( $this->Application->GetVar('ajax') != 'yes' ) { + return; + } + + $object =& $event->getObject(); + /* @var $object kDBItem */ + + // 1. delete given order item by id + $delete_id = $this->Application->GetVar('delete_id'); + + if ( $delete_id !== false ) { + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'OrderItems + WHERE OrderId = ' . $object->GetID() . ' AND OrderItemId = ' . (int)$delete_id; + $this->Conn->Query($sql); + } + + // 2. remove coupon + $remove = $this->Application->GetVar('remove'); + + if ( $remove == 'coupon' ) { + $this->RemoveCoupon($object); + $object->setCheckoutError(OrderCheckoutErrorType::COUPON, OrderCheckoutError::COUPON_REMOVED); + } + elseif ( $remove == 'gift_certificate' ) { + $this->RemoveGiftCertificate($object); + $object->setCheckoutError(OrderCheckoutErrorType::GIFT_CERTIFICATE, OrderCheckoutError::GC_REMOVED); + } + + // 3. update product quantities and recalculate all discounts + $this->Application->HandleEvent($items_event, 'orditems:OnUpdate'); + $event->CallSubEvent('OnRecalculateItems'); + + // 4. remove "orditems" object of kDBItem class, since getOrderInfo uses kDBList object under same prefix + $this->Application->removeObject('orditems'); + + $order_helper =& $this->Application->recallObject('OrderHelper'); + /* @var $order_helper OrderHelper */ + + $event->status = kEvent::erSTOP; + $currency = $this->Application->GetVar('currency', 'selected'); + + echo json_encode( $order_helper->getOrderInfo($object, $currency) ); + } + + /** * Adds item to cart * * @param kEvent $event @@ -946,30 +1010,114 @@ return $item_data; } + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnApplyCoupon(&$event) + { + $code = $this->Application->GetVar('coupon_code'); + + if ($code == '') { + return ; + } + + $object =& $event->getObject(); + /* @var $object OrdersItem */ + + $coupon =& $this->Application->recallObject('coup', null, Array ('skip_autoload' => true)); + /* @var $coupon kDBItem */ + + $coupon->Load($code, 'Code'); + + if ( !$coupon->isLoaded() ) { + $event->status = kEvent::erFAIL; + $object->setCheckoutError(OrderCheckoutErrorType::COUPON, OrderCheckoutError::COUPON_CODE_INVALID); + $event->redirect = false; // check!!! + + return ; + } + + $expire_date = $coupon->GetDBField('Expiration'); + $number_of_use = $coupon->GetDBField('NumberOfUses'); + if ( $coupon->GetDBField('Status') != 1 || ($expire_date && $expire_date < adodb_mktime()) || + (isset($number_of_use) && $number_of_use <= 0)) + { + $event->status = kEvent::erFAIL; + $object->setCheckoutError(OrderCheckoutErrorType::COUPON, OrderCheckoutError::COUPON_CODE_EXPIRED); + $event->redirect = false; + + return ; + } + + $last_used = adodb_mktime(); + $coupon->SetDBField('LastUsedBy', $this->Application->RecallVar('user_id')); + $coupon->SetDBField('LastUsedOn_date', $last_used); + $coupon->SetDBField('LastUsedOn_time', $last_used); + + + if ( isset($number_of_use) ) { + $coupon->SetDBField('NumberOfUses', $number_of_use - 1); + + if ($number_of_use == 1) { + $coupon->SetDBField('Status', 2); + } + } + + $coupon->Update(); + + $this->Application->setUnitOption('ord', 'AutoLoad', true); + $order =& $this->Application->recallObject('ord'); + /* @var $order OrdersItem */ + + $order->SetDBField('CouponId', $coupon->GetDBField('CouponId')); + $order->SetDBField('CouponName', $coupon->GetDBField('Name')); // calculated field + + $order->Update(); + + $object->setCheckoutError(OrderCheckoutErrorType::COUPON, OrderCheckoutError::COUPON_APPLIED); +// OnApplyCoupon is called as hook for OnUpdateCart/OnCheckout, which calls OnRecalcualate themself + } + + /** + * Removes coupon from order + * + * @param kEvent $event + * @deprecated + */ function OnRemoveCoupon(&$event) { $object =& $event->getObject(); + /* @var $object OrdersItem */ + $this->RemoveCoupon($object); + $object->setCheckoutError(OrderCheckoutErrorType::COUPON, OrderCheckoutError::COUPON_REMOVED); + $event->CallSubEvent('OnRecalculateItems'); - $event->SetRedirectParam('checkout_error', 7); } + /** + * Removes coupon from a given order + * + * @param OrdersItem $object + */ function RemoveCoupon(&$object) { - $coupon_id = $object->GetDBField('CouponId'); $coupon =& $this->Application->recallObject('coup', null, Array('skip_autoload' => true)); - $res = $coupon->Load($coupon_id); - $uses = $coupon->GetDBField('NumberOfUses'); + /* @var $coupon kDBItem */ - if($res && isset($uses)) - { - $coupon->SetDBField('NumberOfUses', $uses + 1); - $coupon->SetDBField('Status', 1); + $coupon->Load( $object->GetDBField('CouponId') ); + + if ( $coupon->isLoaded() ) { + $coupon->SetDBField('NumberOfUses', $coupon->GetDBField('NumberOfUses') + 1); + $coupon->SetDBField('Status', STATUS_ACTIVE); $coupon->Update(); } + $object->SetDBField('CouponId', 0); + $object->SetDBField('CouponName', ''); // calculated field $object->SetDBField('CouponDiscount', 0); - } /** @@ -1436,7 +1584,7 @@ } } - $this->finalizePopup($event); + $event->SetRedirectParam('opener', 'u'); } function OnMassPlaceOrder(&$event) @@ -2193,9 +2341,9 @@ */ function CheckQuantites(&$event) { - if ($this->OnRecalculateItems($event)) { // if something has changed in the order - if ($this->Application->isAdminUser) { - if ($this->UseTempTables($event)) { + if ( $this->OnRecalculateItems($event) ) { // if something has changed in the order + if ( $this->Application->isAdminUser ) { + if ( $this->UseTempTables($event) ) { $event->redirect = 'in-commerce/orders/orders_edit_items'; } } @@ -2365,18 +2513,20 @@ $ord_id = $order->GetId(); $shipping_option = $order->GetDBField('ShippingOption'); - $backorder_select = $shipping_option == 0 ? '0 As BackOrderFlag' : 'BackOrderFlag'; + $backorder_select = $shipping_option == 0 ? '0' : 'oi.BackOrderFlag'; // setting PackageNum to 0 for Non-tangible items, for tangibles first package num is always 1 - $query = ' SELECT OrderItemId - FROM '.$table_prefix.'OrderItems - LEFT JOIN '.TABLE_PREFIX.'Products - ON '.TABLE_PREFIX.'Products.ProductId = '.$table_prefix.'OrderItems.ProductId - WHERE '.TABLE_PREFIX.'Products.Type > 1 AND OrderId = '.$ord_id; + $query = ' SELECT oi.OrderItemId + FROM ' . $table_prefix . 'OrderItems oi + LEFT JOIN ' . TABLE_PREFIX . 'Products p ON p.ProductId = oi.ProductId + WHERE p.Type > 1 AND oi.OrderId = ' . $ord_id; $non_tangibles = $this->Conn->GetCol($query); + if ($non_tangibles) { - $query = 'UPDATE '.$table_prefix.'OrderItems SET PackageNum = 0 WHERE OrderItemId IN ('.implode(',', $non_tangibles).')'; + $query = ' UPDATE ' . $table_prefix . 'OrderItems + SET PackageNum = 0 + WHERE OrderItemId IN (' . implode(',', $non_tangibles) . ')'; $this->Conn->Query($query); } @@ -2386,7 +2536,7 @@ // 2 => ProductId // 3 => Shipping PackageNum $query = 'SELECT - '.$backorder_select.', + '.$backorder_select.' AS BackOrderFlagCalc, PackageNum, ProductName, ShippingTypeId, @@ -2407,8 +2557,8 @@ LEFT JOIN '.TABLE_PREFIX.'Products ON '.TABLE_PREFIX.'Products.ProductId = '.$table_prefix.'OrderItems.ProductId WHERE OrderId = '.$ord_id.' - GROUP BY BackOrderFlag, Grouping - ORDER BY BackOrderFlag ASC, PackageNum ASC, ProductType ASC'; + GROUP BY BackOrderFlagCalc, Grouping + ORDER BY BackOrderFlagCalc ASC, PackageNum ASC, ProductType ASC'; $sub_orders = $this->Conn->Query($query); @@ -2474,7 +2624,7 @@ $original_amount = $sub_order->GetDBField('SubTotal') + $sub_order->GetDBField('ShippingCost') + $sub_order->GetDBField('VAT') + $sub_order->GetDBField('ProcessingFee') + $sub_order->GetDBField('InsuranceFee') - $sub_order->GetDBField('GiftCertificateDiscount'); $sub_order->SetDBField('OriginalAmount', $original_amount); - if ($named_grouping_data['Type'] == 1 && ($sub_order_data['BackOrderFlag'] > 0 + if ($named_grouping_data['Type'] == 1 && ($sub_order_data['BackOrderFlagCalc'] > 0 || ($sub_order_data['TotalItems'] != $sub_order_data['TotalReserved'])) ) { $sub_order->SetDBField('Status', ORDER_STATUS_BACKORDERS); @@ -2500,10 +2650,10 @@ break; case PRODUCT_TYPE_TANGIBLE: - $sql = 'SELECT '.$backorder_select.', oi.* + $sql = 'SELECT '.$backorder_select.' AS BackOrderFlagCalc, oi.* FROM '.TABLE_PREFIX.'OrderItems oi LEFT JOIN '.TABLE_PREFIX.'Products p ON p.ProductId = oi.ProductId - WHERE (OrderId = %s) AND (BackOrderFlag = 0) AND (p.Type = '.PRODUCT_TYPE_TANGIBLE.')'; + WHERE (OrderId = %s) AND (BackOrderFlagCalc = 0) AND (p.Type = '.PRODUCT_TYPE_TANGIBLE.')'; $products = $this->Conn->Query( sprintf($sql, $ord_id) ); foreach ($products as $product) { @@ -2648,10 +2798,6 @@ $manager->addProduct($product, $event->getEventParam('ItemData'), $qty, $package_num); $this->Application->HandleEvent($ord_event, 'ord:OnRecalculateItems'); - - /*if ($ord_event->getEventParam('RecalculateChangedCart') && !$this->Application->isAdmin) { - $event->SetRedirectParam('checkout_error', $ord_event->getRedirectParam('checkout_error')); - }*/ } /** @@ -2661,30 +2807,25 @@ */ function UpdateShippingTotal(&$event) { - if ($this->Application->GetVar('ebay_notification') == 1) { + if ( $this->Application->GetVar('ebay_notification') == 1 ) { // TODO: get rid of this "if" - return ; + return; } + $object =& $event->getObject(); - $ord_id = $object->GetId(); + /* @var $object OrdersItem */ - $shipping_option = $object->GetDBField('ShippingOption'); - $backorder_select = $shipping_option == 0 ? '0 As BackOrderFlag' : 'BackOrderFlag'; + $shipping_total = $insurance_fee = 0; + $shipping_info = $object->GetDBField('ShippingInfo') ? unserialize($object->GetDBField('ShippingInfo')) : false; - $table_prefix = $this->TablePrefix($event); - - $shipping_info = $object->GetDBField('ShippingInfo') ? unserialize( $object->GetDBField('ShippingInfo') ) : false; - $shipping_total = 0; - $insurance_fee = 0; - if( is_array($shipping_info) ) - { - foreach ($shipping_info as $a_shipping) - { - // $id_elements = explode('_', $a_shipping['ShippingTypeId']); + if ( is_array($shipping_info) ) { + foreach ($shipping_info as $a_shipping) { +// $id_elements = explode('_', $a_shipping['ShippingTypeId']); $shipping_total += $a_shipping['TotalCost']; $insurance_fee += $a_shipping['InsuranceFee']; } } + $object->SetDBField('ShippingCost', $shipping_total); $object->SetDBField('InsuranceFee', $insurance_fee); // no need to update, it will be called in calling method @@ -2693,7 +2834,7 @@ } /** - * Recompile shopping cart, splitting or grouping orders and backorders depending on total quantityes. + * Recompile shopping cart, splitting or grouping orders and backorders depending on total quantities. * First it counts total qty for each ProductId, and then creates order for available items * and backorder for others. It also updates the sub-total for the order * @@ -2707,11 +2848,6 @@ return ; } - if($checkout_error = $this->Application->GetVar('set_checkout_error')) - { - $event->SetRedirectParam('checkout_error', $checkout_error); - } - $order =& $event->getObject(); /* @var $order OrdersItem */ @@ -2734,16 +2870,12 @@ $manager->setOrder($order); $result = $manager->calculate(); - if ( $manager->getError() ) { - $event->SetRedirectParam('checkout_error', $manager->getError()); - } - - if ($order->GetDBField('CouponId') && $order->GetDBField('CouponDiscount') == 0) { + if ( $order->GetDBField('CouponId') && $order->GetDBField('CouponDiscount') == 0 ) { $this->RemoveCoupon($order); - $event->SetRedirectParam('checkout_error', 8); + $order->setCheckoutError(OrderCheckoutErrorType::COUPON, OrderCheckoutError::COUPON_REMOVED_AUTOMATICALLY); } - if ($result) { + if ( $result ) { $this->UpdateShippingOption($event); } @@ -2753,26 +2885,25 @@ $this->RecalculateTax($event); $this->RecalculateGift($event); - if ($event->Name != 'OnAfterItemUpdate') { + if ( $event->Name != 'OnAfterItemUpdate' ) { $order->Update(); } $event->setEventParam('RecalculateChangedCart', $result); - if (is_object($event->MasterEvent)) { + if ( is_object($event->MasterEvent) ) { $event->MasterEvent->setEventParam('RecalculateChangedCart', $result); } - if ($result && ($event->getEventParam('checkout_error') === false)) { - $event->SetRedirectParam('checkout_error', 1); - } + /*if ( $result && !getArrayValue($event->redirect_params, 'checkout_error') ) { + $event->SetRedirectParam('checkout_error', OrderCheckoutError::STATE_CHANGED); + }*/ - if ($result && is_object($event->MasterEvent) && $event->MasterEvent->Name == 'OnUserLogin') - { - if( ($shop_cart_template = $this->Application->GetVar('shop_cart_template')) - && is_object($event->MasterEvent->MasterEvent) ) - { - $event->MasterEvent->MasterEvent->SetRedirectParam('checkout_error', 9); + if ( $result && is_object($event->MasterEvent) && $event->MasterEvent->Name == 'OnUserLogin' ) { + $shop_cart_template = $this->Application->GetVar('shop_cart_template'); + + if ( $shop_cart_template && is_object($event->MasterEvent->MasterEvent) ) { +// $event->MasterEvent->MasterEvent->SetRedirectParam('checkout_error', OrderCheckoutError::CHANGED_AFTER_LOGIN); $event->MasterEvent->MasterEvent->redirect = $shop_cart_template; } } @@ -3412,12 +3543,67 @@ } // ===== Gift Certificates Related ===== + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnApplyGiftCertificate(&$event) + { + $code = $this->Application->GetVar('giftcert_code'); + + if ( $code == '' ) { + return; + } + + $object =& $event->getObject(); + /* @var $object OrdersItem */ + + $gift_certificate =& $this->Application->recallObject('gc', null, Array ('skip_autoload' => true)); + /* @var $gift_certificate kDBItem */ + + $gift_certificate->Load($code, 'Code'); + + if ( !$gift_certificate->isLoaded() ) { + $event->status = kEvent::erFAIL; + $object->setCheckoutError(OrderCheckoutErrorType::GIFT_CERTIFICATE, OrderCheckoutError::GC_CODE_INVALID); + $event->redirect = false; // check!!! + + return; + } + + $debit = $gift_certificate->GetDBField('Debit'); + $expire_date = $gift_certificate->GetDBField('Expiration'); + + if ( $gift_certificate->GetDBField('Status') != 1 || ($expire_date && $expire_date < adodb_mktime()) || ($debit <= 0) ) { + $event->status = kEvent::erFAIL; + $object->setCheckoutError(OrderCheckoutErrorType::GIFT_CERTIFICATE, OrderCheckoutError::GC_CODE_EXPIRED); + $event->redirect = false; + + return; + } + + $object->SetDBField('GiftCertificateId', $gift_certificate->GetDBField('GiftCertificateId')); + $object->Update(); + + $object->setCheckoutError(OrderCheckoutErrorType::GIFT_CERTIFICATE, OrderCheckoutError::GC_APPLIED); + } + + /** + * Removes gift certificate from order + * + * @param kEvent $event + * @deprecated + */ function OnRemoveGiftCertificate(&$event) { $object =& $event->getObject(); + /* @var $object OrdersItem */ + $this->RemoveGiftCertificate($object); + $object->setCheckoutError(OrderCheckoutErrorType::GIFT_CERTIFICATE, OrderCheckoutError::GC_REMOVED); + $event->CallSubEvent('OnRecalculateItems'); - $event->SetRedirectParam('checkout_error', 107); } function RemoveGiftCertificate(&$object) @@ -3460,6 +3646,8 @@ ini_set('max_execution_time', '0'); $object =& $event->getObject(); + /* @var $object kDBItem */ + $file = $object->GetDBField('ShippingTracking') . '.pdf'; $full_path = USPS_LABEL_FOLDER . $file; @@ -3471,4 +3659,15 @@ header('Content-Disposition: attachment; filename="' . $file . '"'); readfile($full_path); } + + /** + * Enter description here... + * + * @param kEvent $event + */ + function OnCombinedPlaceOrder(&$event) + { + + $event->CallSubEvent('OnUpdate'); + } } \ No newline at end of file