public function processGenerate() { if (!is_array(Tools::getValue('options'))) { $this->errors[] = Tools::displayError('Please select at least one attribute.'); } else { $tab = array_values(Tools::getValue('options')); if (count($tab) && Validate::isLoadedObject($this->product)) { AdminAttributeGeneratorController::setAttributesImpacts($this->product->id, $tab); $this->combinations = array_values(AdminAttributeGeneratorController::createCombinations($tab)); $values = array_values(array_map(array($this, 'addAttribute'), $this->combinations)); // @since 1.5.0 if ($this->product->depends_on_stock == 0) { $attributes = Product::getProductAttributesIds($this->product->id, true); foreach ($attributes as $attribute) { StockAvailable::removeProductFromStockAvailable($this->product->id, $attribute['id_product_attribute'], Context::getContext()->shop); } } SpecificPriceRule::disableAnyApplication(); $this->product->deleteProductAttributes(); $this->product->generateMultipleCombinations($values, $this->combinations); // @since 1.5.0 if ($this->product->depends_on_stock == 0) { $attributes = Product::getProductAttributesIds($this->product->id, true); $quantity = str_replace(',', '.', Tools::getValue('quantity')); foreach ($attributes as $attribute) { StockAvailable::setQuantity($this->product->id, $attribute['id_product_attribute'], $quantity); } } else { StockAvailable::synchronize($this->product->id); } SpecificPriceRule::enableAnyApplication(); SpecificPriceRule::applyAllRules(array((int) $this->product->id)); Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts') . '&id_product=' . (int) Tools::getValue('id_product') . '&updateproduct&key_tab=Combinations&conf=4'); } else { $this->errors[] = Tools::displayError('Unable to initialize these parameters. A combination is missing or an object cannot be loaded.'); } } }
protected function attributeImportOne($info, $default_language, &$groups, &$attributes, $regenerate, $shop_is_feature_active, $validateOnly = false) { AdminImportController::setDefaultValues($info); if (!$shop_is_feature_active) { $info['shop'] = 1; } elseif (!isset($info['shop']) || empty($info['shop'])) { $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); } // Get shops for each attributes $info['shop'] = explode($this->multiple_value_separator, $info['shop']); $id_shop_list = array(); if (is_array($info['shop']) && count($info['shop'])) { foreach ($info['shop'] as $shop) { if (!empty($shop) && !is_numeric($shop)) { $id_shop_list[] = Shop::getIdByName($shop); } elseif (!empty($shop)) { $id_shop_list[] = $shop; } } } if (isset($info['id_product']) && $info['id_product']) { $product = new Product((int) $info['id_product'], false, $default_language); } elseif (Tools::getValue('match_ref') && isset($info['product_reference']) && $info['product_reference']) { $datas = Db::getInstance()->getRow(' SELECT p.`id_product` FROM `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' WHERE p.`reference` = "' . pSQL($info['product_reference']) . '" ', false); if (isset($datas['id_product']) && $datas['id_product']) { $product = new Product((int) $datas['id_product'], false, $default_language); } } else { return; } $id_image = array(); if (isset($info['image_url']) && $info['image_url']) { $info['image_url'] = explode($this->multiple_value_separator, $info['image_url']); if (is_array($info['image_url']) && count($info['image_url'])) { foreach ($info['image_url'] as $key => $url) { $url = trim($url); $product_has_images = (bool) Image::getImages($this->context->language->id, $product->id); $image = new Image(); $image->id_product = (int) $product->id; $image->position = Image::getHighestPosition($product->id) + 1; $image->cover = !$product_has_images ? true : false; if (isset($info['image_alt'])) { $alt = self::split($info['image_alt']); if (isset($alt[$key]) && strlen($alt[$key]) > 0) { $alt = self::createMultiLangField($alt[$key]); $image->legend = $alt; } } $field_error = $image->validateFields(UNFRIENDLY_ERROR, true); $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true); if ($field_error === true && $lang_field_error === true && !$validateOnly && $image->add()) { $image->associateTo($id_shop_list); // FIXME: 2s/image ! if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !$regenerate)) { $this->warnings[] = sprintf($this->trans('Error copying image: %s', array(), 'Admin.Parameters.Notification'), $url); $image->delete(); } else { $id_image[] = (int) $image->id; } // until here } else { if (!$validateOnly) { $this->warnings[] = sprintf($this->trans('%s cannot be saved', array(), 'Admin.Parameters.Notification'), isset($image->id_product) ? ' (' . $image->id_product . ')' : ''); } if ($field_error !== true || $lang_field_error !== true) { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . mysql_error(); } } } } } elseif (isset($info['image_position']) && $info['image_position']) { $info['image_position'] = explode($this->multiple_value_separator, $info['image_position']); if (is_array($info['image_position']) && count($info['image_position'])) { foreach ($info['image_position'] as $position) { // choose images from product by position $images = $product->getImages($default_language); if ($images) { foreach ($images as $row) { if ($row['position'] == (int) $position) { $id_image[] = (int) $row['id_image']; break; } } } if (empty($id_image)) { $this->warnings[] = sprintf($this->trans('No image was found for combination with id_product = %s and image position = %s.', array(), 'Admin.Parameters.Notification'), $product->id, (int) $position); } } } } $id_attribute_group = 0; // groups $groups_attributes = array(); if (isset($info['group'])) { foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) { if (empty($group)) { continue; } $tab_group = explode(':', $group); $group = trim($tab_group[0]); if (!isset($tab_group[1])) { $type = 'select'; } else { $type = trim($tab_group[1]); } // sets group $groups_attributes[$key]['group'] = $group; // if position is filled if (isset($tab_group[2])) { $position = trim($tab_group[2]); } else { $position = false; } if (!isset($groups[$group])) { $obj = new AttributeGroup(); $obj->is_color_group = false; $obj->group_type = pSQL($type); $obj->name[$default_language] = $group; $obj->public_name[$default_language] = $group; $obj->position = !$position ? AttributeGroup::getHigherPosition() + 1 : $position; if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { // here, cannot avoid attributeGroup insertion to avoid an error during validation step. //if (!$validateOnly) { $obj->add(); $obj->associateTo($id_shop_list); $groups[$group] = $obj->id; //} } else { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); } // fills groups attributes $id_attribute_group = $obj->id; $groups_attributes[$key]['id'] = $id_attribute_group; } else { // already exists $id_attribute_group = $groups[$group]; $groups_attributes[$key]['id'] = $id_attribute_group; } } } // inits attribute $id_product_attribute = 0; $id_product_attribute_update = false; $attributes_to_add = array(); // for each attribute if (isset($info['attribute'])) { foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute) { if (empty($attribute)) { continue; } $tab_attribute = explode(':', $attribute); $attribute = trim($tab_attribute[0]); // if position is filled if (isset($tab_attribute[1])) { $position = trim($tab_attribute[1]); } else { $position = false; } if (isset($groups_attributes[$key])) { $group = $groups_attributes[$key]['group']; if (!isset($attributes[$group . '_' . $attribute]) && count($groups_attributes[$key]) == 2) { $id_attribute_group = $groups_attributes[$key]['id']; $obj = new Attribute(); // sets the proper id (corresponding to the right key) $obj->id_attribute_group = $groups_attributes[$key]['id']; $obj->name[$default_language] = str_replace('\\n', '', str_replace('\\r', '', $attribute)); $obj->position = !$position && isset($groups[$group]) ? Attribute::getHigherPosition($groups[$group]) + 1 : $position; if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { if (!$validateOnly) { $obj->add(); $obj->associateTo($id_shop_list); $attributes[$group . '_' . $attribute] = $obj->id; } } else { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); } } $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int) $info['minimal_quantity'] : 1; $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']); $info['price'] = str_replace(',', '.', $info['price']); $info['ecotax'] = str_replace(',', '.', $info['ecotax']); $info['weight'] = str_replace(',', '.', $info['weight']); $info['available_date'] = Validate::isDate($info['available_date']) ? $info['available_date'] : null; if (!Validate::isEan13($info['ean13'])) { $this->warnings[] = sprintf($this->trans('EAN13 "%1s" has incorrect value for product with id %2d.', array(), 'Admin.Parameters.Notification'), $info['ean13'], $product->id); $info['ean13'] = ''; } if ($info['default_on'] && !$validateOnly) { $product->deleteDefaultAttributes(); } // if a reference is specified for this product, get the associate id_product_attribute to UPDATE if (isset($info['reference']) && !empty($info['reference'])) { $id_product_attribute = Combination::getIdByReference($product->id, strval($info['reference'])); // updates the attribute if ($id_product_attribute && !$validateOnly) { // gets all the combinations of this product $attribute_combinations = $product->getAttributeCombinations($default_language); foreach ($attribute_combinations as $attribute_combination) { if ($id_product_attribute && in_array($id_product_attribute, $attribute_combination)) { // FIXME: ~3s/declinaison $product->updateAttribute($id_product_attribute, (double) $info['wholesale_price'], (double) $info['price'], (double) $info['weight'], 0, Configuration::get('PS_USE_ECOTAX') ? (double) $info['ecotax'] : 0, $id_image, strval($info['reference']), strval($info['ean13']), (int) $info['default_on'], 0, strval($info['upc']), (int) $info['minimal_quantity'], $info['available_date'], null, $id_shop_list); $id_product_attribute_update = true; if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); } // until here } } } } // if no attribute reference is specified, creates a new one if (!$id_product_attribute && !$validateOnly) { $id_product_attribute = $product->addCombinationEntity((double) $info['wholesale_price'], (double) $info['price'], (double) $info['weight'], 0, Configuration::get('PS_USE_ECOTAX') ? (double) $info['ecotax'] : 0, (int) $info['quantity'], $id_image, strval($info['reference']), 0, strval($info['ean13']), (int) $info['default_on'], 0, strval($info['upc']), (int) $info['minimal_quantity'], $id_shop_list, $info['available_date']); if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); } } // fills our attributes array, in order to add the attributes to the product_attribute afterwards if (isset($attributes[$group . '_' . $attribute])) { $attributes_to_add[] = (int) $attributes[$group . '_' . $attribute]; } // after insertion, we clean attribute position and group attribute position if (!$validateOnly) { $obj = new Attribute(); $obj->cleanPositions((int) $id_attribute_group, false); AttributeGroup::cleanPositions(); } } } } $product->checkDefaultAttributes(); if (!$product->cache_default_attribute && !$validateOnly) { Product::updateDefaultAttribute($product->id); } if ($id_product_attribute) { if (!$validateOnly) { // now adds the attributes in the attribute_combination table if ($id_product_attribute_update) { Db::getInstance()->execute(' DELETE FROM ' . _DB_PREFIX_ . 'product_attribute_combination WHERE id_product_attribute = ' . (int) $id_product_attribute); } foreach ($attributes_to_add as $attribute_to_add) { Db::getInstance()->execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'product_attribute_combination (id_attribute, id_product_attribute) VALUES (' . (int) $attribute_to_add . ',' . (int) $id_product_attribute . ')', false); } } // set advanced stock managment if (isset($info['advanced_stock_management'])) { if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0) { $this->warnings[] = sprintf($this->trans('Advanced stock management has incorrect value. Not set for product with id %d.', array(), 'Admin.Parameters.Notification'), $product->id); } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1) { $this->warnings[] = sprintf($this->trans('Advanced stock management is not enabled, cannot enable on product with id %d.', array(), 'Admin.Parameters.Notification'), $product->id); } elseif (!$validateOnly) { $product->setAdvancedStockManagement($info['advanced_stock_management']); } // automaticly disable depends on stock, if a_s_m set to disabled if (!$validateOnly && StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0) { StockAvailable::setProductDependsOnStock($product->id, 0, null, $id_product_attribute); } } // Check if warehouse exists if (isset($info['warehouse']) && $info['warehouse']) { if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { $this->warnings[] = sprintf($this->trans('Advanced stock management is not enabled, warehouse is not set on product with id %d.', array(), 'Admin.Parameters.Notification'), $product->id); } else { if (Warehouse::exists($info['warehouse'])) { $warehouse_location_entity = new WarehouseProductLocation(); $warehouse_location_entity->id_product = $product->id; $warehouse_location_entity->id_product_attribute = $id_product_attribute; $warehouse_location_entity->id_warehouse = $info['warehouse']; if (!$validateOnly) { if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false) { $warehouse_location_entity->update(); } else { $warehouse_location_entity->save(); } StockAvailable::synchronize($product->id); } } else { $this->warnings[] = sprintf($this->trans('Warehouse did not exist, cannot set on product %1$s.', array(), 'Admin.Parameters.Notification'), $product->name[$default_language]); } } } // stock available if (isset($info['depends_on_stock'])) { if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1) { $this->warnings[] = sprintf($this->trans('Incorrect value for "Depends on stock" for product %1$s ', array(), 'Admin.Notifications.Error'), $product->name[$default_language]); } elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1) { $this->warnings[] = sprintf($this->trans('Advanced stock management is not enabled, cannot set "Depends on stock" for product %1$s ', array(), 'Admin.Parameters.Notification'), $product->name[$default_language]); } elseif (!$validateOnly) { StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'], null, $id_product_attribute); } // This code allows us to set qty and disable depends on stock if (isset($info['quantity']) && (int) $info['quantity']) { // if depends on stock and quantity, add quantity to stock if ($info['depends_on_stock'] == 1) { $stock_manager = StockManagerFactory::getManager(); $price = str_replace(',', '.', $info['wholesale_price']); if ($price == 0) { $price = 1.0E-6; } $price = round(floatval($price), 6); $warehouse = new Warehouse($info['warehouse']); if (!$validateOnly && $stock_manager->addProduct((int) $product->id, $id_product_attribute, $warehouse, (int) $info['quantity'], 1, $price, true)) { StockAvailable::synchronize((int) $product->id); } } elseif (!$validateOnly) { if ($shop_is_feature_active) { foreach ($id_shop_list as $shop) { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id); } } } } elseif (!$validateOnly) { // if not depends_on_stock set, use normal qty if ($shop_is_feature_active) { foreach ($id_shop_list as $shop) { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id); } } } }
/** * Helper function for AdminSupplyOrdersController::postProcess() * * @see AdminSupplyOrdersController::postProcess() */ protected function postProcessUpdateReceipt() { // gets all box selected $rows = Tools::getValue('supply_order_detailBox'); if (!$rows) { $this->errors[] = Tools::displayError('You did not select any products to update.'); return; } // final array with id_supply_order_detail and value to update $to_update = array(); // gets quantity for each id_order_detail foreach ($rows as $row) { if (Tools::getValue('quantity_received_today_' . $row)) { $to_update[$row] = (int) Tools::getValue('quantity_received_today_' . $row); } } // checks if there is something to update if (!count($to_update)) { $this->errors[] = Tools::displayError('You did not select any products to update.'); return; } $supply_order = new SupplyOrder((int) Tools::getValue('id_supply_order')); foreach ($to_update as $id_supply_order_detail => $quantity) { $supply_order_detail = new SupplyOrderDetail($id_supply_order_detail); if (Validate::isLoadedObject($supply_order_detail) && Validate::isLoadedObject($supply_order)) { // checks if quantity is valid // It's possible to receive more quantity than expected in case of a shipping error from the supplier if (!Validate::isInt($quantity) || $quantity <= 0) { $this->errors[] = sprintf(Tools::displayError('Quantity (%d) for product #%d is not valid'), (int) $quantity, (int) $id_supply_order_detail); } else { // creates the history $supplier_receipt_history = new SupplyOrderReceiptHistory(); $supplier_receipt_history->id_supply_order_detail = (int) $id_supply_order_detail; $supplier_receipt_history->id_employee = (int) $this->context->employee->id; $supplier_receipt_history->employee_firstname = pSQL($this->context->employee->firstname); $supplier_receipt_history->employee_lastname = pSQL($this->context->employee->lastname); $supplier_receipt_history->id_supply_order_state = (int) $supply_order->id_supply_order_state; $supplier_receipt_history->quantity = (int) $quantity; // updates quantity received $supply_order_detail->quantity_received += (int) $quantity; // if current state is "Pending receipt", then we sets it to "Order received in part" if (3 == $supply_order->id_supply_order_state) { $supply_order->id_supply_order_state = 4; } // Adds to stock $warehouse = new Warehouse($supply_order->id_warehouse); if (!Validate::isLoadedObject($warehouse)) { $this->errors[] = Tools::displayError('The warehouse could not be loaded.'); return; } $price = $supply_order_detail->unit_price_te; // converts the unit price to the warehouse currency if needed if ($supply_order->id_currency != $warehouse->id_currency) { // first, converts the price to the default currency $price_converted_to_default_currency = Tools::convertPrice($supply_order_detail->unit_price_te, $supply_order->id_currency, false); // then, converts the newly calculated pri-ce from the default currency to the needed currency $price = Tools::ps_round(Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true), 6); } $manager = StockManagerFactory::getManager(); $res = $manager->addProduct($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $warehouse, (int) $quantity, Configuration::get('PS_STOCK_MVT_SUPPLY_ORDER'), $price, true, $supply_order->id); $location = Warehouse::getProductLocation($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $warehouse->id); $res = Warehouse::setProductlocation($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $warehouse->id, $location ? $location : ''); if ($res) { $supplier_receipt_history->add(); $supply_order_detail->save(); StockAvailable::synchronize($supply_order_detail->id_product); } else { $this->errors[] = Tools::displayError('Something went wrong when setting warehouse on product record'); } } } } $supply_order->id_supply_order_state = $supply_order->id_supply_order_state == 4 && $supply_order->getAllPendingQuantity() > 0 ? 4 : 5; $supply_order->save(); if (!count($this->errors)) { // display confirm message $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; $redirect = self::$currentIndex . '&token=' . $token; $this->redirect_after = $redirect . '&conf=4'; } }
public function resetStockAvailable() { $products = WarehouseProductLocation::getProducts((int) $this->id); foreach ($products as $product) { StockAvailable::synchronize((int) $product['id_product']); } }
public function productHandler($product) { if (empty($product['idproduct'])) { $this->errors[] = Tools::displayError($this->l('Error : the id of the product is missing !')); return false; } $inventory_product = new InventoryProduct(); $inventory_product->id_erpip_inventory = self::$id_erpip_inventory_static; $inventory_product->id_product = $product['idproduct']; $inventory_product->id_product_attribute = $product['idproductattribute']; $inventory_product->qte_before = !isset($product['physicalquantity']) || $product['physicalquantity'] == '' ? 0 : $product['physicalquantity']; $inventory_product->qte_after = !isset($product['foundquantity']) || $product['foundquantity'] == '' ? 0 : (int) $product['foundquantity']; $inventory_product->id_warehouse = Tools::isSubmit('id_warehouse') ? (int) Tools::getValue('id_warehouse') : -1; // if not mvt reason chosen => depend of quanities, select increate or decrease if (!isset($product['idreason']) || $product['idreason'] == '') { if ($inventory_product->qte_before <= $inventory_product->qte_after) { $inventory_product->id_mvt_reason = 1; } else { $inventory_product->id_mvt_reason = 2; } } else { $inventory_product->id_mvt_reason = $product['idreason']; } // Gireg: // only treat products that match to stock manager selected : // Products in advanced stock manager if we re in advanced stock manager // Or product in non advanced stock manager, if we are in non advanced stock manager if ($this->advanced_stock_management == StockAvailable::dependsOnStock((int) $product['idproduct'])) { // If record inventory line --> update stock if ($inventory_product->add()) { // if advanced stock manager if ($this->advanced_stock_management == 1) { $stock = new ErpStock(); $stock->id_product = $product['idproduct']; $stock->id_product_attribute = $product['idproductattribute']; $stock->id_warehouse = $this->id_warehouse; $stock->physical_quantity = !isset($product['foundquantity']) || $product['foundquantity'] == '' ? 0 : (int) $product['foundquantity']; $stock->usable_quantity = !isset($product['foundquantity']) || $product['foundquantity'] == '' ? 0 : (int) $product['foundquantity']; // get reference price $price = $stock->getPriceTe(); // if $price is false, we dont have stock for this product. si quantity is lower than stock, set price to 0 if (isset($product['foundquantity']) && (int) $product['foundquantity'] < $product['physicalquantity'] || ($price = false)) { $price = 0; } $stock->price_te = $price; // if we already have a stock line for this production, we update else we insert if ($stock->id = $stock->getStockId()) { $maj_stock = $stock->update(); } else { $maj_stock = $stock->add(); } } else { $maj_stock = StockAvailable::setQuantity($product['idproduct'], $product['idproductattribute'], (int) $product['foundquantity']); if (is_null($maj_stock)) { $maj_stock = true; } } // if update stock ok --> update location if ($maj_stock) { // no stock change if advanced stock inactive if ($this->advanced_stock_management == 1) { require_once _PS_MODULE_DIR_ . 'erpillicopresta/classes/stock/ErpWarehouseProductLocation.php'; $wpl_id = ErpWarehouseProductLocationClass::getWarehouseProductLocationId($product['idproduct'], $product['idproductattribute']); $warehouse_location = new ErpWarehouseProductLocationClass($wpl_id); $warehouse_location->id_product = $product['idproduct']; $warehouse_location->id_product_attribute = $product['idproductattribute']; $warehouse_location->id_warehouse = $this->id_warehouse; /*if ($product['area'] != '--') $warehouse_location->zone = $product['area']; if ($product['subarea'] != '--') $warehouse_location->sous_zone = $product['subarea'];*/ $warehouse_location->location = $product['location']; $warehouse_location->id_warehouse_product_location = $wpl_id; // if update location ok & advanced stock active -> generate stock movement if ($warehouse_location->update()) { //echo 'Maj location OK'; // No stock movement if advanced stock inactive if ($this->advanced_stock_management == 1) { $stock_mvt = new ErpStockMvt(); $stock_mvt->id_stock = $stock->id; $stock_mvt->id_order = 0; $stock_mvt->id_supply_order = 0; // if not mvt reason selected => depend of quantity to increase or decrease if (!isset($product['idreason']) || $product['idreason'] == '') { if ($inventory_product->qte_before <= $inventory_product->qte_after) { $stock_mvt->id_stock_mvt_reason = 1; } else { $stock_mvt->id_stock_mvt_reason = 2; } } else { $stock_mvt->id_stock_mvt_reason = $product['idreason']; } $stock_mvt->id_employee = $this->id_employee; $stock_mvt->employee_firstname = $this->firstname; $stock_mvt->employee_lastname = $this->lastname; $stock_mvt->price_te = $price; $stock_mvt->current_wa = $price; // Récupération du sign (flèche up / down) // Get sign (arrow up/down) if (isset($product['foundquantity']) && ((int) $product['foundquantity'] >= (int) $product['physicalquantity'] || (int) $product['foundquantity'] == 0)) { $stock_mvt->sign = 1; } else { $stock_mvt->sign = -1; } // calculate the quantity movement of stock $foundquantity = !isset($product['foundquantity']) || $product['foundquantity'] == '' ? 0 : (int) $product['foundquantity']; $physicalquantity = !isset($product['physicalquantity']) || $product['physicalquantity'] == '' ? 0 : (int) $product['physicalquantity']; $mvt = abs($foundquantity - $physicalquantity); $stock_mvt->physical_quantity = $mvt; // Synchronise available stock if ($stock_mvt->add(true)) { StockAvailable::synchronize($product['idproduct']); } else { $this->errors[] = Tools::displayError($this->l('Error while inserting stock movement. Please try again.')); } } else { $this->errors[] = Tools::displayError($this->l('No stock movement. You need to activate the advanced stock management in Preference > Products')); } } else { $this->errors[] = Tools::displayError($this->l('Error while updating product location')); } } } else { $this->errors[] = Tools::displayError($this->l('Error while updating stock')); } } else { $this->errors[] = Tools::displayError($this->l('Error while inserting product inventory row')); } } }
public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null) { if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Function called', 1, null, 'Cart', (int) $id_cart, true); } if (!isset($this->context)) { $this->context = Context::getContext(); } $this->context->cart = new Cart($id_cart); $this->context->customer = new Customer($this->context->cart->id_customer); // The tax cart is loaded before the customer so re-cache the tax calculation method $this->context->cart->setTaxCalculationMethod(); $this->context->language = new Language($this->context->cart->id_lang); $this->context->shop = $shop ? $shop : new Shop($this->context->cart->id_shop); ShopUrl::resetMainDomainCache(); $id_currency = $currency_special ? (int) $currency_special : (int) $this->context->cart->id_currency; $this->context->currency = new Currency($id_currency, null, $this->context->shop->id); if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { $context_country = $this->context->country; } $order_status = new OrderState((int) $id_order_state, (int) $this->context->language->id); if (!Validate::isLoadedObject($order_status)) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status cannot be loaded', 3, null, 'Cart', (int) $id_cart, true); throw new PrestaShopException('Can\'t load Order status'); } if (!$this->active) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Module is not active', 3, null, 'Cart', (int) $id_cart, true); die(Tools::displayError()); } // Does order already exists ? if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false) { if ($secure_key !== false && $secure_key != $this->context->cart->secure_key) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Secure key does not match', 3, null, 'Cart', (int) $id_cart, true); die(Tools::displayError()); } // For each package, generate an order $delivery_option_list = $this->context->cart->getDeliveryOptionList(); $package_list = $this->context->cart->getPackageList(); $cart_delivery_option = $this->context->cart->getDeliveryOption(); // If some delivery options are not defined, or not valid, use the first valid option foreach ($delivery_option_list as $id_address => $package) { if (!isset($cart_delivery_option[$id_address]) || !array_key_exists($cart_delivery_option[$id_address], $package)) { foreach ($package as $key => $val) { $cart_delivery_option[$id_address] = $key; break; } } } $order_list = array(); $order_detail_list = array(); do { $reference = Order::generateReference(); } while (Order::getByReference($reference)->count()); $this->currentOrderReference = $reference; $order_creation_failed = false; $cart_total_paid = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(true, Cart::BOTH), 2); foreach ($cart_delivery_option as $id_address => $key_carriers) { foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data) { foreach ($data['package_list'] as $id_package) { // Rewrite the id_warehouse $package_list[$id_address][$id_package]['id_warehouse'] = (int) $this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int) $id_carrier); $package_list[$id_address][$id_package]['id_carrier'] = $id_carrier; } } } // Make sure CartRule caches are empty CartRule::cleanCache(); $cart_rules = $this->context->cart->getCartRules(); foreach ($cart_rules as $cart_rule) { if (($rule = new CartRule((int) $cart_rule['obj']->id)) && Validate::isLoadedObject($rule)) { if ($error = $rule->checkValidity($this->context, true, true)) { $this->context->cart->removeCartRule((int) $rule->id); if (isset($this->context->cookie) && isset($this->context->cookie->id_customer) && $this->context->cookie->id_customer && !empty($rule->code)) { if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) { Tools::redirect('index.php?controller=order-opc&submitAddDiscount=1&discount_name=' . urlencode($rule->code)); } Tools::redirect('index.php?controller=order&submitAddDiscount=1&discount_name=' . urlencode($rule->code)); } else { $rule_name = isset($rule->name[(int) $this->context->cart->id_lang]) ? $rule->name[(int) $this->context->cart->id_lang] : $rule->code; $error = Tools::displayError(sprintf('CartRule ID %1s (%2s) used in this cart is not valid and has been withdrawn from cart', (int) $rule->id, $rule_name)); PrestaShopLogger::addLog($error, 3, '0000002', 'Cart', (int) $this->context->cart->id); } } } } foreach ($package_list as $id_address => $packageByAddress) { foreach ($packageByAddress as $id_package => $package) { $order = new Order(); $order->product_list = $package['product_list']; if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { $address = new Address($id_address); $this->context->country = new Country($address->id_country, $this->context->cart->id_lang); if (!$this->context->country->active) { throw new PrestaShopException('The delivery address country is not active.'); } } $carrier = null; if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier'])) { $carrier = new Carrier($package['id_carrier'], $this->context->cart->id_lang); $order->id_carrier = (int) $carrier->id; $id_carrier = (int) $carrier->id; } else { $order->id_carrier = 0; $id_carrier = 0; } $order->id_customer = (int) $this->context->cart->id_customer; $order->id_address_invoice = (int) $this->context->cart->id_address_invoice; $order->id_address_delivery = (int) $id_address; $order->id_currency = $this->context->currency->id; $order->id_lang = (int) $this->context->cart->id_lang; $order->id_cart = (int) $this->context->cart->id; $order->reference = $reference; $order->id_shop = (int) $this->context->shop->id; $order->id_shop_group = (int) $this->context->shop->id_shop_group; $order->secure_key = $secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key); $order->payment = $payment_method; if (isset($this->name)) { $order->module = $this->name; } $order->recyclable = $this->context->cart->recyclable; $order->gift = (int) $this->context->cart->gift; $order->gift_message = $this->context->cart->gift_message; $order->mobile_theme = $this->context->cart->mobile_theme; $order->conversion_rate = $this->context->currency->conversion_rate; $amount_paid = !$dont_touch_amount ? Tools::ps_round((double) $amount_paid, 2) : $amount_paid; $order->total_paid_real = 0; $order->total_products = (double) $this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); $order->total_products_wt = (double) $this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); $order->total_discounts_tax_excl = (double) abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); $order->total_discounts_tax_incl = (double) abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); $order->total_discounts = $order->total_discounts_tax_incl; $order->total_shipping_tax_excl = (double) $this->context->cart->getPackageShippingCost((int) $id_carrier, false, null, $order->product_list); $order->total_shipping_tax_incl = (double) $this->context->cart->getPackageShippingCost((int) $id_carrier, true, null, $order->product_list); $order->total_shipping = $order->total_shipping_tax_incl; if (!is_null($carrier) && Validate::isLoadedObject($carrier)) { $order->carrier_tax_rate = $carrier->getTaxesRate(new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); } $order->total_wrapping_tax_excl = (double) abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); $order->total_wrapping_tax_incl = (double) abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); $order->total_wrapping = $order->total_wrapping_tax_incl; $order->total_paid_tax_excl = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_); $order->total_paid_tax_incl = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_); $order->total_paid = $order->total_paid_tax_incl; $order->round_mode = Configuration::get('PS_PRICE_ROUND_MODE'); $order->invoice_date = '0000-00-00 00:00:00'; $order->delivery_date = '0000-00-00 00:00:00'; if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Order is about to be added', 1, null, 'Cart', (int) $id_cart, true); } // Creating order $result = $order->add(); if (!$result) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Order cannot be created', 3, null, 'Cart', (int) $id_cart, true); throw new PrestaShopException('Can\'t save Order'); } // Amount paid by customer is not the right one -> Status = payment error // We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php // if ($order->total_paid != $order->total_paid_real) // We use number_format in order to compare two string if ($order_status->logable && number_format($cart_total_paid, _PS_PRICE_COMPUTE_PRECISION_) != number_format($amount_paid, _PS_PRICE_COMPUTE_PRECISION_)) { $id_order_state = Configuration::get('PS_OS_ERROR'); } $order_list[] = $order; if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderDetail is about to be added', 1, null, 'Cart', (int) $id_cart, true); } // Insert new Order detail list using cart for the current order $order_detail = new OrderDetail(null, null, $this->context); $order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']); $order_detail_list[] = $order_detail; if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderCarrier is about to be added', 1, null, 'Cart', (int) $id_cart, true); } // Adding an entry in order_carrier table if (!is_null($carrier)) { $order_carrier = new OrderCarrier(); $order_carrier->id_order = (int) $order->id; $order_carrier->id_carrier = (int) $id_carrier; $order_carrier->weight = (double) $order->getTotalWeight(); $order_carrier->shipping_cost_tax_excl = (double) $order->total_shipping_tax_excl; $order_carrier->shipping_cost_tax_incl = (double) $order->total_shipping_tax_incl; $order_carrier->add(); } } } // The country can only change if the address used for the calculation is the delivery address, and if multi-shipping is activated if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { $this->context->country = $context_country; } if (!$this->context->country->active) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Country is not active', 3, null, 'Cart', (int) $id_cart, true); throw new PrestaShopException('The order address country is not active.'); } if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Payment is about to be added', 1, null, 'Cart', (int) $id_cart, true); } // Register Payment only if the order status validate the order if ($order_status->logable) { // $order is the last order loop in the foreach // The method addOrderPayment of the class Order make a create a paymentOrder // linked to the order reference and not to the order id if (isset($extra_vars['transaction_id'])) { $transaction_id = $extra_vars['transaction_id']; } else { $transaction_id = null; } if (!$order->addOrderPayment($amount_paid, null, $transaction_id)) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Cannot save Order Payment', 3, null, 'Cart', (int) $id_cart, true); throw new PrestaShopException('Can\'t save Order Payment'); } } // Next ! $only_one_gift = false; $cart_rule_used = array(); $products = $this->context->cart->getProducts(); // Make sure CarRule caches are empty CartRule::cleanCache(); foreach ($order_detail_list as $key => $order_detail) { $order = $order_list[$key]; if (!$order_creation_failed && isset($order->id)) { if (!$secure_key) { $message .= '<br />' . Tools::displayError('Warning: the secure key is empty, check your payment account before validation'); } // Optional message to attach to this order if (isset($message) & !empty($message)) { $msg = new Message(); $message = strip_tags($message, '<br>'); if (Validate::isCleanHtml($message)) { if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Message is about to be added', 1, null, 'Cart', (int) $id_cart, true); } $msg->message = $message; $msg->id_order = (int) $order->id; $msg->private = 1; $msg->add(); } } // Insert new Order detail list using cart for the current order //$orderDetail = new OrderDetail(null, null, $this->context); //$orderDetail->createList($order, $this->context->cart, $id_order_state); // Construct order detail table for the email $products_list = ''; $virtual_product = true; $ppropertiessmartprice_hook1 = null; $product_var_tpl_list = array(); foreach ($order->product_list as $product) { PP::smartyPPAssign(array('cart' => $product, 'currency' => $this->context->currency)); $price = Product::getPriceStatic((int) $product['id_product'], false, $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null, 6, null, false, true, array($product['cart_quantity'], $product['cart_quantity_fractional']), false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $price_wt = Product::getPriceStatic((int) $product['id_product'], true, $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null, 2, null, false, true, array($product['cart_quantity'], $product['cart_quantity_fractional']), false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $ppropertiessmartprice_hook2 = ''; $product_var_tpl = array('reference' => $product['reference'], 'name' => $product['name'] . (isset($product['attributes']) ? ' - ' . $product['attributes'] : '') . PP::smartyDisplayProductName(array('name' => '')) . $ppropertiessmartprice_hook2, 'unit_price' => PP::smartyDisplayPrice(array('price' => Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt)), 'price' => PP::smartyDisplayPrice(array('price' => Product::getTaxCalculationMethod() == PS_TAX_EXC ? $product['total'] : $product['total_wt'], 'quantity' => (int) $product['cart_quantity'], 'm' => 'total')), 'quantity' => PP::smartyDisplayQty(array('quantity' => (int) $product['cart_quantity'])), 'customization' => array()); $customized_datas = Product::getAllCustomizedDatas((int) $order->id_cart); $productHasCustomizedDatas = Product::hasCustomizedDatas($product, $customized_datas); if ($productHasCustomizedDatas && isset($customized_datas[$product['id_product']][$product['id_product_attribute']])) { $product_var_tpl['customization'] = array(); foreach ($customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization) { if ($product['id_cart_product'] == $customization['id_cart_product']) { $customization_text = ''; if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) { foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text) { $customization_text .= $text['name'] . ': ' . $text['value'] . '<br />'; } } if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) { $customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])) . '<br />'; } $customization_quantity = (int) $product['customization_quantity']; $product_var_tpl['customization'][] = array('customization_text' => $customization_text, 'customization_quantity' => PP::smartyDisplayQty(array('quantity' => $customization_quantity)), 'quantity' => PP::smartyDisplayPrice(array('price' => Product::getTaxCalculationMethod() == PS_TAX_EXC ? $product['total_customization'] : $product['total_customization_wt'], 'm' => 'total'))); } } } $product_var_tpl_list[] = $product_var_tpl; // Check if is not a virutal product for the displaying of shipping if (!$product['is_virtual']) { $virtual_product &= false; } } // end foreach ($products) PP::smartyPPAssign(); $product_list_txt = ''; $product_list_html = ''; if (count($product_var_tpl_list) > 0) { $product_list_txt = $this->getEmailTemplateContent('order_conf_product_list.txt', Mail::TYPE_TEXT, $product_var_tpl_list); $product_list_html = $this->getEmailTemplateContent('order_conf_product_list.tpl', Mail::TYPE_HTML, $product_var_tpl_list); } $cart_rules_list = array(); $total_reduction_value_ti = 0; $total_reduction_value_tex = 0; foreach ($cart_rules as $cart_rule) { $package = array('id_carrier' => $order->id_carrier, 'id_address' => $order->id_address_delivery, 'products' => $order->product_list); $values = array('tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package), 'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package)); // If the reduction is not applicable to this order, then continue with the next one if (!$values['tax_excl']) { continue; } // IF // This is not multi-shipping // The value of the voucher is greater than the total of the order // Partial use is allowed // This is an "amount" reduction, not a reduction in % or a gift // THEN // The voucher is cloned with a new value corresponding to the remainder if (count($order_list) == 1 && $values['tax_incl'] > $order->total_products_wt - $total_reduction_value_ti && $cart_rule['obj']->partial_use == 1 && $cart_rule['obj']->reduction_amount > 0) { // Create a new voucher from the original $voucher = new CartRule($cart_rule['obj']->id); // We need to instantiate the CartRule without lang parameter to allow saving it unset($voucher->id); // Set a new voucher code $voucher->code = empty($voucher->code) ? Tools::substr(md5($order->id . '-' . $order->id_customer . '-' . $cart_rule['obj']->id), 0, 16) : $voucher->code . '-2'; if (preg_match('/\\-([0-9]{1,2})\\-([0-9]{1,2})$/', $voucher->code, $matches) && $matches[1] == $matches[2]) { $voucher->code = preg_replace('/' . $matches[0] . '$/', '-' . (int) ($matches[1] + 1), $voucher->code); } // Set the new voucher value if ($voucher->reduction_tax) { $voucher->reduction_amount = $total_reduction_value_ti + $values['tax_incl'] - $order->total_products_wt; // Add total shipping amout only if reduction amount > total shipping if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl) { $voucher->reduction_amount -= $order->total_shipping_tax_incl; } } else { $voucher->reduction_amount = $total_reduction_value_tex + $values['tax_excl'] - $order->total_products; // Add total shipping amout only if reduction amount > total shipping if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl) { $voucher->reduction_amount -= $order->total_shipping_tax_excl; } } if ($voucher->reduction_amount <= 0) { continue; } $voucher->id_customer = $order->id_customer; $voucher->quantity = 1; $voucher->quantity_per_user = 1; $voucher->free_shipping = 0; if ($voucher->add()) { // If the voucher has conditions, they are now copied to the new voucher CartRule::copyConditions($cart_rule['obj']->id, $voucher->id); $params = array('{voucher_amount}' => Tools::displayPrice($voucher->reduction_amount, $this->context->currency, false), '{voucher_num}' => $voucher->code, '{firstname}' => $this->context->customer->firstname, '{lastname}' => $this->context->customer->lastname, '{id_order}' => $order->reference, '{order_name}' => $order->getUniqReference()); Mail::Send((int) $order->id_lang, 'voucher', sprintf(Mail::l('New voucher for your order %s', (int) $order->id_lang), $order->reference), $params, $this->context->customer->email, $this->context->customer->firstname . ' ' . $this->context->customer->lastname, null, null, null, null, _PS_MAIL_DIR_, false, (int) $order->id_shop); } $values['tax_incl'] = $order->total_products_wt - $total_reduction_value_ti; $values['tax_excl'] = $order->total_products - $total_reduction_value_tex; } $total_reduction_value_ti += $values['tax_incl']; $total_reduction_value_tex += $values['tax_excl']; $order->addCartRule($cart_rule['obj']->id, $cart_rule['obj']->name, $values, 0, $cart_rule['obj']->free_shipping); if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && !in_array($cart_rule['obj']->id, $cart_rule_used)) { $cart_rule_used[] = $cart_rule['obj']->id; // Create a new instance of Cart Rule without id_lang, in order to update its quantity $cart_rule_to_update = new CartRule($cart_rule['obj']->id); $cart_rule_to_update->quantity = max(0, $cart_rule_to_update->quantity - 1); $cart_rule_to_update->update(); } $cart_rules_list[] = array('voucher_name' => $cart_rule['obj']->name, 'voucher_reduction' => ($values['tax_incl'] != 0.0 ? '-' : '') . Tools::displayPrice($values['tax_incl'], $this->context->currency, false)); } $cart_rules_list_txt = ''; $cart_rules_list_html = ''; if (count($cart_rules_list) > 0) { $cart_rules_list_txt = $this->getEmailTemplateContent('order_conf_cart_rules.txt', Mail::TYPE_TEXT, $cart_rules_list); $cart_rules_list_html = $this->getEmailTemplateContent('order_conf_cart_rules.tpl', Mail::TYPE_HTML, $cart_rules_list); } // Specify order id for message $old_message = Message::getMessageByCartId((int) $this->context->cart->id); if ($old_message) { $update_message = new Message((int) $old_message['id_message']); $update_message->id_order = (int) $order->id; $update_message->update(); // Add this message in the customer thread $customer_thread = new CustomerThread(); $customer_thread->id_contact = 0; $customer_thread->id_customer = (int) $order->id_customer; $customer_thread->id_shop = (int) $this->context->shop->id; $customer_thread->id_order = (int) $order->id; $customer_thread->id_lang = (int) $this->context->language->id; $customer_thread->email = $this->context->customer->email; $customer_thread->status = 'open'; $customer_thread->token = Tools::passwdGen(12); $customer_thread->add(); $customer_message = new CustomerMessage(); $customer_message->id_customer_thread = $customer_thread->id; $customer_message->id_employee = 0; $customer_message->message = $update_message->message; $customer_message->private = 0; if (!$customer_message->add()) { $this->errors[] = Tools::displayError('An error occurred while saving message'); } } if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Hook validateOrder is about to be called', 1, null, 'Cart', (int) $id_cart, true); } // Hook validate order Hook::exec('actionValidateOrder', array('cart' => $this->context->cart, 'order' => $order, 'customer' => $this->context->customer, 'currency' => $this->context->currency, 'orderStatus' => $order_status)); foreach ($this->context->cart->getProducts() as $product) { if ($order_status->logable) { ProductSale::addProductSale((int) $product['id_product'], (int) $product['cart_quantity']); } } if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status is about to be added', 1, null, 'Cart', (int) $id_cart, true); } // Set the order status $new_history = new OrderHistory(); $new_history->id_order = (int) $order->id; $new_history->changeIdOrderState((int) $id_order_state, $order, true); $new_history->addWithemail(true, $extra_vars); // Switch to back order if needed if (Configuration::get('PS_STOCK_MANAGEMENT') && $order_detail->getStockState()) { $history = new OrderHistory(); $history->id_order = (int) $order->id; $history->changeIdOrderState(Configuration::get($order->valid ? 'PS_OS_OUTOFSTOCK_PAID' : 'PS_OS_OUTOFSTOCK_UNPAID'), $order, true); $history->addWithemail(); } unset($order_detail); // Order is reloaded because the status just changed $order = new Order($order->id); // Send an e-mail to customer (one order = one email) if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && $this->context->customer->id) { $invoice = new Address($order->id_address_invoice); $delivery = new Address($order->id_address_delivery); $delivery_state = $delivery->id_state ? new State($delivery->id_state) : false; $invoice_state = $invoice->id_state ? new State($invoice->id_state) : false; $data = array('{firstname}' => $this->context->customer->firstname, '{lastname}' => $this->context->customer->lastname, '{email}' => $this->context->customer->email, '{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"), '{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"), '{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array('firstname' => '<span style="font-weight:bold;">%s</span>', 'lastname' => '<span style="font-weight:bold;">%s</span>')), '{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array('firstname' => '<span style="font-weight:bold;">%s</span>', 'lastname' => '<span style="font-weight:bold;">%s</span>')), '{delivery_company}' => $delivery->company, '{delivery_firstname}' => $delivery->firstname, '{delivery_lastname}' => $delivery->lastname, '{delivery_address1}' => $delivery->address1, '{delivery_address2}' => $delivery->address2, '{delivery_city}' => $delivery->city, '{delivery_postal_code}' => $delivery->postcode, '{delivery_country}' => $delivery->country, '{delivery_state}' => $delivery->id_state ? $delivery_state->name : '', '{delivery_phone}' => $delivery->phone ? $delivery->phone : $delivery->phone_mobile, '{delivery_other}' => $delivery->other, '{invoice_company}' => $invoice->company, '{invoice_vat_number}' => $invoice->vat_number, '{invoice_firstname}' => $invoice->firstname, '{invoice_lastname}' => $invoice->lastname, '{invoice_address2}' => $invoice->address2, '{invoice_address1}' => $invoice->address1, '{invoice_city}' => $invoice->city, '{invoice_postal_code}' => $invoice->postcode, '{invoice_country}' => $invoice->country, '{invoice_state}' => $invoice->id_state ? $invoice_state->name : '', '{invoice_phone}' => $invoice->phone ? $invoice->phone : $invoice->phone_mobile, '{invoice_other}' => $invoice->other, '{order_name}' => $order->getUniqReference(), '{date}' => Tools::displayDate(date('Y-m-d H:i:s'), null, 1), '{carrier}' => $virtual_product || !isset($carrier->name) ? Tools::displayError('No carrier') : $carrier->name, '{payment}' => Tools::substr($order->payment, 0, 32), '{products}' => $product_list_html, '{products_txt}' => $product_list_txt, '{discounts}' => $cart_rules_list_html, '{discounts_txt}' => $cart_rules_list_txt, '{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false), '{total_products}' => Tools::displayPrice($order->total_paid - $order->total_shipping - $order->total_wrapping + $order->total_discounts, $this->context->currency, false), '{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false), '{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false), '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false), '{total_tax_paid}' => Tools::displayPrice($order->total_products_wt - $order->total_products + ($order->total_shipping_tax_incl - $order->total_shipping_tax_excl), $this->context->currency, false)); if (is_array($extra_vars)) { $data = array_merge($data, $extra_vars); } // Join PDF invoice if ((int) Configuration::get('PS_INVOICE') && $order_status->invoice && $order->invoice_number) { $pdf = new PDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE, $this->context->smarty); $file_attachement = array(); $file_attachement['content'] = $pdf->render(false); $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf'; $file_attachement['mime'] = 'application/pdf'; } else { $file_attachement = null; } if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - Mail is about to be sent', 1, null, 'Cart', (int) $id_cart, true); } if (Validate::isEmail($this->context->customer->email)) { Mail::Send((int) $order->id_lang, 'order_conf', Mail::l('Order confirmation', (int) $order->id_lang), $data, $this->context->customer->email, $this->context->customer->firstname . ' ' . $this->context->customer->lastname, null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int) $order->id_shop); } } // updates stock in shops if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { $product_list = $order->getProducts(); foreach ($product_list as $product) { // if the available quantities depends on the physical stock if (StockAvailable::dependsOnStock($product['product_id'])) { // synchronizes StockAvailable::synchronize($product['product_id'], $order->id_shop); } } } } else { $error = Tools::displayError('Order creation failed'); PrestaShopLogger::addLog($error, 4, '0000002', 'Cart', (int) $order->id_cart); die($error); } } // End foreach $order_detail_list // Update Order Details Tax in case cart rules have free shipping foreach ($order->getOrderDetailList() as $detail) { $order_detail = new OrderDetail($detail['id_order_detail']); $order_detail->updateTaxAmount($order); } // Use the last order as currentOrder if (isset($order) && $order->id) { $this->currentOrder = (int) $order->id; } if (self::DEBUG_MODE) { PrestaShopLogger::addLog('PaymentModule::validateOrder - End of validateOrder', 1, null, 'Cart', (int) $id_cart, true); } return true; } else { $error = Tools::displayError('Cart cannot be loaded or an order has already been placed using this cart'); PrestaShopLogger::addLog($error, 4, '0000001', 'Cart', (int) $this->context->cart->id); die($error); } }
/** * AdminController::postProcess() override * @see AdminController::postProcess() */ public function postProcess() { parent::postProcess(); // Checks access if (Tools::isSubmit('addStock') && !($this->tabAccess['add'] === '1')) { $this->errors[] = Tools::displayError('You do not have the required permission to add stock.'); } if (Tools::isSubmit('removeStock') && !($this->tabAccess['delete'] === '1')) { $this->errors[] = Tools::displayError('You do not have the required permission to delete stock'); } if (Tools::isSubmit('transferStock') && !($this->tabAccess['edit'] === '1')) { $this->errors[] = Tools::displayError('You do not have the required permission to transfer stock.'); } if (count($this->errors)) { return; } // Global checks when add / remove / transfer product if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock') || Tools::isSubmit('transferstock')) && Tools::isSubmit('is_post')) { // get product ID $id_product = (int) Tools::getValue('id_product', 0); if ($id_product <= 0) { $this->errors[] = Tools::displayError('The selected product is not valid.'); } // get product_attribute ID $id_product_attribute = (int) Tools::getValue('id_product_attribute', 0); // check the product hash $check = Tools::getValue('check', ''); $check_valid = md5(_COOKIE_KEY_ . $id_product . $id_product_attribute); if ($check != $check_valid) { $this->errors[] = Tools::displayError('The selected product is not valid.'); } // get quantity and check that the post value is really an integer // If it's not, we have nothing to do $quantity = Tools::getValue('quantity', 0); if (!is_numeric($quantity) || (int) $quantity <= 0) { $this->errors[] = Tools::displayError('The quantity value is not valid.'); } $quantity = (int) $quantity; $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; $redirect = self::$currentIndex . '&token=' . $token; } // Global checks when add / remove product if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock')) && Tools::isSubmit('is_post')) { // get warehouse id $id_warehouse = (int) Tools::getValue('id_warehouse', 0); if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) { $this->errors[] = Tools::displayError('The selected warehouse is not valid.'); } // get stock movement reason id $id_stock_mvt_reason = (int) Tools::getValue('id_stock_mvt_reason', 0); if ($id_stock_mvt_reason <= 0 || !StockMvtReason::exists($id_stock_mvt_reason)) { $this->errors[] = Tools::displayError('The reason is not valid.'); } // get usable flag $usable = Tools::getValue('usable', null); if (is_null($usable)) { $this->errors[] = Tools::displayError('You have to specify whether the product quantity is usable for sale on shops or not.'); } $usable = (bool) $usable; } if (Tools::isSubmit('addstock') && Tools::isSubmit('is_post')) { // get product unit price $price = str_replace(',', '.', Tools::getValue('price', 0)); if (!is_numeric($price)) { $this->errors[] = Tools::displayError('The product price is not valid.'); } $price = round(floatval($price), 6); // get product unit price currency id $id_currency = (int) Tools::getValue('id_currency', 0); if ($id_currency <= 0 || (!($result = Currency::getCurrency($id_currency)) || empty($result))) { $this->errors[] = Tools::displayError('The selected currency is not valid.'); } // if all is ok, add stock if (count($this->errors) == 0) { $warehouse = new Warehouse($id_warehouse); // convert price to warehouse currency if needed if ($id_currency != $warehouse->id_currency) { // First convert price to the default currency $price_converted_to_default_currency = Tools::convertPrice($price, $id_currency, false); // Convert the new price from default currency to needed currency $price = Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true); } // add stock $stock_manager = StockManagerFactory::getManager(); if ($stock_manager->addProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $price, $usable)) { // Create warehouse_product_location entry if we add stock to a new warehouse $id_wpl = (int) WarehouseProductLocation::getIdByProductAndWarehouse($id_product, $id_product_attribute, $id_warehouse); if (!$id_wpl) { $wpl = new WarehouseProductLocation(); $wpl->id_product = (int) $id_product; $wpl->id_product_attribute = (int) $id_product_attribute; $wpl->id_warehouse = (int) $id_warehouse; $wpl->save(); } StockAvailable::synchronize($id_product); if (Tools::isSubmit('addstockAndStay')) { $redirect = self::$currentIndex . '&id_product=' . (int) $id_product; if ($id_product_attribute) { $redirect .= '&id_product_attribute=' . (int) $id_product_attribute; } $redirect .= '&addstock&token=' . $token; } Tools::redirectAdmin($redirect . '&conf=1'); } else { $this->errors[] = Tools::displayError('An error occurred. No stock was added.'); } } } if (Tools::isSubmit('removestock') && Tools::isSubmit('is_post')) { // if all is ok, remove stock if (count($this->errors) == 0) { $warehouse = new Warehouse($id_warehouse); // remove stock $stock_manager = StockManagerFactory::getManager(); $removed_products = $stock_manager->removeProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $usable); if (count($removed_products) > 0) { StockAvailable::synchronize($id_product); Tools::redirectAdmin($redirect . '&conf=2'); } else { $physical_quantity_in_stock = (int) $stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), false); $usable_quantity_in_stock = (int) $stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), true); $not_usable_quantity = $physical_quantity_in_stock - $usable_quantity_in_stock; if ($usable_quantity_in_stock < $quantity) { $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int) $quantity, (int) $usable_quantity_in_stock); } elseif ($not_usable_quantity < $quantity) { $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int) $quantity, (int) $not_usable_quantity); } else { $this->errors[] = Tools::displayError('It is not possible to remove the specified quantity. Therefore no stock was removed.'); } } } } if (Tools::isSubmit('transferstock') && Tools::isSubmit('is_post')) { // get source warehouse id $id_warehouse_from = (int) Tools::getValue('id_warehouse_from', 0); if ($id_warehouse_from <= 0 || !Warehouse::exists($id_warehouse_from)) { $this->errors[] = Tools::displayError('The source warehouse is not valid.'); } // get destination warehouse id $id_warehouse_to = (int) Tools::getValue('id_warehouse_to', 0); if ($id_warehouse_to <= 0 || !Warehouse::exists($id_warehouse_to)) { $this->errors[] = Tools::displayError('The destination warehouse is not valid.'); } // get usable flag for source warehouse $usable_from = Tools::getValue('usable_from', null); if (is_null($usable_from)) { $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your source warehouse(s) is ready for sale or not.'); } $usable_from = (bool) $usable_from; // get usable flag for destination warehouse $usable_to = Tools::getValue('usable_to', null); if (is_null($usable_to)) { $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your destination warehouse(s) is ready for sale or not.'); } $usable_to = (bool) $usable_to; // if we can process stock transfers if (count($this->errors) == 0) { // transfer stock $stock_manager = StockManagerFactory::getManager(); $is_transfer = $stock_manager->transferBetweenWarehouses($id_product, $id_product_attribute, $quantity, $id_warehouse_from, $id_warehouse_to, $usable_from, $usable_to); StockAvailable::synchronize($id_product); if ($is_transfer) { Tools::redirectAdmin($redirect . '&conf=3'); } else { $this->errors[] = Tools::displayError('It is not possible to transfer the specified quantity. No stock was transferred.'); } } } }
public function productImport() { // do standard stuff; need to copy/paste // because silly PS does not allow to hook inside of the import loop... $this->receiveTab(); $handle = $this->openCsvFile(); $default_language_id = (int) Configuration::get('PS_LANG_DEFAULT'); $id_lang = Language::getIdByIso(Tools::getValue('iso_lang')); if (!Validate::isUnsignedId($id_lang)) { $id_lang = $default_language_id; } AdminImportController::setLocale(); $shop_ids = Shop::getCompleteListOfShopsID(); for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { if (Tools::getValue('convert')) { $line = $this->utf8EncodeArray($line); } $info = AdminImportController::getMaskedRow($line); if (Tools::getValue('forceIDs') && isset($info['id']) && (int) $info['id']) { $product = new Product((int) $info['id']); } elseif (Tools::getValue('match_ref') && array_key_exists('reference', $info)) { $datas = Db::getInstance()->getRow(' SELECT p.`id_product` FROM `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' WHERE p.`reference` = "' . pSQL($info['reference']) . '" '); if (isset($datas['id_product']) && $datas['id_product']) { $product = new Product((int) $datas['id_product']); } else { $product = new Product(); } } elseif (array_key_exists('id', $info) && (int) $info['id'] && Product::existsInDatabase((int) $info['id'], 'product')) { $product = new Product((int) $info['id']); } else { $product = new Product(); } if (isset($product->id) && $product->id && Product::existsInDatabase((int) $product->id, 'product')) { $product->loadStockData(); $category_data = Product::getProductCategories((int) $product->id); if (is_array($category_data)) { foreach ($category_data as $tmp) { if (!isset($product->category) || !$product->category || is_array($product->category)) { $product->category[] = $tmp; } } } } AdminImportController::setEntityDefaultValues($product); AdminImportController::arrayWalk($info, array('AdminImportController', 'fillInfo'), $product); /* * 2015-03-26 - JLE SPECIFIC : * Import language specific infos */ foreach ($this->csv_translated_fields as $field) { foreach ($this->csv_languages as $lang) { if (isset($info[$field . "_" . $lang])) { $lang_id = Language::getIdByIso($lang); $product->{$field}[$lang_id] = $info[$field . "_" . $lang]; } } } /* * END SPECIFIC */ if (!Shop::isFeatureActive()) { $product->shop = 1; } elseif (!isset($product->shop) || empty($product->shop)) { $product->shop = implode($this->multiple_value_separator, Shop::getContextListShopID()); } if (!Shop::isFeatureActive()) { $product->id_shop_default = 1; } else { $product->id_shop_default = (int) Context::getContext()->shop->id; } // link product to shops $product->id_shop_list = array(); foreach (explode($this->multiple_value_separator, $product->shop) as $shop) { if (!empty($shop) && !is_numeric($shop)) { $product->id_shop_list[] = Shop::getIdByName($shop); } elseif (!empty($shop)) { $product->id_shop_list[] = $shop; } } if ((int) $product->id_tax_rules_group != 0) { if (Validate::isLoadedObject(new TaxRulesGroup($product->id_tax_rules_group))) { $address = $this->context->shop->getAddress(); $tax_manager = TaxManagerFactory::getManager($address, $product->id_tax_rules_group); $product_tax_calculator = $tax_manager->getTaxCalculator(); $product->tax_rate = $product_tax_calculator->getTotalRate(); } else { $this->addProductWarning('id_tax_rules_group', $product->id_tax_rules_group, Tools::displayError('Invalid tax rule group ID. You first need to create a group with this ID.')); } } if (isset($product->manufacturer) && is_numeric($product->manufacturer) && Manufacturer::manufacturerExists((int) $product->manufacturer)) { $product->id_manufacturer = (int) $product->manufacturer; } elseif (isset($product->manufacturer) && is_string($product->manufacturer) && !empty($product->manufacturer)) { if ($manufacturer = Manufacturer::getIdByName($product->manufacturer)) { $product->id_manufacturer = (int) $manufacturer; } else { $manufacturer = new Manufacturer(); $manufacturer->name = $product->manufacturer; if (($field_error = $manufacturer->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $manufacturer->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $manufacturer->add()) { $product->id_manufacturer = (int) $manufacturer->id; } else { $this->errors[] = sprintf(Tools::displayError('%1$s (ID: %2$s) cannot be saved'), $manufacturer->name, isset($manufacturer->id) && !empty($manufacturer->id) ? $manufacturer->id : 'null'); $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . Db::getInstance()->getMsgError(); } } } if (isset($product->supplier) && is_numeric($product->supplier) && Supplier::supplierExists((int) $product->supplier)) { $product->id_supplier = (int) $product->supplier; } elseif (isset($product->supplier) && is_string($product->supplier) && !empty($product->supplier)) { if ($supplier = Supplier::getIdByName($product->supplier)) { $product->id_supplier = (int) $supplier; } else { $supplier = new Supplier(); $supplier->name = $product->supplier; $supplier->active = true; if (($field_error = $supplier->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $supplier->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $supplier->add()) { $product->id_supplier = (int) $supplier->id; $supplier->associateTo($product->id_shop_list); } else { $this->errors[] = sprintf(Tools::displayError('%1$s (ID: %2$s) cannot be saved'), $supplier->name, isset($supplier->id) && !empty($supplier->id) ? $supplier->id : 'null'); $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . Db::getInstance()->getMsgError(); } } } if (isset($product->price_tex) && !isset($product->price_tin)) { $product->price = $product->price_tex; } elseif (isset($product->price_tin) && !isset($product->price_tex)) { $product->price = $product->price_tin; // If a tax is already included in price, withdraw it from price if ($product->tax_rate) { $product->price = (double) number_format($product->price / (1 + $product->tax_rate / 100), 6, '.', ''); } } elseif (isset($product->price_tin) && isset($product->price_tex)) { $product->price = $product->price_tex; } if (!Configuration::get('PS_USE_ECOTAX')) { $product->ecotax = 0; } if (isset($product->category) && is_array($product->category) && count($product->category)) { $product->id_category = array(); // Reset default values array foreach ($product->category as $value) { if (is_numeric($value)) { if (Category::categoryExists((int) $value)) { $product->id_category[] = (int) $value; } else { $category_to_create = new Category(); $category_to_create->id = (int) $value; $category_to_create->name = AdminImportController::createMultiLangField($value); $category_to_create->active = 1; $category_to_create->id_parent = Configuration::get('PS_HOME_CATEGORY'); // Default parent is home for unknown category to create $category_link_rewrite = Tools::link_rewrite($category_to_create->name[$default_language_id]); $category_to_create->link_rewrite = AdminImportController::createMultiLangField($category_link_rewrite); if (($field_error = $category_to_create->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $category_to_create->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $category_to_create->add()) { $product->id_category[] = (int) $category_to_create->id; } else { $this->errors[] = sprintf(Tools::displayError('%1$s (ID: %2$s) cannot be saved'), $category_to_create->name[$default_language_id], isset($category_to_create->id) && !empty($category_to_create->id) ? $category_to_create->id : 'null'); $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . Db::getInstance()->getMsgError(); } } } elseif (is_string($value) && !empty($value)) { $category = Category::searchByPath($default_language_id, trim($value), $this, 'productImportCreateCat'); if ($category['id_category']) { $product->id_category[] = (int) $category['id_category']; } else { $this->errors[] = sprintf(Tools::displayError('%1$s cannot be saved'), trim($value)); } } } $product->id_category = array_values(array_unique($product->id_category)); } if (!isset($product->id_category_default) || !$product->id_category_default) { $product->id_category_default = isset($product->id_category[0]) ? (int) $product->id_category[0] : (int) Configuration::get('PS_HOME_CATEGORY'); } $link_rewrite = is_array($product->link_rewrite) && isset($product->link_rewrite[$id_lang]) ? trim($product->link_rewrite[$id_lang]) : ''; $valid_link = Validate::isLinkRewrite($link_rewrite); if (isset($product->link_rewrite[$id_lang]) && empty($product->link_rewrite[$id_lang]) || !$valid_link) { $link_rewrite = Tools::link_rewrite($product->name[$id_lang]); if ($link_rewrite == '') { $link_rewrite = 'friendly-url-autogeneration-failed'; } } if (!$valid_link) { $this->warnings[] = sprintf(Tools::displayError('Rewrite link for %1$s (ID: %2$s) was re-written as %3$s.'), $product->name[$id_lang], isset($info['id']) && !empty($info['id']) ? $info['id'] : 'null', $link_rewrite); } if (!(Tools::getValue('match_ref') || Tools::getValue('forceIDs')) || !(is_array($product->link_rewrite) && count($product->link_rewrite) && !empty($product->link_rewrite[$id_lang]))) { $product->link_rewrite = AdminImportController::createMultiLangField($link_rewrite); } // replace the value of separator by coma if ($this->multiple_value_separator != ',') { if (is_array($product->meta_keywords)) { foreach ($product->meta_keywords as &$meta_keyword) { if (!empty($meta_keyword)) { $meta_keyword = str_replace($this->multiple_value_separator, ',', $meta_keyword); } } } } // Convert comma into dot for all floating values foreach (Product::$definition['fields'] as $key => $array) { if ($array['type'] == Product::TYPE_FLOAT) { $product->{$key} = str_replace(',', '.', $product->{$key}); } } // Indexation is already 0 if it's a new product, but not if it's an update $product->indexed = 0; $res = false; $field_error = $product->validateFields(UNFRIENDLY_ERROR, true); $lang_field_error = $product->validateFieldsLang(UNFRIENDLY_ERROR, true); if ($field_error === true && $lang_field_error === true) { // check quantity if ($product->quantity == null) { $product->quantity = 0; } // If match ref is specified && ref product && ref product already in base, trying to update if (Tools::getValue('match_ref') && $product->reference && $product->existsRefInDatabase($product->reference)) { $datas = Db::getInstance()->getRow(' SELECT product_shop.`date_add`, p.`id_product` FROM `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' WHERE p.`reference` = "' . pSQL($product->reference) . '" '); $product->id = (int) $datas['id_product']; $product->date_add = pSQL($datas['date_add']); $res = $product->update(); } elseif ($product->id && Product::existsInDatabase((int) $product->id, 'product')) { $datas = Db::getInstance()->getRow(' SELECT product_shop.`date_add` FROM `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' WHERE p.`id_product` = ' . (int) $product->id); $product->date_add = pSQL($datas['date_add']); $res = $product->update(); } // If no id_product or update failed $product->force_id = (bool) Tools::getValue('forceIDs'); if (!$res) { if (isset($product->date_add) && $product->date_add != '') { $res = $product->add(false); } else { $res = $product->add(); } } if ($product->getType() == Product::PTYPE_VIRTUAL) { StockAvailable::setProductOutOfStock((int) $product->id, 1); } else { StockAvailable::setProductOutOfStock((int) $product->id, (int) $product->out_of_stock); } } $shops = array(); $product_shop = explode($this->multiple_value_separator, $product->shop); foreach ($product_shop as $shop) { if (empty($shop)) { continue; } $shop = trim($shop); if (!empty($shop) && !is_numeric($shop)) { $shop = Shop::getIdByName($shop); } if (in_array($shop, $shop_ids)) { $shops[] = $shop; } else { $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Shop is not valid')); } } if (empty($shops)) { $shops = Shop::getContextListShopID(); } // If both failed, mysql error if (!$res) { $this->errors[] = sprintf(Tools::displayError('%1$s (ID: %2$s) cannot be saved'), isset($info['name']) && !empty($info['name']) ? Tools::safeOutput($info['name']) : 'No Name', isset($info['id']) && !empty($info['id']) ? Tools::safeOutput($info['id']) : 'No ID'); $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . Db::getInstance()->getMsgError(); } else { // Product supplier if (isset($product->id) && $product->id && isset($product->id_supplier) && property_exists($product, 'supplier_reference')) { $id_product_supplier = (int) ProductSupplier::getIdByProductAndSupplier((int) $product->id, 0, (int) $product->id_supplier); if ($id_product_supplier) { $product_supplier = new ProductSupplier($id_product_supplier); } else { $product_supplier = new ProductSupplier(); } $product_supplier->id_product = (int) $product->id; $product_supplier->id_product_attribute = 0; $product_supplier->id_supplier = (int) $product->id_supplier; $product_supplier->product_supplier_price_te = $product->wholesale_price; $product_supplier->product_supplier_reference = $product->supplier_reference; $product_supplier->save(); } // SpecificPrice (only the basic reduction feature is supported by the import) if (!Shop::isFeatureActive()) { $info['shop'] = 1; } elseif (!isset($info['shop']) || empty($info['shop'])) { $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); } // Get shops for each attributes $info['shop'] = explode($this->multiple_value_separator, $info['shop']); $id_shop_list = array(); foreach ($info['shop'] as $shop) { if (!empty($shop) && !is_numeric($shop)) { $id_shop_list[] = (int) Shop::getIdByName($shop); } elseif (!empty($shop)) { $id_shop_list[] = $shop; } } if (isset($info['reduction_price']) && $info['reduction_price'] > 0 || isset($info['reduction_percent']) && $info['reduction_percent'] > 0) { foreach ($id_shop_list as $id_shop) { $specific_price = SpecificPrice::getSpecificPrice($product->id, $id_shop, 0, 0, 0, 1, 0, 0, 0, 0); if (is_array($specific_price) && isset($specific_price['id_specific_price'])) { $specific_price = new SpecificPrice((int) $specific_price['id_specific_price']); } else { $specific_price = new SpecificPrice(); } $specific_price->id_product = (int) $product->id; $specific_price->id_specific_price_rule = 0; $specific_price->id_shop = $id_shop; $specific_price->id_currency = 0; $specific_price->id_country = 0; $specific_price->id_group = 0; $specific_price->price = -1; $specific_price->id_customer = 0; $specific_price->from_quantity = 1; $specific_price->reduction = isset($info['reduction_price']) && $info['reduction_price'] ? $info['reduction_price'] : $info['reduction_percent'] / 100; $specific_price->reduction_type = isset($info['reduction_price']) && $info['reduction_price'] ? 'amount' : 'percentage'; $specific_price->from = isset($info['reduction_from']) && Validate::isDate($info['reduction_from']) ? $info['reduction_from'] : '0000-00-00 00:00:00'; $specific_price->to = isset($info['reduction_to']) && Validate::isDate($info['reduction_to']) ? $info['reduction_to'] : '0000-00-00 00:00:00'; if (!$specific_price->save()) { $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Discount is invalid')); } } } /* * 2015-03-26 - JLE SPECIFIC : * Import group specific prices */ foreach ($this->groups as $group) { if (isset($info['group' . $group['id_group'] . "_price"])) { // $group_price = str_replace(',', '.', $info['group'.$group['id_group']."_price"]); $group_price = (double) str_replace(',', '.', trim($info['group' . $group['id_group'] . "_price"])); foreach ($id_shop_list as $id_shop) { $specific_price = SpecificPrice::getSpecificPrice($product->id, $id_shop, 0, 0, $group['id_group'], 1, 0, 0, 0, 0); if (is_array($specific_price) && isset($specific_price['id_specific_price'])) { $specific_price = new SpecificPrice((int) $specific_price['id_specific_price']); } else { $specific_price = new SpecificPrice(); } $specific_price->id_product = (int) $product->id; $specific_price->id_specific_price_rule = 0; $specific_price->id_shop = $id_shop; $specific_price->id_currency = 0; $specific_price->id_country = 0; $specific_price->id_group = $group['id_group']; $specific_price->price = $group_price; $specific_price->id_customer = 0; $specific_price->from_quantity = 1; $specific_price->reduction = 0; $specific_price->reduction_type = 'amount'; $specific_price->from = '0000-00-00 00:00:00'; $specific_price->to = '0000-00-00 00:00:00'; if (!$specific_price->save()) { $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Discount is invalid')); } } } } /* * END SPECIFIC 2015-03-26 */ if (isset($product->tags) && !empty($product->tags)) { if (isset($product->id) && $product->id) { $tags = Tag::getProductTags($product->id); if (is_array($tags) && count($tags)) { if (!empty($product->tags)) { $product->tags = explode($this->multiple_value_separator, $product->tags); } if (is_array($product->tags) && count($product->tags)) { foreach ($product->tags as $key => $tag) { if (!empty($tag)) { $product->tags[$key] = trim($tag); } } $tags[$id_lang] = $product->tags; $product->tags = $tags; } } } // Delete tags for this id product, for no duplicating error Tag::deleteTagsForProduct($product->id); if (!is_array($product->tags) && !empty($product->tags)) { $product->tags = AdminImportController::createMultiLangField($product->tags); foreach ($product->tags as $key => $tags) { $is_tag_added = Tag::addTags($key, $product->id, $tags, $this->multiple_value_separator); if (!$is_tag_added) { $this->addProductWarning(Tools::safeOutput($info['name']), $product->id, $this->l('Tags list is invalid')); break; } } } else { foreach ($product->tags as $key => $tags) { $str = ''; foreach ($tags as $one_tag) { $str .= $one_tag . $this->multiple_value_separator; } $str = rtrim($str, $this->multiple_value_separator); $is_tag_added = Tag::addTags($key, $product->id, $str, $this->multiple_value_separator); if (!$is_tag_added) { $this->addProductWarning(Tools::safeOutput($info['name']), (int) $product->id, 'Invalid tag(s) (' . $str . ')'); break; } } } } //delete existing images if "delete_existing_images" is set to 1 if (isset($product->delete_existing_images)) { if ((bool) $product->delete_existing_images) { $product->deleteImages(); } } if (isset($product->image) && is_array($product->image) && count($product->image)) { $product_has_images = (bool) Image::getImages($this->context->language->id, (int) $product->id); foreach ($product->image as $key => $url) { $url = trim($url); $error = false; if (!empty($url)) { $url = str_replace(' ', '%20', $url); $image = new Image(); $image->id_product = (int) $product->id; $image->position = Image::getHighestPosition($product->id) + 1; $image->cover = !$key && !$product_has_images ? true : false; // file_exists doesn't work with HTTP protocol if (($field_error = $image->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true && $image->add()) { // associate image to selected shops $image->associateTo($shops); if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !Tools::getValue('regenerate'))) { $image->delete(); $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); } } else { $error = true; } } else { $error = true; } if ($error) { $this->warnings[] = sprintf(Tools::displayError('Product #%1$d: the picture (%2$s) cannot be saved.'), $image->id_product, $url); } } } if (isset($product->id_category) && is_array($product->id_category)) { $product->updateCategories(array_map('intval', $product->id_category)); } $product->checkDefaultAttributes(); if (!$product->cache_default_attribute) { Product::updateDefaultAttribute($product->id); } // Features import $features = get_object_vars($product); if (isset($features['features']) && !empty($features['features'])) { foreach (explode($this->multiple_value_separator, $features['features']) as $single_feature) { if (empty($single_feature)) { continue; } $tab_feature = explode(':', $single_feature); $feature_name = isset($tab_feature[0]) ? trim($tab_feature[0]) : ''; $feature_value = isset($tab_feature[1]) ? trim($tab_feature[1]) : ''; $position = isset($tab_feature[2]) ? (int) $tab_feature[2] - 1 : false; $custom = isset($tab_feature[3]) ? (int) $tab_feature[3] : false; if (!empty($feature_name) && !empty($feature_value)) { $id_feature = (int) Feature::addFeatureImport($feature_name, $position); $id_product = null; if (Tools::getValue('forceIDs') || Tools::getValue('match_ref')) { $id_product = (int) $product->id; } $id_feature_value = (int) FeatureValue::addFeatureValueImport($id_feature, $feature_value, $id_product, $id_lang, $custom); Product::addFeatureProductImport($product->id, $id_feature, $id_feature_value); } } } // clean feature positions to avoid conflict Feature::cleanPositions(); // set advanced stock managment if (isset($product->advanced_stock_management)) { if ($product->advanced_stock_management != 1 && $product->advanced_stock_management != 0) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product %1$s '), $product->name[$default_language_id]); } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management == 1) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot enable on product %1$s '), $product->name[$default_language_id]); } else { $product->setAdvancedStockManagement($product->advanced_stock_management); } // automaticly disable depends on stock, if a_s_m set to disabled if (StockAvailable::dependsOnStock($product->id) == 1 && $product->advanced_stock_management == 0) { StockAvailable::setProductDependsOnStock($product->id, 0); } } // Check if warehouse exists if (isset($product->warehouse) && $product->warehouse) { if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse not set on product %1$s '), $product->name[$default_language_id]); } else { if (Warehouse::exists($product->warehouse)) { // Get already associated warehouses $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id); // Delete any entry in warehouse for this product foreach ($associated_warehouses_collection as $awc) { $awc->delete(); } $warehouse_location_entity = new WarehouseProductLocation(); $warehouse_location_entity->id_product = $product->id; $warehouse_location_entity->id_product_attribute = 0; $warehouse_location_entity->id_warehouse = $product->warehouse; if (WarehouseProductLocation::getProductLocation($product->id, 0, $product->warehouse) !== false) { $warehouse_location_entity->update(); } else { $warehouse_location_entity->save(); } StockAvailable::synchronize($product->id); } else { $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'), $product->name[$default_language_id]); } } } // stock available if (isset($product->depends_on_stock)) { if ($product->depends_on_stock != 0 && $product->depends_on_stock != 1) { $this->warnings[] = sprintf(Tools::displayError('Incorrect value for "depends on stock" for product %1$s '), $product->name[$default_language_id]); } elseif ((!$product->advanced_stock_management || $product->advanced_stock_management == 0) && $product->depends_on_stock == 1) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management not enabled, cannot set "depends on stock" for product %1$s '), $product->name[$default_language_id]); } else { StockAvailable::setProductDependsOnStock($product->id, $product->depends_on_stock); } // This code allows us to set qty and disable depends on stock if (isset($product->quantity) && (int) $product->quantity) { // if depends on stock and quantity, add quantity to stock if ($product->depends_on_stock == 1) { $stock_manager = StockManagerFactory::getManager(); $price = str_replace(',', '.', $product->wholesale_price); if ($price == 0) { $price = 1.0E-6; } $price = round(floatval($price), 6); $warehouse = new Warehouse($product->warehouse); if ($stock_manager->addProduct((int) $product->id, 0, $warehouse, (int) $product->quantity, 1, $price, true)) { StockAvailable::synchronize((int) $product->id); } } else { if (Shop::isFeatureActive()) { foreach ($shops as $shop) { StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $this->context->shop->id); } } } } else { if (Shop::isFeatureActive()) { foreach ($shops as $shop) { StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, 0, (int) $product->quantity, (int) $this->context->shop->id); } } } } $this->closeCsvFile($handle); }
/** * AdminController::postProcess() override * @see AdminController::postProcess() */ public function postProcess() { $this->is_editing_order = false; // Checks access if (Tools::isSubmit('submitAddsupply_order') && !($this->tabAccess['add'] === '1')) { $this->errors[] = Tools::displayError($this->l('You do not have permission to add a supply order.')); } if (Tools::isSubmit('submitBulkUpdatesupply_order_detail') && !($this->tabAccess['edit'] === '1')) { $this->errors[] = Tools::displayError($this->l('You do not have permission to edit an order.')); } // Trick to use both Supply Order as template and actual orders if (Tools::isSubmit('is_template')) { $_GET['mod'] = 'template'; } // checks if supply order reference is unique if (Tools::isSubmit('reference')) { // gets the reference $ref = pSQL(Tools::getValue('reference')); if (Tools::getValue('id_supply_order') != 0 && SupplyOrder::getReferenceById((int) Tools::getValue('id_supply_order')) != $ref) { if ((int) SupplyOrder::exists($ref) != 0) { $this->errors[] = Tools::displayError($this->l('The reference has to be unique.')); } } else { if (Tools::getValue('id_supply_order') == 0 && (int) SupplyOrder::exists($ref) != 0) { $this->errors[] = Tools::displayError($this->l('The reference has to be unique.')); } } } if ($this->errors) { return; } // Global checks when add / update a supply order if (Tools::isSubmit('submitAddsupply_order') || Tools::isSubmit('submitAddsupply_orderAndStay')) { $this->action = 'save'; $this->is_editing_order = true; // get supplier ID $id_supplier = (int) Tools::getValue('id_supplier', 0); if ($id_supplier <= 0 || !Supplier::supplierExists($id_supplier)) { $this->errors[] = Tools::displayError($this->l('The selected supplier is not valid.')); } // get warehouse id $id_warehouse = (int) Tools::getValue('id_warehouse', 0); if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) { $this->errors[] = Tools::displayError($this->l('The selected warehouse is not valid.')); } // get currency id $id_currency = (int) Tools::getValue('id_currency', 0); if ($id_currency <= 0 || (!($result = Currency::getCurrency($id_currency)) || empty($result))) { $this->errors[] = Tools::displayError($this->l('The selected currency is not valid.')); } // get delivery date $delivery_expected = new DateTime(pSQL(Tools::getValue('date_delivery_expected'))); // converts date to timestamp if ($delivery_expected <= new DateTime('yesterday')) { $this->errors[] = Tools::displayError($this->l('The date you specified cannot be in the past.')); } // gets threshold $quantity_threshold = null; if (Tools::getValue('load_products') && Validate::isInt(Tools::getValue('load_products'))) { $quantity_threshold = (int) Tools::getValue('load_products'); } if (!count($this->errors)) { // forces date for templates if (Tools::isSubmit('is_template') && !Tools::getValue('date_delivery_expected')) { $_POST['date_delivery_expected'] = date('Y-m-d h:i:s'); } // specify initial state $_POST['id_supply_order_state'] = 1; //defaut creation state // specify global reference currency $_POST['id_ref_currency'] = Currency::getDefaultCurrency()->id; // specify supplier name $_POST['supplier_name'] = Supplier::getNameById($id_supplier); //specific discount check $_POST['discount_rate'] = (double) str_replace(array(' ', ','), array('', '.'), Tools::getValue('discount_rate', 0)); } // manage each associated product $this->manageOrderProducts(); // if the threshold is defined and we are saving the order if (Tools::isSubmit('submitAddsupply_order') && $quantity_threshold != null) { $this->loadProducts($quantity_threshold); } } // Manage state change if (Tools::isSubmit('submitChangestate') && Tools::isSubmit('id_supply_order') && Tools::isSubmit('id_supply_order_state')) { if ($this->tabAccess['edit'] != '1') { $this->errors[] = Tools::displayError($this->l('You do not have permission to change the order status.')); } // get state ID $id_state = (int) Tools::getValue('id_supply_order_state', 0); if ($id_state <= 0) { $this->errors[] = Tools::displayError($this->l('The selected supply order status is not valid.')); } // get supply order ID $id_supply_order = (int) Tools::getValue('id_supply_order', 0); if ($id_supply_order <= 0) { $this->errors[] = Tools::displayError($this->l('The supply order ID is not valid.')); } if (!count($this->errors)) { // try to load supply order $supply_order = new SupplyOrder($id_supply_order); if (Validate::isLoadedObject($supply_order)) { // get valid available possible states for this order $states = SupplyOrderState::getSupplyOrderStates($supply_order->id_supply_order_state); foreach ($states as $state) { // if state is valid, change it in the order if ($id_state == $state['id_supply_order_state']) { $new_state = new SupplyOrderState($id_state); $old_state = new SupplyOrderState($supply_order->id_supply_order_state); // special case of validate state - check if there are products in the order and the required state is not an enclosed state if ($supply_order->isEditable() && !$supply_order->hasEntries() && !$new_state->enclosed) { $this->errors[] = Tools::displayError($this->l('It is not possible to change the status of this order because you did not order any products.')); } if (!count($this->errors)) { $supply_order->id_supply_order_state = $state['id_supply_order_state']; if ($supply_order->save()) { // if pending_receipt, // or if the order is being canceled, // synchronizes StockAvailable if ($new_state->pending_receipt && !$new_state->receipt_state || $old_state->receipt_state && $new_state->enclosed && !$new_state->receipt_state) { $supply_order_details = $supply_order->getEntries(); $products_done = array(); foreach ($supply_order_details as $supply_order_detail) { if (!in_array($supply_order_detail['id_product'], $products_done)) { StockAvailable::synchronize($supply_order_detail['id_product']); $products_done[] = $supply_order_detail['id_product']; } } } $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; $redirect = self::$currentIndex . '&token=' . $token; $this->redirect_after = $redirect . '&conf=5'; } } } } } else { $this->errors[] = Tools::displayError($this->l('The selected supplier is not valid.')); } } } // updates receipt if (Tools::isSubmit('submitFiltersupply_order_detail') && Tools::isSubmit('submitBulkUpdatesupply_order_detail') && Tools::isSubmit('id_supply_order')) { $this->postProcessUpdateReceipt(); } // use template to create a supply order if (Tools::isSubmit('create_supply_order') && Tools::isSubmit('id_supply_order')) { $this->postProcessCopyFromTemplate(); } if (!count($this->errors) && $this->is_editing_order || !$this->is_editing_order) { parent::postProcess(); } }
public function postProcess() { // Warehouse $warehouses = Warehouse::getWarehouses(true); // if we already pick a warehouse source and location, we filter on twice to not display selections of the other if (Tools::isSubmit('warehouseA') && Tools::getValue('warehouseA') != -1 && Tools::isSubmit('warehouseB') && Tools::getValue('warehouseB') != -1) { $warehouseA = Tools::getValue('warehouseA'); $warehouseB = Tools::getValue('warehouseB'); $warehousesA = array(); $warehousesB = array(); foreach ($warehouses as $warehouse) { if ($warehouse['id_warehouse'] != $warehouseA) { array_push($warehousesB, $warehouse); } if ($warehouse['id_warehouse'] != $warehouseB) { array_push($warehousesA, $warehouse); } } } elseif (Tools::isSubmit('warehouseA') && Tools::getValue('warehouseA') != -1) { $warehouseA = Tools::getValue('warehouseA'); $warehousesB = array(); foreach ($warehouses as $warehouse) { if ($warehouse['id_warehouse'] != $warehouseA) { array_push($warehousesB, $warehouse); } } $warehousesA = $warehouses; // Restaure B list on no selection $this->context->smarty->assign(array('warehouseB' => -1)); } elseif (Tools::isSubmit('warehouseB') && Tools::getValue('warehouseB') != -1) { $warehouseB = Tools::getValue('warehouseB'); $warehousesA = array(); foreach ($warehouses as $warehouse) { if ($warehouse['id_warehouse'] != $warehouseB) { array_push($warehousesA, $warehouse); } } $warehousesB = $warehouses; } else { $warehousesA = $warehouses; $warehousesB = $warehouses; } // validate_transfer if (Tools::isSubmit('validate_transfer')) { $transfer_ok = false; if (Tools::isSubmit('id_stockA') && Tools::isSubmit('id_stockB') && Tools::isSubmit('id_employee') && Tools::isSubmit('firstname') && Tools::isSubmit('lastname') && Tools::isSubmit('values')) { // After transfert, delete cookies to get a blank display if (Tools::isSubmit('deleteCookie')) { $cookie = new Cookie('psAdmin'); $cookie->warehouseA = ''; $cookie->warehouseB = ''; } /* Initialisation */ $ids_mvt = array(); // Call the helper "traducteur" of the chain transfert require_once _PS_MODULE_DIR_ . 'erpillicopresta/classes/helpers/StockTransferHelper.php'; require_once _PS_MODULE_DIR_ . 'erpillicopresta/classes/stock/ErpStock.php'; $values = StockTransferHelper::getTransfertDataAsArray(Tools::getValue('values')); /* For each movement recorded */ foreach ($values as $value) { $id_product = $value['id_product']; $id_product_attribute = $value['id_product_attribute']; $transfer_quantity = $value['quantity']; $id_stock_s1 = $value['id_stock_s1']; $id_stock_s2 = $value['id_stock_s2']; if (empty($id_stock_s1)) { $this->errors[] = 'Error while updating the stock for a product : stock id missing !'; return true; } // update stock un warehouse A (source) $stock = new ErpStock((int) $id_stock_s1); $stock->physical_quantity -= $transfer_quantity; $stock->usable_quantity -= $transfer_quantity; if ($stock->physical_quantity < 0) { $stock->physical_quantity = 0; } if ($stock->usable_quantity < 0) { $stock->usable_quantity = 0; } /* Update Stock */ if ($stock->update()) { /* Movment A to B */ $stock_mvt = new ErpStockMvt(); $stock_mvt->id_stock = $stock->id; $stock_mvt->id_order = 0; $stock_mvt->id_supply_order = 0; $stock_mvt->id_stock_mvt_reason = 6; $stock_mvt->id_employee = Tools::getValue('id_employee'); $stock_mvt->employee_firstname = Tools::getValue('firstname'); $stock_mvt->employee_lastname = Tools::getValue('lastname'); $stock_mvt->price_te = $stock->getPriceTe(); $stock_mvt->current_wa = $stock->getPriceTe(); $stock_mvt->sign = -1; $stock_mvt->physical_quantity = $transfer_quantity; // if movment OK, update stock in B warehouse (location) if ($stock_mvt->add(true)) { // add id movment stock generated (useful to generate the warehouse delivery notice) array_push($ids_mvt, $stock_mvt->getLastId()); if ((int) $id_stock_s2 > 0) { $stock_s2 = new ErpStock((int) $id_stock_s2); $stock_s2->physical_quantity += $transfer_quantity; $stock_s2->usable_quantity += $transfer_quantity; } else { require_once _PS_MODULE_DIR_ . 'erpillicopresta/classes/ErpProduct.php'; //get product information $product_stock = new ProductCore((int) $id_product, (int) $id_product_attribute); // stock not existe we add row in stock table $stock_s2 = new ErpStock(); $stock_s2->physical_quantity += $transfer_quantity; $stock_s2->usable_quantity += $transfer_quantity; $stock_s2->id_product = (int) $id_product; $stock_s2->id_product_attribute = (int) $id_product_attribute; $stock_s2->id_warehouse = (int) Tools::getValue('id_stockB'); $stock_s2->price_te = $product_stock->wholesale_price; $stock_s2->ean13 = $product_stock->ean13; $stock_s2->upc = $product_stock->upc; } /* of OK, movment from B to A */ if ($stock_s2->save()) { $stock_mvt->id_stock = $stock_s2->id; $stock_mvt->id_stock_mvt_reason = 7; $stock_mvt->sign = 1; // add id movment stock generated (useful to generate warehouse inter delivery) if ($stock_mvt->add(true)) { array_push($ids_mvt, $stock_mvt->getLastId()); } else { $this->errors[] = 'Error while updating the stock for a product'; } } else { $this->errors[] = 'Error while updating the stock for a product'; } } else { $this->errors[] = 'Error while updating the stock for a product'; } } else { $this->errors[] = 'Error while updating the stock for a product'; } // synchronize availbale stock ::quantity StockAvailable::synchronize($id_product); } $ids_mvt = implode('|', $ids_mvt); // we reset values $transfer_ok = true; } } // transfer is ok, we redirect the user to home page of transfer if (Tools::isSubmit('validate_transfer') && isset($transfer_ok) && $transfer_ok) { $url_redirect = self::$currentIndex . '&token=' . Tools::getAdminTokenLite('AdminStockTransfer'); $url_redirect .= '&validate_transfer&ids_mvt=' . $ids_mvt . '&ids_mvt_csv=' . Tools::getValue('ids_mvt_csv'); $url_redirect .= '&id_warehouse_src=' . Tools::getValue('id_warehouse_src') . '&id_warehouse_dst=' . Tools::getValue('id_warehouse_dst'); Tools::redirectAdmin($url_redirect); } if (Tools::isSubmit('ids_mvt_csv') && Tools::isSubmit('get_csv_transfer')) { $this->renderCSV(); } // Generate PDF of tranfert if (Tools::isSubmit('ids_mvt') && Tools::isSubmit('action') && Tools::getValue('action') == 'generateTransferPDF') { $this->processGenerateTransferPDF(); } // to get erp feature list require_once _PS_MODULE_DIR_ . 'erpillicopresta/models/ErpFeature.php'; // send warehouse liste to template $this->context->smarty->assign(array('warehousesA' => $warehousesA, 'warehousesB' => $warehousesB, 'categories' => Category::getSimpleCategories((int) $this->context->language->id), 'suppliers' => Supplier::getSuppliers(), 'manufacturers' => Manufacturer::getManufacturers(), 'id_category' => -1, 'id_supplier' => -1, 'id_manufacturer' => -1, 'name_or_ean' => '', 'erp_feature' => ErpFeature::getFeaturesWithToken($this->context->language->iso_code), 'template_path' => $this->template_path)); }
public static function synchronize($id_product, $order_id_shop = null) { if (!Validate::isUnsignedId($id_product)) { return false; } if (Pack::isPack($id_product)) { if (Validate::isLoadedObject($product = new Product((int) $id_product))) { if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || $product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0) { $products_pack = Pack::getItems($id_product, (int) Configuration::get('PS_LANG_DEFAULT')); foreach ($products_pack as $product_pack) { StockAvailable::synchronize($product_pack->id, $order_id_shop); } } } else { return false; } } $ids_warehouse = Warehouse::getWarehousesGroupedByShops(); if ($order_id_shop !== null) { $order_warehouses = array(); $wh = Warehouse::getWarehouses(false, (int) $order_id_shop); foreach ($wh as $warehouse) { $order_warehouses[] = $warehouse['id_warehouse']; } } $ids_product_attribute = array(); foreach (Product::getProductAttributesIds($id_product) as $id_product_attribute) { $ids_product_attribute[] = $id_product_attribute['id_product_attribute']; } $out_of_stock = StockAvailable::outOfStock($id_product); $manager = StockManagerFactory::getManager(); foreach ($ids_warehouse as $id_shop => $warehouses) { if (StockAvailable::dependsOnStock($id_product, $id_shop)) { $product_quantity = 0; if (empty($ids_product_attribute)) { $allowed_warehouse_for_product = WareHouse::getProductWarehouseList((int) $id_product, 0, (int) $id_shop); $allowed_warehouse_for_product_clean = array(); foreach ($allowed_warehouse_for_product as $warehouse) { $allowed_warehouse_for_product_clean[] = (int) $warehouse['id_warehouse']; } $allowed_warehouse_for_product_clean = array_intersect($allowed_warehouse_for_product_clean, $warehouses); if ($order_id_shop != null && !count(array_intersect($allowed_warehouse_for_product_clean, $order_warehouses))) { continue; } $product_quantity = $manager->getProductRealQuantities($id_product, null, $allowed_warehouse_for_product_clean, true); Hook::exec('actionUpdateQuantity', array('id_product' => $id_product, 'id_product_attribute' => 0, 'quantity' => $product_quantity)); } else { foreach ($ids_product_attribute as $id_product_attribute) { $allowed_warehouse_for_combination = WareHouse::getProductWarehouseList((int) $id_product, (int) $id_product_attribute, (int) $id_shop); $allowed_warehouse_for_combination_clean = array(); foreach ($allowed_warehouse_for_combination as $warehouse) { $allowed_warehouse_for_combination_clean[] = (int) $warehouse['id_warehouse']; } $allowed_warehouse_for_combination_clean = array_intersect($allowed_warehouse_for_combination_clean, $warehouses); if ($order_id_shop != null && !count(array_intersect($allowed_warehouse_for_combination_clean, $order_warehouses))) { continue; } $quantity = $manager->getProductRealQuantities($id_product, $id_product_attribute, $allowed_warehouse_for_combination_clean, true); $query = new DbQuery(); $query->select('COUNT(*)'); $query->from('stock_available'); $query->where('id_product = ' . (int) $id_product . ' AND id_product_attribute = ' . (int) $id_product_attribute . StockAvailable::addSqlShopRestriction(null, $id_shop)); if ((int) Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query)) { $query = array('table' => 'stock_available', 'data' => PP::hydrateQty(array(), 'quantity', $quantity), 'where' => 'id_product = ' . (int) $id_product . ' AND id_product_attribute = ' . (int) $id_product_attribute . StockAvailable::addSqlShopRestriction(null, $id_shop)); Db::getInstance()->update($query['table'], $query['data'], $query['where']); } else { $query = array('table' => 'stock_available', 'data' => PP::hydrateQty(array('depends_on_stock' => 1, 'out_of_stock' => $out_of_stock, 'id_product' => (int) $id_product, 'id_product_attribute' => (int) $id_product_attribute), 'quantity', $quantity)); StockAvailable::addSqlShopParams($query['data']); Db::getInstance()->insert($query['table'], $query['data']); } $product_quantity += $quantity; Hook::exec('actionUpdateQuantity', array('id_product' => $id_product, 'id_product_attribute' => $id_product_attribute, 'quantity' => $quantity)); } } $query = array('table' => 'stock_available', 'data' => PP::hydrateQty(array(), 'quantity', $product_quantity), 'where' => 'id_product = ' . (int) $id_product . ' AND id_product_attribute = 0' . StockAvailable::addSqlShopRestriction(null, $id_shop)); Db::getInstance()->update($query['table'], $query['data'], $query['where']); } } if (count($ids_warehouse) == 0 && StockAvailable::dependsOnStock((int) $id_product)) { Db::getInstance()->update('stock_available', array('quantity' => 0, 'quantity_remainder' => 0), 'id_product = ' . (int) $id_product); } Cache::clean('StockAvailable::getQuantityAvailableByProduct_' . (int) $id_product . '*'); }
private function upsert($line) { $product = DB::getInstance()->getValue("SELECT `id_product` FROM `" . _DB_PREFIX_ . "product` WHERE `reference` LIKE '{$line['reference']}'"); $product = new Product($product); $product->reference = $line['reference']; $product->name = array('1' => $line['name'], '2' => $line['name'], '3' => $line['name']); $product->description = array('1' => $line['description'], '2' => $line['description'], '3' => $line['description']); $product->description_short = array('1' => $line['description_short'], '2' => $line['description_short'], '3' => $line['description_short']); $product->link_rewrite = array('1' => Tools::link_rewrite($line['name']), '2' => Tools::link_rewrite($line['name']), '3' => Tools::link_rewrite($line['name'])); $product->available_now = array('1' => "Есть в наличии", '2' => "Есть в наличии", '3' => "Есть в наличии"); $product->id_category_default = $line['category']; $product->quantity = (int) $line['count']; $product->advanced_stock_management = 1; //использовать Advanced Stock management $product->depends_on_stock = 1; //1 - доступное количество на основе ASM. 0 - указывается вручную $product->out_of_stock = 1; //2 - как в Preferences product. 1 - allow (Как в Preferences - не дает заказать товар на сайте) $product->price = $line['price']; $product->weight = $line['weight'] / 1000; $product->id_tax_rules_group = $line['id_tax']; $product->save(); $product->updateCategories(array($line['category'])); $product->deleteFeatures(); if ($line['author']) { $id_feature_value = FeatureValue::addFeatureValueImport(9, $line['author'], null, Configuration::get('PS_LANG_DEFAULT')); Product::addFeatureProductImport($product->id, 9, $id_feature_value); } if ($line['year']) { $id_feature_value = FeatureValue::addFeatureValueImport(10, $line['year'], null, Configuration::get('PS_LANG_DEFAULT')); Product::addFeatureProductImport($product->id, 10, $id_feature_value); } if ($line['paperback']) { if ($line['paperback'] == 1) { $id_feature_value = 1; } else { $id_feature_value = 2; } //$id_feature_value = FeatureValue::addFeatureValueImport(11, $line['paperback'], null, Configuration::get('PS_LANG_DEFAULT')); Product::addFeatureProductImport($product->id, 11, $id_feature_value); //1 - id значения "твёрдый переплёт" у харакатеристики "Переплёт", 149226 - мягкая обложка } if ($line['pages']) { $id_feature_value = FeatureValue::addFeatureValueImport(12, $line['pages'], null, Configuration::get('PS_LANG_DEFAULT'), true); Product::addFeatureProductImport($product->id, 12, $id_feature_value); } /* if ($line['weight']) { $id_feature_value = FeatureValue::addFeatureValueImport(4, $line['weight'], null, Configuration::get('PS_LANG_DEFAULT'), true); Product::addFeatureProductImport($product->id, 4, $id_feature_value); } */ if ($line['isbn']) { $id_feature_value = FeatureValue::addFeatureValueImport(13, $line['isbn'], null, Configuration::get('PS_LANG_DEFAULT'), true); Product::addFeatureProductImport($product->id, 13, $id_feature_value); } if ($line['publishing']) { $id_feature_value = FeatureValue::addFeatureValueImport(14, $line['publishing'], null, Configuration::get('PS_LANG_DEFAULT'), true); Product::addFeatureProductImport($product->id, 14, $id_feature_value); } $location = WarehouseProductLocation::getIdByProductAndWarehouse($product->id, 0, $line['warehouse']); $location = new WarehouseProductLocation($location); $location->id_product = $product->id; $location->id_product_attribute = 0; $location->id_warehouse = $line['warehouse']; $location->save(); /* $stock = DB::getInstance()->getValue("SELECT `id_stock` FROM `" . _DB_PREFIX_ . "stock` WHERE `id_product` = {$product->id} AND `id_warehouse` = {$line['warehouse']}"); $stock = new Stock($stock); $stock->id_product = $product->id; $stock->id_product_attribute = 0; $stock->id_warehouse = $line['warehouse']; $stock->physical_quantity = $line['count']; $stock->usable_quantity = $line['count']; $stock->price_te = 0; $stock->save(); */ //установить зависимость количества товара от остатка на складе для каждого магазинеа //исходим из того, что в настройках Мультимагазина остаток НЕ единый на все магазины $id_product = $product->id; $depends_on_stock = true; $out_of_stock = 1; //2 - как в Preferences product. 1 - allow (ставь 1, т.к. 2 (как в Preferences) не дает заказать товар на сайте) for ($id_shop = 1; $id_shop <= 4; $id_shop++) { StockAvailable::setProductDependsOnStock($id_product, $depends_on_stock, $id_shop); } //разрешить или запретить продажу товара без остатка /* для магазина 2,3 запретить продажу, если нет в наличии. out_of_stock = 0 2 Second shop Gelikon 3 First shop Gelikon */ $out_of_stock = 0; StockAvailable::setProductOutOfStock($id_product, $out_of_stock, 2); StockAvailable::setProductOutOfStock($id_product, $out_of_stock, 3); /* Для online и заказов по телефону разрешить заказ товара, которого нет в наличии 1 Gelikon DE online 4 Заказы по телефону */ $out_of_stock = 1; StockAvailable::setProductOutOfStock($id_product, $out_of_stock, 1); StockAvailable::setProductOutOfStock($id_product, $out_of_stock, 4); //Добавить партию товара на склад с записью в журнал движения товаров $id_product = $product->id; $id_product_attribute = 0; $id_stock_mvt_reason = 1; $price = 1; $id_currency = 1; $id_warehouse = $line['warehouse']; $warehouse = new Warehouse($id_warehouse); $stock_manager = StockManagerFactory::getManager(); if ($line['count'] != 0) { //echo "добавляем товар "; $is_usable = true; $quantity = $line['count']; // add stock if ($stock_manager->addProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $price, $is_usable)) { StockAvailable::synchronize($id_product); } else { $errors[] = Tools::displayError('An error occurred. No stock was added.'); } } /* $available = DB::getInstance()->getValue("SELECT `id_stock_available` FROM `". _DB_PREFIX_ . "stock_available` WHERE `id_product` = {$product->id} AND `id_shop` = " . Context::getContext()->shop->id); $available = new StockAvailable($available); $available->id_product = $product->id; $available->id_product_attribute = 0; //$available->id_shop = Context::getContext()->shop->id; $available->quantity = StockManagerFactory::getManager()->getProductPhysicalQuantities($product->id, 0); $available->save(); StockAvailable::setProductDependsOnStock($product->id, true, null); StockAvailable::setProductOutOfStock($product->id, 1, null); //allow */ while (strlen($line['reference']) < 9) { $line['reference'] = '0' . $line['reference']; } if (file_exists(_PS_ROOT_DIR_ . '/upload/import/' . $line['reference'] . '.jpg')) { $product->deleteImages(); $image = new Image(); $image->id_product = $product->id; $image->cover = 1; $image->position = 0; $image->save(); $name = $image->getPathForCreation(); copy(_PS_ROOT_DIR_ . '/upload/import/' . $line['reference'] . '.jpg', $name . '.' . $image->image_format); $types = ImageType::getImagesTypes('products'); foreach ($types as $type) { ImageManager::resize(_PS_ROOT_DIR_ . '/upload/import/' . $line['reference'] . '.jpg', $name . '-' . $type['name'] . '.' . $image->image_format, $type['width'], $type['height'], $image->image_format); } } /* Db::getInstance()->update('stock_available', array( 'depends_on_stock' => (int)1, //1 - доступное количество на основе ASM. 0 - указывается вручную 'out_of_stock' => (int)1, //1-allow ), 'id_product='.$product->id.''); $affrows = Db::getInstance()->Affected_Rows(); var_dump($affrows); */ //var_dump($product->reference); //echo "<br/><br/><br/><br/>"; }
public function postProcess() { // If id_order is sent, we instanciate a new Order object if (Tools::isSubmit('id_order') && Tools::getValue('id_order') > 0) { $order = new Order(Tools::getValue('id_order')); if (!Validate::isLoadedObject($order)) { throw new PrestaShopException('Can\'t load Order object'); } } /* Update shipping number */ if (Tools::isSubmit('submitShippingNumber') && isset($order)) { if ($this->tabAccess['edit'] === '1') { $order_carrier = new OrderCarrier(Tools::getValue('id_order_carrier')); if (!Validate::isLoadedObject($order_carrier)) { $this->errors[] = Tools::displayError('Order carrier ID is invalid'); } elseif (!Validate::isTrackingNumber(Tools::getValue('tracking_number'))) { $this->errors[] = Tools::displayError('Tracking number is incorrect'); } else { // update shipping number // Keep these two following lines for backward compatibility, remove on 1.6 version $order->shipping_number = Tools::getValue('tracking_number'); $order->update(); // Update order_carrier $order_carrier->tracking_number = pSQL(Tools::getValue('tracking_number')); if ($order_carrier->update()) { // Send mail to customer $customer = new Customer((int) $order->id_customer); $carrier = new Carrier((int) $order->id_carrier, $order->id_lang); if (!Validate::isLoadedObject($customer)) { throw new PrestaShopException('Can\'t load Customer object'); } if (!Validate::isLoadedObject($carrier)) { throw new PrestaShopException('Can\'t load Carrier object'); } $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url), '{firstname}' => $customer->firstname, '{lastname}' => $customer->lastname, '{id_order}' => $order->id, '{order_name}' => $order->getUniqReference()); if (@Mail::Send((int) $order->id_lang, 'in_transit', Mail::l('Package in transit', (int) $order->id_lang), $templateVars, $customer->email, $customer->firstname . ' ' . $customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int) $order->id_shop)) { Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order)); Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token); } else { $this->errors[] = Tools::displayError('An error occurred while sending e-mail to the customer.'); } } else { $this->errors[] = Tools::displayError('Order carrier can\'t be updated'); } } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } elseif (Tools::isSubmit('submitState') && isset($order)) { if ($this->tabAccess['edit'] === '1') { $order_state = new OrderState(Tools::getValue('id_order_state')); if (!Validate::isLoadedObject($order_state)) { $this->errors[] = Tools::displayError('Invalid new order status'); } else { $current_order_state = $order->getCurrentOrderState(); if ($current_order_state->id != $order_state->id) { // Create new OrderHistory $history = new OrderHistory(); $history->id_order = $order->id; $history->id_employee = (int) $this->context->employee->id; $use_existings_payment = false; if (!$order->hasInvoice()) { $use_existings_payment = true; } $history->changeIdOrderState($order_state->id, $order->id, $use_existings_payment); $carrier = new Carrier($order->id_carrier, $order->id_lang); $templateVars = array(); if ($history->id_order_state == Configuration::get('PS_OS_SHIPPING') && $order->shipping_number) { $templateVars = array('{followup}' => str_replace('@', $order->shipping_number, $carrier->url)); } // Save all changes if ($history->addWithemail(true, $templateVars)) { // synchronizes quantities if needed.. if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { foreach ($order->getProducts() as $product) { if (StockAvailable::dependsOnStock($product['product_id'])) { StockAvailable::synchronize($product['product_id'], (int) $product['id_shop']); } } } Tools::redirectAdmin(self::$currentIndex . '&id_order=' . (int) $order->id . '&vieworder&token=' . $this->token); } $this->errors[] = Tools::displayError('An error occurred while changing the status or was unable to send e-mail to the customer.'); } else { $this->errors[] = Tools::displayError('This order is already assigned this status'); } } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } elseif (Tools::isSubmit('submitMessage') && isset($order)) { if ($this->tabAccess['edit'] === '1') { $customer = new Customer(Tools::getValue('id_customer')); if (!Validate::isLoadedObject($customer)) { $this->errors[] = Tools::displayError('Customer is invalid'); } elseif (!Tools::getValue('message')) { $this->errors[] = Tools::displayError('Message cannot be blank'); } else { /* Get message rules and and check fields validity */ $rules = call_user_func(array('Message', 'getValidationRules'), 'Message'); foreach ($rules['required'] as $field) { if (($value = Tools::getValue($field)) == false && (string) $value != '0') { if (!Tools::getValue('id_' . $this->table) || $field != 'passwd') { $this->errors[] = sprintf(Tools::displayError('field %s is required.'), $field); } } } foreach ($rules['size'] as $field => $maxLength) { if (Tools::getValue($field) && Tools::strlen(Tools::getValue($field)) > $maxLength) { $this->errors[] = sprintf(Tools::displayError('field %1$s is too long (%2$d chars max).'), $field, $maxLength); } } foreach ($rules['validate'] as $field => $function) { if (Tools::getValue($field)) { if (!Validate::$function(htmlentities(Tools::getValue($field), ENT_COMPAT, 'UTF-8'))) { $this->errors[] = sprintf(Tools::displayError('field %s is invalid.'), $field); } } } if (!count($this->errors)) { //check if a thread already exist $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($customer->email, $order->id); if (!$id_customer_thread) { $customer_thread = new CustomerThread(); $customer_thread->id_contact = 0; $customer_thread->id_customer = (int) $order->id_customer; $customer_thread->id_shop = (int) $this->context->shop->id; $customer_thread->id_order = (int) $order->id; $customer_thread->id_lang = (int) $this->context->language->id; $customer_thread->email = $customer->email; $customer_thread->status = 'open'; $customer_thread->token = Tools::passwdGen(12); $customer_thread->add(); } else { $customer_thread = new CustomerThread((int) $id_customer_thread); } $customer_message = new CustomerMessage(); $customer_message->id_customer_thread = $customer_thread->id; $customer_message->id_employee = (int) $this->context->employee->id; $customer_message->message = htmlentities(Tools::getValue('message'), ENT_COMPAT, 'UTF-8'); $customer_message->private = Tools::getValue('visibility'); if (!$customer_message->add()) { $this->errors[] = Tools::displayError('An error occurred while saving message'); } elseif ($customer_message->private) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . (int) $order->id . '&vieworder&conf=11&token=' . $this->token); } else { $message = $customer_message->message; if (Configuration::get('PS_MAIL_TYPE') != Mail::TYPE_TEXT) { $message = Tools::nl2br($customer_message->message); } $varsTpl = array('{lastname}' => $customer->lastname, '{firstname}' => $customer->firstname, '{id_order}' => $order->id, '{order_name}' => $order->getUniqReference(), '{message}' => $message); if (@Mail::Send((int) $order->id_lang, 'order_merchant_comment', Mail::l('New message regarding your order', (int) $order->id_lang), $varsTpl, $customer->email, $customer->firstname . ' ' . $customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int) $order->id_shop)) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=11' . '&token=' . $this->token); } } $this->errors[] = Tools::displayError('An error occurred while sending e-mail to the customer.'); } } } else { $this->errors[] = Tools::displayError('You do not have permission to delete here.'); } } elseif (Tools::isSubmit('partialRefund') && isset($order)) { if ($this->tabAccess['edit'] == '1') { if (is_array($_POST['partialRefundProduct'])) { $amount = 0; $order_detail_list = array(); foreach ($_POST['partialRefundProduct'] as $id_order_detail => $amount_detail) { $order_detail_list[$id_order_detail]['quantity'] = (int) $_POST['partialRefundProductQuantity'][$id_order_detail]; if (empty($amount_detail)) { $order_detail = new OrderDetail((int) $id_order_detail); $order_detail_list[$id_order_detail]['amount'] = $order_detail->unit_price_tax_incl * $order_detail_list[$id_order_detail]['quantity']; } else { $order_detail_list[$id_order_detail]['amount'] = (double) $amount_detail; } $amount += $order_detail_list[$id_order_detail]['amount']; } $shipping_cost_amount = (double) str_replace(',', '.', Tools::getValue('partialRefundShippingCost')); if ($shipping_cost_amount > 0) { $amount += $shipping_cost_amount; } if ($amount > 0) { if (!OrderSlip::createPartialOrderSlip($order, $amount, $shipping_cost_amount, $order_detail_list)) { $this->errors[] = Tools::displayError('Cannot generate partial credit slip'); } // Generate voucher if (Tools::isSubmit('generateDiscountRefund') && !count($this->errors)) { $cart_rule = new CartRule(); $cart_rule->description = sprintf($this->l('Credit Slip for order #%d'), $order->id); $languages = Language::getLanguages(false); foreach ($languages as $language) { // Define a temporary name $cart_rule->name[$language['id_lang']] = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id); } // Define a temporary code $cart_rule->code = sprintf('V0C%1$dO%2$d', $order->id_customer, $order->id); $cart_rule->quantity = 1; $cart_rule->quantity_per_user = 1; // Specific to the customer $cart_rule->id_customer = $order->id_customer; $now = time(); $cart_rule->date_from = date('Y-m-d H:i:s', $now); $cart_rule->date_to = date('Y-m-d H:i:s', $now + 3600 * 24 * 365.25); /* 1 year */ $cart_rule->active = 1; $cart_rule->reduction_amount = $amount; $cart_rule->reduction_tax = true; $cart_rule->minimum_amount_currency = $order->id_currency; $cart_rule->reduction_currency = $order->id_currency; if (!$cart_rule->add()) { $this->errors[] = Tools::displayError('Cannot generate voucher'); } else { // Update the voucher code and name foreach ($languages as $language) { $cart_rule->name[$language['id_lang']] = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id); } $cart_rule->code = sprintf('V%1$dC%2$dO%3$d', $cart_rule->id, $order->id_customer, $order->id); if (!$cart_rule->update()) { $this->errors[] = Tools::displayError('Cannot generate voucher'); } else { $currency = $this->context->currency; $params['{voucher_amount}'] = Tools::displayPrice($cart_rule->reduction_amount, $currency, false); $params['{voucher_num}'] = $cart_rule->code; $customer = new Customer((int) $order->id_customer); @Mail::Send((int) $order->id_lang, 'voucher', sprintf(Mail::l('New voucher regarding your order %s', (int) $order->id_lang), $order->reference), $params, $customer->email, $customer->firstname . ' ' . $customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int) $order->id_shop); } } } } else { $this->errors[] = Tools::displayError('You have to write an amount if you want to do a partial credit slip'); } // Redirect if no errors if (!count($this->errors)) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=30&token=' . $this->token); } } else { $this->errors[] = Tools::displayError('Partial refund data is incorrect'); } } else { $this->errors[] = Tools::displayError('You do not have permission to delete here.'); } } elseif (Tools::isSubmit('cancelProduct') && isset($order)) { if ($this->tabAccess['delete'] === '1') { if (!Tools::isSubmit('id_order_detail')) { $this->errors[] = Tools::displayError('You must select a product'); } elseif (!Tools::isSubmit('cancelQuantity')) { $this->errors[] = Tools::displayError('You must enter a quantity'); } else { $productList = Tools::getValue('id_order_detail'); if ($productList) { $productList = array_map('intval', $productList); } $customizationList = Tools::getValue('id_customization'); if ($customizationList) { $customizationList = array_map('intval', $customizationList); } $qtyList = Tools::getValue('cancelQuantity'); if ($qtyList) { $qtyList = array_map('intval', $qtyList); } $customizationQtyList = Tools::getValue('cancelCustomizationQuantity'); if ($customizationQtyList) { $customizationQtyList = array_map('intval', $customizationQtyList); } $full_product_list = $productList; $full_quantity_list = $qtyList; if ($customizationList) { foreach ($customizationList as $key => $id_order_detail) { $full_product_list[(int) $id_order_detail] = $id_order_detail; $full_quantity_list[(int) $id_order_detail] += $customizationQtyList[$key]; } } if ($productList || $customizationList) { if ($productList) { $id_cart = Cart::getCartIdByOrderId($order->id); $customization_quantities = Customization::countQuantityByCart($id_cart); foreach ($productList as $key => $id_order_detail) { $qtyCancelProduct = abs($qtyList[$key]); if (!$qtyCancelProduct) { $this->errors[] = Tools::displayError('No quantity selected for product.'); } $order_detail = new OrderDetail($id_order_detail); $customization_quantity = 0; if (array_key_exists($order_detail->product_id, $customization_quantities) && array_key_exists($order_detail->product_attribute_id, $customization_quantities[$order_detail->product_id])) { $customization_quantity = (int) $customization_quantities[$order_detail->product_id][$order_detail->product_attribute_id]; } if ($order_detail->product_quantity - $customization_quantity - $order_detail->product_quantity_refunded - $order_detail->product_quantity_return < $qtyCancelProduct) { $this->errors[] = Tools::displayError('Invalid quantity selected for product.'); } } } if ($customizationList) { $customization_quantities = Customization::retrieveQuantitiesFromIds(array_keys($customizationList)); foreach ($customizationList as $id_customization => $id_order_detail) { $qtyCancelProduct = abs($customizationQtyList[$id_customization]); $customization_quantity = $customization_quantities[$id_customization]; if (!$qtyCancelProduct) { $this->errors[] = Tools::displayError('No quantity selected for product.'); } if ($qtyCancelProduct > $customization_quantity['quantity'] - ($customization_quantity['quantity_refunded'] + $customization_quantity['quantity_returned'])) { $this->errors[] = Tools::displayError('Invalid quantity selected for product.'); } } } if (!count($this->errors) && $productList) { foreach ($productList as $key => $id_order_detail) { $qty_cancel_product = abs($qtyList[$key]); $order_detail = new OrderDetail((int) $id_order_detail); // Reinject product if (!$order->hasBeenDelivered() || $order->hasBeenDelivered() && Tools::isSubmit('reinjectQuantities')) { $reinjectable_quantity = (int) $order_detail->product_quantity - (int) $order_detail->product_quantity_reinjected; $quantity_to_reinject = $qty_cancel_product > $reinjectable_quantity ? $reinjectable_quantity : $qty_cancel_product; // @since 1.5.0 : Advanced Stock Management $product_to_inject = new Product($order_detail->product_id, false, $this->context->language->id, $order->id_shop); $product = new Product($order_detail->product_id); if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management && $order_detail->id_warehouse != 0) { $manager = StockManagerFactory::getManager(); $movements = StockMvt::getNegativeStockMvts($order_detail->id_order, $order_detail->product_id, $order_detail->product_attribute_id, $quantity_to_reinject); foreach ($movements as $movement) { $manager->addProduct($order_detail->product_id, $order_detail->product_attribute_id, new Warehouse($movement['id_warehouse']), $movement['physical_quantity'], null, $movement['price_te'], true); } StockAvailable::synchronize($order_detail->product_id); } else { if ($order_detail->id_warehouse == 0) { StockAvailable::updateQuantity($order_detail->product_id, $order_detail->product_attribute_id, $quantity_to_reinject, $order->id_shop); } else { $this->errors[] = Tools::displayError('Cannot re-stock product'); } } } // Delete product $order_detail = new OrderDetail((int) $id_order_detail); if (!$order->deleteProduct($order, $order_detail, $qtyCancelProduct)) { $this->errors[] = Tools::displayError('An error occurred during deletion of the product.') . ' <span class="bold">' . $order_detail->product_name . '</span>'; } Hook::exec('actionProductCancel', array('order' => $order, 'id_order_detail' => (int) $id_order_detail)); } } if (!count($this->errors) && $customizationList) { foreach ($customizationList as $id_customization => $id_order_detail) { $order_detail = new OrderDetail((int) $id_order_detail); $qtyCancelProduct = abs($customizationQtyList[$id_customization]); if (!$order->deleteCustomization($id_customization, $qtyCancelProduct, $order_detail)) { $this->errors[] = Tools::displayError('An error occurred during deletion of product customization.') . ' ' . $id_customization; } } } // E-mail params if ((Tools::isSubmit('generateCreditSlip') || Tools::isSubmit('generateDiscount')) && !count($this->errors)) { $customer = new Customer((int) $order->id_customer); $params['{lastname}'] = $customer->lastname; $params['{firstname}'] = $customer->firstname; $params['{id_order}'] = $order->id; $params['{order_name}'] = $order->getUniqReference(); } // Generate credit slip if (Tools::isSubmit('generateCreditSlip') && !count($this->errors)) { if (!OrderSlip::createOrderSlip($order, $full_product_list, $full_quantity_list, Tools::isSubmit('shippingBack'))) { $this->errors[] = Tools::displayError('Cannot generate credit slip'); } else { Hook::exec('actionOrderSlipAdd', array('order' => $order, 'productList' => $full_product_list, 'qtyList' => $full_quantity_list)); @Mail::Send((int) $order->id_lang, 'credit_slip', Mail::l('New credit slip regarding your order', $order->id_lang), $params, $customer->email, $customer->firstname . ' ' . $customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int) $order->id_shop); } } // Generate voucher if (Tools::isSubmit('generateDiscount') && !count($this->errors)) { $cartrule = new CartRule(); $languages = Language::getLanguages($order); $cartrule->description = sprintf($this->l('Credit Slip for order #%d'), $order->id); foreach ($languages as $language) { // Define a temporary name $cartrule->name[$language['id_lang']] = 'V0C' . (int) $order->id_customer . 'O' . (int) $order->id; } // Define a temporary code $cartrule->code = 'V0C' . (int) $order->id_customer . 'O' . (int) $order->id; $cartrule->quantity = 1; $cartrule->quantity_per_user = 1; // Specific to the customer $cartrule->id_customer = $order->id_customer; $now = time(); $cartrule->date_from = date('Y-m-d H:i:s', $now); $cartrule->date_to = date('Y-m-d H:i:s', $now + 3600 * 24 * 365.25); /* 1 year */ $cartrule->active = 1; $products = $order->getProducts(false, $full_product_list, $full_quantity_list); $total = 0; foreach ($products as $product) { $total += $product['unit_price_tax_incl'] * $product['product_quantity']; } if (Tools::isSubmit('shippingBack')) { $total += $order->total_shipping; } $cartrule->reduction_amount = $total; $cartrule->reduction_tax = true; $cartrule->minimum_amount_currency = $order->id_currency; $cartrule->reduction_currency = $order->id_currency; if (!$cartrule->add()) { $this->errors[] = Tools::displayError('Cannot generate voucher'); } else { // Update the voucher code and name foreach ($languages as $language) { $cartrule->name[$language['id_lang']] = 'V' . (int) $cartrule->id . 'C' . (int) $order->id_customer . 'O' . $order->id; } $cartrule->code = 'V' . (int) $cartrule->id . 'C' . (int) $order->id_customer . 'O' . $order->id; if (!$cartrule->update()) { $this->errors[] = Tools::displayError('Cannot generate voucher'); } else { $currency = $this->context->currency; $params['{voucher_amount}'] = Tools::displayPrice($cartrule->reduction_amount, $currency, false); $params['{voucher_num}'] = $cartrule->code; @Mail::Send((int) $order->id_lang, 'voucher', sprintf(Mail::l('New voucher regarding your order %s', (int) $order->id_lang), $order->reference), $params, $customer->email, $customer->firstname . ' ' . $customer->lastname, null, null, null, null, _PS_MAIL_DIR_, true, (int) $order->id_shop); } } } } else { $this->errors[] = Tools::displayError('No product or quantity selected.'); } // Redirect if no errors if (!count($this->errors)) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=31&token=' . $this->token); } } } else { $this->errors[] = Tools::displayError('You do not have permission to delete here.'); } } elseif (Tools::isSubmit('messageReaded')) { Message::markAsReaded(Tools::getValue('messageReaded'), $this->context->employee->id); } elseif (Tools::isSubmit('submitAddPayment') && isset($order)) { if ($this->tabAccess['edit'] === '1') { $amount = str_replace(',', '.', Tools::getValue('payment_amount')); $currency = new Currency(Tools::getValue('payment_currency')); $order_has_invoice = $order->hasInvoice(); if ($order_has_invoice) { $order_invoice = new OrderInvoice(Tools::getValue('payment_invoice')); } else { $order_invoice = null; } if (!Validate::isLoadedObject($order)) { $this->errors[] = Tools::displayError('Order can\'t be found'); } elseif (!Validate::isNegativePrice($amount)) { $this->errors[] = Tools::displayError('Amount is invalid'); } elseif (!Validate::isString(Tools::getValue('payment_method'))) { $this->errors[] = Tools::displayError('Payment method is invalid'); } elseif (!Validate::isString(Tools::getValue('payment_transaction_id'))) { $this->errors[] = Tools::displayError('Transaction ID is invalid'); } elseif (!Validate::isLoadedObject($currency)) { $this->errors[] = Tools::displayError('Currency is invalid'); } elseif ($order_has_invoice && !Validate::isLoadedObject($order_invoice)) { $this->errors[] = Tools::displayError('Invoice is invalid'); } elseif (!Validate::isDate(Tools::getValue('payment_date'))) { $this->errors[] = Tools::displayError('Date is invalid'); } else { if (!$order->addOrderPayment($amount, Tools::getValue('payment_method'), Tools::getValue('payment_transaction_id'), $currency, Tools::getValue('payment_date'), $order_invoice)) { $this->errors[] = Tools::displayError('An error occurred on adding order payment'); } else { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token); } } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } elseif (Tools::isSubmit('submitEditNote')) { $note = Tools::getValue('note'); $order_invoice = new OrderInvoice((int) Tools::getValue('id_order_invoice')); if (Validate::isLoadedObject($order_invoice) && Validate::isCleanHtml($note)) { if ($this->tabAccess['edit'] === '1') { $order_invoice->note = $note; if ($order_invoice->save()) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order_invoice->id_order . '&vieworder&conf=4&token=' . $this->token); } else { $this->errors[] = Tools::displayError('Unable to save invoice note.'); } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } else { $this->errors[] = Tools::displayError('Unable to load invoice for edit note.'); } } elseif (Tools::isSubmit('submitAddOrder') && ($id_cart = Tools::getValue('id_cart')) && ($module_name = Tools::getValue('payment_module_name')) && ($id_order_state = Tools::getValue('id_order_state')) && Validate::isModuleName($module_name)) { if ($this->tabAccess['edit'] === '1') { $payment_module = Module::getInstanceByName($module_name); $cart = new Cart((int) $id_cart); Context::getContext()->currency = new Currency((int) $cart->id_currency); Context::getContext()->customer = new Customer((int) $cart->id_customer); $employee = new Employee((int) Context::getContext()->cookie->id_employee); $payment_module->validateOrder((int) $cart->id, (int) $id_order_state, $cart->getOrderTotal(true, Cart::BOTH), $payment_module->displayName, $this->l('Manual order - Employee:') . Tools::safeOutput(substr($employee->firstname, 0, 1) . '. ' . $employee->lastname), array(), null, false, $cart->secure_key); if ($payment_module->currentOrder) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $payment_module->currentOrder . '&vieworder' . '&token=' . $this->token); } } else { $this->errors[] = Tools::displayError('You do not have permission to add here.'); } } elseif ((Tools::isSubmit('submitAddressShipping') || Tools::isSubmit('submitAddressInvoice')) && isset($order)) { if ($this->tabAccess['edit'] === '1') { $address = new Address(Tools::getValue('id_address')); if (Validate::isLoadedObject($address)) { // Update the address on order if (Tools::isSubmit('submitAddressShipping')) { $order->id_address_delivery = $address->id; } elseif (Tools::isSubmit('submitAddressInvoice')) { $order->id_address_invoice = $address->id; } $order->update(); Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token); } else { $this->errors[] = Tools::displayErrror('This address can\'t be loaded'); } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } elseif (Tools::isSubmit('submitChangeCurrency') && isset($order)) { if ($this->tabAccess['edit'] === '1') { if (Tools::getValue('new_currency') != $order->id_currency && !$order->valid) { $old_currency = new Currency($order->id_currency); $currency = new Currency(Tools::getValue('new_currency')); if (!Validate::isLoadedObject($currency)) { throw new PrestaShopException('Can\'t load Currency object'); } // Update order detail amount foreach ($order->getOrderDetailList() as $row) { $order_detail = new OrderDetail($row['id_order_detail']); $fields = array('ecotax', 'product_price', 'reduction_amount', 'total_shipping', 'total_shipping_tax_excl', 'total_shipping_tax_incl', 'total_products', 'total_products_wt', 'total_paid', 'total_paid_tax_incl', 'total_paid_tax_excl', 'total_paid_real', 'product_quantity_discount', 'purchase_supplier_price', 'reduction_amount_tax_incl', 'reduction_amount_tax_excl'); foreach ($fields as $field) { $order_detail->{$field} = Tools::convertPriceFull($order_detail->{$field}, $old_currency, $currency); } $order_detail->update(); } $id_order_carrier = Db::getInstance()->getValue(' SELECT `id_order_carrier` FROM `' . _DB_PREFIX_ . 'order_carrier` WHERE `id_order` = ' . (int) $order->id); if ($id_order_carrier) { $order_carrier = new OrderCarrier($id_order_carrier); $order_carrier->shipping_cost_tax_excl = (double) Tools::convertPriceFull($order_carrier->shipping_cost_tax_excl, $old_currency, $currency); $order_carrier->shipping_cost_tax_incl = (double) Tools::convertPriceFull($order_carrier->shipping_cost_tax_incl, $old_currency, $currency); $order_carrier->update(); } // Update order amount $fields = array('total_discounts', 'total_discounts_tax_incl', 'total_discounts_tax_excl', 'total_paid', 'total_paid_tax_incl', 'total_paid_tax_excl', 'total_paid_real', 'total_products', 'total_products_wt', 'total_shipping', 'total_shipping_tax_incl', 'total_shipping_tax_excl', 'total_wrapping', 'total_wrapping_tax_incl', 'total_wrapping_tax_excl'); foreach ($fields as $field) { $order->{$field} = Tools::convertPriceFull($order->{$field}, $old_currency, $currency); } // Update currency in order $order->id_currency = $currency->id; $order->update(); } else { $this->errors[] = Tools::displayError('You cannot change the currency'); } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } elseif (Tools::isSubmit('submitGenerateInvoice') && isset($order)) { if (!Configuration::get('PS_INVOICE')) { $this->errors[] = Tools::displayError('Invoice management has been disabled'); } elseif ($order->hasInvoice()) { $this->errors[] = Tools::displayError('This order already has an invoice'); } else { $order->setInvoice(true); Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token); } } elseif (Tools::isSubmit('submitDeleteVoucher') && isset($order)) { if ($this->tabAccess['edit'] === '1') { $order_cart_rule = new OrderCartRule(Tools::getValue('id_order_cart_rule')); if (Validate::isLoadedObject($order_cart_rule) && $order_cart_rule->id_order == $order->id) { if ($order_cart_rule->id_order_invoice) { $order_invoice = new OrderInvoice($order_cart_rule->id_order_invoice); if (!Validate::isLoadedObject($order_invoice)) { throw new PrestaShopException('Can\'t load Order Invoice object'); } // Update amounts of Order Invoice $order_invoice->total_discount_tax_excl -= $order_cart_rule->value_tax_excl; $order_invoice->total_discount_tax_incl -= $order_cart_rule->value; $order_invoice->total_paid_tax_excl += $order_cart_rule->value_tax_excl; $order_invoice->total_paid_tax_incl += $order_cart_rule->value; // Update Order Invoice $order_invoice->update(); } // Update amounts of order $order->total_discounts -= $order_cart_rule->value; $order->total_discounts_tax_incl -= $order_cart_rule->value; $order->total_discounts_tax_excl -= $order_cart_rule->value_tax_excl; $order->total_paid += $order_cart_rule->value; $order->total_paid_tax_incl += $order_cart_rule->value; $order->total_paid_tax_excl += $order_cart_rule->value_tax_excl; // Delete Order Cart Rule and update Order $order_cart_rule->delete(); $order->update(); Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token); } else { $this->errors[] = Tools::displayError('Cannot edit this Order Cart Rule'); } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } elseif (Tools::getValue('submitNewVoucher') && isset($order)) { if ($this->tabAccess['edit'] === '1') { if (!Tools::getValue('discount_name')) { $this->errors[] = Tools::displayError('You must specify a name in order to create a new discount'); } else { if ($order->hasInvoice()) { // If the discount is for only one invoice if (!Tools::isSubmit('discount_all_invoices')) { $order_invoice = new OrderInvoice(Tools::getValue('discount_invoice')); if (!Validate::isLoadedObject($order_invoice)) { throw new PrestaShopException('Can\'t load Order Invoice object'); } } } $cart_rules = array(); switch (Tools::getValue('discount_type')) { // Percent type case 1: if (Tools::getValue('discount_value') < 100) { if (isset($order_invoice)) { $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * Tools::getValue('discount_value') / 100, 2); $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * Tools::getValue('discount_value') / 100, 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); } elseif ($order->hasInvoice()) { $order_invoices_collection = $order->getInvoicesCollection(); foreach ($order_invoices_collection as $order_invoice) { $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round($order_invoice->total_paid_tax_incl * Tools::getValue('discount_value') / 100, 2); $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round($order_invoice->total_paid_tax_excl * Tools::getValue('discount_value') / 100, 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); } } else { $cart_rules[0]['value_tax_incl'] = Tools::ps_round($order->total_paid_tax_incl * Tools::getValue('discount_value') / 100, 2); $cart_rules[0]['value_tax_excl'] = Tools::ps_round($order->total_paid_tax_excl * Tools::getValue('discount_value') / 100, 2); } } else { $this->errors[] = Tools::displayError('Discount value is invalid'); } break; // Amount type // Amount type case 2: if (isset($order_invoice)) { if (Tools::getValue('discount_value') > $order_invoice->total_paid_tax_incl) { $this->errors[] = Tools::displayError('Discount value is greater than the order invoice total'); } else { $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round(Tools::getValue('discount_value'), 2); $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round(Tools::getValue('discount_value') / (1 + $order->getTaxesAverageUsed() / 100), 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); } } elseif ($order->hasInvoice()) { $order_invoices_collection = $order->getInvoicesCollection(); foreach ($order_invoices_collection as $order_invoice) { if (Tools::getValue('discount_value') > $order_invoice->total_paid_tax_incl) { $this->errors[] = Tools::displayError('Discount value is greater than the order invoice total (Invoice:') . $order_invoice->getInvoiceNumberFormatted(Context::getContext()->language->id) . ')'; } else { $cart_rules[$order_invoice->id]['value_tax_incl'] = Tools::ps_round(Tools::getValue('discount_value'), 2); $cart_rules[$order_invoice->id]['value_tax_excl'] = Tools::ps_round(Tools::getValue('discount_value') / (1 + $order->getTaxesAverageUsed() / 100), 2); // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); } } } else { if (Tools::getValue('discount_value') > $order->total_paid_tax_incl) { $this->errors[] = Tools::displayError('Discount value is greater than the order total'); } else { $cart_rules[0]['value_tax_incl'] = Tools::ps_round(Tools::getValue('discount_value'), 2); $cart_rules[0]['value_tax_excl'] = Tools::ps_round(Tools::getValue('discount_value') / (1 + $order->getTaxesAverageUsed() / 100), 2); } } break; // Free shipping type // Free shipping type case 3: if (isset($order_invoice)) { if ($order_invoice->total_shipping_tax_incl > 0) { $cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl; $cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl; // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); } } elseif ($order->hasInvoice()) { $order_invoices_collection = $order->getInvoicesCollection(); foreach ($order_invoices_collection as $order_invoice) { if ($order_invoice->total_shipping_tax_incl <= 0) { continue; } $cart_rules[$order_invoice->id]['value_tax_incl'] = $order_invoice->total_shipping_tax_incl; $cart_rules[$order_invoice->id]['value_tax_excl'] = $order_invoice->total_shipping_tax_excl; // Update OrderInvoice $this->applyDiscountOnInvoice($order_invoice, $cart_rules[$order_invoice->id]['value_tax_incl'], $cart_rules[$order_invoice->id]['value_tax_excl']); } } else { $cart_rules[0]['value_tax_incl'] = $order->total_shipping_tax_incl; $cart_rules[0]['value_tax_excl'] = $order->total_shipping_tax_excl; } break; default: $this->errors[] = Tools::displayError('Discount type is invalid'); } $res = true; foreach ($cart_rules as &$cart_rule) { $cartRuleObj = new CartRule(); $cartRuleObj->date_from = date('Y-m-d H:i:s', strtotime('-1 hour', strtotime($order->date_add))); $cartRuleObj->date_to = date('Y-m-d H:i:s', strtotime('+1 hour')); $cartRuleObj->name[Configuration::get('PS_LANG_DEFAULT')] = Tools::getValue('discount_name'); $cartRuleObj->quantity = 0; $cartRuleObj->quantity_per_user = 1; if (Tools::getValue('discount_type') == 1) { $cartRuleObj->reduction_percent = Tools::getValue('discount_value'); } elseif (Tools::getValue('discount_type') == 2) { $cartRuleObj->reduction_amount = $cart_rule['value_tax_excl']; } elseif (Tools::getValue('discount_type') == 3) { $cartRuleObj->free_shipping = 1; } $cartRuleObj->active = 0; if ($res = $cartRuleObj->add()) { $cart_rule['id'] = $cartRuleObj->id; } else { break; } } if ($res) { foreach ($cart_rules as $id_order_invoice => $cart_rule) { // Create OrderCartRule $order_cart_rule = new OrderCartRule(); $order_cart_rule->id_order = $order->id; $order_cart_rule->id_cart_rule = $cart_rule['id']; $order_cart_rule->id_order_invoice = $id_order_invoice; $order_cart_rule->name = Tools::getValue('discount_name'); $order_cart_rule->value = $cart_rule['value_tax_incl']; $order_cart_rule->value_tax_excl = $cart_rule['value_tax_excl']; $res &= $order_cart_rule->add(); $order->total_discounts += $order_cart_rule->value; $order->total_discounts_tax_incl += $order_cart_rule->value; $order->total_discounts_tax_excl += $order_cart_rule->value_tax_excl; $order->total_paid -= $order_cart_rule->value; $order->total_paid_tax_incl -= $order_cart_rule->value; $order->total_paid_tax_excl -= $order_cart_rule->value_tax_excl; } // Update Order $res &= $order->update(); } if ($res) { Tools::redirectAdmin(self::$currentIndex . '&id_order=' . $order->id . '&vieworder&conf=4&token=' . $this->token); } else { $this->errors[] = Tools::displayError('An error occurred on OrderCartRule creation'); } } } else { $this->errors[] = Tools::displayError('You do not have permission to edit here.'); } } parent::postProcess(); }
public function attributeImport() { $default_language = Configuration::get('PS_LANG_DEFAULT'); $groups = array(); foreach (AttributeGroup::getAttributesGroups($default_language) as $group) { $groups[$group['name']] = (int) $group['id_attribute_group']; } $attributes = array(); foreach (Attribute::getAttributes($default_language) as $attribute) { $attributes[$attribute['attribute_group'] . '_' . $attribute['name']] = (int) $attribute['id_attribute']; } $this->receiveTab(); $handle = $this->openCsvFile(); AdminImportController::setLocale(); for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { if (count($line) == 1 && empty($line[0])) { continue; } if (Tools::getValue('convert')) { $line = $this->utf8EncodeArray($line); } $info = AdminImportController::getMaskedRow($line); $info = array_map('trim', $info); if (self::ignoreRow($info)) { continue; } AdminImportController::setDefaultValues($info); if (!Shop::isFeatureActive()) { $info['shop'] = 1; } elseif (!isset($info['shop']) || empty($info['shop'])) { $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); } $info['shop'] = explode($this->multiple_value_separator, $info['shop']); $id_shop_list = array(); if (is_array($info['shop']) && count($info['shop'])) { foreach ($info['shop'] as $shop) { if (!empty($shop) && !is_numeric($shop)) { $id_shop_list[] = Shop::getIdByName($shop); } elseif (!empty($shop)) { $id_shop_list[] = $shop; } } } if (isset($info['id_product']) && is_string($info['id_product'])) { $prod = self::findProductByName($default_language, $info['id_product']); if ($prod['id_product']) { $info['id_product'] = $prod['id_product']; } else { unset($info['id_product']); } } if (!isset($info['id_product']) && Tools::getValue('match_ref') && isset($info['product_reference']) && $info['product_reference']) { $datas = Db::getInstance()->getRow(' SELECT p.`id_product` FROM `' . _DB_PREFIX_ . 'product` p ' . Shop::addSqlAssociation('product', 'p') . ' WHERE p.`reference` = "' . pSQL($info['product_reference']) . '" '); if (isset($datas['id_product']) && $datas['id_product']) { $info['id_product'] = $datas['id_product']; } } if (isset($info['id_product'])) { $product = new Product((int) $info['id_product'], false, $default_language); } else { continue; } $id_image = array(); if (array_key_exists('delete_existing_images', $info) && $info['delete_existing_images'] && !isset($this->cache_image_deleted[(int) $product->id])) { $product->deleteImages(); $this->cache_image_deleted[(int) $product->id] = true; } if (isset($info['image_url']) && $info['image_url']) { $info['image_url'] = explode(',', $info['image_url']); if (is_array($info['image_url']) && count($info['image_url'])) { foreach ($info['image_url'] as $url) { $url = trim($url); $product_has_images = (bool) Image::getImages($this->context->language->id, $product->id); $image = new Image(); $image->id_product = (int) $product->id; $image->position = Image::getHighestPosition($product->id) + 1; $image->cover = !$product_has_images ? true : false; $field_error = $image->validateFields(UNFRIENDLY_ERROR, true); $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true); if ($field_error === true && $lang_field_error === true && $image->add()) { $image->associateTo($id_shop_list); if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !Tools::getValue('regenerate'))) { $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); $image->delete(); } else { $id_image[] = (int) $image->id; } } else { $this->warnings[] = sprintf(Tools::displayError('%s cannot be saved'), isset($image->id_product) ? ' (' . $image->id_product . ')' : ''); $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . mysql_error(); } } } } elseif (isset($info['image_position']) && $info['image_position']) { $info['image_position'] = explode(',', $info['image_position']); if (is_array($info['image_position']) && count($info['image_position'])) { foreach ($info['image_position'] as $position) { $images = $product->getImages($default_language); if ($images) { foreach ($images as $row) { if ($row['position'] == (int) $position) { $id_image[] = (int) $row['id_image']; break; } } } if (empty($id_image)) { $this->warnings[] = sprintf(Tools::displayError('No image was found for combination with id_product = %s and image position = %s.'), $product->id, (int) $position); } } } } $id_attribute_group = 0; $groups_attributes = array(); if (isset($info['group'])) { foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) { if (empty($group)) { continue; } $tab_group = explode(':', $group); $group = trim($tab_group[0]); if (!isset($tab_group[1])) { $type = 'select'; } else { $type = trim($tab_group[1]); } $groups_attributes[$key]['group'] = $group; if (isset($tab_group[2])) { $position = trim($tab_group[2]); } else { $position = false; } if (!isset($groups[$group])) { $obj = new AttributeGroup(); $obj->is_color_group = false; $obj->group_type = pSQL($type); $obj->name[$default_language] = $group; $obj->public_name[$default_language] = $group; $obj->position = !$position ? AttributeGroup::getHigherPosition() + 1 : $position; if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { $obj->add(); $obj->associateTo($id_shop_list); $groups[$group] = $obj->id; } else { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); } $id_attribute_group = $obj->id; $groups_attributes[$key]['id'] = $id_attribute_group; } else { $id_attribute_group = $groups[$group]; $groups_attributes[$key]['id'] = $id_attribute_group; } } } $id_product_attribute = 0; $id_product_attribute_update = false; $attributes_to_add = array(); if (isset($info['attribute'])) { foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute) { if (empty($attribute)) { continue; } $tab_attribute = explode(':', $attribute); $attribute = trim($tab_attribute[0]); if (isset($tab_attribute[1])) { $position = trim($tab_attribute[1]); } else { $position = false; } if (isset($groups_attributes[$key])) { $group = $groups_attributes[$key]['group']; if (!isset($attributes[$group . '_' . $attribute]) && count($groups_attributes[$key]) == 2) { $id_attribute_group = $groups_attributes[$key]['id']; $obj = new Attribute(); $obj->id_attribute_group = $groups_attributes[$key]['id']; $obj->name[$default_language] = str_replace('\\n', '', str_replace('\\r', '', $attribute)); $obj->position = !$position && isset($groups[$group]) ? Attribute::getHigherPosition($groups[$group]) + 1 : $position; if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { $obj->add(); $obj->associateTo($id_shop_list); $attributes[$group . '_' . $attribute] = $obj->id; } else { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); } } $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int) $info['minimal_quantity'] : 1; $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']); $info['price'] = str_replace(',', '.', $info['price']); $info['ecotax'] = str_replace(',', '.', $info['ecotax']); $info['weight'] = str_replace(',', '.', $info['weight']); $info['available_date'] = Validate::isDate($info['available_date']) ? $info['available_date'] : null; if (!Validate::isEan13($info['ean13'])) { $this->warnings[] = sprintf(Tools::displayError('EAN13 "%1s" has incorrect value for product with id %2d.'), $info['ean13'], $product->id); $info['ean13'] = ''; } if ($info['default_on']) { $product->deleteDefaultAttributes(); } if (isset($info['reference']) && !empty($info['reference'])) { $id_product_attribute = Combination::getIdByReference($product->id, (string) $info['reference']); if ($id_product_attribute) { $attribute_combinations = $product->getAttributeCombinations($default_language); foreach ($attribute_combinations as $attribute_combination) { if ($id_product_attribute && in_array($id_product_attribute, $attribute_combination)) { $product->updateAttribute($id_product_attribute, (double) $info['wholesale_price'], (double) $info['price'], (double) $info['weight'], 0, Configuration::get('PS_USE_ECOTAX') ? (double) $info['ecotax'] : 0, $id_image, (string) $info['reference'], (string) $info['ean13'], (int) $info['default_on'], 0, (string) $info['upc'], (int) $info['minimal_quantity'], $info['available_date'], null, $id_shop_list); $id_product_attribute_update = true; if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); } } } } } if (!$id_product_attribute) { $id_product_attribute = $product->addCombinationEntity((double) $info['wholesale_price'], (double) $info['price'], (double) $info['weight'], 0, Configuration::get('PS_USE_ECOTAX') ? (double) $info['ecotax'] : 0, (int) $info['quantity'], $id_image, (string) $info['reference'], 0, (string) $info['ean13'], (int) $info['default_on'], 0, (string) $info['upc'], (int) $info['minimal_quantity'], $id_shop_list, $info['available_date']); if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); } } if (isset($attributes[$group . '_' . $attribute])) { $attributes_to_add[] = (int) $attributes[$group . '_' . $attribute]; } $obj = new Attribute(); $obj->cleanPositions((int) $id_attribute_group, false); AttributeGroup::cleanPositions(); } } } $product->checkDefaultAttributes(); if (!$product->cache_default_attribute) { Product::updateDefaultAttribute($product->id); } if ($id_product_attribute) { if ($id_product_attribute_update) { Db::getInstance()->execute(' DELETE FROM ' . _DB_PREFIX_ . 'product_attribute_combination WHERE id_product_attribute = ' . (int) $id_product_attribute); } foreach ($attributes_to_add as $attribute_to_add) { Db::getInstance()->execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'product_attribute_combination (id_attribute, id_product_attribute) VALUES (' . (int) $attribute_to_add . ',' . (int) $id_product_attribute . ')'); } if (isset($info['advanced_stock_management'])) { if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product with id %d.'), $product->id); } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot enable on product with id %d.'), $product->id); } else { $product->setAdvancedStockManagement($info['advanced_stock_management']); } if (StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0) { StockAvailable::setProductDependsOnStock($product->id, 0, null, $id_product_attribute); } } if (isset($info['warehouse']) && $info['warehouse']) { if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse is not set on product with id %d.'), $product->id); } else { if (Warehouse::exists($info['warehouse'])) { $warehouse_location_entity = new WarehouseProductLocation(); $warehouse_location_entity->id_product = $product->id; $warehouse_location_entity->id_product_attribute = $id_product_attribute; $warehouse_location_entity->id_warehouse = $info['warehouse']; if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false) { $warehouse_location_entity->update(); } else { $warehouse_location_entity->save(); } StockAvailable::synchronize($product->id); } else { $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s.'), $product->name[$default_language]); } } } if (isset($info['depends_on_stock'])) { if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1) { $this->warnings[] = sprintf(Tools::displayError('Incorrect value for depends on stock for product %1$s '), $product->name[$default_language]); } elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, cannot set depends on stock %1$s '), $product->name[$default_language]); } else { StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'], null, $id_product_attribute); } if (isset($info['quantity']) && $info['quantity']) { if ($info['depends_on_stock'] == 1) { $stock_manager = StockManagerFactory::getManager(); $price = str_replace(',', '.', $info['wholesale_price']); if ($price == 0) { $price = 1.0E-6; } $price = round((double) $price, 6); $warehouse = new Warehouse($info['warehouse']); if ($stock_manager->addProduct((int) $product->id, $id_product_attribute, $warehouse, $info['quantity'], 1, $price, true)) { StockAvailable::synchronize((int) $product->id); } } else { if (Shop::isFeatureActive()) { foreach ($id_shop_list as $shop) { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, $info['quantity'], (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, $info['quantity'], $this->context->shop->id); } } } } else { if (Shop::isFeatureActive()) { foreach ($id_shop_list as $shop) { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id); } } } } $this->closeCsvFile($handle); }
/** * Post treatment for warehouses */ public function processWarehouses() { if ((int) Tools::getValue('warehouse_loaded') === 1 && Validate::isLoadedObject($product = new Product((int) ($id_product = Tools::getValue('id_product'))))) { // Get all id_product_attribute $attributes = $product->getAttributesResume($this->context->language->id); if (empty($attributes)) { $attributes[] = array('id_product_attribute' => 0, 'attribute_designation' => ''); } // Get all available warehouses $warehouses = Warehouse::getWarehouses(true); // Get already associated warehouses $associated_warehouses_collection = WarehouseProductLocation::getCollection($product->id); $elements_to_manage = array(); // get form inforamtion foreach ($attributes as $attribute) { foreach ($warehouses as $warehouse) { $key = $warehouse['id_warehouse'] . '_' . $product->id . '_' . $attribute['id_product_attribute']; // get elements to manage if (Tools::isSubmit('check_warehouse_' . $key)) { $location = Tools::getValue('location_warehouse_' . $key, ''); $elements_to_manage[$key] = $location; } } } // Delete entry if necessary foreach ($associated_warehouses_collection as $awc) { if (!array_key_exists($awc->id_warehouse . '_' . $awc->id_product . '_' . $awc->id_product_attribute, $elements_to_manage)) { $awc->delete(); } } // Manage locations foreach ($elements_to_manage as $key => $location) { $params = explode('_', $key); $wpl_id = (int) WarehouseProductLocation::getIdByProductAndWarehouse((int) $params[1], (int) $params[2], (int) $params[0]); if (empty($wpl_id)) { //create new record $warehouse_location_entity = new WarehouseProductLocation(); $warehouse_location_entity->id_product = (int) $params[1]; $warehouse_location_entity->id_product_attribute = (int) $params[2]; $warehouse_location_entity->id_warehouse = (int) $params[0]; $warehouse_location_entity->location = pSQL($location); $warehouse_location_entity->save(); } else { $warehouse_location_entity = new WarehouseProductLocation((int) $wpl_id); $location = pSQL($location); if ($location != $warehouse_location_entity->location) { $warehouse_location_entity->location = pSQL($location); $warehouse_location_entity->update(); } } } StockAvailable::synchronize((int) $id_product); } }
/** * Helper function for AdminAdvancedSupplyOrderController::postProcess() * * @see AdminAdvancedSupplyOrderController::postProcess() */ protected function postProcessUpdateReceipt() { // gets all box selected $rows = Tools::getValue('supply_order_detailBox'); if (!$rows) { $this->errors[] = Tools::displayError($this->l('You did not select any product to update.')); return; } // final array with id_supply_order_detail and value to update $to_update = array(); $comment = array(); // gets quantity for each id_order_detail //--ERP information add new product foreach ($rows as $row) { // If _new, it mean new product, then we explode to get the number if (strpos($row, "_") !== false) { $row = explode('_', $row); $row = $row[1]; // Commande courante $supply_order = new SupplyOrder((int) Tools::getValue('id_supply_order')); // Currency courant $currency = new Currency($supply_order->id_ref_currency); // Objet supply order detail $supply_order_detail = new SupplyOrderDetail(); $supply_order_detail->id = 0; $supply_order_detail->reference = Tools::getValue("input_reference_{$row}"); $supply_order_detail->name = Tools::getValue("input_name_displayed_{$row}"); $supply_order_detail->ean13 = Tools::getValue("input_ean13_{$row}"); $supply_order_detail->upc = Tools::getValue("input_upc_{$row}"); $supply_order_detail->unit_price_te = Tools::getValue("input_unit_price_te_{$row}"); $supply_order_detail->discount_rate = Tools::getValue("input_discount_rate_{$row}"); $supply_order_detail->tax_rate = Tools::getValue("input_tax_rate_{$row}"); $supply_order_detail->quantity_expected = 0; $supply_order_detail->exchange_rate = $currency->conversion_rate; $supply_order_detail->id_currency = $currency->id; $supply_order_detail->id_supply_order = $supply_order->id; $supply_order_detail->supplier_reference = Tools::getValue("input_supplier_reference_{$row}") == null ? '' : Tools::getValue("input_supplier_reference_{$row}"); $supply_order_detail->name_displayed = Tools::getValue('input_name_displayed_' . $row); $ids = Tools::getValue("input_id_product_{$row}"); // If declension we explode if (strrpos($ids, "_")) { $ids = explode('_', $ids); $supply_order_detail->id_product = $ids[0]; $supply_order_detail->id_product_attribute = $ids[1]; } else { $supply_order_detail->id_product = $ids; $supply_order_detail->id_product_attribute = 0; } // Name $supply_order_detail->name = Product::getProductName($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $supply_order->id_lang); $errors = $supply_order_detail->validateController(); // if there is a problem, handle error for the current product // error > 1 only because quantity_expected is always in error // Then errors are displayed if there is more than 1 error if (count($errors) > 1) { // add the product to error array => display again product line $this->order_products_errors[] = array('id_product' => $supply_order_detail->id_product, 'id_product_attribute' => $supply_order_detail->id_product_attribute, 'unit_price_te' => $supply_order_detail->unit_price_te, 'quantity_expected' => $supply_order_detail->quantity_expected, 'discount_rate' => $supply_order_detail->discount_rate, 'tax_rate' => $supply_order_detail->tax_rate, 'name' => $supply_order_detail->name, 'name_displayed' => $supply_order_detail->name_displayed, 'reference' => $supply_order_detail->reference, 'supplier_reference' => $supply_order_detail->supplier_reference, 'ean13' => $supply_order_detail->ean13, 'upc' => $supply_order_detail->upc); $error_str = '<ul>'; foreach ($errors as $e) { $error_str .= '<li>' . $this->l('field') . ' ' . $e . '</li>'; } $error_str .= '</ul>'; $this->errors[] = Tools::displayError($this->l('Please check the product information:') . $supply_order_detail->name . ' ' . $error_str); } else { $supply_order_detail->save(); $to_update[Db::getInstance()->Insert_ID()] = (int) Tools::getValue('quantity_received_today_' . $row); $comment[Db::getInstance()->Insert_ID()] = Tools::getValue('input_comment_' . $row); //--ERP information // creates erp_supplier_order_detail for new product if ((int) $supply_order_detail->id > 0) { $erp_supply_order_detail = new ErpSupplyOrderDetail(); $erp_supply_order_detail->id_supply_order_detail = (int) $supply_order_detail->id; $erp_supply_order_detail->comment = Tools::getValue('input_comment_' . $row, ''); $validation_esod = $erp_supply_order_detail->validateController(); // checks erp_supplier_order_detail validity if (count($validation_esod) > 0) { foreach ($validation_esod as $item) { $this->errors[] = $item; } $this->errors[] = Tools::displayError('The ErpIllicopresta Supplier Order Detail is not correct. Please make sure all of the required fields are completed.'); } else { $erp_supply_order_detail->save(); } } } } else { if (Tools::isSubmit('quantity_received_today_' . $row)) { if (Tools::isSubmit('input_comment_' . $row)) { $comment[Db::getInstance()->Insert_ID()] = Tools::getValue('input_comment_' . $row); } $to_update[$row] = (int) Tools::getValue('quantity_received_today_' . $row); } } } // checks if there is something to update if (!count($to_update)) { $this->errors[] = Tools::displayError($this->l('You did not select any product to update.')); return; } foreach ($to_update as $id_supply_order_detail => $quantity) { $supply_order_detail = new SupplyOrderDetail($id_supply_order_detail); $supply_order = new SupplyOrder((int) Tools::getValue('id_supply_order')); if (Validate::isLoadedObject($supply_order_detail) && Validate::isLoadedObject($supply_order)) { // checks if quantity is valid // It's possible to receive more quantity than expected in case of a shipping error from the supplier if (!Validate::isInt($quantity) || $quantity <= 0) { $this->errors[] = sprintf(Tools::displayError($this->l('Quantity (%d) for product #%d is not valid')), (int) $quantity, (int) $id_supply_order_detail); } else { // creates the history $supplier_receipt_history = new SupplyOrderReceiptHistory(); $supplier_receipt_history->id_supply_order_detail = (int) $id_supply_order_detail; $supplier_receipt_history->id_employee = (int) $this->context->employee->id; $supplier_receipt_history->employee_firstname = pSQL($this->context->employee->firstname); $supplier_receipt_history->employee_lastname = pSQL($this->context->employee->lastname); $supplier_receipt_history->id_supply_order_state = (int) $supply_order->id_supply_order_state; $supplier_receipt_history->quantity = (int) $quantity; // updates quantity received $supply_order_detail->quantity_received += (int) $quantity; // if current state is "Pending receipt", then we sets it to "Order received in part" if (3 == $supply_order->id_supply_order_state) { $supply_order->id_supply_order_state = 4; } // Adds to stock $warehouse = new Warehouse($supply_order->id_warehouse); if (!Validate::isLoadedObject($warehouse)) { $this->errors[] = Tools::displayError($this->l('The warehouse could not be loaded.')); return; } $price = $supply_order_detail->unit_price_te; // converts the unit price to the warehouse currency if needed if ($supply_order->id_currency != $warehouse->id_currency) { // first, converts the price to the default currency $price_converted_to_default_currency = Tools::convertPrice($supply_order_detail->unit_price_te, $supply_order->id_currency, false); // then, converts the newly calculated pri-ce from the default currency to the needed currency $price = Tools::ps_round(Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true), 6); } $manager = StockManagerFactory::getManager(); $res = $manager->addProduct($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $warehouse, (int) $quantity, Configuration::get('PS_STOCK_MVT_SUPPLY_ORDER'), $price, true, $supply_order->id); if ($res) { StockAvailable::synchronize($supply_order_detail->id_product); } else { $this->errors[] = Tools::displayError($this->l('Error while adding products to the warehouse.')); } $location = Warehouse::getProductLocation($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $warehouse->id); $res = Warehouse::setProductlocation($supply_order_detail->id_product, $supply_order_detail->id_product_attribute, $warehouse->id, $location ? $location : ''); //-ERP information // if ($res) { $supplier_receipt_history->add(); $supply_order_detail->save(); $supply_order->save(); } else { $this->errors[] = Tools::displayError($this->l('Error while setting warehouse on product record')); } } } } if (!count($this->errors)) { // display confirm message $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; $redirect = self::$currentIndex . '&token=' . $token; $this->redirect_after = $redirect . '&conf=4'; } }
public function processGenerate() { if (!is_array(Tools::getValue('options'))) { $this->errors[] = $this->trans('Please select at least one attribute.', array(), 'Admin.Catalog.Notification'); } else { $tab = array_values(Tools::getValue('options')); if (count($tab) && Validate::isLoadedObject($this->product)) { AdminAttributeGeneratorController::setAttributesImpacts($this->product->id, $tab); $this->combinations = array_values(AdminAttributeGeneratorController::createCombinations($tab)); $values = array_values(array_map(array($this, 'addAttribute'), $this->combinations)); // @since 1.5.0 if ($this->product->depends_on_stock == 0) { $attributes = Product::getProductAttributesIds($this->product->id, true); foreach ($attributes as $attribute) { StockAvailable::removeProductFromStockAvailable($this->product->id, $attribute['id_product_attribute'], Context::getContext()->shop); } } SpecificPriceRule::disableAnyApplication(); $this->product->deleteProductAttributes(); $this->product->generateMultipleCombinations($values, $this->combinations); // Reset cached default attribute for the product and get a new one Product::getDefaultAttribute($this->product->id, 0, true); Product::updateDefaultAttribute($this->product->id); // @since 1.5.0 if ($this->product->depends_on_stock == 0) { $attributes = Product::getProductAttributesIds($this->product->id, true); $quantity = (int) Tools::getValue('quantity'); foreach ($attributes as $attribute) { if (Shop::getContext() == Shop::CONTEXT_ALL) { $shops_list = Shop::getShops(); if (is_array($shops_list)) { foreach ($shops_list as $current_shop) { if (isset($current_shop['id_shop']) && (int) $current_shop['id_shop'] > 0) { StockAvailable::setQuantity($this->product->id, (int) $attribute['id_product_attribute'], $quantity, (int) $current_shop['id_shop']); } } } } else { StockAvailable::setQuantity($this->product->id, (int) $attribute['id_product_attribute'], $quantity); } } } else { StockAvailable::synchronize($this->product->id); } SpecificPriceRule::enableAnyApplication(); SpecificPriceRule::applyAllRules(array((int) $this->product->id)); Tools::redirectAdmin($this->context->link->getAdminLink('AdminProducts') . '&id_product=' . (int) Tools::getValue('id_product') . '&updateproduct&key_tab=Combinations&conf=4'); } else { $this->errors[] = $this->trans('Unable to initialize these parameters. A combination is missing or an object cannot be loaded.'); } } }
$old_state = new SupplyOrderState($supply_order->id_supply_order_state); // special case of validate state - check if there are products in the order and the required state is not an enclosed state if ($supply_order->isEditable() && !$supply_order->hasEntries() && !$new_state->enclosed) { echo Tools::jsonEncode(array('error' => $erpip->l('It is not possible to change the status of this order because you did not order any product.', 'erpillicopresta'))); } else { $supply_order->id_supply_order_state = $state['id_supply_order_state']; if ($supply_order->save()) { // if pending_receipt, // or if the order is being canceled, // synchronizes StockAvailable if ($new_state->pending_receipt && !$new_state->receipt_state || $old_state->receipt_state && $new_state->enclosed && !$new_state->receipt_state) { $supply_order_details = $supply_order->getEntries(); $products_done = array(); foreach ($supply_order_details as $supply_order_detail) { if (!in_array($supply_order_detail['id_product'], $products_done)) { StockAvailable::synchronize($supply_order_detail['id_product']); $products_done[] = $supply_order_detail['id_product']; } } } echo Tools::jsonEncode(array('message' => $erpip->l('Supply order state updated successfully !'))); } } } } } break; default: echo $erpip->l('Error : the requested action does not exist (parameter "action" is invalide) : ') . Tools::getValue('action'); break; }
protected function reinjectQuantity($order_detail, $qty_cancel_product, $delete = false) { // Reinject product $reinjectable_quantity = (int) $order_detail->product_quantity - (int) $order_detail->product_quantity_reinjected; $quantity_to_reinject = $qty_cancel_product > $reinjectable_quantity ? $reinjectable_quantity : $qty_cancel_product; // @since 1.5.0 : Advanced Stock Management $product_to_inject = new Product($order_detail->product_id, false, (int) $this->context->language->id, (int) $order_detail->id_shop); $product = new Product($order_detail->product_id, false, (int) $this->context->language->id, (int) $order_detail->id_shop); if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management && $order_detail->id_warehouse != 0) { $manager = StockManagerFactory::getManager(); $movements = StockMvt::getNegativeStockMvts($order_detail->id_order, $order_detail->product_id, $order_detail->product_attribute_id, $quantity_to_reinject); $left_to_reinject = $quantity_to_reinject; foreach ($movements as $movement) { if ($left_to_reinject > $movement['physical_quantity']) { $quantity_to_reinject = $movement['physical_quantity']; } $left_to_reinject -= $quantity_to_reinject; if (Pack::isPack((int) $product->id)) { // Gets items if ($product->pack_stock_type == 1 || $product->pack_stock_type == 2 || $product->pack_stock_type == 3 && Configuration::get('PS_PACK_STOCK_TYPE') > 0) { $products_pack = Pack::getItems((int) $product->id, (int) Configuration::get('PS_LANG_DEFAULT')); // Foreach item foreach ($products_pack as $product_pack) { if ($product_pack->advanced_stock_management == 1) { $manager->addProduct($product_pack->id, $product_pack->id_pack_product_attribute, new Warehouse($movement['id_warehouse']), $product_pack->pack_quantity * $quantity_to_reinject, null, $movement['price_te'], true); } } } if ($product->pack_stock_type == 0 || $product->pack_stock_type == 2 || $product->pack_stock_type == 3 && (Configuration::get('PS_PACK_STOCK_TYPE') == 0 || Configuration::get('PS_PACK_STOCK_TYPE') == 2)) { $manager->addProduct($order_detail->product_id, $order_detail->product_attribute_id, new Warehouse($movement['id_warehouse']), $quantity_to_reinject, null, $movement['price_te'], true); } } else { $manager->addProduct($order_detail->product_id, $order_detail->product_attribute_id, new Warehouse($movement['id_warehouse']), $quantity_to_reinject, null, $movement['price_te'], true); } } $id_product = $order_detail->product_id; if ($delete) { $order_detail->delete(); } StockAvailable::synchronize($id_product); } elseif ($order_detail->id_warehouse == 0) { StockAvailable::updateQuantity($order_detail->product_id, $order_detail->product_attribute_id, $quantity_to_reinject, $order_detail->id_shop); if ($delete) { $order_detail->delete(); } } else { $this->errors[] = Tools::displayError('This product cannot be re-stocked.'); } }
public function attributeImport() { $default_language = Configuration::get('PS_LANG_DEFAULT'); $groups = array(); foreach (AttributeGroup::getAttributesGroups($default_language) as $group) { $groups[$group['name']] = (int) $group['id_attribute_group']; } $attributes = array(); foreach (Attribute::getAttributes($default_language) as $attribute) { $attributes[$attribute['attribute_group'] . '_' . $attribute['name']] = (int) $attribute['id_attribute']; } $this->receiveTab(); $handle = $this->openCsvFile(); AdminImportController::setLocale(); for ($current_line = 0; $line = fgetcsv($handle, MAX_LINE_SIZE, $this->separator); $current_line++) { if (count($line) == 1 && empty($line[0])) { continue; } if (Tools::getValue('convert')) { $line = $this->utf8EncodeArray($line); } $info = AdminImportController::getMaskedRow($line); $info = array_map('trim', $info); AdminImportController::setDefaultValues($info); if (!Shop::isFeatureActive()) { $info['shop'] = 1; } elseif (!isset($info['shop']) || empty($info['shop'])) { $info['shop'] = implode($this->multiple_value_separator, Shop::getContextListShopID()); } // Get shops for each attributes $info['shop'] = explode($this->multiple_value_separator, $info['shop']); $id_shop_list = array(); if (is_array($info['shop']) && count($info['shop'])) { foreach ($info['shop'] as $shop) { if (!empty($shop) && !is_numeric($shop)) { $id_shop_list[] = Shop::getIdByName($shop); } elseif (!empty($shop)) { $id_shop_list[] = $shop; } } } if (isset($info['id_product'])) { $product = new Product((int) $info['id_product'], false, $default_language); } else { continue; } $id_image = null; //delete existing images if "delete_existing_images" is set to 1 if (array_key_exists('delete_existing_images', $info) && $info['delete_existing_images'] && !isset($this->cache_image_deleted[(int) $product->id])) { $product->deleteImages(); $this->cache_image_deleted[(int) $product->id] = true; } if (isset($info['image_url']) && $info['image_url']) { $product_has_images = (bool) Image::getImages($this->context->language->id, $product->id); $url = $info['image_url']; $image = new Image(); $image->id_product = (int) $product->id; $image->position = Image::getHighestPosition($product->id) + 1; $image->cover = !$product_has_images ? true : false; $field_error = $image->validateFields(UNFRIENDLY_ERROR, true); $lang_field_error = $image->validateFieldsLang(UNFRIENDLY_ERROR, true); if ($field_error === true && $lang_field_error === true && $image->add()) { $image->associateTo($id_shop_list); if (!AdminImportController::copyImg($product->id, $image->id, $url, 'products', !Tools::getValue('regenerate'))) { $this->warnings[] = sprintf(Tools::displayError('Error copying image: %s'), $url); $image->delete(); } else { $id_image = array($image->id); } } else { $this->warnings[] = sprintf(Tools::displayError('%s cannot be saved'), isset($image->id_product) ? ' (' . $image->id_product . ')' : ''); $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : '') . mysql_error(); } } elseif (isset($info['image_position']) && $info['image_position']) { $images = $product->getImages($default_language); if ($images) { foreach ($images as $row) { if ($row['position'] == (int) $info['image_position']) { $id_image = array($row['id_image']); break; } } } if (!$id_image) { $this->warnings[] = sprintf(Tools::displayError('No image was found for combination with id_product = %s and image position = %s.'), $product->id, (int) $info['image_position']); } } $id_attribute_group = 0; // groups $groups_attributes = array(); if (isset($info['group'])) { foreach (explode($this->multiple_value_separator, $info['group']) as $key => $group) { if (empty($group)) { continue; } $tab_group = explode(':', $group); $group = trim($tab_group[0]); if (!isset($tab_group[1])) { $type = 'select'; } else { $type = trim($tab_group[1]); } // sets group $groups_attributes[$key]['group'] = $group; // if position is filled if (isset($tab_group[2])) { $position = trim($tab_group[2]); } else { $position = false; } if (!isset($groups[$group])) { $obj = new AttributeGroup(); $obj->is_color_group = false; $obj->group_type = pSQL($type); $obj->name[$default_language] = $group; $obj->public_name[$default_language] = $group; $obj->position = !$position ? AttributeGroup::getHigherPosition() + 1 : $position; if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { $obj->add(); $obj->associateTo($id_shop_list); $groups[$group] = $obj->id; } else { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); } // fills groups attributes $id_attribute_group = $obj->id; $groups_attributes[$key]['id'] = $id_attribute_group; } else { $id_attribute_group = $groups[$group]; $groups_attributes[$key]['id'] = $id_attribute_group; } } } // inits attribute $id_product_attribute = 0; $id_product_attribute_update = false; $attributes_to_add = array(); // for each attribute if (isset($info['attribute'])) { foreach (explode($this->multiple_value_separator, $info['attribute']) as $key => $attribute) { if (empty($attribute)) { continue; } $tab_attribute = explode(':', $attribute); $attribute = trim($tab_attribute[0]); // if position is filled if (isset($tab_attribute[1])) { $position = trim($tab_attribute[1]); } else { $position = false; } if (isset($groups_attributes[$key])) { $group = $groups_attributes[$key]['group']; if (!isset($attributes[$group . '_' . $attribute]) && count($groups_attributes[$key]) == 2) { $id_attribute_group = $groups_attributes[$key]['id']; $obj = new Attribute(); // sets the proper id (corresponding to the right key) $obj->id_attribute_group = $groups_attributes[$key]['id']; $obj->name[$default_language] = str_replace('\\n', '', str_replace('\\r', '', $attribute)); $obj->position = !$position && isset($groups[$group]) ? Attribute::getHigherPosition($groups[$group]) + 1 : $position; if (($field_error = $obj->validateFields(UNFRIENDLY_ERROR, true)) === true && ($lang_field_error = $obj->validateFieldsLang(UNFRIENDLY_ERROR, true)) === true) { $obj->add(); $obj->associateTo($id_shop_list); $attributes[$group . '_' . $attribute] = $obj->id; } else { $this->errors[] = ($field_error !== true ? $field_error : '') . (isset($lang_field_error) && $lang_field_error !== true ? $lang_field_error : ''); } } $info['minimal_quantity'] = isset($info['minimal_quantity']) && $info['minimal_quantity'] ? (int) $info['minimal_quantity'] : 1; $info['wholesale_price'] = str_replace(',', '.', $info['wholesale_price']); $info['price'] = str_replace(',', '.', $info['price']); $info['ecotax'] = str_replace(',', '.', $info['ecotax']); $info['weight'] = str_replace(',', '.', $info['weight']); // if a reference is specified for this product, get the associate id_product_attribute to UPDATE if (isset($info['reference']) && !empty($info['reference'])) { $id_product_attribute = Combination::getIdByReference($product->id, strval($info['reference'])); // updates the attribute if ($id_product_attribute) { // gets all the combinations of this product $attribute_combinations = $product->getAttributeCombinations($default_language); foreach ($attribute_combinations as $attribute_combination) { if ($id_product_attribute && in_array($id_product_attribute, $attribute_combination)) { $product->updateAttribute($id_product_attribute, (double) $info['wholesale_price'], (double) $info['price'], (double) $info['weight'], 0, (double) $info['ecotax'], $id_image, strval($info['reference']), strval($info['ean13']), (int) $info['default_on'], 0, strval($info['upc']), (int) $info['minimal_quantity'], 0, null, $id_shop_list); $id_product_attribute_update = true; if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); } } } } } // if no attribute reference is specified, creates a new one if (!$id_product_attribute) { $id_product_attribute = $product->addCombinationEntity((double) $info['wholesale_price'], (double) $info['price'], (double) $info['weight'], 0, (double) $info['ecotax'], (int) $info['quantity'], $id_image, strval($info['reference']), 0, strval($info['ean13']), (int) $info['default_on'], 0, strval($info['upc']), (int) $info['minimal_quantity'], $id_shop_list); if (isset($info['supplier_reference']) && !empty($info['supplier_reference'])) { $product->addSupplierReference($product->id_supplier, $id_product_attribute, $info['supplier_reference']); } } // fills our attributes array, in order to add the attributes to the product_attribute afterwards if (isset($attributes[$group . '_' . $attribute])) { $attributes_to_add[] = (int) $attributes[$group . '_' . $attribute]; } // after insertion, we clean attribute position and group attribute position $obj = new Attribute(); $obj->cleanPositions((int) $id_attribute_group, false); AttributeGroup::cleanPositions(); } } } $product->checkDefaultAttributes(); if (!$product->cache_default_attribute) { Product::updateDefaultAttribute($product->id); } if ($id_product_attribute) { // now adds the attributes in the attribute_combination table if ($id_product_attribute_update) { Db::getInstance()->execute(' DELETE FROM ' . _DB_PREFIX_ . 'product_attribute_combination WHERE id_product_attribute = ' . (int) $id_product_attribute); } foreach ($attributes_to_add as $attribute_to_add) { Db::getInstance()->execute(' INSERT IGNORE INTO ' . _DB_PREFIX_ . 'product_attribute_combination (id_attribute, id_product_attribute) VALUES (' . (int) $attribute_to_add . ',' . (int) $id_product_attribute . ')'); } // set advanced stock managment if (isset($info['advanced_stock_management'])) { if ($info['advanced_stock_management'] != 1 && $info['advanced_stock_management'] != 0) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management has incorrect value. Not set for product with id %s '), $product->id); } elseif (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $info['advanced_stock_management'] == 1) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, can not enable on product with id %s '), $product->id); } else { $product->setAdvancedStockManagement($info['advanced_stock_management']); } // automaticly disable depends on stock, if a_s_m set to disabled if (StockAvailable::dependsOnStock($product->id) == 1 && $info['advanced_stock_management'] == 0) { StockAvailable::setProductDependsOnStock($product->id, 0, null, $id_product_attribute); } } // Check if warehouse exists if ($info['warehouse']) { if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management is not enabled, warehouse not set on product with id %s '), $product->id); } else { if (Warehouse::exists($info['warehouse'])) { $warehouse_location_entity = new WarehouseProductLocation(); $warehouse_location_entity->id_product = $product->id; $warehouse_location_entity->id_product_attribute = $id_product_attribute; $warehouse_location_entity->id_warehouse = $info['warehouse']; if (WarehouseProductLocation::getProductLocation($product->id, $id_product_attribute, $info['warehouse']) !== false) { $warehouse_location_entity->update(); } else { $warehouse_location_entity->save(); } StockAvailable::synchronize($product->id); } else { $this->warnings[] = sprintf(Tools::displayError('Warehouse did not exist, cannot set on product %1$s '), $product->name[$default_language_id]); } } } // stock available if (isset($info['depends_on_stock'])) { if ($info['depends_on_stock'] != 0 && $info['depends_on_stock'] != 1) { $this->warnings[] = sprintf(Tools::displayError('Incorrect value for depends on stock for product %1$s '), $product->name[$default_language_id]); } elseif ((!$info['advanced_stock_management'] || $info['advanced_stock_management'] == 0) && $info['depends_on_stock'] == 1) { $this->warnings[] = sprintf(Tools::displayError('Advanced stock management not enabled, can not set depends on stock %1$s '), $product->name[$default_language_id]); } else { StockAvailable::setProductDependsOnStock($product->id, $info['depends_on_stock'], null, $id_product_attribute); } // This code allows us to set qty and disable depends on stock if (isset($info['quantity']) && $info['depends_on_stock'] == 0) { if (Shop::isFeatureActive()) { foreach ($shops as $shop) { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id); } } elseif (isset($info['quantity']) && $info['depends_on_stock'] == 1) { // add stock $stock_manager = StockManagerFactory::getManager(); $price = str_replace(',', '.', $info['wholesale_price']); if ($price == 0) { $price = 1.0E-6; } $price = round(floatval($price), 6); $warehouse = new Warehouse($info['warehouse']); if ($stock_manager->addProduct((int) $product->id, $id_product_attribute, $warehouse, (int) $info['quantity'], 1, $price, true)) { StockAvailable::synchronize((int) $product->id); } } } else { if (Shop::isFeatureActive()) { foreach ($shops as $shop) { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], (int) $shop); } } else { StockAvailable::setQuantity((int) $product->id, $id_product_attribute, (int) $info['quantity'], $this->context->shop->id); } } } } $this->closeCsvFile($handle); }
protected function reinjectQuantity($order_detail, $qty_cancel_product) { // Reinject product $reinjectable_quantity = (int) $order_detail->product_quantity - (int) $order_detail->product_quantity_reinjected; $quantity_to_reinject = $qty_cancel_product > $reinjectable_quantity ? $reinjectable_quantity : $qty_cancel_product; // @since 1.5.0 : Advanced Stock Management $product_to_inject = new Product($order_detail->product_id, false, (int) $this->context->language->id, (int) $order_detail->id_shop); $product = new Product($order_detail->product_id, false, (int) $this->context->language->id, (int) $order_detail->id_shop); if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management && $order_detail->id_warehouse != 0) { $manager = StockManagerFactory::getManager(); $movements = StockMvt::getNegativeStockMvts($order_detail->id_order, $order_detail->product_id, $order_detail->product_attribute_id, $quantity_to_reinject); $left_to_reinject = $quantity_to_reinject; foreach ($movements as $movement) { if ($left_to_reinject > $movement['physical_quantity']) { $quantity_to_reinject = $movement['physical_quantity']; } $left_to_reinject -= $quantity_to_reinject; $manager->addProduct($order_detail->product_id, $order_detail->product_attribute_id, new Warehouse($movement['id_warehouse']), $quantity_to_reinject, null, $movement['price_te'], true); } StockAvailable::synchronize($order_detail->product_id); } elseif ($order_detail->id_warehouse == 0) { StockAvailable::updateQuantity($order_detail->product_id, $order_detail->product_attribute_id, $quantity_to_reinject, $order_detail->id_shop); } else { $this->errors[] = Tools::displayError('This product cannot be re-stocked.'); } }
/** * Validate an order in database * Function called from a payment module * * @param integer $id_cart Value * @param integer $id_order_state Value * @param float $amount_paid Amount really paid by customer (in the default currency) * @param string $payment_method Payment method (eg. 'Credit card') * @param string $message Message to attach to order */ public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null) { $this->context->cart = new Cart($id_cart); $this->context->customer = new Customer($this->context->cart->id_customer); $this->context->language = new Language($this->context->cart->id_lang); $this->context->shop = $shop ? $shop : new Shop($this->context->cart->id_shop); $id_currency = $currency_special ? (int) $currency_special : (int) $this->context->cart->id_currency; $this->context->currency = new Currency($id_currency, null, $this->context->shop->id); if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { $context_country = $this->context->country; } $order_status = new OrderState((int) $id_order_state, (int) $this->context->language->id); if (!Validate::isLoadedObject($order_status)) { throw new PrestaShopException('Can\'t load Order state status'); } if (!$this->active) { die(Tools::displayError()); } // Does order already exists ? if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false) { if ($secure_key !== false && $secure_key != $this->context->cart->secure_key) { die(Tools::displayError()); } // For each package, generate an order $delivery_option_list = $this->context->cart->getDeliveryOptionList(); $package_list = $this->context->cart->getPackageList(); $cart_delivery_option = $this->context->cart->getDeliveryOption(); // If some delivery options are not defined, or not valid, use the first valid option foreach ($delivery_option_list as $id_address => $package) { if (!isset($cart_delivery_option[$id_address]) || !array_key_exists($cart_delivery_option[$id_address], $package)) { foreach ($package as $key => $val) { $cart_delivery_option[$id_address] = $key; break; } } } $order_list = array(); $order_detail_list = array(); $reference = Order::generateReference(); $this->currentOrderReference = $reference; $order_creation_failed = false; $cart_total_paid = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(true, Cart::BOTH), 2); foreach ($cart_delivery_option as $id_address => $key_carriers) { foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data) { foreach ($data['package_list'] as $id_package) { // Rewrite the id_warehouse $package_list[$id_address][$id_package]['id_warehouse'] = (int) $this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int) $id_carrier); $package_list[$id_address][$id_package]['id_carrier'] = $id_carrier; } } } // Make sure CarRule caches are empty CartRule::cleanCache(); foreach ($package_list as $id_address => $packageByAddress) { foreach ($packageByAddress as $id_package => $package) { $order = new Order(); $order->product_list = $package['product_list']; if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { $address = new Address($id_address); $this->context->country = new Country($address->id_country, $this->context->cart->id_lang); } $carrier = null; if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier'])) { $carrier = new Carrier($package['id_carrier'], $this->context->cart->id_lang); $order->id_carrier = (int) $carrier->id; $id_carrier = (int) $carrier->id; } else { $order->id_carrier = 0; $id_carrier = 0; } $order->id_customer = (int) $this->context->cart->id_customer; $order->id_address_invoice = (int) $this->context->cart->id_address_invoice; $order->id_address_delivery = (int) $id_address; $order->id_currency = $this->context->currency->id; $order->id_lang = (int) $this->context->cart->id_lang; $order->id_cart = (int) $this->context->cart->id; $order->reference = $reference; $order->id_shop = (int) $this->context->shop->id; $order->id_shop_group = (int) $this->context->shop->id_shop_group; $order->secure_key = $secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key); $order->payment = $payment_method; if (isset($this->name)) { $order->module = $this->name; } $order->recyclable = $this->context->cart->recyclable; $order->gift = (int) $this->context->cart->gift; $order->gift_message = $this->context->cart->gift_message; $order->mobile_theme = $this->context->cart->mobile_theme; $order->conversion_rate = $this->context->currency->conversion_rate; $amount_paid = !$dont_touch_amount ? Tools::ps_round((double) $amount_paid, 2) : $amount_paid; $order->total_paid_real = 0; $order->total_products = (double) $this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); $order->total_products_wt = (double) $this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier); $order->total_discounts_tax_excl = (double) abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); $order->total_discounts_tax_incl = (double) abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier)); $order->total_discounts = $order->total_discounts_tax_incl; $order->total_shipping_tax_excl = (double) $this->context->cart->getPackageShippingCost((int) $id_carrier, false, null, $order->product_list); $order->total_shipping_tax_incl = (double) $this->context->cart->getPackageShippingCost((int) $id_carrier, true, null, $order->product_list); $order->total_shipping = $order->total_shipping_tax_incl; if (!is_null($carrier) && Validate::isLoadedObject($carrier)) { $order->carrier_tax_rate = $carrier->getTaxesRate(new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')})); } $order->total_wrapping_tax_excl = (double) abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); $order->total_wrapping_tax_incl = (double) abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier)); $order->total_wrapping = $order->total_wrapping_tax_incl; $order->total_paid_tax_excl = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), 2); $order->total_paid_tax_incl = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), 2); $order->total_paid = $order->total_paid_tax_incl; $order->invoice_date = '0000-00-00 00:00:00'; $order->delivery_date = '0000-00-00 00:00:00'; // Creating order $result = $order->add(); if (!$result) { throw new PrestaShopException('Can\'t save Order'); } // Amount paid by customer is not the right one -> Status = payment error // We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php // if ($order->total_paid != $order->total_paid_real) // We use number_format in order to compare two string if ($order_status->logable && number_format($cart_total_paid, 2) != number_format($amount_paid, 2)) { $id_order_state = Configuration::get('PS_OS_ERROR'); } $order_list[] = $order; // Insert new Order detail list using cart for the current order $order_detail = new OrderDetail(null, null, $this->context); $order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']); $order_detail_list[] = $order_detail; // Adding an entry in order_carrier table if (!is_null($carrier)) { $order_carrier = new OrderCarrier(); $order_carrier->id_order = (int) $order->id; $order_carrier->id_carrier = (int) $id_carrier; $order_carrier->weight = (double) $order->getTotalWeight(); $order_carrier->shipping_cost_tax_excl = (double) $order->total_shipping_tax_excl; $order_carrier->shipping_cost_tax_incl = (double) $order->total_shipping_tax_incl; $order_carrier->add(); } } } // The country can only change if the address used for the calculation is the delivery address, and if multi-shipping is activated if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') { $this->context->country = $context_country; } // Register Payment only if the order status validate the order if ($order_status->logable) { // $order is the last order loop in the foreach // The method addOrderPayment of the class Order make a create a paymentOrder // linked to the order reference and not to the order id if (isset($extra_vars['transaction_id'])) { $transaction_id = $extra_vars['transaction_id']; } else { $transaction_id = null; } if (!$order->addOrderPayment($amount_paid, null, $transaction_id)) { throw new PrestaShopException('Can\'t save Order Payment'); } } // Next ! $only_one_gift = false; $cart_rule_used = array(); $products = $this->context->cart->getProducts(); $cart_rules = $this->context->cart->getCartRules(); // Make sure CarRule caches are empty CartRule::cleanCache(); foreach ($order_detail_list as $key => $order_detail) { $order = $order_list[$key]; if (!$order_creation_failed && isset($order->id)) { if (!$secure_key) { $message .= '<br />' . Tools::displayError('Warning: the secure key is empty, check your payment account before validation'); } // Optional message to attach to this order if (isset($message) & !empty($message)) { $msg = new Message(); $message = strip_tags($message, '<br>'); if (Validate::isCleanHtml($message)) { $msg->message = $message; $msg->id_order = intval($order->id); $msg->private = 1; $msg->add(); } } // Insert new Order detail list using cart for the current order //$orderDetail = new OrderDetail(null, null, $this->context); //$orderDetail->createList($order, $this->context->cart, $id_order_state); // Construct order detail table for the email $products_list = ''; $virtual_product = true; foreach ($products as $key => $product) { $price = Product::getPriceStatic((int) $product['id_product'], false, $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null, 6, null, false, true, $product['cart_quantity'], false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $price_wt = Product::getPriceStatic((int) $product['id_product'], true, $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null, 2, null, false, true, $product['cart_quantity'], false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')}); $customization_quantity = 0; $customized_datas = Product::getAllCustomizedDatas((int) $order->id_cart); if (isset($customized_datas[$product['id_product']][$product['id_product_attribute']])) { $customization_text = ''; foreach ($customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization) { if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) { foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text) { $customization_text .= $text['name'] . ': ' . $text['value'] . '<br />'; } } if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) { $customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])) . '<br />'; } $customization_text .= '---<br />'; } $customization_text = rtrim($customization_text, '---<br />'); $customization_quantity = (int) $product['customization_quantity']; $products_list .= '<tr style="background-color: ' . ($key % 2 ? '#DDE2E6' : '#EBECEE') . ';"> <td style="padding: 0.6em 0.4em;width: 15%;">' . $product['reference'] . '</td> <td style="padding: 0.6em 0.4em;width: 30%;"><strong>' . $product['name'] . (isset($product['attributes']) ? ' - ' . $product['attributes'] : '') . ' - ' . Tools::displayError('Customized') . (!empty($customization_text) ? ' - ' . $customization_text : '') . '</strong></td> <td style="padding: 0.6em 0.4em; width: 20%;">' . Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt, $this->context->currency, false) . '</td> <td style="padding: 0.6em 0.4em; width: 15%;">' . $customization_quantity . '</td> <td style="padding: 0.6em 0.4em; width: 20%;">' . Tools::displayPrice($customization_quantity * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt), $this->context->currency, false) . '</td> </tr>'; } if (!$customization_quantity || (int) $product['cart_quantity'] > $customization_quantity) { $products_list .= '<tr style="background-color: ' . ($key % 2 ? '#DDE2E6' : '#EBECEE') . ';"> <td style="padding: 0.6em 0.4em;width: 15%;">' . $product['reference'] . '</td> <td style="padding: 0.6em 0.4em;width: 30%;"><strong>' . $product['name'] . (isset($product['attributes']) ? ' - ' . $product['attributes'] : '') . '</strong></td> <td style="padding: 0.6em 0.4em; width: 20%;">' . Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt, $this->context->currency, false) . '</td> <td style="padding: 0.6em 0.4em; width: 15%;">' . ((int) $product['cart_quantity'] - $customization_quantity) . '</td> <td style="padding: 0.6em 0.4em; width: 20%;">' . Tools::displayPrice(((int) $product['cart_quantity'] - $customization_quantity) * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt), $this->context->currency, false) . '</td> </tr>'; } // Check if is not a virutal product for the displaying of shipping if (!$product['is_virtual']) { $virtual_product &= false; } } // end foreach ($products) $cart_rules_list = ''; foreach ($cart_rules as $cart_rule) { $package = array('id_carrier' => $order->id_carrier, 'id_address' => $order->id_address_delivery, 'products' => $order->product_list); $values = array('tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package), 'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package)); // If the reduction is not applicable to this order, then continue with the next one if (!$values['tax_excl']) { continue; } /* IF ** - This is not multi-shipping ** - The value of the voucher is greater than the total of the order ** - Partial use is allowed ** - This is an "amount" reduction, not a reduction in % or a gift ** THEN ** The voucher is cloned with a new value corresponding to the remainder */ if (count($order_list) == 1 && $values['tax_incl'] > $order->total_products_wt && $cart_rule['obj']->partial_use == 1 && $cart_rule['obj']->reduction_amount > 0) { // Create a new voucher from the original $voucher = new CartRule($cart_rule['obj']->id); // We need to instantiate the CartRule without lang parameter to allow saving it unset($voucher->id); // Set a new voucher code $voucher->code = empty($voucher->code) ? substr(md5($order->id . '-' . $order->id_customer . '-' . $cart_rule['obj']->id), 0, 16) : $voucher->code . '-2'; if (preg_match('/\\-([0-9]{1,2})\\-([0-9]{1,2})$/', $voucher->code, $matches) && $matches[1] == $matches[2]) { $voucher->code = preg_replace('/' . $matches[0] . '$/', '-' . (intval($matches[1]) + 1), $voucher->code); } // Set the new voucher value if ($voucher->reduction_tax) { $voucher->reduction_amount = $values['tax_incl'] - $order->total_products_wt; } else { $voucher->reduction_amount = $values['tax_excl'] - $order->total_products; } $voucher->id_customer = $order->id_customer; $voucher->quantity = 1; if ($voucher->add()) { // If the voucher has conditions, they are now copied to the new voucher CartRule::copyConditions($cart_rule['obj']->id, $voucher->id); $params = array('{voucher_amount}' => Tools::displayPrice($voucher->reduction_amount, $this->context->currency, false), '{voucher_num}' => $voucher->code, '{firstname}' => $this->context->customer->firstname, '{lastname}' => $this->context->customer->lastname, '{id_order}' => $order->reference, '{order_name}' => $order->getUniqReference()); Mail::Send((int) $order->id_lang, 'voucher', sprintf(Mail::l('New voucher regarding your order %s', (int) $order->id_lang), $order->reference), $params, $this->context->customer->email, $this->context->customer->firstname . ' ' . $this->context->customer->lastname, null, null, null, null, _PS_MAIL_DIR_, false, (int) $order->id_shop); } $values['tax_incl'] -= $values['tax_incl'] - $order->total_products_wt; $values['tax_excl'] -= $values['tax_excl'] - $order->total_products; } $order->addCartRule($cart_rule['obj']->id, $cart_rule['obj']->name, $values, 0, $cart_rule['obj']->free_shipping); if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && !in_array($cart_rule['obj']->id, $cart_rule_used)) { $cart_rule_used[] = $cart_rule['obj']->id; // Create a new instance of Cart Rule without id_lang, in order to update its quantity $cart_rule_to_update = new CartRule($cart_rule['obj']->id); $cart_rule_to_update->quantity = max(0, $cart_rule_to_update->quantity - 1); $cart_rule_to_update->update(); } $cart_rules_list .= ' <tr> <td colspan="4" style="padding:0.6em 0.4em;text-align:right">' . Tools::displayError('Voucher name:') . ' ' . $cart_rule['obj']->name . '</td> <td style="padding:0.6em 0.4em;text-align:right">' . ($values['tax_incl'] != 0.0 ? '-' : '') . Tools::displayPrice($values['tax_incl'], $this->context->currency, false) . '</td> </tr>'; } // Specify order id for message $old_message = Message::getMessageByCartId((int) $this->context->cart->id); if ($old_message) { $update_message = new Message((int) $old_message['id_message']); $update_message->id_order = (int) $order->id; $update_message->update(); // Add this message in the customer thread $customer_thread = new CustomerThread(); $customer_thread->id_contact = 0; $customer_thread->id_customer = (int) $order->id_customer; $customer_thread->id_shop = (int) $this->context->shop->id; $customer_thread->id_order = (int) $order->id; $customer_thread->id_lang = (int) $this->context->language->id; $customer_thread->email = $this->context->customer->email; $customer_thread->status = 'open'; $customer_thread->token = Tools::passwdGen(12); $customer_thread->add(); $customer_message = new CustomerMessage(); $customer_message->id_customer_thread = $customer_thread->id; $customer_message->id_employee = 0; $customer_message->message = $update_message->message; $customer_message->private = 0; if (!$customer_message->add()) { $this->errors[] = Tools::displayError('An error occurred while saving message'); } } // Hook validate order Hook::exec('actionValidateOrder', array('cart' => $this->context->cart, 'order' => $order, 'customer' => $this->context->customer, 'currency' => $this->context->currency, 'orderStatus' => $order_status)); foreach ($this->context->cart->getProducts() as $product) { if ($order_status->logable) { ProductSale::addProductSale((int) $product['id_product'], (int) $product['cart_quantity']); } } if (Configuration::get('PS_STOCK_MANAGEMENT') && $order_detail->getStockState()) { $history = new OrderHistory(); $history->id_order = (int) $order->id; $history->changeIdOrderState(Configuration::get('PS_OS_OUTOFSTOCK'), $order, true); $history->addWithemail(); } // Set order state in order history ONLY even if the "out of stock" status has not been yet reached // So you migth have two order states $new_history = new OrderHistory(); $new_history->id_order = (int) $order->id; $new_history->changeIdOrderState((int) $id_order_state, $order, true); $new_history->addWithemail(true, $extra_vars); unset($order_detail); // Order is reloaded because the status just changed $order = new Order($order->id); // Send an e-mail to customer (one order = one email) if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && $this->context->customer->id) { $invoice = new Address($order->id_address_invoice); $delivery = new Address($order->id_address_delivery); $delivery_state = $delivery->id_state ? new State($delivery->id_state) : false; $invoice_state = $invoice->id_state ? new State($invoice->id_state) : false; $data = array('{firstname}' => $this->context->customer->firstname, '{lastname}' => $this->context->customer->lastname, '{email}' => $this->context->customer->email, '{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"), '{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"), '{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array('firstname' => '<span style="font-weight:bold;">%s</span>', 'lastname' => '<span style="font-weight:bold;">%s</span>')), '{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array('firstname' => '<span style="font-weight:bold;">%s</span>', 'lastname' => '<span style="font-weight:bold;">%s</span>')), '{delivery_company}' => $delivery->company, '{delivery_firstname}' => $delivery->firstname, '{delivery_lastname}' => $delivery->lastname, '{delivery_address1}' => $delivery->address1, '{delivery_address2}' => $delivery->address2, '{delivery_city}' => $delivery->city, '{delivery_postal_code}' => $delivery->postcode, '{delivery_country}' => $delivery->country, '{delivery_state}' => $delivery->id_state ? $delivery_state->name : '', '{delivery_phone}' => $delivery->phone ? $delivery->phone : $delivery->phone_mobile, '{delivery_other}' => $delivery->other, '{invoice_company}' => $invoice->company, '{invoice_vat_number}' => $invoice->vat_number, '{invoice_firstname}' => $invoice->firstname, '{invoice_lastname}' => $invoice->lastname, '{invoice_address2}' => $invoice->address2, '{invoice_address1}' => $invoice->address1, '{invoice_city}' => $invoice->city, '{invoice_postal_code}' => $invoice->postcode, '{invoice_country}' => $invoice->country, '{invoice_state}' => $invoice->id_state ? $invoice_state->name : '', '{invoice_phone}' => $invoice->phone ? $invoice->phone : $invoice->phone_mobile, '{invoice_other}' => $invoice->other, '{order_name}' => $order->getUniqReference(), '{date}' => Tools::displayDate(date('Y-m-d H:i:s'), (int) $order->id_lang, 1), '{carrier}' => $virtual_product ? Tools::displayError('No carrier') : $carrier->name, '{payment}' => Tools::substr($order->payment, 0, 32), '{products}' => $this->formatProductAndVoucherForEmail($products_list), '{discounts}' => $this->formatProductAndVoucherForEmail($cart_rules_list), '{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false), '{total_products}' => Tools::displayPrice($order->total_paid - $order->total_shipping - $order->total_wrapping + $order->total_discounts, $this->context->currency, false), '{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false), '{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false), '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false)); if (is_array($extra_vars)) { $data = array_merge($data, $extra_vars); } // Join PDF invoice if ((int) Configuration::get('PS_INVOICE') && $order_status->invoice && $order->invoice_number) { $pdf = new PDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE, $this->context->smarty); $file_attachement['content'] = $pdf->render(false); $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf'; $file_attachement['mime'] = 'application/pdf'; } else { $file_attachement = null; } if (Validate::isEmail($this->context->customer->email)) { Mail::Send((int) $order->id_lang, 'order_conf', Mail::l('Order confirmation', (int) $order->id_lang), $data, $this->context->customer->email, $this->context->customer->firstname . ' ' . $this->context->customer->lastname, null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int) $order->id_shop); } } // updates stock in shops if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) { $product_list = $order->getProducts(); foreach ($product_list as $product) { // if the available quantities depends on the physical stock if (StockAvailable::dependsOnStock($product['product_id'])) { // synchronizes StockAvailable::synchronize($product['product_id'], $order->id_shop); } } } } else { $error = Tools::displayError('Order creation failed'); Logger::addLog($error, 4, '0000002', 'Cart', intval($order->id_cart)); die($error); } } // End foreach $order_detail_list // Use the last order as currentOrder $this->currentOrder = (int) $order->id; return true; } else { $error = Tools::displayError('Cart cannot be loaded or an order has already been placed using this cart'); Logger::addLog($error, 4, '0000001', 'Cart', intval($this->context->cart->id)); die($error); } }
/** * For a given id_product, sets if stock available depends on stock * * @param int $id_product * @param int $depends_on_stock Optional : true by default * @param int $id_shop Optional : gets context by default */ public static function setProductDependsOnStock($id_product, $depends_on_stock = true, $id_shop = null, $id_product_attribute = 0) { if (!Validate::isUnsignedId($id_product)) { return false; } $existing_id = StockAvailable::getStockAvailableIdByProductId((int) $id_product, (int) $id_product_attribute, $id_shop); if ($existing_id > 0) { Db::getInstance()->update('stock_available', array('depends_on_stock' => (int) $depends_on_stock), 'id_stock_available = ' . (int) $existing_id); } else { $params = array('depends_on_stock' => (int) $depends_on_stock, 'id_product' => (int) $id_product, 'id_product_attribute' => (int) $id_product_attribute); StockAvailable::addSqlShopParams($params, $id_shop); Db::getInstance()->insert('stock_available', $params); } // depends on stock.. hence synchronizes if ($depends_on_stock) { StockAvailable::synchronize($id_product); } }
public function postProcess() { $this->adminControllerPostProcess(); if (Tools::isSubmit('addStock') && !($this->tabAccess['add'] === '1')) { $this->errors[] = Tools::displayError('You do not have the required permission to add stock.'); } if (Tools::isSubmit('removeStock') && !($this->tabAccess['delete'] === '1')) { $this->errors[] = Tools::displayError('You do not have the required permission to delete stock'); } if (Tools::isSubmit('transferStock') && !($this->tabAccess['edit'] === '1')) { $this->errors[] = Tools::displayError('You do not have the required permission to transfer stock.'); } if (count($this->errors)) { return; } if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock') || Tools::isSubmit('transferstock')) && Tools::isSubmit('is_post')) { $id_product = (int) Tools::getValue('id_product', 0); if ($id_product <= 0) { $this->errors[] = Tools::displayError('The selected product is not valid.'); } $id_product_attribute = (int) Tools::getValue('id_product_attribute', 0); $check = Tools::getValue('check', ''); $check_valid = md5(_COOKIE_KEY_ . $id_product . $id_product_attribute); if ($check != $check_valid) { $this->errors[] = Tools::displayError('The selected product is not valid.'); } $quantity = Tools::getValue('quantity', 0); $quantity = PP::normalizeProductQty($quantity, $id_product); if (!is_numeric($quantity) || $quantity <= 0) { $this->errors[] = Tools::displayError('The quantity value is not valid.'); } $token = Tools::getValue('token') ? Tools::getValue('token') : $this->token; $redirect = self::$currentIndex . '&token=' . $token; } if ((Tools::isSubmit('addstock') || Tools::isSubmit('removestock')) && Tools::isSubmit('is_post')) { $id_warehouse = (int) Tools::getValue('id_warehouse', 0); if ($id_warehouse <= 0 || !Warehouse::exists($id_warehouse)) { $this->errors[] = Tools::displayError('The selected warehouse is not valid.'); } $id_stock_mvt_reason = (int) Tools::getValue('id_stock_mvt_reason', 0); if ($id_stock_mvt_reason <= 0 || !StockMvtReason::exists($id_stock_mvt_reason)) { $this->errors[] = Tools::displayError('The reason is not valid.'); } $usable = Tools::getValue('usable', null); if (is_null($usable)) { $this->errors[] = Tools::displayError('You have to specify whether the product quantity is usable for sale on shops or not.'); } $usable = (bool) $usable; } if (Tools::isSubmit('addstock') && Tools::isSubmit('is_post')) { $price = str_replace(',', '.', Tools::getValue('price', 0)); if (!is_numeric($price)) { $this->errors[] = Tools::displayError('The product price is not valid.'); } $price = round((double) $price, 6); $id_currency = (int) Tools::getValue('id_currency', 0); if ($id_currency <= 0 || (!($result = Currency::getCurrency($id_currency)) || empty($result))) { $this->errors[] = Tools::displayError('The selected currency is not valid.'); } if (count($this->errors) == 0) { $warehouse = new Warehouse($id_warehouse); if ($id_currency != $warehouse->id_currency) { $price_converted_to_default_currency = Tools::convertPrice($price, $id_currency, false); $price = Tools::convertPrice($price_converted_to_default_currency, $warehouse->id_currency, true); } $stock_manager = StockManagerFactory::getManager(); if ($stock_manager->addProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $price, $usable)) { $id_wpl = (int) WarehouseProductLocation::getIdByProductAndWarehouse($id_product, $id_product_attribute, $id_warehouse); if (!$id_wpl) { $wpl = new WarehouseProductLocation(); $wpl->id_product = (int) $id_product; $wpl->id_product_attribute = (int) $id_product_attribute; $wpl->id_warehouse = (int) $id_warehouse; $wpl->save(); } StockAvailable::synchronize($id_product); if (Tools::isSubmit('addstockAndStay')) { $redirect = self::$currentIndex . '&id_product=' . (int) $id_product; if ($id_product_attribute) { $redirect .= '&id_product_attribute=' . (int) $id_product_attribute; } $redirect .= '&addstock&token=' . $token; } Tools::redirectAdmin($redirect . '&conf=1'); } else { $this->errors[] = Tools::displayError('An error occurred. No stock was added.'); } } } if (Tools::isSubmit('removestock') && Tools::isSubmit('is_post')) { if (count($this->errors) == 0) { $warehouse = new Warehouse($id_warehouse); $stock_manager = StockManagerFactory::getManager(); $removed_products = $stock_manager->removeProduct($id_product, $id_product_attribute, $warehouse, $quantity, $id_stock_mvt_reason, $usable); if (count($removed_products) > 0) { StockAvailable::synchronize($id_product); Tools::redirectAdmin($redirect . '&conf=2'); } else { $physical_quantity_in_stock = (int) $stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), false); $usable_quantity_in_stock = (int) $stock_manager->getProductPhysicalQuantities($id_product, $id_product_attribute, array($warehouse->id), true); $not_usable_quantity = $physical_quantity_in_stock - $usable_quantity_in_stock; if ($usable_quantity_in_stock < $quantity) { $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int) $quantity, (int) $usable_quantity_in_stock); } elseif ($not_usable_quantity < $quantity) { $this->errors[] = sprintf(Tools::displayError('You don\'t have enough usable quantity. Cannot remove %d items out of %d.'), (int) $quantity, (int) $not_usable_quantity); } else { $this->errors[] = Tools::displayError('It is not possible to remove the specified quantity. Therefore no stock was removed.'); } } } } if (Tools::isSubmit('transferstock') && Tools::isSubmit('is_post')) { $id_warehouse_from = (int) Tools::getValue('id_warehouse_from', 0); if ($id_warehouse_from <= 0 || !Warehouse::exists($id_warehouse_from)) { $this->errors[] = Tools::displayError('The source warehouse is not valid.'); } $id_warehouse_to = (int) Tools::getValue('id_warehouse_to', 0); if ($id_warehouse_to <= 0 || !Warehouse::exists($id_warehouse_to)) { $this->errors[] = Tools::displayError('The destination warehouse is not valid.'); } $usable_from = Tools::getValue('usable_from', null); if (is_null($usable_from)) { $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your source warehouse(s) is ready for sale or not.'); } $usable_from = (bool) $usable_from; $usable_to = Tools::getValue('usable_to', null); if (is_null($usable_to)) { $this->errors[] = Tools::displayError('You have to specify whether the product quantity in your destination warehouse(s) is ready for sale or not.'); } $usable_to = (bool) $usable_to; if (count($this->errors) == 0) { $stock_manager = StockManagerFactory::getManager(); $is_transfer = $stock_manager->transferBetweenWarehouses($id_product, $id_product_attribute, $quantity, $id_warehouse_from, $id_warehouse_to, $usable_from, $usable_to); StockAvailable::synchronize($id_product); if ($is_transfer) { Tools::redirectAdmin($redirect . '&conf=3'); } else { $this->errors[] = Tools::displayError('It is not possible to transfer the specified quantity. No stock was transferred.'); } } } }