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