/**
     * Loads products which quantity (hysical quantity) is equal or less than $threshold
     * @param int $threshold
     */
    protected function loadProducts($threshold)
    {
        // if there is already an order
        if (Tools::getValue('id_supply_order')) {
            $supply_order = new SupplyOrder((int) Tools::getValue('id_supply_order'));
        } else {
            // else, we just created a new order
            $supply_order = $this->object;
        }
        // if order is not valid, return;
        if (!Validate::isLoadedObject($supply_order)) {
            return;
        }
        // resets products if needed
        if (Tools::getValue('id_supply_order')) {
            $supply_order->resetProducts();
        }
        // gets products
        $query = new DbQuery();
        $query->select('
			ps.id_product,
			ps.id_product_attribute,
			ps.product_supplier_reference as supplier_reference,
			ps.product_supplier_price_te as unit_price_te,
			ps.id_currency,
			IFNULL(pa.reference, IFNULL(p.reference, \'\')) as reference,
			IFNULL(pa.ean13, IFNULL(p.ean13, \'\')) as ean13,
			IFNULL(pa.upc, IFNULL(p.upc, \'\')) as upc');
        $query->from('product_supplier', 'ps');
        $query->leftJoin('stock', 's', '
			s.id_product = ps.id_product
			AND s.id_product_attribute = ps.id_product_attribute
			AND s.id_warehouse = ' . (int) $supply_order->id_warehouse);
        $query->innerJoin('warehouse_product_location', 'wpl', '
			wpl.id_product = ps.id_product
			AND wpl.id_product_attribute = ps.id_product_attribute
			AND wpl.id_warehouse = ' . (int) $supply_order->id_warehouse . '
		');
        $query->leftJoin('product', 'p', 'p.id_product = ps.id_product');
        $query->leftJoin('product_attribute', 'pa', '
			pa.id_product_attribute = ps.id_product_attribute
			AND p.id_product = ps.id_product
		');
        $query->where('ps.id_supplier = ' . (int) $supply_order->id_supplier);
        // gets items
        $items = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($query);
        // loads order currency
        $order_currency = new Currency($supply_order->id_currency);
        if (!Validate::isLoadedObject($order_currency)) {
            return;
        }
        $manager = StockManagerFactory::getManager();
        foreach ($items as $item) {
            $diff = (int) $threshold;
            if ($supply_order->is_template != 1) {
                $real_quantity = (int) $manager->getProductRealQuantities($item['id_product'], $item['id_product_attribute'], $supply_order->id_warehouse, true);
                $diff = (int) $threshold - (int) $real_quantity;
            }
            if ($diff >= 0) {
                // sets supply_order_detail
                $supply_order_detail = new SupplyOrderDetail();
                $supply_order_detail->id_supply_order = $supply_order->id;
                $supply_order_detail->id_currency = $order_currency->id;
                $supply_order_detail->id_product = $item['id_product'];
                $supply_order_detail->id_product_attribute = $item['id_product_attribute'];
                $supply_order_detail->reference = $item['reference'];
                $supply_order_detail->supplier_reference = $item['supplier_reference'];
                $supply_order_detail->name = Product::getProductName($item['id_product'], $item['id_product_attribute'], $supply_order->id_lang);
                $supply_order_detail->ean13 = $item['ean13'];
                $supply_order_detail->upc = $item['upc'];
                $supply_order_detail->quantity_expected = (int) $diff == 0 ? 1 : (int) $diff;
                $supply_order_detail->exchange_rate = $order_currency->conversion_rate;
                $product_currency = new Currency($item['id_currency']);
                if (Validate::isLoadedObject($product_currency)) {
                    $supply_order_detail->unit_price_te = Tools::convertPriceFull($item['unit_price_te'], $product_currency, $order_currency);
                } else {
                    $supply_order_detail->unit_price_te = 0;
                }
                $supply_order_detail->save();
                unset($product_currency);
            }
        }
        // updates supply order
        $supply_order->update();
    }
 /**
  * Ths method manage associated products to the order when updating it
  */
 public function manageOrderProducts()
 {
     // load supply order
     $id_supply_order = (int) Tools::getValue('id_supply_order', null);
     $products_already_in_order = array();
     if ($id_supply_order != null) {
         $supply_order = new SupplyOrder($id_supply_order);
         if (Validate::isLoadedObject($supply_order)) {
             // tests if the supplier or currency have changed in the supply order
             $new_supplier_id = (int) Tools::getValue('id_supplier');
             $new_currency_id = (int) Tools::getValue('id_currency');
             if ($new_supplier_id != $supply_order->id_supplier || $new_currency_id != $supply_order->id_currency) {
                 // resets all products in this order
                 $supply_order->resetProducts();
             } else {
                 $products_already_in_order = $supply_order->getEntries();
                 $currency = new Currency($supply_order->id_ref_currency);
                 // gets all product ids to manage
                 $product_ids_str = Tools::getValue('product_ids', null);
                 $product_ids = explode('|', $product_ids_str);
                 $product_ids_to_delete_str = Tools::getValue('product_ids_to_delete', null);
                 $product_ids_to_delete = array_unique(explode('|', $product_ids_to_delete_str));
                 //delete products that are not managed anymore
                 foreach ($products_already_in_order as $paio) {
                     $product_ok = false;
                     foreach ($product_ids_to_delete as $id) {
                         $id_check = $paio['id_product'] . '_' . $paio['id_product_attribute'];
                         if ($id_check == $id) {
                             $product_ok = true;
                         }
                     }
                     if ($product_ok === true) {
                         $entry = new SupplyOrderDetail($paio['id_supply_order_detail']);
                         $entry->delete();
                         //--ERP information
                         // delete bind in erp_supply_order_detail table
                         $id_erpip_supply_order_detail = ErpSupplyOrderDetail::getErpSupplierOrderDetailIdBySupplierOrderDetailId((int) $paio['id_supply_order_detail']);
                         if ((int) $id_erpip_supply_order_detail > 0) {
                             $erp_supply_order_detail = new ErpSupplyOrderDetail((int) $id_erpip_supply_order_detail);
                             $erp_supply_order_detail->delete();
                         }
                     }
                 }
                 // manage each product
                 foreach ($product_ids as $id) {
                     // if quantity is null, we dont save product in supply order
                     if (Tools::getValue('input_quantity_expected_' . $id, 0) == '0') {
                         continue;
                     }
                     $errors = array();
                     // check if a checksum is available for this product and test it
                     $check = Tools::getValue('input_check_' . $id, '');
                     $check_valid = md5(_COOKIE_KEY_ . $id);
                     if ($check_valid != $check) {
                         continue;
                     }
                     $pos = strpos($id, '_');
                     if ($pos === false) {
                         continue;
                     }
                     // Load / Create supply order detail
                     $entry = new SupplyOrderDetail();
                     $id_supply_order_detail = (int) Tools::getValue('input_id_' . $id, 0);
                     if ($id_supply_order_detail > 0) {
                         $existing_entry = new SupplyOrderDetail($id_supply_order_detail);
                         if (Validate::isLoadedObject($supply_order)) {
                             $entry =& $existing_entry;
                         }
                     }
                     // get product informations
                     $entry->id_product = Tools::substr($id, 0, $pos);
                     $entry->id_product_attribute = Tools::substr($id, $pos + 1);
                     $entry->unit_price_te = (double) str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_unit_price_te_' . $id, 0));
                     $entry->quantity_expected = (int) str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_quantity_expected_' . $id, 0));
                     $entry->discount_rate = (double) str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_discount_rate_' . $id, 0));
                     $entry->tax_rate = (double) str_replace(array(' ', ','), array('', '.'), Tools::getValue('input_tax_rate_' . $id, 0));
                     $entry->reference = Tools::getValue('input_reference_' . $id, '');
                     $entry->supplier_reference = Tools::getValue('input_supplier_reference_' . $id, '');
                     $entry->ean13 = Tools::getValue('input_ean13_' . $id, '');
                     $entry->upc = Tools::getValue('input_upc_' . $id, '');
                     // fixed bug of discount_value_te field while % is null
                     if ($entry->discount_rate == '0.000000') {
                         $entry->discount_value_te = '0.000000';
                     }
                     //get the product name in the order language
                     $entry->name = Product::getProductName($entry->id_product, $entry->id_product_attribute, $supply_order->id_lang);
                     if (empty($entry->name)) {
                         $entry->name = '';
                     }
                     if ($entry->supplier_reference == null) {
                         $entry->supplier_reference = '';
                     }
                     $entry->exchange_rate = $currency->conversion_rate;
                     $entry->id_currency = $currency->id;
                     $entry->id_supply_order = $supply_order->id;
                     $errors = $entry->validateController();
                     //get the product name displayed in the backoffice according to the employee language
                     $entry->name_displayed = Tools::getValue('input_name_displayed_' . $id, '');
                     // if there is a problem, handle error for the current product
                     if (count($errors) > 0) {
                         // add the product to error array => display again product line
                         $this->order_products_errors[] = array('id_product' => $entry->id_product, 'id_product_attribute' => $entry->id_product_attribute, 'unit_price_te' => $entry->unit_price_te, 'quantity_expected' => $entry->quantity_expected, 'discount_rate' => $entry->discount_rate, 'tax_rate' => $entry->tax_rate, 'name' => $entry->name, 'name_displayed' => $entry->name_displayed, 'reference' => $entry->reference, 'supplier_reference' => $entry->supplier_reference, 'ean13' => $entry->ean13, 'upc' => $entry->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:') . $entry->name . ' ' . $error_str);
                     } else {
                         $entry->save();
                     }
                     //-ERP information
                     // updates/creates erp_supplier_order_detail if it does not exist
                     if (Tools::isSubmit('id_erpip_supply_order_detail_' . $id) && (int) Tools::getValue('id_erpip_supply_order_detail_' . $id) > 0) {
                         $erp_supply_order_detail = new ErpSupplyOrderDetail((int) Tools::getValue('id_erpip_supply_order_detail_' . $id));
                     } else {
                         $erp_supply_order_detail = new ErpSupplyOrderDetail();
                     }
                     // creates erp_supplier_order_detail
                     $erp_supply_order_detail->comment = Tools::getValue('input_comment_' . $id, '');
                     $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 {
                         if (Tools::isSubmit('id_erpip_supply_order_detail_' . $id) && Tools::getValue('id_erpip_supply_order_detail_' . $id) > 0) {
                             $erp_supply_order_detail->update();
                         } else {
                             $erp_supply_order_detail->save();
                             $_POST['id_erpip_supply_order_detail'][$erp_supply_order_detail->id] = $entry->id;
                         }
                     }
                 }
             }
         }
     }
 }
 /**
  * @see ObjectModel::validateController()
  *
  * @param bool $htmlentities Optional
  * @return array Errors, if any..
  */
 public function validateController($htmlentities = true)
 {
     $errors = array();
     /* required fields */
     $fields_required = $this->fieldsRequired;
     if (isset(self::$fieldsRequiredDatabase[get_class($this)])) {
         $fields_required = array_merge($this->fieldsRequired, self::$fieldsRequiredDatabase[get_class($this)]);
     }
     foreach ($fields_required as $field) {
         if (($value = $this->{$field}) == false && (string) $value != '0') {
             if (!$this->id || $field != 'passwd') {
                 $errors[] = '<b>' . SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities) . '</b> ' . Tools::displayError('is required.');
             }
         }
     }
     /* Checks maximum fields sizes */
     foreach ($this->fieldsSize as $field => $max_length) {
         if ($value = $this->{$field} && Tools::strlen($value) > $max_length) {
             $errors[] = sprintf(Tools::displayError('%1$s is too long. Maximum length: %2$d'), SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities), $max_length);
         }
     }
     /* Checks fields validity */
     foreach ($this->fieldsValidate as $field => $function) {
         if ($value = $this->{$field}) {
             if (!Validate::$function($value) && (!empty($value) || in_array($field, $this->fieldsRequired))) {
                 $errors[] = '<b>' . SupplyOrderDetail::displayFieldName($field, get_class($this), $htmlentities) . '</b> ' . Tools::displayError('is invalid.');
             } elseif ($field == 'passwd') {
                 if ($value = Tools::getValue($field)) {
                     $this->{$field} = Tools::encrypt($value);
                 } else {
                     $this->{$field} = $value;
                 }
             }
         }
     }
     if ($this->quantity_expected <= 0) {
         $errors[] = '<b>' . SupplyOrderDetail::displayFieldName('quantity_expected', get_class($this)) . '</b> ' . Tools::displayError('is invalid.');
     }
     if ($this->tax_rate < 0 || $this->tax_rate > 100) {
         $errors[] = '<b>' . SupplyOrderDetail::displayFieldName('tax_rate', get_class($this)) . '</b> ' . Tools::displayError('is invalid.');
     }
     if ($this->discount_rate < 0 || $this->discount_rate > 100) {
         $errors[] = '<b>' . SupplyOrderDetail::displayFieldName('discount_rate', get_class($this)) . '</b> ' . Tools::displayError('is invalid.');
     }
     return $errors;
 }
 public function initOrderingContent()
 {
     // list order id by created providers
     $supply_order_created = array();
     $this->show_toolbar = true;
     $this->display = 'ordering';
     if ($this->is_1_6) {
         $this->initPageHeaderToolbar();
     }
     $this->initToolbar();
     $datas = $this->getDataGeneration();
     if (!empty($datas['data_return'])) {
         //get default currencie
         $id_default_currency = Configuration::get('PS_CURRENCY_DEFAULT');
         // get default id lang
         $id_default_lang = Configuration::get('PS_LANG_DEFAULT');
         foreach ($datas['data_return'] as $id_supplier => $products_info) {
             // Get provider datas
             $supplier = new Supplier((int) $id_supplier);
             // get warehouse datas, delivery date and tax for the provider order
             $id_warehouse_data = Tools::getValue('id_warehouse');
             $date_delivery_expected_data = Tools::getValue('date_delivery_expected');
             $tax_rate_data = Tools::getValue('tax_rate');
             $tax_rate_data = $tax_rate_data[$id_supplier];
             // id warehouse
             $id_warehouse = $id_warehouse_data[$id_supplier];
             // delivery date
             $date_delivery_expected = $date_delivery_expected_data[$id_supplier];
             // create the provider order
             $supply_order = new SupplyOrder();
             $supply_order->reference = ErpSupplyOrderClasses::getNextSupplyOrderReference();
             $supply_order->id_supplier = $id_supplier;
             $supply_order->supplier_name = $supplier->name;
             $supply_order->id_warehouse = $id_warehouse;
             $supply_order->id_currency = $id_default_currency;
             $supply_order->id_lang = $id_default_lang;
             $supply_order->id_supply_order_state = 1;
             $supply_order->id_ref_currency = (int) Currency::getDefaultCurrency()->id;
             $supply_order->date_delivery_expected = $date_delivery_expected;
             // if recording is ok, create the order lines
             if ($supply_order->add()) {
                 // get the provider id order
                 $id_supply_order = $this->getLastIdSupplyOrder();
                 $supply_order_created[] = $id_supply_order;
                 // Ajout de son historique
                 // add historical
                 $history = new SupplyOrderHistory();
                 $history->id_supply_order = $id_supply_order;
                 $history->id_state = 3;
                 $history->id_employee = (int) $this->context->employee->id;
                 $history->employee_firstname = pSQL($this->context->employee->firstname);
                 $history->employee_lastname = pSQL($this->context->employee->lastname);
                 $history->save();
                 // Create entries for provider order
                 if (!empty($products_info)) {
                     $i = 0;
                     foreach ($products_info as $item) {
                         if (!isset($item['product_id'])) {
                             continue;
                         }
                         $supply_order_detail = new SupplyOrderDetail();
                         $supply_order_detail->id_supply_order = $id_supply_order;
                         $supply_order_detail->id_currency = (int) Currency::getDefaultCurrency()->id;
                         $supply_order_detail->id_product = $item['product_id'];
                         $supply_order_detail->id_product_attribute = $item['product_attribute_id'];
                         $supply_order_detail->reference = $item['product_reference'];
                         $supply_order_detail->supplier_reference = $item['product_supplier_reference'];
                         $supply_order_detail->name = $item['product_name'];
                         $supply_order_detail->ean13 = $item['product_ean13'];
                         $supply_order_detail->upc = $item['product_upc'];
                         $supply_order_detail->quantity_expected = $item['total_product_quantity'];
                         $supply_order_detail->exchange_rate = 1;
                         $supply_order_detail->unit_price_te = $item['unit_price_tax_excl'];
                         $supply_order_detail->tax_rate = $tax_rate_data[$i];
                         $supply_order_detail->save();
                         // Get the supply order created
                         $id_supply_order_detail = $this->getLastIdSupplyOrderDetail();
                         // Record the relation between provider order and customer order
                         if (!empty($item)) {
                             foreach ($item['concerned_id_order_detail'] as $customer_link) {
                                 $supply_order_customer = new ErpSupplyOrderCustomer();
                                 $supply_order_customer->id_customer = $customer_link['id_customer'];
                                 $supply_order_customer->id_order_detail = $customer_link['id_order_detail'];
                                 $supply_order_customer->id_supply_order_detail = $id_supply_order_detail;
                                 $supply_order_customer->id_supply_order = $id_supply_order;
                                 $supply_order_customer->save();
                             }
                         }
                         $i++;
                     }
                     // Rerecording provider order data to update totals
                     $supply_order->save();
                 }
             }
         }
         // update provider order status
         if (!empty($datas['order_to_change_state'])) {
             foreach ($datas['order_to_change_state'] as $id_order) {
                 $order_change_state = new Order((int) $id_order);
                 $order_change_state->setCurrentState($this->generate_order_state_to, (int) $this->context->employee->id);
             }
         }
         $this->confirmations[] = $this->l('Order saved successfully !');
         // remove treated order in cookies
         $this->context->cookie->__unset('unselected_orders');
     } else {
         $this->errors[] = Tools::displayError($this->l('No data available for ordering ! You must select at least one order.'));
     }
     $this->context->smarty->assign(array('content' => '', 'show_toolbar ' => 'true', 'show_toolbar' => true, 'toolbar_btn' => $this->toolbar_btn, 'title' => $this->l('Supply Order : order screen'), 'toolbar_scroll' => $this->toolbar_scroll, 'token' => $this->token, 'url_post' => self::$currentIndex . '&token=' . $this->token, 'supply_order_created' => !empty($supply_order_created) ? implode(',', $supply_order_created) : ''));
     $this->createTemplate('ordering.tpl');
     $this->template = 'ordering.tpl';
 }