Пример #1
0
 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/>";
 }
Пример #2
0
 /**
  * Get products grouped by package and by addresses to be sent individualy (one package = one shipping cost).
  *
  * @return array array(
  *                   0 => array( // First address
  *                       0 => array(  // First package
  *                           'product_list' => array(...),
  *                           'carrier_list' => array(...),
  *                           'id_warehouse' => array(...),
  *                       ),
  *                   ),
  *               );
  * @todo Add avaibility check
  */
 public function getPackageList($flush = false)
 {
     static $cache = array();
     if (isset($cache[(int) $this->id . '_' . (int) $this->id_address_delivery]) && $cache[(int) $this->id . '_' . (int) $this->id_address_delivery] !== false && !$flush) {
         return $cache[(int) $this->id . '_' . (int) $this->id_address_delivery];
     }
     $product_list = $this->getProducts();
     // Step 1 : Get product informations (warehouse_list and carrier_list), count warehouse
     // Determine the best warehouse to determine the packages
     // For that we count the number of time we can use a warehouse for a specific delivery address
     $warehouse_count_by_address = array();
     $warehouse_carrier_list = array();
     $stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT');
     foreach ($product_list as &$product) {
         if ((int) $product['id_address_delivery'] == 0) {
             $product['id_address_delivery'] = (int) $this->id_address_delivery;
         }
         if (!isset($warehouse_count_by_address[$product['id_address_delivery']])) {
             $warehouse_count_by_address[$product['id_address_delivery']] = array();
         }
         $product['warehouse_list'] = array();
         if ($stock_management_active && ((int) $product['advanced_stock_management'] == 1 || Pack::usesAdvancedStockManagement((int) $product['id_product']))) {
             $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute'], $this->id_shop);
             if (count($warehouse_list) == 0) {
                 $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute']);
             }
             // Does the product is in stock ?
             // If yes, get only warehouse where the product is in stock
             $warehouse_in_stock = array();
             $manager = StockManagerFactory::getManager();
             foreach ($warehouse_list as $key => $warehouse) {
                 $product_real_quantities = $manager->getProductRealQuantities($product['id_product'], $product['id_product_attribute'], array($warehouse['id_warehouse']), true);
                 if ($product_real_quantities > 0 || Pack::isPack((int) $product['id_product'])) {
                     $warehouse_in_stock[] = $warehouse;
                 }
             }
             if (!empty($warehouse_in_stock)) {
                 $warehouse_list = $warehouse_in_stock;
                 $product['in_stock'] = true;
             } else {
                 $product['in_stock'] = false;
             }
         } else {
             //simulate default warehouse
             $warehouse_list = array(0);
             $product['in_stock'] = StockAvailable::getQuantityAvailableByProduct($product['id_product'], $product['id_product_attribute']) > 0;
         }
         foreach ($warehouse_list as $warehouse) {
             if (!isset($warehouse_carrier_list[$warehouse['id_warehouse']])) {
                 $warehouse_object = new Warehouse($warehouse['id_warehouse']);
                 $warehouse_carrier_list[$warehouse['id_warehouse']] = $warehouse_object->getCarriers();
             }
             $product['warehouse_list'][] = $warehouse['id_warehouse'];
             if (!isset($warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']])) {
                 $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']] = 0;
             }
             $warehouse_count_by_address[$product['id_address_delivery']][$warehouse['id_warehouse']]++;
         }
     }
     unset($product);
     arsort($warehouse_count_by_address);
     // Step 2 : Group product by warehouse
     $grouped_by_warehouse = array();
     foreach ($product_list as &$product) {
         if (!isset($grouped_by_warehouse[$product['id_address_delivery']])) {
             $grouped_by_warehouse[$product['id_address_delivery']] = array('in_stock' => array(), 'out_of_stock' => array());
         }
         $product['carrier_list'] = array();
         $id_warehouse = 0;
         foreach ($warehouse_count_by_address[$product['id_address_delivery']] as $id_war => $val) {
             if (in_array((int) $id_war, $product['warehouse_list'])) {
                 $product['carrier_list'] = array_merge($product['carrier_list'], Carrier::getAvailableCarrierList(new Product($product['id_product']), $id_war, $product['id_address_delivery'], null, $this));
                 if (!$id_warehouse) {
                     $id_warehouse = (int) $id_war;
                 }
             }
         }
         if (!isset($grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse])) {
             $grouped_by_warehouse[$product['id_address_delivery']]['in_stock'][$id_warehouse] = array();
             $grouped_by_warehouse[$product['id_address_delivery']]['out_of_stock'][$id_warehouse] = array();
         }
         if (!$this->allow_seperated_package) {
             $key = 'in_stock';
         } else {
             $key = $product['in_stock'] ? 'in_stock' : 'out_of_stock';
         }
         if (empty($product['carrier_list'])) {
             $product['carrier_list'] = array(0);
         }
         $grouped_by_warehouse[$product['id_address_delivery']][$key][$id_warehouse][] = $product;
     }
     unset($product);
     // Step 3 : grouped product from grouped_by_warehouse by available carriers
     $grouped_by_carriers = array();
     foreach ($grouped_by_warehouse as $id_address_delivery => $products_in_stock_list) {
         if (!isset($grouped_by_carriers[$id_address_delivery])) {
             $grouped_by_carriers[$id_address_delivery] = array('in_stock' => array(), 'out_of_stock' => array());
         }
         foreach ($products_in_stock_list as $key => $warehouse_list) {
             if (!isset($grouped_by_carriers[$id_address_delivery][$key])) {
                 $grouped_by_carriers[$id_address_delivery][$key] = array();
             }
             foreach ($warehouse_list as $id_warehouse => $product_list) {
                 if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse])) {
                     $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse] = array();
                 }
                 foreach ($product_list as $product) {
                     $package_carriers_key = implode(',', $product['carrier_list']);
                     if (!isset($grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key])) {
                         $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key] = array('product_list' => array(), 'carrier_list' => $product['carrier_list'], 'warehouse_list' => $product['warehouse_list']);
                     }
                     $grouped_by_carriers[$id_address_delivery][$key][$id_warehouse][$package_carriers_key]['product_list'][] = $product;
                 }
             }
         }
     }
     $package_list = array();
     // Step 4 : merge product from grouped_by_carriers into $package to minimize the number of package
     foreach ($grouped_by_carriers as $id_address_delivery => $products_in_stock_list) {
         if (!isset($package_list[$id_address_delivery])) {
             $package_list[$id_address_delivery] = array('in_stock' => array(), 'out_of_stock' => array());
         }
         foreach ($products_in_stock_list as $key => $warehouse_list) {
             if (!isset($package_list[$id_address_delivery][$key])) {
                 $package_list[$id_address_delivery][$key] = array();
             }
             // Count occurance of each carriers to minimize the number of packages
             $carrier_count = array();
             foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) {
                 foreach ($products_grouped_by_carriers as $data) {
                     foreach ($data['carrier_list'] as $id_carrier) {
                         if (!isset($carrier_count[$id_carrier])) {
                             $carrier_count[$id_carrier] = 0;
                         }
                         $carrier_count[$id_carrier]++;
                     }
                 }
             }
             arsort($carrier_count);
             foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) {
                 if (!isset($package_list[$id_address_delivery][$key][$id_warehouse])) {
                     $package_list[$id_address_delivery][$key][$id_warehouse] = array();
                 }
                 foreach ($products_grouped_by_carriers as $data) {
                     foreach ($carrier_count as $id_carrier => $rate) {
                         if (in_array($id_carrier, $data['carrier_list'])) {
                             if (!isset($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier])) {
                                 $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier] = array('carrier_list' => $data['carrier_list'], 'warehouse_list' => $data['warehouse_list'], 'product_list' => array());
                             }
                             $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'] = array_intersect($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['carrier_list'], $data['carrier_list']);
                             $package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'] = array_merge($package_list[$id_address_delivery][$key][$id_warehouse][$id_carrier]['product_list'], $data['product_list']);
                             break;
                         }
                     }
                 }
             }
         }
     }
     // Step 5 : Reduce depth of $package_list
     $final_package_list = array();
     foreach ($package_list as $id_address_delivery => $products_in_stock_list) {
         if (!isset($final_package_list[$id_address_delivery])) {
             $final_package_list[$id_address_delivery] = array();
         }
         foreach ($products_in_stock_list as $key => $warehouse_list) {
             foreach ($warehouse_list as $id_warehouse => $products_grouped_by_carriers) {
                 foreach ($products_grouped_by_carriers as $data) {
                     $final_package_list[$id_address_delivery][] = array('product_list' => $data['product_list'], 'carrier_list' => $data['carrier_list'], 'warehouse_list' => $data['warehouse_list'], 'id_warehouse' => $id_warehouse);
                 }
             }
         }
     }
     $cache[(int) $this->id] = $final_package_list;
     return $final_package_list;
 }
Пример #3
0
 /**
  *
  * This method allow to add stock information on a product detail
  * @param array &$product
  */
 protected function setProductCurrentStock(&$product)
 {
     if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && (int) $product['advanced_stock_management'] == 1 && (int) $product['id_warehouse'] > 0) {
         $product['current_stock'] = StockManagerFactory::getManager()->getProductPhysicalQuantities($product['product_id'], $product['product_attribute_id'], null, true);
     } else {
         $product['current_stock'] = '--';
     }
 }
Пример #4
0
 /**
  * Webservice : used to get the real quantity of a product
  */
 public function getWsRealQuantity()
 {
     $manager = StockManagerFactory::getManager();
     $quantity = $manager->getProductRealQuantities($this->id_product, $this->id_product_attribute, $this->id_warehouse, true);
     return $quantity;
 }
Пример #5
0
 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.');
     }
 }
Пример #6
0
    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);
                }
            }
        }
    }
Пример #7
0
 protected function processBulkDelete()
 {
     if ($this->tabAccess['delete'] === '1') {
         if (is_array($this->boxes) && !empty($this->boxes)) {
             $object = new $this->className();
             if (isset($object->noZeroObject) && (count(call_user_func(array($this->className, $object->noZeroObject))) <= 1 || count($_POST[$this->table . 'Box']) == count(call_user_func(array($this->className, $object->noZeroObject))))) {
                 $this->errors[] = Tools::displayError('You need at least one object.') . ' <b>' . $this->table . '</b><br />' . Tools::displayError('You cannot delete all of the items.');
             } else {
                 $success = 1;
                 $products = Tools::getValue($this->table . 'Box');
                 if (is_array($products) && ($count = count($products))) {
                     // Deleting products can be quite long on a cheap server. Let's say 1.5 seconds by product (I've seen it!).
                     if (intval(ini_get('max_execution_time')) < round($count * 1.5)) {
                         ini_set('max_execution_time', round($count * 1.5));
                     }
                     if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                         $stock_manager = StockManagerFactory::getManager();
                     }
                     foreach ($products as $id_product) {
                         $product = new Product((int) $id_product);
                         /*
                          * @since 1.5.0
                          * It is NOT possible to delete a product if there are currently:
                          * - physical stock for this product
                          * - supply order(s) for this product
                          */
                         if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && $product->advanced_stock_management) {
                             $physical_quantity = $stock_manager->getProductPhysicalQuantities($product->id, 0);
                             $real_quantity = $stock_manager->getProductRealQuantities($product->id, 0);
                             if ($physical_quantity > 0 || $real_quantity > $physical_quantity) {
                                 $this->errors[] = sprintf(Tools::displayError('You cannot delete the product #%d because there is physical stock left.'), $product->id);
                             }
                         }
                         if (!count($this->errors)) {
                             if ($product->delete()) {
                                 PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int) $product->id, true, (int) $this->context->employee->id);
                             } else {
                                 $success = false;
                             }
                         } else {
                             $success = 0;
                         }
                     }
                 }
                 if ($success) {
                     $id_category = (int) Tools::getValue('id_category');
                     $category_url = empty($id_category) ? '' : '&id_category=' . (int) $id_category;
                     $this->redirect_after = self::$currentIndex . '&conf=2&token=' . $this->token . $category_url;
                 } else {
                     $this->errors[] = Tools::displayError('An error occurred while deleting this selection.');
                 }
             }
         } else {
             $this->errors[] = Tools::displayError('You must select at least one element to delete.');
         }
     } else {
         $this->errors[] = Tools::displayError('You do not have permission to delete this.');
     }
 }
Пример #8
0
								<th>' . $erpip->l('Quantity') . '</th>';
            if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                $message .= '<th>' . $erpip->l('Physical Stock') . '</th>
							 <th>' . $erpip->l('Usable Stock') . '</th>
							 <th>' . $erpip->l('Real Stock') . '</th>';
            } else {
                $message .= '<th>' . $erpip->l('Stock') . '</th>';
            }
            $message .= '</tr>';
            foreach ($produits as &$prod) {
                $objProd = new Product($prod['product_id']);
                $message .= '<tr>';
                /*  If order neither sent nor cancelled nor current order */
                $message .= '<td>' . $objProd->reference . '</td><td>' . $objProd->getProductName($prod['product_id'], $prod['product_attribute_id']) . '</td><td>' . $prod['product_quantity'] . '</td>';
                if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                    $manager = StockManagerFactory::getManager();
                    $message .= '<td>' . $manager->getProductPhysicalQuantities($prod['product_id'], $prod['product_attribute_id']) . '</td>' . '<td>' . $manager->getProductPhysicalQuantities($prod['product_id'], $prod['product_attribute_id'], null, true) . '</td>' . '<td>' . $manager->getProductRealQuantities($prod['product_id'], $prod['product_attribute_id']) . '</td>';
                } else {
                    $message .= '<td>' . StockAvailable::getQuantityAvailableByProduct($prod['product_id'], $prod['product_attribute_id']) . '</td>';
                }
                $message .= '</tr>';
            }
            $message .= '</table>';
            print $message;
        }
        break;
    case 'productSupplierPrice':
        /*  If we have called the script with a term to search */
        if (Tools::isSubmit('id_product') && Tools::isSubmit('id_product_attribute')) {
            $id_product = Tools::getValue('id_product');
            $id_product_attribute = Tools::getValue('id_product_attribute');
    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);
    }
Пример #10
0
 /**
  * Assign template vars related to page content
  * @see FrontController::initContent()
  */
 public function initContent()
 {
     parent::initContent();
     if (!$this->errors) {
         if (Pack::isPack((int) $this->product->id) && !Pack::isInStock((int) $this->product->id)) {
             $this->product->quantity = 0;
         }
         $this->product->description = $this->transformDescriptionWithImg($this->product->description);
         /* Получаем остатки по складам и передаем в Smarty 
          * TODO - вынести в отдельный модуль
          * TODO - если надо, добавить обработку атрибутов (товары, отличающиеся цветом, размером и т.д.)
          * TODO - real_quantity - количество, в котором есть будущие поставки. Если это не нужно, считать по-другому
          */
         $all_warehouses = Warehouse::getWarehouses(true);
         if ($all_warehouses) {
             $wh_stock = array();
             //ppp($all_warehouses);
             foreach ($all_warehouses as $warehouse) {
                 $id_warehouse = $warehouse['id_warehouse'];
                 $warehouse = new Warehouse($id_warehouse);
                 $manager = StockManagerFactory::getManager();
                 $real_quantity = $manager->getProductRealQuantities((int) $this->product->id, 0, $id_warehouse, true);
                 $wh_stock[$id_warehouse]['real_quantity'] = $real_quantity;
                 /*
                 ppp("остаток: ");
                 ppp($real_quantity);
                 */
                 $address = new Address($warehouse->id_address);
                 $wh_stock[$id_warehouse]['country'] = $address->country;
                 $wh_stock[$id_warehouse]['address1'] = $address->address1;
                 $wh_stock[$id_warehouse]['address2'] = $address->address2;
                 $wh_stock[$id_warehouse]['postcode'] = $address->postcode;
                 $wh_stock[$id_warehouse]['city'] = $address->city;
                 $wh_stock[$id_warehouse]['phone'] = $address->phone;
                 //ppp($address);
             }
             $this->context->smarty->assign('wh_stock', $wh_stock);
         }
         /* Конец получения остатков по складам */
         // Assign to the template the id of the virtual product. "0" if the product is not downloadable.
         $this->context->smarty->assign('virtual', ProductDownload::getIdFromIdProduct((int) $this->product->id));
         $this->context->smarty->assign('customizationFormTarget', Tools::safeOutput(urldecode($_SERVER['REQUEST_URI'])));
         if (Tools::isSubmit('submitCustomizedDatas')) {
             // If cart has not been saved, we need to do it so that customization fields can have an id_cart
             // We check that the cookie exists first to avoid ghost carts
             if (!$this->context->cart->id && isset($_COOKIE[$this->context->cookie->getName()])) {
                 $this->context->cart->add();
                 $this->context->cookie->id_cart = (int) $this->context->cart->id;
             }
             $this->pictureUpload();
             $this->textRecord();
             $this->formTargetFormat();
         } else {
             if (Tools::getIsset('deletePicture') && !$this->context->cart->deleteCustomizationToProduct($this->product->id, Tools::getValue('deletePicture'))) {
                 $this->errors[] = Tools::displayError('An error occurred while deleting the selected picture.');
             }
         }
         $pictures = array();
         $text_fields = array();
         if ($this->product->customizable) {
             $files = $this->context->cart->getProductCustomization($this->product->id, Product::CUSTOMIZE_FILE, true);
             foreach ($files as $file) {
                 $pictures['pictures_' . $this->product->id . '_' . $file['index']] = $file['value'];
             }
             $texts = $this->context->cart->getProductCustomization($this->product->id, Product::CUSTOMIZE_TEXTFIELD, true);
             foreach ($texts as $text_field) {
                 $text_fields['textFields_' . $this->product->id . '_' . $text_field['index']] = str_replace('<br />', "\n", $text_field['value']);
             }
         }
         $this->context->smarty->assign(array('pictures' => $pictures, 'textFields' => $text_fields));
         // Assign template vars related to the category + execute hooks related to the category
         $this->assignCategory();
         // Assign template vars related to the price and tax
         $this->assignPriceAndTax();
         // Assign template vars related to the images
         $this->assignImages();
         // Assign attribute groups to the template
         $this->assignAttributesGroups();
         // Assign attributes combinations to the template
         $this->assignAttributesCombinations();
         // Pack management
         $pack_items = $this->product->cache_is_pack ? Pack::getItemTable($this->product->id, $this->context->language->id, true) : array();
         $this->context->smarty->assign('packItems', $pack_items);
         $this->context->smarty->assign('packs', Pack::getPacksTable($this->product->id, $this->context->language->id, true, 1));
         if (isset($this->category->id) && $this->category->id) {
             $return_link = Tools::safeOutput($this->context->link->getCategoryLink($this->category));
         } else {
             $return_link = 'javascript: history.back();';
         }
         $this->context->smarty->assign(array('stock_management' => Configuration::get('PS_STOCK_MANAGEMENT'), 'customizationFields' => $this->product->customizable ? $this->product->getCustomizationFields($this->context->language->id) : false, 'accessories' => $this->product->getAccessories($this->context->language->id), 'return_link' => $return_link, 'product' => $this->product, 'product_manufacturer' => new Manufacturer((int) $this->product->id_manufacturer, $this->context->language->id), 'token' => Tools::getToken(false), 'features' => $this->product->getFrontFeatures($this->context->language->id), 'attachments' => $this->product->cache_has_attachments ? $this->product->getAttachments($this->context->language->id) : array(), 'allow_oosp' => $this->product->isAvailableWhenOutOfStock((int) $this->product->out_of_stock), 'last_qties' => (int) Configuration::get('PS_LAST_QTIES'), 'HOOK_EXTRA_LEFT' => Hook::exec('displayLeftColumnProduct'), 'HOOK_EXTRA_RIGHT' => Hook::exec('displayRightColumnProduct'), 'HOOK_PRODUCT_OOS' => Hook::exec('actionProductOutOfStock', array('product' => $this->product)), 'HOOK_PRODUCT_ACTIONS' => Hook::exec('displayProductButtons', array('product' => $this->product)), 'HOOK_PRODUCT_TAB' => Hook::exec('displayProductTab', array('product' => $this->product)), 'HOOK_PRODUCT_TAB_CONTENT' => Hook::exec('displayProductTabContent', array('product' => $this->product)), 'HOOK_PRODUCT_CONTENT' => Hook::exec('displayProductContent', array('product' => $this->product)), 'display_qties' => (int) Configuration::get('PS_DISPLAY_QTIES'), 'display_ht' => !Tax::excludeTaxeOption(), 'currencySign' => $this->context->currency->sign, 'currencyRate' => $this->context->currency->conversion_rate, 'currencyFormat' => $this->context->currency->format, 'currencyBlank' => $this->context->currency->blank, 'jqZoomEnabled' => Configuration::get('PS_DISPLAY_JQZOOM'), 'ENT_NOQUOTES' => ENT_NOQUOTES, 'outOfStockAllowed' => (int) Configuration::get('PS_ORDER_OUT_OF_STOCK'), 'errors' => $this->errors, 'body_classes' => array($this->php_self . '-' . $this->product->id, $this->php_self . '-' . $this->product->link_rewrite, 'category-' . (isset($this->category) ? $this->category->id : ''), 'category-' . (isset($this->category) ? $this->category->getFieldByLang('link_rewrite') : '')), 'display_discount_price' => Configuration::get('PS_DISPLAY_DISCOUNT_PRICE')));
     }
     $this->setTemplate(_PS_THEME_DIR_ . 'product.tpl');
 }
    public function ajaxGetProductsForSupplyOrder()
    {
        require_once _PS_MODULE_DIR_ . 'erpillicopresta/classes/stock/ErpSupplyOrderClasses.php';
        require_once _PS_MODULE_DIR_ . 'erpillicopresta/erpillicopresta.php';
        /* manage advanced stock */
        $stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT');
        $sales_forecast_type = Configuration::get('ERP_SALES_FORECAST_CHOICE');
        $id_supplier = (int) Tools::getValue('id_supplier', false);
        $id_currency = (int) Tools::getValue('id_currency', false);
        $id_categorie = (int) Tools::getValue('id_categorie', false);
        $id_manufacturer = (int) Tools::getValue('id_manufacturer', false);
        $id_warehouse = (int) Tools::getValue('id_warehouse', null);
        $existing_ids = Tools::getValue('ids');
        //$token_get_product      = Tools::getValue('token');
        $products = ErpSupplyOrderClasses::searchProduct($id_supplier, $id_categorie, $id_manufacturer, $id_currency);
        if (!empty($products)) {
            $advanced_stock_token = Tools::getAdminToken('AdminAdvancedStock' . (int) Tab::getIdFromClassName('AdminAdvancedStock') . (int) $this->context->employee->id);
            foreach ($products as $product) {
                // If product already in destination array, continue
                if (strrpos($existing_ids, $product['id']) !== false) {
                    continue;
                }
                $ids = explode('_', $product['id']);
                $id_product = $ids[0];
                $id_product_attribute = $ids[1];
                // If the advanced stock manager is activated
                if ($stock_management_active == '1') {
                    // Get the physical and usable quantities
                    $query = new DbQuery();
                    $query->select('physical_quantity');
                    $query->select('usable_quantity');
                    $query->from('stock');
                    $query->where('id_product = ' . (int) $id_product . ' AND id_product_attribute = ' . (int) $id_product_attribute);
                    $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
                    /* the two quantities */
                    $physical_quantity = (int) $res['physical_quantity'];
                    $usable_quantity = (int) $res['usable_quantity'];
                    // The real quantity depends of the warehouse
                    $manager = StockManagerFactory::getManager();
                    $product['stock'] = $real_quantity = (int) $manager->getProductRealQuantities($id_product, $id_product_attribute, $id_warehouse, true);
                } else {
                    // get the free quantities
                    $product['stock'] = $usable_quantity = (int) Product::getQuantity($id_product, $id_product_attribute);
                }
                /*  TAX */
                /*  Get the current tax */
                $query = new DbQuery();
                $query->select('rate');
                $query->from('tax', 't');
                $query->innerJoin('tax_rule', 'tr', 'tr.id_tax = t.id_tax');
                $query->innerJoin('product', 'p', 'p.id_tax_rules_group = tr.id_tax_rules_group');
                $query->where('p.id_product = ' . (int) $id_product);
                $query->where('tr.id_country IN (SELECT id_country
                                                FROM ' . _DB_PREFIX_ . 'address
                                                WHERE id_supplier = ' . (int) $id_supplier . ')');
                $product['tax_rate'] = round(Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($query), 1);
                $prices = ErpSupplyOrderClasses::getWholesalePrice((int) $id_product, (int) $id_product_attribute, (int) $id_supplier);
                $product['unit_price_te'] = Tools::convertPriceFull($prices, new Currency((int) $id_currency));
                // sales quantity for X rolling month
                $quantity_sales = ErpSupplyOrderClasses::getQuantitySales((int) $id_product, (int) $id_product_attribute);
                // if sale forecast is activ
                if ($sales_forecast_type != 0) {
                    // if we use the 6 month rolling method
                    if ($sales_forecast_type == 1) {
                        $sales_forecasts = round(ErpSupplyOrderClasses::getProductSalesForecasts($id_product, $id_product_attribute), 1);
                    } else {
                        $sales_forecasts = round(ErpSupplyOrderClasses::getProductSalesForecastsByPeriod($id_product, $id_product_attribute), 1);
                    }
                } else {
                    $sales_forecasts = 'NA';
                }
                // Sales gain
                $sales_gains = ErpSupplyOrderClasses::getProductSalesGains($id_product, $id_product_attribute);
                // Prepare the hidden json foreach line
                $product['comment'] = '';
                $product_json = Tools::jsonEncode($product);
                echo '<tr>
                                        <td class="product_json hide">' . $product_json . '</td>
                                        <td><input type="checkbox" class="select_product" name="select_product"/></td>
                                        <td>' . $product['supplier_reference'] . '</td>
                                        <td>' . $product['reference'] . '</td>
                                        <td>
                                                         <a href="#" class="cluetip-supply-price" title="' . $this->l('Supplier Price') . '"
                                                                                        rel="index.php?controller=AdminAdvancedStock&ajax=1&id_product=' . $id_product . '&id_product_attribute=' . $id_product_attribute . '&id_currency=' . $id_currency . '&task=getProductSupplierPrice&token=' . $advanced_stock_token . '" >
                                                                                                                           <img src="themes/default/img/icon-search.png">
                                                        </a>
                                                        ' . $product['name'] . '
                                        </td>';
                if (Configuration::get(ErpIllicopresta::getControllerStatusName('AdminAdvancedSupplyOrder'))) {
                    echo '<td align="center"> <p style="background-color:' . ErpSupplyOrderClasses::getStockLevelColor($real_quantity) . '; width:16px; height:16px"></p> </td>';
                }
                echo '<td align="center">' . $usable_quantity . '</td>
                                        ' . ($stock_management_active == '1' ? '
                                                                        <td align="center">' . $physical_quantity . '</td>
                                                                        <td align="center">' . $real_quantity . '</td>' : '') . '';
                if (Configuration::get(ErpIllicopresta::getControllerStatusName('AdminAdvancedSupplyOrder'))) {
                    echo '<td align="center">' . $quantity_sales . '</td>
                                                <td align="center">' . $sales_gains . '</td>';
                    if (Configuration::get('ERP_SALES_FORECAST_CHOICE') != 0) {
                        echo '<td>' . $sales_forecasts . '</td>';
                    }
                }
                echo '<td align="center"><input type="text" class="quantity_ordered" size="2" /></td>
                                        <td align="center"> <input type="text" name="comment" class="comment"/></td>
                                        
				</tr>';
            }
        } else {
            echo '<div class="list-empty-msg">
				<i class="icon-warning-sign list-empty-icon"></i>
				' . $this->l('No product found !') . '
			</div>';
        }
    }
Пример #12
0
    public static function getAllProductInStock($advanced_stock_management, $warehouse)
    {
        $query = new DbQuery();
        // If Advanced Stock Management go through table ps_stock
        if ($advanced_stock_management) {
            $query->select('p.id_product, IFNULL(pa.id_product_attribute, 0) as id_product_attribute');
            $query->from('product', 'p');
            $query->leftJoin('product_attribute', 'pa', 'p.id_product = pa.id_product');
            if ($warehouse != -1) {
                $query->where('(
										(
												p.id_product IN (SELECT id_product FROM ' . _DB_PREFIX_ . 'stock WHERE id_warehouse = ' . (int) $warehouse . ')
												AND IFNULL(pa.id_product_attribute, 0)IN(SELECT id_product_attribute FROM ' . _DB_PREFIX_ . 'stock WHERE id_warehouse =' . (int) $warehouse . '
										)
								)
								OR (
												p.id_product IN (SELECT id_product FROM ' . _DB_PREFIX_ . 'warehouse_product_location WHERE id_warehouse = ' . (int) $warehouse . ')
												AND IFNULL(pa.id_product_attribute, 0)IN (SELECT id_product_attribute FROM ' . _DB_PREFIX_ . 'warehouse_product_location WHERE id_warehouse = ' . (int) $warehouse . ')
										)
								)');
            }
        } else {
            $query->select('id_product, id_product_attribute, quantity');
            $query->from('stock_available');
        }
        $stock = Db::getInstance()->ExecuteS($query);
        $nb_items = count($stock);
        for ($i = 0; $i < $nb_items; ++$i) {
            $item =& $stock[$i];
            // gets stock manager
            $manager = StockManagerFactory::getManager();
            // If Advanced Stock Management get quantities & valuation
            if ($advanced_stock_management) {
                // gets quantities and valuation
                $query = new DbQuery();
                $query->select('SUM(physical_quantity) as physical_quantity');
                $query->select('SUM(usable_quantity) as usable_quantity');
                $query->select('SUM(price_te * physical_quantity) as valuation');
                $query->from('stock');
                $query->where('id_product = ' . (int) $item['id_product'] . ' AND id_product_attribute = ' . (int) $item['id_product_attribute']);
                $query->where('id_warehouse = ' . (int) $warehouse);
                $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
                // Quantities
                $item['physical_quantity'] = $res['physical_quantity'];
                $item['usable_quantity'] = $res['usable_quantity'];
                $item['quantity'] = 0;
                // gets real_quantity depending on the warehouse
                $item['real_quantity'] = $manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], $warehouse, true);
                // Valuation (pump)
                $item['valuation'] = $res['valuation'];
            } else {
                $item['physical_quantity'] = 0;
                $item['usable_quantity'] = 0;
                $item['real_quantity'] = 0;
                $item['valuation'] = 0;
            }
            // Sale price
            // Product
            if ((int) $item['id_product_attribute'] == 0) {
                $query = 'SELECT p.price as price';
                $query .= ' FROM ' . _DB_PREFIX_ . 'product p';
                $query .= ' WHERE p.id_product = ' . (int) $item['id_product'];
            } else {
                $query = 'SELECT (p.price + pa.price) as price';
                $query .= ' FROM ' . _DB_PREFIX_ . 'product p';
                $query .= ' LEFT JOIN ' . _DB_PREFIX_ . 'product_attribute pa ON (p.id_product = pa.id_product)';
                $query .= ' WHERE p.id_product = ' . (int) $item['id_product'];
                $query .= ' AND pa.id_product_attribute = ' . (int) $item['id_product_attribute'];
            }
            $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
            $item['price_te'] = $res['price'];
            // Purchase price
            $item['wholesale_price'] = self::getWholesalePrice($item['id_product'], $item['id_product_attribute']);
            // Location
            //$item['location']= ErpWarehouseProductLocationClass::getCompleteLocation($item['id_product'], $item['id_product_attribute'],(int)$warehouse);
        }
        return $stock;
    }
Пример #13
0
    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);
    }
Пример #14
0
 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 . '*');
 }
 public function ajaxGetProducts()
 {
     if (Tools::isSubmit('id_order')) {
         $product_return_template = array();
         require_once _PS_MODULE_DIR_ . 'erpillicopresta/classes/order/ErpOrder.php';
         $objOrder = new ErpOrder((int) Tools::getValue('id_order'));
         $produits = $objOrder->getListOfProductsWithQuantity();
         if (!empty($produits)) {
             foreach ($produits as $key => &$prod) {
                 $objProd = new Product($prod['product_id']);
                 // If order is neither sent, nor cancelled, nor the current one
                 $product_return_template[$key]['reference'] = $objProd->reference;
                 $product_return_template[$key]['name'] = $objProd->getProductName($prod['product_id'], $prod['product_attribute_id']);
                 $product_return_template[$key]['quantity'] = $prod['product_quantity'];
                 if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                     $manager = StockManagerFactory::getManager();
                     $product_return_template[$key]['physical_stock'] = $manager->getProductPhysicalQuantities($prod['product_id'], $prod['product_attribute_id']);
                     $product_return_template[$key]['usable_stock'] = $manager->getProductPhysicalQuantities($prod['product_id'], $prod['product_attribute_id'], null, true);
                     $product_return_template[$key]['real_stock'] = $manager->getProductRealQuantities($prod['product_id'], $prod['product_attribute_id']);
                 } else {
                     $product_return_template[$key]['stock'] = StockAvailable::getQuantityAvailableByProduct($prod['product_id'], $prod['product_attribute_id']);
                 }
             }
         }
         $this->context->smarty->assign(array('products' => $product_return_template));
         echo $this->context->smarty->fetch(_PS_MODULE_DIR_ . 'erpillicopresta/views/templates/admin/advanced_order/quick_view.tpl');
         die;
     }
 }
 public function postProcess()
 {
     $this->adminControllerPostProcess();
     // 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);
         $quantity = PP::normalizeProductQty($quantity, $id_product);
         if (!is_numeric($quantity) || $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((double) $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.');
             }
         }
     }
 }
Пример #17
0
    /**
     * Sets the new state of the given order
     *
     * @param int $new_order_state
     * @param int/object $id_order
     * @param bool $use_existing_payment
     */
    public function changeIdOrderState($new_order_state, $id_order, $use_existing_payment = false)
    {
        if (!$new_order_state || !$id_order) {
            return;
        }
        if (!is_object($id_order) && is_numeric($id_order)) {
            $order = new Order((int) $id_order);
        } elseif (is_object($id_order)) {
            $order = $id_order;
        } else {
            return;
        }
        ShopUrl::cacheMainDomainForShop($order->id_shop);
        $new_os = new OrderState((int) $new_order_state, $order->id_lang);
        $old_os = $order->getCurrentOrderState();
        $is_validated = $this->isValidated();
        // executes hook
        if (in_array($new_os->id, array(Configuration::get('PS_OS_PAYMENT'), Configuration::get('PS_OS_WS_PAYMENT')))) {
            Hook::exec('actionPaymentConfirmation', array('id_order' => (int) $order->id), null, false, true, false, $order->id_shop);
        }
        // executes hook
        Hook::exec('actionOrderStatusUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int) $order->id), null, false, true, false, $order->id_shop);
        if (Validate::isLoadedObject($order) && $new_os instanceof OrderState) {
            // An email is sent the first time a virtual item is validated
            $virtual_products = $order->getVirtualProducts();
            if ($virtual_products && (!$old_os || !$old_os->logable) && $new_os && $new_os->logable) {
                $context = Context::getContext();
                $assign = array();
                foreach ($virtual_products as $key => $virtual_product) {
                    $id_product_download = ProductDownload::getIdFromIdProduct($virtual_product['product_id']);
                    $product_download = new ProductDownload($id_product_download);
                    // If this virtual item has an associated file, we'll provide the link to download the file in the email
                    if ($product_download->display_filename != '') {
                        $assign[$key]['name'] = $product_download->display_filename;
                        $dl_link = $product_download->getTextLink(false, $virtual_product['download_hash']) . '&id_order=' . (int) $order->id . '&secure_key=' . $order->secure_key;
                        $assign[$key]['link'] = $dl_link;
                        if (isset($virtual_product['download_deadline']) && $virtual_product['download_deadline'] != '0000-00-00 00:00:00') {
                            $assign[$key]['deadline'] = Tools::displayDate($virtual_product['download_deadline']);
                        }
                        if ($product_download->nb_downloadable != 0) {
                            $assign[$key]['downloadable'] = (int) $product_download->nb_downloadable;
                        }
                    }
                }
                $customer = new Customer((int) $order->id_customer);
                $links = '<ul>';
                foreach ($assign as $product) {
                    $links .= '<li>';
                    $links .= '<a href="' . $product['link'] . '">' . Tools::htmlentitiesUTF8($product['name']) . '</a>';
                    if (isset($product['deadline'])) {
                        $links .= '&nbsp;' . Tools::htmlentitiesUTF8(Tools::displayError('expires on', false)) . '&nbsp;' . $product['deadline'];
                    }
                    if (isset($product['downloadable'])) {
                        $links .= '&nbsp;' . Tools::htmlentitiesUTF8(sprintf(Tools::displayError('downloadable %d time(s)', false), (int) $product['downloadable']));
                    }
                    $links .= '</li>';
                }
                $links .= '</ul>';
                $data = array('{lastname}' => $customer->lastname, '{firstname}' => $customer->firstname, '{id_order}' => (int) $order->id, '{order_name}' => $order->getUniqReference(), '{nbProducts}' => count($virtual_products), '{virtualProducts}' => $links);
                // If there's at least one downloadable file
                if (!empty($assign)) {
                    Mail::Send((int) $order->id_lang, 'download_product', Mail::l('Virtual product to download', $order->id_lang), $data, $customer->email, $customer->firstname . ' ' . $customer->lastname, null, null, null, null, _PS_MAIL_DIR_, false, (int) $order->id_shop);
                }
            }
            // @since 1.5.0 : gets the stock manager
            $manager = null;
            if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                $manager = StockManagerFactory::getManager();
            }
            $errorOrCanceledStatuses = array(Configuration::get('PS_OS_ERROR'), Configuration::get('PS_OS_CANCELED'));
            // foreach products of the order
            if (Validate::isLoadedObject($old_os)) {
                foreach ($order->getProductsDetail() as $product) {
                    // if becoming logable => adds sale
                    if ($new_os->logable && !$old_os->logable) {
                        ProductSale::addProductSale($product['product_id'], $product['product_quantity']);
                        // @since 1.5.0 - Stock Management
                        if (!Pack::isPack($product['product_id']) && in_array($old_os->id, $errorOrCanceledStatuses) && !StockAvailable::dependsOnStock($product['id_product'], (int) $order->id_shop)) {
                            StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int) $product['product_quantity'], $order->id_shop);
                        }
                    } elseif (!$new_os->logable && $old_os->logable) {
                        ProductSale::removeProductSale($product['product_id'], $product['product_quantity']);
                        // @since 1.5.0 - Stock Management
                        if (!Pack::isPack($product['product_id']) && in_array($new_os->id, $errorOrCanceledStatuses) && !StockAvailable::dependsOnStock($product['id_product'])) {
                            StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int) $product['product_quantity'], $order->id_shop);
                        }
                    } elseif (!$new_os->logable && !$old_os->logable && in_array($new_os->id, $errorOrCanceledStatuses) && !in_array($old_os->id, $errorOrCanceledStatuses) && !StockAvailable::dependsOnStock($product['id_product'])) {
                        StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int) $product['product_quantity'], $order->id_shop);
                    }
                    // @since 1.5.0 : if the order is being shipped and this products uses the advanced stock management :
                    // decrements the physical stock using $id_warehouse
                    if ($new_os->shipped == 1 && $old_os->shipped == 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Warehouse::exists($product['id_warehouse']) && $manager != null && ((int) $product['advanced_stock_management'] == 1 || Pack::usesAdvancedStockManagement($product['product_id']))) {
                        // gets the warehouse
                        $warehouse = new Warehouse($product['id_warehouse']);
                        // decrements the stock (if it's a pack, the StockManager does what is needed)
                        $manager->removeProduct($product['product_id'], $product['product_attribute_id'], $warehouse, $product['product_quantity'], Configuration::get('PS_STOCK_CUSTOMER_ORDER_REASON'), true, (int) $order->id);
                    } elseif ($new_os->shipped == 0 && $old_os->shipped == 1 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Warehouse::exists($product['id_warehouse']) && $manager != null && ((int) $product['advanced_stock_management'] == 1 || Pack::usesAdvancedStockManagement($product['product_id']))) {
                        // if the product is a pack, we restock every products in the pack using the last negative stock mvts
                        if (Pack::isPack($product['product_id'])) {
                            $pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT', null, null, $order->id_shop));
                            foreach ($pack_products as $pack_product) {
                                if ($pack_product->advanced_stock_management == 1) {
                                    $mvts = StockMvt::getNegativeStockMvts($order->id, $pack_product->id, 0, $pack_product->pack_quantity * $product['product_quantity']);
                                    foreach ($mvts as $mvt) {
                                        $manager->addProduct($pack_product->id, 0, new Warehouse($mvt['id_warehouse']), $mvt['physical_quantity'], null, $mvt['price_te'], true);
                                    }
                                    if (!StockAvailable::dependsOnStock($product['id_product'])) {
                                        StockAvailable::updateQuantity($pack_product->id, 0, (int) $pack_product->pack_quantity * $product['product_quantity'], $order->id_shop);
                                    }
                                }
                            }
                        } else {
                            $mvts = StockMvt::getNegativeStockMvts($order->id, $product['product_id'], $product['product_attribute_id'], $product['product_quantity']);
                            foreach ($mvts as $mvt) {
                                $manager->addProduct($product['product_id'], $product['product_attribute_id'], new Warehouse($mvt['id_warehouse']), $mvt['physical_quantity'], null, $mvt['price_te'], true);
                            }
                        }
                    }
                }
            }
        }
        $this->id_order_state = (int) $new_order_state;
        // changes invoice number of order ?
        if (!Validate::isLoadedObject($new_os) || !Validate::isLoadedObject($order)) {
            die(Tools::displayError('Invalid new order state'));
        }
        // the order is valid if and only if the invoice is available and the order is not cancelled
        $order->current_state = $this->id_order_state;
        $order->valid = $new_os->logable;
        $order->update();
        if ($new_os->invoice && !$order->invoice_number) {
            $order->setInvoice($use_existing_payment);
        }
        // set orders as paid
        if ($new_os->paid == 1) {
            $invoices = $order->getInvoicesCollection();
            if ($order->total_paid != 0) {
                $payment_method = Module::getInstanceByName($order->module);
            }
            foreach ($invoices as $invoice) {
                $rest_paid = $invoice->getRestPaid();
                if ($rest_paid > 0) {
                    $payment = new OrderPayment();
                    $payment->order_reference = $order->reference;
                    $payment->id_currency = $order->id_currency;
                    $payment->amount = $rest_paid;
                    if ($order->total_paid != 0) {
                        $payment->payment_method = $payment_method->displayName;
                    } else {
                        $payment->payment_method = null;
                    }
                    // Update total_paid_real value for backward compatibility reasons
                    if ($payment->id_currency == $order->id_currency) {
                        $order->total_paid_real += $payment->amount;
                    } else {
                        $order->total_paid_real += Tools::ps_round(Tools::convertPrice($payment->amount, $payment->id_currency, false), 2);
                    }
                    $order->save();
                    $payment->conversion_rate = 1;
                    $payment->save();
                    Db::getInstance()->execute('
					INSERT INTO `' . _DB_PREFIX_ . 'order_invoice_payment`
					VALUES(' . (int) $invoice->id . ', ' . (int) $payment->id . ', ' . (int) $order->id . ')');
                }
            }
        }
        // updates delivery date even if it was already set by another state change
        if ($new_os->delivery) {
            $order->setDelivery();
        }
        // executes hook
        Hook::exec('actionOrderStatusPostUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int) $order->id), null, false, true, false, $order->id_shop);
        ShopUrl::resetMainDomainCache();
    }
Пример #18
0
 public function hookActionProductCoverage($params)
 {
     // if not advanced stock management, nothing to do
     if (!Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
         return;
     }
     // retrieves informations
     $id_product = (int) $params['id_product'];
     $id_product_attribute = (int) $params['id_product_attribute'];
     $warehouse = $params['warehouse'];
     $product = new Product($id_product);
     if (!Validate::isLoadedObject($product)) {
         return;
     }
     if (!$product->advanced_stock_management) {
         return;
     }
     // sets warehouse id to get the coverage
     if (!Validate::isLoadedObject($warehouse)) {
         $id_warehouse = 0;
     } else {
         $id_warehouse = (int) $warehouse->id;
     }
     // coverage of the product
     $warning_coverage = (int) Configuration::getGlobalValue('MA_PRODUCT_COVERAGE');
     $coverage = StockManagerFactory::getManager()->getProductCoverage($id_product, $id_product_attribute, $warning_coverage, $id_warehouse);
     // if we need to send a notification
     if ($product->active == 1 && $coverage < $warning_coverage && !empty($this->merchant_mails) && Configuration::getGlobalValue('MA_MERCHANT_COVERAGE')) {
         $context = Context::getContext();
         $id_lang = (int) $context->language->id;
         $id_shop = (int) $context->shop->id;
         $iso = Language::getIsoById($id_lang);
         $product_name = Product::getProductName($id_product, $id_product_attribute, $id_lang);
         $template_vars = array('{current_coverage}' => $coverage, '{warning_coverage}' => $warning_coverage, '{product}' => pSQL($product_name));
         if (file_exists(dirname(__FILE__) . '/mails/' . $iso . '/productcoverage.txt') && file_exists(dirname(__FILE__) . '/mails/' . $iso . '/productcoverage.html')) {
             // Send 1 email by merchant mail, because Mail::Send doesn't work with an array of recipients
             $merchant_mails = explode(self::__MA_MAIL_DELIMITOR__, $this->merchant_mails);
             foreach ($merchant_mails as $merchant_mail) {
                 Mail::Send($id_lang, 'productcoverage', Mail::l('Stock coverage', $id_lang), $template_vars, $merchant_mail, null, (string) Configuration::get('PS_SHOP_EMAIL'), (string) Configuration::get('PS_SHOP_NAME'), null, null, dirname(__FILE__) . '/mails/', null, $id_shop);
             }
         }
     }
 }
Пример #19
0
 public function getDeliveryOptionList(Country $default_country = null, $flush = false)
 {
     static $cache = null;
     if ($cache !== null && !$flush) {
         return $cache;
     }
     $delivery_option_list = array();
     $carriers_price = array();
     $carrier_collection = array();
     $package_list = $this->getPackageList();
     // Foreach addresses
     foreach ($package_list as $id_address => $packages) {
         // Initialize vars
         $delivery_option_list[$id_address] = array();
         $carriers_price[$id_address] = array();
         $common_carriers = null;
         $best_price_carriers = array();
         $best_grade_carriers = array();
         $carriers_instance = array();
         // Get country
         if ($id_address) {
             $address = new Address($id_address);
             $country = new Country($address->id_country);
         } else {
             $country = $default_country;
         }
         // Foreach packages, get the carriers with best price, best position and best grade
         foreach ($packages as $id_package => $package) {
             // No carriers available
             if (count($package['carrier_list']) == 1 && current($package['carrier_list']) == 0) {
                 $package['carrier_list'] = array(103, 96, 97);
                 //					$cache = array();
                 //					return $cache;
             }
             $carriers_price[$id_address][$id_package] = array();
             // Get all common carriers for each packages to the same address
             if (is_null($common_carriers)) {
                 $common_carriers = $package['carrier_list'];
             } else {
                 $common_carriers = array_intersect($common_carriers, $package['carrier_list']);
             }
             $best_price = null;
             $best_price_carrier = null;
             $best_grade = null;
             $best_grade_carrier = null;
             // Foreach carriers of the package, calculate his price, check if it the best price, position and grade
             foreach ($package['carrier_list'] as $id_carrier) {
                 if (!isset($carriers_instance[$id_carrier])) {
                     $carriers_instance[$id_carrier] = new Carrier($id_carrier);
                 }
                 $price_with_tax = $this->getPackageShippingCost($id_carrier, true, $country, $package['product_list']);
                 $price_without_tax = $this->getPackageShippingCost($id_carrier, false, $country, $package['product_list']);
                 if (is_null($best_price) || $price_with_tax < $best_price) {
                     $best_price = $price_with_tax;
                     $best_price_carrier = $id_carrier;
                 }
                 $carriers_price[$id_address][$id_package][$id_carrier] = array('without_tax' => $price_without_tax, 'with_tax' => $price_with_tax);
                 $grade = $carriers_instance[$id_carrier]->grade;
                 if (is_null($best_grade) || $grade > $best_grade) {
                     $best_grade = $grade;
                     $best_grade_carrier = $id_carrier;
                 }
             }
             $best_price_carriers[$id_package] = $best_price_carrier;
             $best_grade_carriers[$id_package] = $best_grade_carrier;
         }
         // Reset $best_price_carrier, it's now an array
         $best_price_carrier = array();
         $key = '';
         // Get the delivery option with the lower price
         foreach ($best_price_carriers as $id_package => $id_carrier) {
             $key .= $id_carrier . ',';
             if (!isset($best_price_carrier[$id_carrier])) {
                 $best_price_carrier[$id_carrier] = array('price_with_tax' => 0, 'price_without_tax' => 0, 'package_list' => array(), 'product_list' => array());
             }
             $best_price_carrier[$id_carrier]['price_with_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'];
             $best_price_carrier[$id_carrier]['price_without_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'];
             $best_price_carrier[$id_carrier]['package_list'][] = $id_package;
             $best_price_carrier[$id_carrier]['product_list'] = array_merge($best_price_carrier[$id_carrier]['product_list'], $packages[$id_package]['product_list']);
             $best_price_carrier[$id_carrier]['instance'] = $carriers_instance[$id_carrier];
         }
         // Add the delivery option with best price as best price
         $delivery_option_list[$id_address][$key] = array('carrier_list' => $best_price_carrier, 'is_best_price' => true, 'is_best_grade' => false, 'unique_carrier' => count($best_price_carrier) <= 1);
         // Reset $best_grade_carrier, it's now an array
         $best_grade_carrier = array();
         $key = '';
         // Get the delivery option with the best grade
         foreach ($best_grade_carriers as $id_package => $id_carrier) {
             $key .= $id_carrier . ',';
             if (!isset($best_grade_carrier[$id_carrier])) {
                 $best_grade_carrier[$id_carrier] = array('price_with_tax' => 0, 'price_without_tax' => 0, 'package_list' => array(), 'product_list' => array());
             }
             $best_grade_carrier[$id_carrier]['price_with_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'];
             $best_grade_carrier[$id_carrier]['price_without_tax'] += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'];
             $best_grade_carrier[$id_carrier]['package_list'][] = $id_package;
             $best_grade_carrier[$id_carrier]['product_list'] = array_merge($best_grade_carrier[$id_carrier]['product_list'], $packages[$id_package]['product_list']);
             $best_grade_carrier[$id_carrier]['instance'] = $carriers_instance[$id_carrier];
         }
         // Add the delivery option with best grade as best grade
         if (!isset($delivery_option_list[$id_address][$key])) {
             $delivery_option_list[$id_address][$key] = array('carrier_list' => $best_grade_carrier, 'is_best_price' => false, 'unique_carrier' => count($best_grade_carrier) <= 1);
         }
         $delivery_option_list[$id_address][$key]['is_best_grade'] = true;
         // Get all delivery options with a unique carrier
         foreach ($common_carriers as $id_carrier) {
             $key = '';
             $package_list = array();
             $product_list = array();
             $price_with_tax = 0;
             $price_without_tax = 0;
             foreach ($packages as $id_package => $package) {
                 $key .= $id_carrier . ',';
                 $price_with_tax += $carriers_price[$id_address][$id_package][$id_carrier]['with_tax'];
                 $price_without_tax += $carriers_price[$id_address][$id_package][$id_carrier]['without_tax'];
                 $package_list[] = $id_package;
                 $product_list = array_merge($product_list, $package['product_list']);
             }
             if (!isset($delivery_option_list[$id_address][$key])) {
                 $delivery_option_list[$id_address][$key] = array('is_best_price' => false, 'is_best_grade' => false, 'unique_carrier' => true, 'carrier_list' => array($id_carrier => array('price_with_tax' => $price_with_tax, 'price_without_tax' => $price_without_tax, 'instance' => $carriers_instance[$id_carrier], 'package_list' => $package_list, 'product_list' => $product_list)));
             } else {
                 $delivery_option_list[$id_address][$key]['unique_carrier'] = count($delivery_option_list[$id_address][$key]['carrier_list']) <= 1;
             }
         }
     }
     $cart_rules = CartRule::getCustomerCartRules(Context::getContext()->cookie->id_lang, Context::getContext()->cookie->id_customer, true);
     $free_carriers_rules = array();
     foreach ($cart_rules as $cart_rule) {
         if ($cart_rule['free_shipping'] && $cart_rule['carrier_restriction']) {
             $cr = new CartRule((int) $cart_rule['id_cart_rule']);
             if (Validate::isLoadedObject($cr)) {
                 $carriers = $cr->getAssociatedRestrictions('carrier', true, false);
                 if (is_array($carriers) && count($carriers) && isset($carriers['selected'])) {
                     foreach ($carriers['selected'] as $carrier) {
                         if (isset($carrier['id_carrier']) && $carrier['id_carrier']) {
                             $free_carriers_rules[] = (int) $carrier['id_carrier'];
                         }
                     }
                 }
             }
         }
     }
     $product_stock_1 = false;
     $product_stock_2 = false;
     $custom = false;
     $stock_management_active = Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT');
     if ($stock_management_active) {
         $products = $this->getProducts();
         foreach ($products as $product) {
             $flag = false;
             $warehouse_list = Warehouse::getProductWarehouseList($product['id_product'], $product['id_product_attribute']);
             $manager = StockManagerFactory::getManager();
             foreach ($warehouse_list as $key => $warehouse) {
                 $product_real_quantities = $manager->getProductRealQuantities($product['id_product'], $product['id_product_attribute'], array($warehouse['id_warehouse']), true);
                 if ($key == 0 && $product_real_quantities > 0) {
                     $flag = true;
                     $product_stock_1 = true;
                 }
                 if ($key == 1 && $product_real_quantities > 0) {
                     $product_stock_2 = true;
                     $flag = true;
                 }
             }
             if (!$flag) {
                 $custom = true;
                 break;
             }
         }
     }
     $langs = Language::getLanguages();
     // For each delivery options :
     //    - Set the carrier list
     //    - Calculate the price
     //    - Calculate the average position
     foreach ($delivery_option_list as $id_address => $delivery_option) {
         foreach ($delivery_option as $key => $value) {
             $total_price_with_tax = 0;
             $total_price_without_tax = 0;
             $position = 0;
             foreach ($value['carrier_list'] as $id_carrier => $data) {
                 $total_price_with_tax += $data['price_with_tax'];
                 $total_price_without_tax += $data['price_without_tax'];
                 $total_price_without_tax_with_rules = in_array($id_carrier, $free_carriers_rules) ? 0 : $total_price_without_tax;
                 if (!isset($carrier_collection[$id_carrier])) {
                     $carrier_collection[$id_carrier] = new Carrier($id_carrier);
                 }
                 switch (true) {
                     case $custom:
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Шарлотенбурге') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '2-3 недели';
                             }
                         }
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Русском доме') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '2-3 недели';
                             }
                         }
                         break;
                     case !$custom && ($product_stock_1 && $product_stock_2):
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Шарлотенбурге') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '2 дня';
                             }
                         }
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Русском доме') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '2 дня';
                             }
                         }
                         break;
                     case !$custom && (!$product_stock_1 && $product_stock_2):
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Шарлотенбурге') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '2 дня';
                             }
                         }
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Русском доме') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '1 день';
                             }
                         }
                         break;
                     case !$custom && ($product_stock_1 && !$product_stock_2):
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Шарлотенбурге') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '1 день';
                             }
                         }
                         if ($carrier_collection[$id_carrier]->name == 'Самовывоз в Русском доме') {
                             foreach ($langs as $lang) {
                                 $carrier_collection[$id_carrier]->delay[$lang['id_lang']] = '2 дня';
                             }
                         }
                         break;
                 }
                 $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['instance'] = $carrier_collection[$id_carrier];
                 if (file_exists(_PS_SHIP_IMG_DIR_ . $id_carrier . '.jpg')) {
                     $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = _THEME_SHIP_DIR_ . $id_carrier . '.jpg';
                 } else {
                     $delivery_option_list[$id_address][$key]['carrier_list'][$id_carrier]['logo'] = false;
                 }
                 $position += $carrier_collection[$id_carrier]->position;
             }
             $delivery_option_list[$id_address][$key]['total_price_with_tax'] = $total_price_with_tax;
             $delivery_option_list[$id_address][$key]['total_price_without_tax'] = $total_price_without_tax;
             $delivery_option_list[$id_address][$key]['is_free'] = !$total_price_without_tax_with_rules ? true : false;
             $delivery_option_list[$id_address][$key]['position'] = $position / count($value['carrier_list']);
         }
     }
     // Sort delivery option list
     foreach ($delivery_option_list as &$array) {
         uasort($array, array('Cart', 'sortDeliveryOptionList'));
     }
     $cache = $delivery_option_list;
     return $delivery_option_list;
 }
Пример #20
0
    /**
     * Sets the new state of the given order
     *
     * @param int $new_order_state
     * @param int $id_order
     * @param bool $use_existing_payment
     */
    public function changeIdOrderState($new_order_state, &$id_order, $use_existing_payment = false)
    {
        if (!$new_order_state || !$id_order) {
            return;
        }
        if (!is_object($id_order) && is_numeric($id_order)) {
            $order = new Order((int) $id_order);
        } elseif (is_object($id_order)) {
            $order = $id_order;
        } else {
            return;
        }
        $new_os = new OrderState((int) $new_order_state, $order->id_lang);
        $old_os = $order->getCurrentOrderState();
        $is_validated = $this->isValidated();
        // executes hook
        if ($new_os->id == Configuration::get('PS_OS_PAYMENT')) {
            Hook::exec('actionPaymentConfirmation', array('id_order' => (int) $order->id));
        }
        // executes hook
        Hook::exec('actionOrderStatusUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int) $order->id));
        if (Validate::isLoadedObject($order) && $old_os instanceof OrderState && $new_os instanceof OrderState) {
            // @since 1.5.0 : gets the stock manager
            $manager = null;
            if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                $manager = StockManagerFactory::getManager();
            }
            // foreach products of the order
            foreach ($order->getProductsDetail() as $product) {
                // if becoming logable => adds sale
                if ($new_os->logable && !$old_os->logable) {
                    ProductSale::addProductSale($product['product_id'], $product['product_quantity']);
                    // @since 1.5.0 - Stock Management
                    if (!Pack::isPack($product['product_id']) && ($old_os->id == Configuration::get('PS_OS_ERROR') || $old_os->id == Configuration::get('PS_OS_CANCELED')) && !StockAvailable::dependsOnStock($product['id_product'], (int) $order->id_shop)) {
                        StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], -(int) $product['product_quantity'], $order->id_shop);
                    }
                } elseif (!$new_os->logable && $old_os->logable) {
                    ProductSale::removeProductSale($product['product_id'], $product['product_quantity']);
                    // @since 1.5.0 - Stock Management
                    if (!Pack::isPack($product['product_id']) && ($new_os->id == Configuration::get('PS_OS_ERROR') || $new_os->id == Configuration::get('PS_OS_CANCELED')) && !StockAvailable::dependsOnStock($product['id_product'])) {
                        StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int) $product['product_quantity'], $order->id_shop);
                    }
                } elseif (!$new_os->logable && !$old_os->logable && ($new_os->id == Configuration::get('PS_OS_ERROR') || $new_os->id == Configuration::get('PS_OS_CANCELED')) && !StockAvailable::dependsOnStock($product['id_product'])) {
                    StockAvailable::updateQuantity($product['product_id'], $product['product_attribute_id'], (int) $product['product_quantity'], $order->id_shop);
                }
                // @since 1.5.0 : if the order is being shipped and this products uses the advanced stock management :
                // decrements the physical stock using $id_warehouse
                if ($new_os->shipped == 1 && $old_os->shipped == 0 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Warehouse::exists($product['id_warehouse']) && $manager != null && ((int) $product['advanced_stock_management'] == 1 || Pack::usesAdvancedStockManagement($product['product_id']))) {
                    // gets the warehouse
                    $warehouse = new Warehouse($product['id_warehouse']);
                    // decrements the stock (if it's a pack, the StockManager does what is needed)
                    $manager->removeProduct($product['product_id'], $product['product_attribute_id'], $warehouse, $product['product_quantity'], Configuration::get('PS_STOCK_CUSTOMER_ORDER_REASON'), true, (int) $order->id);
                } elseif ($new_os->shipped == 0 && $old_os->shipped == 1 && Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Warehouse::exists($product['id_warehouse']) && $manager != null && ((int) $product['advanced_stock_management'] == 1 || Pack::usesAdvancedStockManagement($product['product_id']))) {
                    // if the product is a pack, we restock every products in the pack using the last negative stock mvts
                    if (Pack::isPack($product['product_id'])) {
                        $pack_products = Pack::getItems($product['product_id'], Configuration::get('PS_LANG_DEFAULT'));
                        foreach ($pack_products as $pack_product) {
                            if ($pack_product->advanced_stock_management == 1) {
                                $mvts = StockMvt::getNegativeStockMvts($order->id, $pack_product->id, 0, $pack_product->pack_quantity * $product['product_quantity']);
                                foreach ($mvts as $mvt) {
                                    $manager->addProduct($pack_product->id, 0, new Warehouse($mvt['id_warehouse']), $mvt['physical_quantity'], null, $mvt['price_te'], true);
                                }
                                if (!StockAvailable::dependsOnStock($product['id_product'])) {
                                    StockAvailable::updateQuantity($pack_product->id, 0, (int) $pack_product->pack_quantity * $product['product_quantity'], $order->id_shop);
                                }
                            }
                        }
                    } else {
                        $mvts = StockMvt::getNegativeStockMvts($order->id, $product['product_id'], $product['product_attribute_id'], $product['product_quantity']);
                        foreach ($mvts as $mvt) {
                            $manager->addProduct($product['product_id'], $product['product_attribute_id'], new Warehouse($mvt['id_warehouse']), $mvt['physical_quantity'], null, $mvt['price_te'], true);
                        }
                    }
                }
            }
        }
        $this->id_order_state = (int) $new_order_state;
        // changes invoice number of order ?
        if (!Validate::isLoadedObject($new_os) || !Validate::isLoadedObject($order)) {
            die(Tools::displayError('Invalid new order state'));
        }
        // the order is valid if and only if the invoice is available and the order is not cancelled
        $order->current_state = $this->id_order_state;
        $order->valid = $new_os->logable;
        $order->update();
        if ($new_os->invoice && !$order->invoice_number) {
            $order->setInvoice($use_existing_payment);
        }
        // set orders as paid
        if ($new_os->paid == 1) {
            $invoices = $order->getInvoicesCollection();
            if ($order->total_paid != 0) {
                $payment_method = Module::getInstanceByName($order->module);
            }
            foreach ($invoices as $invoice) {
                $rest_paid = $invoice->getRestPaid();
                if ($rest_paid > 0) {
                    $payment = new OrderPayment();
                    $payment->order_reference = $order->reference;
                    $payment->id_currency = $order->id_currency;
                    $payment->amount = $rest_paid;
                    if ($order->total_paid != 0) {
                        $payment->payment_method = $payment_method->displayName;
                    } else {
                        $payment->payment_method = null;
                    }
                    // Update total_paid_real value for backward compatibility reasons
                    if ($payment->id_currency == $order->id_currency) {
                        $order->total_paid_real += $payment->amount;
                    } else {
                        $order->total_paid_real += Tools::ps_round(Tools::convertPrice($payment->amount, $payment->id_currency, false), 2);
                    }
                    $order->save();
                    $payment->conversion_rate = 1;
                    $payment->save();
                    Db::getInstance()->execute('
					INSERT INTO `' . _DB_PREFIX_ . 'order_invoice_payment`
					VALUES(' . (int) $invoice->id . ', ' . (int) $payment->id . ', ' . (int) $order->id . ')');
                }
            }
        }
        // updates delivery date even if it was already set by another state change
        if ($new_os->delivery) {
            $order->setDelivery();
        }
        // executes hook
        Hook::exec('actionOrderStatusPostUpdate', array('newOrderStatus' => $new_os, 'id_order' => (int) $order->id));
    }
 /**
  * AdminController::getList() override
  * @see AdminController::getList()
  *
  * @param int         $id_lang
  * @param string|null $order_by
  * @param string|null $order_way
  * @param int         $start
  * @param int|null    $limit
  * @param int|bool    $id_lang_shop
  *
  * @throws PrestaShopException
  */
 public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
 {
     parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop);
     if ($this->display == 'details') {
         $nb_items = count($this->_list);
         for ($i = 0; $i < $nb_items; ++$i) {
             $item =& $this->_list[$i];
             $item['name'] = Product::getProductName($item['id_product'], $item['id']);
             // computes coverage
             $coverage = StockManagerFactory::getManager()->getProductCoverage($item['id_product'], $item['id'], Tools::getValue('period') ? (int) Tools::getValue('period') : 7, $this->getCurrentCoverageWarehouse() == -1 ? null : Tools::getValue('id_warehouse', -1));
             if ($coverage != -1) {
                 // if coverage is available
                 if ($coverage < $this->getCurrentWarning()) {
                     // if highlight needed
                     $item['color'] = '#BDE5F8';
                 }
                 $item['coverage'] = $coverage;
             } else {
                 // infinity
                 $item['coverage'] = '--';
             }
             // computes quantity sold
             $qty_sold = $this->getQuantitySold($item['id_product'], $item['id'], $this->getCurrentCoveragePeriod());
             if (!$qty_sold) {
                 $item['qty_sold'] = '--';
             } else {
                 $item['qty_sold'] = $qty_sold;
             }
         }
     } else {
         $nb_items = count($this->_list);
         for ($i = 0; $i < $nb_items; ++$i) {
             $item =& $this->_list[$i];
             if (array_key_exists('variations', $item) && (int) $item['variations'] <= 0) {
                 // computes coverage and displays (highlights if needed)
                 $coverage = StockManagerFactory::getManager()->getProductCoverage($item['id'], 0, $this->getCurrentCoveragePeriod(), $this->getCurrentCoverageWarehouse() == -1 ? null : $this->getCurrentCoverageWarehouse());
                 if ($coverage != -1) {
                     // coverage is available
                     if ($coverage < $this->getCurrentWarning()) {
                         $item['color'] = '#BDE5F8';
                     }
                     $item['coverage'] = $coverage;
                 } else {
                     // infinity
                     $item['coverage'] = '--';
                 }
                 // computes quantity sold
                 $qty_sold = $this->getQuantitySold($item['id'], 0, $this->getCurrentCoveragePeriod());
                 if (!$qty_sold) {
                     $item['qty_sold'] = '--';
                 } else {
                     $item['qty_sold'] = $qty_sold;
                 }
                 // removes 'details' action on products without attributes
                 $this->addRowActionSkipList('details', array($item['id']));
             } else {
                 $item['stock'] = $this->l('See details');
                 $item['reference'] = '--';
                 $item['ean13'] = '--';
                 $item['upc'] = '--';
             }
         }
     }
 }
Пример #22
0
    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']) {
            Product::addFeatureProductImport($product->id, 11, 1); //1 - id значения "переплёт" у харакатеристики "Переплёт"
        }

        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();

        $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/>";
    }
 /**
  * AdminController::getList() override
  * @see AdminController::getList()
  *
  * @param int         $id_lang
  * @param string|null $order_by
  * @param string|null $order_way
  * @param int         $start
  * @param int|null    $limit
  * @param int|bool    $id_lang_shop
  *
  * @throws PrestaShopException
  */
 public function getList($id_lang, $order_by = null, $order_way = null, $start = 0, $limit = null, $id_lang_shop = false)
 {
     if (Tools::isSubmit('id_stock')) {
         parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop);
         $nb_items = count($this->_list);
         for ($i = 0; $i < $nb_items; $i++) {
             $item =& $this->_list[$i];
             $manager = StockManagerFactory::getManager();
             // gets quantities and valuation
             $query = new DbQuery();
             $query->select('SUM(physical_quantity) as physical_quantity');
             $query->select('SUM(usable_quantity) as usable_quantity');
             $query->select('SUM(price_te * physical_quantity) as valuation');
             $query->from('stock');
             $query->where('id_product = ' . (int) $item['id_product'] . ' AND id_product_attribute = ' . (int) $item['id_product_attribute']);
             if ($this->getCurrentCoverageWarehouse() != -1) {
                 $query->where('id_warehouse = ' . (int) $this->getCurrentCoverageWarehouse());
             }
             $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
             $item['physical_quantity'] = $res['physical_quantity'];
             $item['usable_quantity'] = $res['usable_quantity'];
             $item['valuation'] = $res['valuation'];
             $item['real_quantity'] = $manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], $this->getCurrentCoverageWarehouse() == -1 ? null : array($this->getCurrentCoverageWarehouse()), true);
         }
     } else {
         if ((Tools::isSubmit('csv_quantities') || Tools::isSubmit('csv_prices')) && (int) Tools::getValue('id_warehouse') != -1) {
             $limit = false;
         }
         $order_by_valuation = false;
         $order_by_real_quantity = false;
         if ($this->context->cookie->{$this->table . 'Orderby'} == 'valuation') {
             unset($this->context->cookie->{$this->table . 'Orderby'});
             $order_by_valuation = true;
         } elseif ($this->context->cookie->{$this->table . 'Orderby'} == 'real_quantity') {
             unset($this->context->cookie->{$this->table . 'Orderby'});
             $order_by_real_quantity = true;
         }
         parent::getList($id_lang, $order_by, $order_way, $start, $limit, $id_lang_shop);
         $nb_items = count($this->_list);
         for ($i = 0; $i < $nb_items; ++$i) {
             $item =& $this->_list[$i];
             $item['price_te'] = '--';
             $item[$this->identifier] = $item['id_product'] . '_' . $item['id_product_attribute'];
             // gets stock manager
             $manager = StockManagerFactory::getManager();
             // gets quantities and valuation
             $query = new DbQuery();
             $query->select('SUM(physical_quantity) as physical_quantity');
             $query->select('SUM(usable_quantity) as usable_quantity');
             $query->select('SUM(price_te * physical_quantity) as valuation');
             $query->from('stock');
             $query->where('id_product = ' . (int) $item['id_product'] . ' AND id_product_attribute = ' . (int) $item['id_product_attribute']);
             if ($this->getCurrentCoverageWarehouse() != -1) {
                 $query->where('id_warehouse = ' . (int) $this->getCurrentCoverageWarehouse());
             }
             $res = Db::getInstance(_PS_USE_SQL_SLAVE_)->getRow($query);
             $item['physical_quantity'] = $res['physical_quantity'];
             $item['usable_quantity'] = $res['usable_quantity'];
             // gets real_quantity depending on the warehouse
             $item['real_quantity'] = $manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], $this->getCurrentCoverageWarehouse() == -1 ? null : array($this->getCurrentCoverageWarehouse()), true);
             // removes the valuation if the filter corresponds to 'all warehouses'
             if ($this->getCurrentCoverageWarehouse() == -1) {
                 $item['valuation'] = 'N/A';
             } else {
                 $item['valuation'] = $res['valuation'];
             }
         }
         if ($this->getCurrentCoverageWarehouse() != -1 && $order_by_valuation) {
             usort($this->_list, array($this, 'valuationCmp'));
         } elseif ($order_by_real_quantity) {
             usort($this->_list, array($this, 'realQuantityCmp'));
         }
     }
 }
 protected function processBulkDelete()
 {
     if ($this->tabAccess['delete'] === '1') {
         if (is_array($this->boxes) && !empty($this->boxes)) {
             $object = new $this->className();
             if (isset($object->noZeroObject) && (count(call_user_func(array($this->className, $object->noZeroObject))) <= 1 || count($_POST[$this->table . 'Box']) == count(call_user_func(array($this->className, $object->noZeroObject))))) {
                 $this->errors[] = Tools::displayError('You need at least one object.') . ' <b>' . $this->table . '</b><br />' . Tools::displayError('You cannot delete all of the items.');
             } else {
                 $success = 1;
                 $offers = Tools::getValue($this->table . 'Box');
                 if (is_array($offers) && ($count = count($offers))) {
                     // Deleting offers can be quite long on a cheap server. Let's say 1.5 seconds by offer (I've seen it!).
                     if (intval(ini_get('max_execution_time')) < round($count * 1.5)) {
                         ini_set('max_execution_time', round($count * 1.5));
                     }
                     if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                         $stock_manager = StockManagerFactory::getManager();
                     }
                     foreach ($offers as $id_offer) {
                         $offer = new AphOffer((int) $id_offer);
                         if (!count($this->errors)) {
                             if ($offer->delete()) {
                                 PrestaShopLogger::addLog(sprintf($this->l('%s deletion', 'AdminTab', false, false), $this->className), 1, null, $this->className, (int) $offer->id, true, (int) $this->context->employee->id);
                             } else {
                                 $success = false;
                             }
                         } else {
                             $success = 0;
                         }
                     }
                 }
                 if ($success) {
                     $this->redirect_after = self::$currentIndex . '&conf=2&token=' . $this->token;
                 } else {
                     $this->errors[] = Tools::displayError('An error occurred while deleting this selection.');
                 }
             }
         } else {
             $this->errors[] = Tools::displayError('You must select at least one element to delete.');
         }
     } else {
         $this->errors[] = Tools::displayError('You do not have permission to delete this.');
     }
 }
 /**
  * Check stock for a given product or product attribute
  * and manage available actions in consequence
  *
  * @param array $item                 Reference to the current item
  * @param bool  $is_product_variation Specify if it's a product or a product variation
  */
 protected function skipActionByStock(&$item, $is_product_variation = false)
 {
     $stock_manager = StockManagerFactory::getManager();
     //get stocks for this product
     if ($is_product_variation) {
         $stock = $stock_manager->getProductPhysicalQuantities($item['id_product'], $item['id']);
     } else {
         $stock = $stock_manager->getProductPhysicalQuantities($item['id'], 0);
     }
     //affects stock to the list for display
     $item['stock'] = $stock;
     if ($stock <= 0) {
         //there is no stock, we can only add stock
         $this->addRowActionSkipList('removestock', array($item['id']));
         $this->addRowActionSkipList('transferstock', array($item['id']));
     }
 }
Пример #26
0
 /**
  * For a given product, returns its real quantity
  *
  * @since 1.5.0
  * @param int $id_product
  * @param int $id_product_attribute
  * @param int $id_warehouse
  * @param int $id_shop
  * @return int real_quantity
  */
 public static function getRealQuantity($id_product, $id_product_attribute = 0, $id_warehouse = 0, $id_shop = null)
 {
     static $manager = null;
     if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && is_null($manager)) {
         $manager = StockManagerFactory::getManager();
     }
     if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT') && Product::usesAdvancedStockManagement($id_product) && StockAvailable::dependsOnStock($id_product, $id_shop)) {
         return $manager->getProductRealQuantities($id_product, $id_product_attribute, $id_warehouse, true);
     } else {
         return StockAvailable::getQuantityAvailableByProduct($id_product, $id_product_attribute, $id_shop);
     }
 }
Пример #27
0
 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.');
     }
 }
    /**
     * Loads products which quantity (hysical quantity) is equal or less than $threshold
     * @param int $threshold
     */
    protected function loadProducts($threshold)
    {
        // if there is already an order
        if (Tools::getValue('id_supply_order')) {
            $supply_order = new SupplyOrder((int) Tools::getValue('id_supply_order'));
        } else {
            // else, we just created a new order
            $supply_order = $this->object;
        }
        // if order is not valid, return;
        if (!Validate::isLoadedObject($supply_order)) {
            return;
        }
        // resets products if needed
        if (Tools::getValue('id_supply_order')) {
            $supply_order->resetProducts();
        }
        // gets products
        $query = new DbQuery();
        $query->select('
			ps.id_product,
			ps.id_product_attribute,
			ps.product_supplier_reference as supplier_reference,
			ps.product_supplier_price_te as unit_price_te,
			ps.id_currency,
			IFNULL(pa.reference, IFNULL(p.reference, \'\')) as reference,
			IFNULL(pa.ean13, IFNULL(p.ean13, \'\')) as ean13,
			IFNULL(pa.upc, IFNULL(p.upc, \'\')) as upc');
        $query->from('product_supplier', 'ps');
        $query->leftJoin('stock', 's', '
			s.id_product = ps.id_product
			AND s.id_product_attribute = ps.id_product_attribute
			AND s.id_warehouse = ' . (int) $supply_order->id_warehouse);
        $query->innerJoin('warehouse_product_location', 'wpl', '
			wpl.id_product = ps.id_product
			AND wpl.id_product_attribute = ps.id_product_attribute
			AND wpl.id_warehouse = ' . (int) $supply_order->id_warehouse . '
		');
        $query->leftJoin('product', 'p', 'p.id_product = ps.id_product');
        $query->leftJoin('product_attribute', 'pa', '
			pa.id_product_attribute = ps.id_product_attribute
			AND p.id_product = ps.id_product
		');
        $query->where('ps.id_supplier = ' . (int) $supply_order->id_supplier);
        // gets items
        $items = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
        // loads order currency
        $order_currency = new Currency($supply_order->id_currency);
        if (!Validate::isLoadedObject($order_currency)) {
            return;
        }
        $manager = StockManagerFactory::getManager();
        foreach ($items as $item) {
            $diff = (int) $threshold;
            if ($supply_order->is_template != 1) {
                $real_quantity = (int) $manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], $supply_order->id_warehouse, true);
                $diff = (int) $threshold - (int) $real_quantity;
            }
            if ($diff >= 0) {
                // sets supply_order_detail
                $supply_order_detail = new SupplyOrderDetail();
                $supply_order_detail->id_supply_order = $supply_order->id;
                $supply_order_detail->id_currency = $order_currency->id;
                $supply_order_detail->id_product = $item['id_product'];
                $supply_order_detail->id_product_attribute = $item['id_product_attribute'];
                $supply_order_detail->reference = $item['reference'];
                $supply_order_detail->supplier_reference = $item['supplier_reference'];
                $supply_order_detail->name = Product::getProductName($item['id_product'], $item['id_product_attribute'], $supply_order->id_lang);
                $supply_order_detail->ean13 = $item['ean13'];
                $supply_order_detail->upc = $item['upc'];
                $supply_order_detail->quantity_expected = (int) $diff == 0 ? 1 : (int) $diff;
                $supply_order_detail->exchange_rate = $order_currency->conversion_rate;
                $product_currency = new Currency($item['id_currency']);
                if (Validate::isLoadedObject($product_currency)) {
                    $supply_order_detail->unit_price_te = Tools::convertPriceFull($item['unit_price_te'], $product_currency, $order_currency);
                } else {
                    $supply_order_detail->unit_price_te = 0;
                }
                $supply_order_detail->save();
                unset($product_currency);
            }
        }
        // updates supply order
        $supply_order->update();
    }
Пример #29
0
 /**
  * For a given id_product, synchronizes StockAvailable::quantity with Stock::usable_quantity
  *
  * @param int $id_product
  */
 public static function synchronize($id_product, $order_id_shop = null)
 {
     if (!Validate::isUnsignedId($id_product)) {
         return false;
     }
     // gets warehouse ids grouped by shops
     $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'];
         }
     }
     // gets all product attributes ids
     $ids_product_attribute = array();
     foreach (Product::getProductAttributesIds($id_product) as $id_product_attribute) {
         $ids_product_attribute[] = $id_product_attribute['id_product_attribute'];
     }
     // Allow to order the product when out of stock?
     $out_of_stock = StockAvailable::outOfStock($id_product);
     $manager = StockManagerFactory::getManager();
     // loops on $ids_warehouse to synchronize quantities
     foreach ($ids_warehouse as $id_shop => $warehouses) {
         // first, checks if the product depends on stock for the given shop $id_shop
         if (StockAvailable::dependsOnStock($id_product, $id_shop)) {
             // init quantity
             $product_quantity = 0;
             // if it's a simple product
             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);
             } 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' => 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' => array('quantity' => $quantity, 'depends_on_stock' => 1, 'out_of_stock' => $out_of_stock, 'id_product' => (int) $id_product, 'id_product_attribute' => (int) $id_product_attribute));
                         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));
                 }
             }
             // updates
             // if $id_product has attributes, it also updates the sum for all attributes
             $query = array('table' => 'stock_available', 'data' => 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']);
         }
     }
     // In case there are no warehouses, removes product from StockAvailable
     if (count($ids_warehouse) == 0) {
         Db::getInstance()->update('stock_available', array('quantity' => 0), 'id_product = ' . (int) $id_product);
     }
 }
Пример #30
0
    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();
    }