/** * 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; }
/** * Calculate the shipment price for the given Shipper ID, order price and * total weight. * * Returns the shipment price in default currency, or -1 if there is any kind * of problem with the shipment conditions. * The weight is converted from string using {@link Weight::getWeight()} * to make sure that grams are used. * Note: You have to convert the returned value to the customers' currency * using {@link Currency::getCurrencyPrice()}! * @param integer $shipperId The Shipper ID * @param double $price The total order price * @param integer $weight The total order weight in grams. * @return double The cost for shipping in the default * currency, or -1. * @static */ static function calculateShipmentPrice($shipperId, $price, $weight) { if (empty(self::$arrShippers)) { self::init(); } // Are there conditions available from this shipper? // Otherwise, don't even try to find one. return if (!isset(self::$arrShipments[$shipperId])) { return -1; } // check shipments available by this shipper $arrShipment = self::$arrShipments[$shipperId]; // Find the best match for the current order weight and shipment cost. // Arbitrary upper limit - we *SHOULD* be able to find one that's lower! // We'll just try to find the cheapest way to handle the delivery. $lowest_cost = 1.0E+100; // Temporary shipment cost $fee = 0; // Found flag is set to the index of a suitable shipment, if encountered below. // If the flag stays at -1, there is no way to deliver it! $found = -1; // Try all the available shipments // (see Shipment.class.php::getJSArrays()) foreach ($arrShipment as $shipment_id => $conditions) { $free_from = $conditions['free_from']; $max_weight = Weight::getWeight($conditions['max_weight']); // Get the shipment conditions that are closest to our order: // We have to make sure the maximum weight is big enough for the order, // or that it's unspecified (don't care) if ($max_weight > 0 && $weight <= $max_weight || $max_weight == 0) { // If free_from is set, the order amount has to be higher than that // in order to get the shipping for free. if ($free_from > 0 && $price >= $free_from) { // We're well within the weight limit, and the order is also expensive // enough to get a free shipping. $fee = '0.00'; } else { // Either the order amount is too low, or free_from is unset, or zero, // so the shipping has to be paid for in any case. $fee = $conditions['fee']; } // We found a kind of shipment that can handle the order, but maybe // it's too expensive. - keep the cheapest way to deliver it if ($fee < $lowest_cost) { // Found a cheaper one. keep the index. $found = $shipment_id; $lowest_cost = $fee; } } } if ($found > 0) { // After checking all the shipments, we found the lowest cost for the // given weight and order price. - update the shipping cost return $lowest_cost; } // Cannot find suitable shipment conditions for the selected shipper. return -1; }
/** * Stores the posted Product, if any * @return boolean True on success, null on noop, false otherwise */ static function store_product() { global $_ARRAYLANG; if (!isset($_POST['bstore'])) { return null; } $product_name = contrexx_input2raw($_POST['product_name']); $product_code = contrexx_input2raw($_POST['product_code']); // Multiple Categories $category_id = isset($_POST['shopCategoriesAssigned']) ? contrexx_input2raw(join(',', $_POST['shopCategoriesAssigned'])) : ''; $customer_price = $_POST['customer_price']; $reseller_price = $_POST['reseller_price']; $discount_active = !empty($_POST['discount_active']); $discount_price = $_POST['discount_price']; //DBG::log("ShopManager::store_product(): customer_price $customer_price, reseller_price $reseller_price, discount_price $discount_price"); $vat_id = $_POST['vat_id']; $short = contrexx_input2raw($_POST['short']); $long = contrexx_input2raw($_POST['long']); $stock = $_POST['stock']; $stock_visible = !empty($_POST['stock_visible']); $uri = contrexx_input2raw($_POST['uri']); $active = !empty($_POST['articleActive']); $b2b = !empty($_POST['B2B']); $b2c = !empty($_POST['B2C']); $date_start = contrexx_input2raw($_POST['date_start']); $date_end = contrexx_input2raw($_POST['date_end']); $manufacturer_id = isset($_POST['manufacturer_id']) ? contrexx_input2int($_POST['manufacturer_id']) : 0; $minimum_order_quantity = $_POST['minimum_order_quantity']; // Currently not used on the detail page // $flags = (isset($_POST['Flags']) // ? join(' ', $_POST['Flags']) : ''); $distribution = $_POST['distribution']; // Different meaning of the "weight" field for downloads! // The getWeight() method will treat purely numeric values // like the validity period (in days) the same as a weight // without its unit and simply return its integer value. $weight = $distribution == 'delivery' ? Weight::getWeight($_POST['weight']) : $_POST['accountValidity']; // Assigned frontend groups for protected downloads $usergroup_ids = isset($_POST['groupsAssigned']) ? implode(',', $_POST['groupsAssigned']) : ''; $discount_group_count_id = $_POST['discount_group_count_id']; $discount_group_article_id = $_POST['discount_group_article_id']; //DBG::log("ShopManager::store_product(): Set \$discount_group_article_id to $discount_group_article_id"); $keywords = contrexx_input2raw($_POST['keywords']); for ($i = 1; $i <= 3; ++$i) { // Images outside the above directory are copied to the shop image folder. // Note that the image paths below do not include the document root, but // are relative to it. $picture = contrexx_input2raw($_POST['productImage' . $i]); // Ignore the picture if it's the default image! // Storing it would be pointless. // Images outside the above directory are copied to the shop image folder. // Note that the image paths below do not include the document root, but // are relative to it. if ($picture == self::$defaultImage || !self::moveImage($picture)) { $picture = ''; } // Update the posted path (used below) $_POST['productImage' . $i] = $picture; } // add all to pictures DBstring $imageName = base64_encode($_POST['productImage1']) . '?' . base64_encode($_POST['productImage1_width']) . '?' . base64_encode($_POST['productImage1_height']) . ':' . base64_encode($_POST['productImage2']) . '?' . base64_encode($_POST['productImage2_width']) . '?' . base64_encode($_POST['productImage2_height']) . ':' . base64_encode($_POST['productImage3']) . '?' . base64_encode($_POST['productImage3_width']) . '?' . base64_encode($_POST['productImage3_height']); // Note that the flags of the Product *MUST NOT* be changed // when inserting or updating the Product data, as the original // flags are needed for their own update later. $objProduct = null; $product_id = intval($_POST['id']); if ($product_id) { $objProduct = Product::getById($product_id); } $new = false; if (!$objProduct) { $new = true; $objProduct = new Product($product_code, $category_id, $product_name, $distribution, $customer_price, $active, 0, $weight); if (!$objProduct->store()) { return \Message::error($_ARRAYLANG['TXT_SHOP_PRODUCT_ERROR_STORING']); } // $product_id = $objProduct->id(); } // Apply the changes to all Products with the same Product code. // Note: This is disabled for the time being, as virtual categories are, too. // if ($product_code != '') { // $arrProduct = Products::getByCustomId($product_code); // } else { // $arrProduct = array($objProduct); // } // if (!is_array($arrProduct)) return false; // foreach ($arrProduct as $objProduct) { // Update each product $objProduct->code($product_code); // NOTE: Only change the parent ShopCategory for a Product // that is in a real ShopCategory. $objProduct->category_id($category_id); $objProduct->name($product_name); $objProduct->distribution($distribution); $objProduct->price($customer_price); $objProduct->active($active); // On the overview only: $objProduct->ord(); $objProduct->weight($weight); $objProduct->resellerprice($reseller_price); $objProduct->discount_active($discount_active); $objProduct->discountprice($discount_price); $objProduct->vat_id($vat_id); $objProduct->short($short); $objProduct->long($long); $objProduct->stock($stock); $objProduct->minimum_order_quantity($minimum_order_quantity); $objProduct->stock_visible($stock_visible); $objProduct->uri($uri); $objProduct->b2b($b2b); $objProduct->b2c($b2c); $objProduct->date_start($date_start); $objProduct->date_end($date_end); $objProduct->manufacturer_id($manufacturer_id); $objProduct->pictures($imageName); // Currently not used on the detail page // $objProduct->flags($flags); $objProduct->usergroup_ids($usergroup_ids); $objProduct->group_id($discount_group_count_id); $objProduct->article_id($discount_group_article_id); $objProduct->keywords($keywords); //DBG::log("ShopManager::store_product(): Product: reseller_price ".$objProduct->resellerprice()); // Remove old Product Attributes. // They are re-added below. $objProduct->clearAttributes(); // Add current product attributes if (isset($_POST['options']) && is_array($_POST['options'])) { foreach ($_POST['options'] as $valueId => $nameId) { $order = intval($_POST['productOptionsSortId'][$nameId]); $objProduct->addAttribute(intval($valueId), $order); } } // Mind that this will always be an *update*, see the call to // store() above. if (!$objProduct->store()) { return \Message::error($_ARRAYLANG['TXT_SHOP_PRODUCT_ERROR_STORING']); } // } // Add/remove Categories and Products to/from // virtual ShopCategories. // Note that this *MUST* be called *AFTER* the Product is updated // or inserted. // Virtual categories are disabled for the time being // Products::changeFlagsByProductCode( // $product_code, $flags // ); $objImage = new \ImageManager(); $arrImages = Products::get_image_array_from_base64($imageName); // Create thumbnails if not available, or update them foreach ($arrImages as $arrImage) { if (!empty($arrImage['img']) && $arrImage['img'] != ShopLibrary::noPictureName) { if (!$objImage->_createThumbWhq(\Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteImagesShopPath() . '/', \Cx\Core\Core\Controller\Cx::instanciate()->getWebsiteImagesShopWebPath() . '/', $arrImage['img'], \Cx\Core\Setting\Controller\Setting::getValue('thumbnail_max_width', 'Shop'), \Cx\Core\Setting\Controller\Setting::getValue('thumbnail_max_height', 'Shop'), \Cx\Core\Setting\Controller\Setting::getValue('thumbnail_quality', 'Shop'))) { \Message::error(sprintf($_ARRAYLANG['TXT_SHOP_COULD_NOT_CREATE_THUMBNAIL'], $arrImage['img'])); } } } \Message::ok($new ? $_ARRAYLANG['TXT_DATA_RECORD_ADDED_SUCCESSFUL'] : $_ARRAYLANG['TXT_DATA_RECORD_UPDATED_SUCCESSFUL']); switch ($_POST['afterStoreAction']) { case 'newEmpty': \Cx\Core\Csrf\Controller\Csrf::redirect('index.php?cmd=Shop' . MODULE_INDEX . '&act=products&tpl=manage'); case 'newTemplate': \Cx\Core\Csrf\Controller\Csrf::redirect('index.php?cmd=Shop' . MODULE_INDEX . '&act=products&tpl=manage&id=' . $objProduct->id() . '&new=1'); } \Cx\Core\Csrf\Controller\Csrf::redirect('index.php?cmd=Shop' . MODULE_INDEX . '&act=products'); // Never reached return true; }