/** * Updates the status of the Order with the given ID * * If the order exists and has the pending status (status == 0), * it is updated according to the payment and distribution type. * Note that status other than pending are never changed! * If the optional argument $newOrderStatus is set and not pending, * the order status is set to that value instead. * Returns the new Order status on success. * If either the order ID is invalid, or if the update fails, returns * the Order status "pending" (zero). * @access private * @static * @param integer $order_id The ID of the current order * @param integer $newOrderStatus The optional new order status. * @param string $handler The Payment type name in use * @return integer The new order status (may be zero) * if the order status can be changed * accordingly, zero otherwise */ static function update_status($order_id, $newOrderStatus = 0, $handler = NULL) { global $objDatabase, $_ARRAYLANG; if (is_null($handler) && isset($_REQUEST['handler'])) { $handler = contrexx_input2raw($_REQUEST['handler']); } $order_id = intval($order_id); if ($order_id == 0) { return Order::STATUS_CANCELLED; } $query = "\n SELECT status, payment_id, shipment_id\n FROM " . DBPREFIX . "module_shop" . MODULE_INDEX . "_orders\n WHERE id={$order_id}"; $objResult = $objDatabase->Execute($query); if (!$objResult || $objResult->EOF) { return Order::STATUS_CANCELLED; } $status = $objResult->fields['status']; // Never change a non-pending status! // Whether a payment was successful or not, the status must be // left alone. if ($status != Order::STATUS_PENDING) { // The status of the order is not pending. // This may be due to a wrong order ID, a page reload, // or a PayPal IPN that has been received already. // No order status is changed automatically in these cases! // Leave it as it is. return $status; } // Determine and verify the payment handler $payment_id = $objResult->fields['payment_id']; //if (!$payment_id) DBG::log("update_status($order_id, $newOrderStatus): Failed to find Payment ID for Order ID $order_id"); $processor_id = Payment::getPaymentProcessorId($payment_id); //if (!$processor_id) DBG::log("update_status($order_id, $newOrderStatus): Failed to find Processor ID for Payment ID $payment_id"); $processorName = PaymentProcessing::getPaymentProcessorName($processor_id); //if (!$processorName) DBG::log("update_status($order_id, $newOrderStatus): Failed to find Processor Name for Processor ID $processor_id"); // The payment processor *MUST* match the handler returned. if (!preg_match("/^{$handler}/i", $processorName)) { //DBG::log("update_status($order_id, $newOrderStatus): Mismatching Handlers: Order $processorName, Request ".$_GET['handler']); return Order::STATUS_CANCELLED; } // Only if the optional new order status argument is zero, // determine the new status automatically. if ($newOrderStatus == Order::STATUS_PENDING) { // The new order status is determined by two properties: // - The method of payment (instant/deferred), and // - The method of delivery (if any). // If the payment takes place instantly (currently, all // external payments processors are considered to do so), // and there is no delivery needed (because it's all // downloads), the order status is switched to 'completed' // right away. // If only one of these conditions is met, the status is set to // 'paid', or 'delivered' respectively. // If neither condition is met, the status is set to 'confirmed'. $newOrderStatus = Order::STATUS_CONFIRMED; $processorType = PaymentProcessing::getCurrentPaymentProcessorType($processor_id); $shipmentId = $objResult->fields['shipment_id']; if ($processorType == 'external') { // External payment types are considered instant. // See $_SESSION['shop']['isInstantPayment']. if ($shipmentId == 0) { // instant, download -> completed $newOrderStatus = Order::STATUS_COMPLETED; } else { // There is a shipper, so this order will bedelivered. // See $_SESSION['shop']['isDelivery']. // instant, delivery -> paid $newOrderStatus = Order::STATUS_PAID; } } else { // Internal payment types are considered deferred. if ($shipmentId == 0) { // deferred, download -> shipped $newOrderStatus = Order::STATUS_SHIPPED; } //else { deferred, delivery -> confirmed } } } $query = "\n UPDATE " . DBPREFIX . "module_shop" . MODULE_INDEX . "_orders\n SET status='{$newOrderStatus}'\n WHERE id={$order_id}"; $objResult = $objDatabase->Execute($query); if (!$objResult) { // The query failed, but all the data is okay. // Don't cancel the order, leave it as it is and let the shop // manager handle this. Return pending status. return Order::STATUS_PENDING; } if ($newOrderStatus == Order::STATUS_CONFIRMED || $newOrderStatus == Order::STATUS_PAID || $newOrderStatus == Order::STATUS_SHIPPED || $newOrderStatus == Order::STATUS_COMPLETED) { if (!ShopLibrary::sendConfirmationMail($order_id)) { // Note that this message is only shown when the page is // displayed, which may be on another request! \Message::error($_ARRAYLANG['TXT_SHOP_UNABLE_TO_SEND_EMAIL']); } } // The shopping cart *MUST* be flushed right after this method // returns a true value (greater than zero). // If the new order status is zero however, the cart may // be left alone and the payment process can be tried again. return $newOrderStatus; }
/** * Stores the Order * * Takes all values as found in the POST array * @global array $_ARRAYLANG Language array * @global ADONewConnection $objDatabase Database connection object * @return boolean True on success, false otherwise * @static */ static function storeFromPost() { global $objDatabase, $_ARRAYLANG; $order_id = isset($_POST['order_id']) ? intval($_POST['order_id']) : null; if (empty($order_id)) { return null; } // calculate the total order sum in the selected currency of the customer $totalOrderSum = floatval($_POST['shippingPrice']) + floatval($_POST['paymentPrice']); // the tax amount will be set, even if it's included in the price already. // thus, we have to check the setting. if (!Vat::isIncluded()) { $totalOrderSum += floatval($_POST['taxPrice']); } // store the product details and add the price of each product // to the total order sum $totalOrderSum $order = self::getById($order_id); $orderOptions = $order->getOptionArray(); foreach ($_REQUEST['product_list'] as $orderItemId => $product_id) { if ($orderItemId != 0 && $product_id == 0) { // delete the product from the list $query = "\n DELETE FROM " . DBPREFIX . "module_shop" . MODULE_INDEX . "_order_items\n WHERE id={$orderItemId}"; $objResult = $objDatabase->Execute($query); if (!$objResult) { return self::errorHandler(); } $query = "\n DELETE FROM " . DBPREFIX . "module_shop" . MODULE_INDEX . "_order_attributes\n WHERE id={$orderItemId}"; $objResult = $objDatabase->Execute($query); if (!$objResult) { return self::errorHandler(); } } elseif ($product_id != 0) { $objProduct = Product::getById($product_id); if (!$objProduct) { \Message::error(sprintf($_ARRAYLANG['TXT_SHOP_PRODUCT_NOT_FOUND'], $product_id)); continue; } $product_name = $objProduct->name(); $productPrice = $price = $_REQUEST['productPrice'][$orderItemId]; if (isset($orderOptions[$orderItemId])) { foreach ($orderOptions[$orderItemId] as $optionValues) { foreach ($optionValues as $value) { $price += $value['price']; } } } $price = Currency::formatPrice($price); $productPrice = Currency::formatPrice($productPrice); $quantity = max(1, intval($_REQUEST['productQuantity'][$orderItemId])); $totalOrderSum += $price * $quantity; $vat_rate = Vat::format($_REQUEST['productTaxPercent'][$orderItemId]); $weight = Weight::getWeight($_REQUEST['productWeight'][$orderItemId]); if ($orderItemId == 0) { // Add a new product to the list if (!self::insertItem($order_id, $product_id, $product_name, $productPrice, $quantity, $vat_rate, $weight, array())) { return false; } } else { // Update the order item if (!self::updateItem($orderItemId, $product_id, $product_name, $productPrice, $quantity, $vat_rate, $weight, array())) { return false; } } } } $objUser = \FWUser::getFWUserObject()->objUser; // Store the order details // TODO: Should add verification for POSTed fields and ignore unset values! $query = "\n UPDATE " . DBPREFIX . "module_shop" . MODULE_INDEX . "_orders\n SET `sum`=" . floatval($totalOrderSum) . ",\n `shipment_amount`=" . floatval($_POST['shippingPrice']) . ",\n `payment_amount`=" . floatval($_POST['paymentPrice']) . ",\n `status`='" . intval($_POST['order_status']) . "',\n `billing_gender`='" . contrexx_input2db($_POST['billing_gender']) . "',\n `billing_company`='" . contrexx_input2db($_POST['billing_company']) . "',\n `billing_firstname`='" . contrexx_input2db($_POST['billing_firstname']) . "',\n `billing_lastname`='" . contrexx_input2db($_POST['billing_lastname']) . "',\n `billing_address`='" . contrexx_input2db($_POST['billing_address']) . "',\n `billing_city`='" . contrexx_input2db($_POST['billing_city']) . "',\n `billing_zip`='" . contrexx_input2db($_POST['billing_zip']) . "',\n `billing_country_id`='" . intval($_POST['billing_country_id']) . "',\n `billing_phone`='" . contrexx_input2db($_POST['billing_phone']) . "',\n `billing_fax`='" . contrexx_input2db($_POST['billing_fax']) . "',\n `billing_email`='" . contrexx_input2db($_POST['billing_email']) . "',\n `gender`='" . contrexx_input2db($_POST['shipPrefix']) . "',\n `company`='" . contrexx_input2db($_POST['shipCompany']) . "',\n `firstname`='" . contrexx_input2db($_POST['shipFirstname']) . "',\n `lastname`='" . contrexx_input2db($_POST['shipLastname']) . "',\n `address`='" . contrexx_input2db($_POST['shipAddress']) . "',\n `city`='" . contrexx_input2db($_POST['shipCity']) . "',\n `zip`='" . contrexx_input2db($_POST['shipZip']) . "',\n `country_id`=" . intval($_POST['shipCountry']) . ",\n `phone`='" . contrexx_input2db($_POST['shipPhone']) . "',\n `vat_amount`=" . floatval($_POST['taxPrice']) . ",\n `shipment_id`=" . intval($_POST['shipperId']) . ",\n `modified_by`='" . $objUser->getUsername() . "',\n `modified_on`='" . date('Y-m-d H:i:s') . "'\n WHERE `id`={$order_id}"; // should not be changed, see above // ", payment_id = ".intval($_POST['paymentId']). if (!$objDatabase->Execute($query)) { \Message::error($_ARRAYLANG['TXT_SHOP_ORDER_ERROR_STORING']); return self::errorHandler(); } \Message::ok($_ARRAYLANG['TXT_DATA_RECORD_UPDATED_SUCCESSFUL']); // Send an email to the customer, if requested if (!empty($_POST['sendMail'])) { $result = ShopLibrary::sendConfirmationMail($order_id); if (!$result) { return \Message::error($_ARRAYLANG['TXT_MESSAGE_SEND_ERROR']); } \Message::ok(sprintf($_ARRAYLANG['TXT_EMAIL_SEND_SUCCESSFULLY'], $result)); } return true; }