dolibarr  9.0.0
replenish.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2013 C├ędric Salvador <csalvador@gpcsolutions.fr>
3  * Copyright (C) 2013-2018 Laurent Destaileur <ely@users.sourceforge.net>
4  * Copyright (C) 2014 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2016 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2016 ATM Consulting <support@atm-consulting.fr>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
28 require '../../main.inc.php';
29 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
34 require_once './lib/replenishment.lib.php';
35 
36 // Load translation files required by the page
37 $langs->loadLangs(array('products', 'stocks', 'orders'));
38 
39 // Security check
40 if ($user->societe_id) {
41  $socid = $user->societe_id;
42 }
43 $result=restrictedArea($user,'produit|service');
44 
45 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
46 $hookmanager->initHooks(array('stockreplenishlist'));
47 
48 //checks if a product has been ordered
49 
50 $action = GETPOST('action','alpha');
51 $sref = GETPOST('sref', 'alpha');
52 $snom = GETPOST('snom', 'alpha');
53 $sall = trim((GETPOST('search_all', 'alphanohtml')!='')?GETPOST('search_all', 'alphanohtml'):GETPOST('sall', 'alphanohtml'));
54 $type = GETPOST('type','int');
55 $tobuy = GETPOST('tobuy', 'int');
56 $salert = GETPOST('salert', 'alpha');
57 $mode = GETPOST('mode','alpha');
58 $draftorder = GETPOST('draftorder','alpha');
59 
60 
61 $fourn_id = GETPOST('fourn_id','int');
62 $fk_supplier = GETPOST('fk_supplier','int');
63 $fk_entrepot = GETPOST('fk_entrepot','int');
64 $texte = '';
65 
66 $sortfield = GETPOST('sortfield','alpha');
67 $sortorder = GETPOST('sortorder','alpha');
68 $page = GETPOST('page','int');
69 if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1
70 $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit;
71 $offset = $limit * $page ;
72 
73 if (!$sortfield) {
74  $sortfield = 'p.ref';
75 }
76 
77 if (!$sortorder) {
78  $sortorder = 'ASC';
79 }
80 
81 // Define virtualdiffersfromphysical
82 $virtualdiffersfromphysical=0;
83 if (! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT)
84 || ! empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)
85 || ! empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE))
86 {
87  $virtualdiffersfromphysical=1; // According to increase/decrease stock options, virtual and physical stock may differs.
88 }
89 $usevirtualstock=0;
90 if ($mode == 'virtual') $usevirtualstock=1;
91 
92 $parameters=array();
93 $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
94 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
95 
96 /*
97  * Actions
98  */
99 
100 if (GETPOST('button_removefilter_x','alpha') || GETPOST('button_removefilter.x','alpha') || GETPOST('button_removefilter','alpha') || isset($_POST['valid'])) // Both test are required to be compatible with all browsers
101 {
102  $sref = '';
103  $snom = '';
104  $sal = '';
105  $salert = '';
106  $draftorder='';
107 }
108 if($draftorder == 'on') $draftchecked = "checked";
109 
110 // Create orders
111 if ($action == 'order' && isset($_POST['valid']))
112 {
113  $linecount = GETPOST('linecount', 'int');
114  $box = 0;
115  $errorQty = 0;
116  unset($_POST['linecount']);
117  if ($linecount > 0)
118  {
119  $db->begin();
120 
121  $suppliers = array();
122  require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php';
123  $productsupplier = new ProductFournisseur($db);
124  for ($i = 0; $i < $linecount; $i++)
125  {
126  if (GETPOST('choose' . $i, 'alpha') === 'on' && GETPOST('fourn' . $i, 'int') > 0)
127  {
128  //one line
129  $box = $i;
130  $supplierpriceid = GETPOST('fourn'.$i, 'int');
131  //get all the parameters needed to create a line
132  $qty = GETPOST('tobuy'.$i, 'int');
133  $idprod=$productsupplier->get_buyprice($supplierpriceid, $qty);
134  $res=$productsupplier->fetch($idprod);
135  if ($res && $idprod > 0)
136  {
137  if ($qty)
138  {
139  //might need some value checks
140  $obj = $db->fetch_object($resql);
141  $line = new CommandeFournisseurLigne($db);
142  $line->qty = $qty;
143  $line->fk_product = $idprod;
144 
145  //$product = new Product($db);
146  //$product->fetch($obj->fk_product);
147  if (! empty($conf->global->MAIN_MULTILANGS))
148  {
149  $productsupplier->getMultiLangs();
150  }
151  $line->desc = $productsupplier->description;
152  if (! empty($conf->global->MAIN_MULTILANGS))
153  {
154  // TODO Get desc in language of thirdparty
155  }
156 
157  $line->tva_tx = $productsupplier->vatrate_supplier;
158  $line->subprice = $productsupplier->fourn_pu;
159  $line->total_ht = $productsupplier->fourn_pu * $qty;
160  $tva = $line->tva_tx / 100;
161  $line->total_tva = $line->total_ht * $tva;
162  $line->total_ttc = $line->total_ht + $line->total_tva;
163  $line->remise_percent = $productsupplier->remise_percent;
164  $line->ref_fourn = $productsupplier->ref_supplier;
165  $line->type = $productsupplier->type;
166  $line->fk_unit = $productsupplier->fk_unit;
167  $suppliers[$productsupplier->fourn_socid]['lines'][] = $line;
168  }
169  }
170  elseif ($idprod == -1)
171  {
172  $errorQty++;
173  }
174  else
175  {
176  $error=$db->lasterror();
177  dol_print_error($db);
178  }
179  $db->free($resql);
180  unset($_POST['fourn' . $i]);
181  }
182  unset($_POST[$i]);
183  }
184 
185  //we now know how many orders we need and what lines they have
186  $i = 0;
187  $orders = array();
188  $suppliersid = array_keys($suppliers);
189  foreach ($suppliers as $supplier)
190  {
191  $order = new CommandeFournisseur($db);
192  // Check if an order for the supplier exists
193  $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."commande_fournisseur";
194  $sql.= " WHERE fk_soc = ".$suppliersid[$i];
195  $sql.= " AND source = 42 AND fk_statut = 0";
196  $sql.= " AND entity IN (".getEntity('commande_fournisseur').")";
197  $sql.= " ORDER BY date_creation DESC";
198  $resql = $db->query($sql);
199  if($resql && $db->num_rows($resql) > 0) {
200  $obj = $db->fetch_object($resql);
201  $order->fetch($obj->rowid);
202  foreach ($supplier['lines'] as $line) {
203  $result = $order->addline(
204  $line->desc,
205  $line->subprice,
206  $line->qty,
207  $line->tva_tx,
208  $line->localtax1_tx,
209  $line->localtax2_tx,
210  $line->fk_product,
211  0,
212  $line->ref_fourn,
213  $line->remise_percent,
214  'HT',
215  0,
216  $line->type,
217  0,
218  false,
219  null,
220  null,
221  0,
222  $line->fk_unit
223  );
224  }
225  if ($result < 0) {
226  $fail++;
227  $msg = $langs->trans('OrderFail') . "&nbsp;:&nbsp;";
228  $msg .= $order->error;
229  setEventMessages($msg, null, 'errors');
230  } else {
231  $id = $result;
232  }
233  } else {
234  $order->socid = $suppliersid[$i];
235  $order->fetch_thirdparty();
236  //trick to know which orders have been generated this way
237  $order->source = 42;
238  foreach ($supplier['lines'] as $line) {
239  $order->lines[] = $line;
240  }
241  $order->cond_reglement_id = $order->thirdparty->cond_reglement_supplier_id;
242  $order->mode_reglement_id = $order->thirdparty->mode_reglement_supplier_id;
243  $id = $order->create($user);
244  if ($id < 0) {
245  $fail++;
246  $msg = $langs->trans('OrderFail') . "&nbsp;:&nbsp;";
247  $msg .= $order->error;
248  setEventMessages($msg, null, 'errors');
249  }
250  $i++;
251  }
252  }
253 
254  if($errorQty) setEventMessages($langs->trans('ErrorOrdersNotCreatedQtyTooLow'), null, 'warnings');
255 
256  if (! $fail && $id)
257  {
258  $db->commit();
259 
260  setEventMessages($langs->trans('OrderCreated'), null, 'mesgs');
261  header('Location: replenishorders.php');
262  exit;
263  }
264  else
265  {
266  $db->rollback();
267  }
268  }
269  if ($box == 0)
270  {
271  setEventMessages($langs->trans('SelectProductWithNotNullQty'), null, 'warnings');
272  }
273 }
274 
275 
276 /*
277  * View
278  */
279 
280 $form = new Form($db);
281 $formproduct = new FormProduct($db);
282 $prod = new Product($db);
283 
284 $title = $langs->trans('Status');
285 
286 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
287  $sqldesiredtock=$db->ifsql("pse.desiredstock IS NULL", "p.desiredstock", "pse.desiredstock");
288  $sqlalertstock=$db->ifsql("pse.seuil_stock_alerte IS NULL", "p.seuil_stock_alerte", "pse.seuil_stock_alerte");
289 } else {
290  $sqldesiredtock='p.desiredstock';
291  $sqlalertstock='p.seuil_stock_alerte';
292 }
293 
294 
295 $sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price,';
296 $sql.= ' p.price_ttc, p.price_base_type,p.fk_product_type,';
297 $sql.= ' p.tms as datem, p.duration, p.tobuy,';
298 $sql.= ' p.desiredstock, p.seuil_stock_alerte,';
299 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
300  $sql.= ' pse.desiredstock as desiredstockpse, pse.seuil_stock_alerte as seuil_stock_alertepse,';
301 }
302 $sql.= ' '.$sqldesiredtock.' as desiredstockcombined, '.$sqlalertstock.' as seuil_stock_alertecombined,';
303 $sql.= ' SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").') as stock_physique';
304 $sql.= ' FROM ' . MAIN_DB_PREFIX . 'product as p';
305 $sql.= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'product_stock as s';
306 $sql.= ' ON (p.rowid = s.fk_product AND s.fk_entrepot IN (SELECT ent.rowid FROM '.MAIN_DB_PREFIX.'entrepot AS ent WHERE ent.entity IN('.getEntity('stock').')))';
307 if ($fk_supplier > 0) {
308  $sql.= ' INNER JOIN '.MAIN_DB_PREFIX.'product_fournisseur_price pfp ON (pfp.fk_product = p.rowid AND pfp.fk_soc = '.$fk_supplier.')';
309 }
310 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
311  $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_warehouse_properties AS pse ON (p.rowid = pse.fk_product AND pse.fk_entrepot = '.$fk_entrepot.')';
312 }
313 $sql.= ' WHERE p.entity IN (' . getEntity('product') . ')';
314 if ($sall) $sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall);
315 // if the type is not 1, we show all products (type = 0,2,3)
316 if (dol_strlen($type)) {
317  if ($type == 1) {
318  $sql .= ' AND p.fk_product_type = 1';
319  } else {
320  $sql .= ' AND p.fk_product_type <> 1';
321  }
322 }
323 if ($sref) $sql.=natural_search('p.ref', $sref);
324 if ($snom) $sql.=natural_search('p.label', $snom);
325 $sql.= ' AND p.tobuy = 1';
326 if (!empty($canvas)) $sql .= ' AND p.canvas = "' . $db->escape($canvas) . '"';
327 $sql.= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price';
328 $sql.= ', p.price_ttc, p.price_base_type,p.fk_product_type, p.tms';
329 $sql.= ', p.duration, p.tobuy';
330 $sql.= ', p.desiredstock';
331 $sql.= ', p.seuil_stock_alerte';
332 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0) {
333  $sql.= ', pse.desiredstock' ;
334  $sql.= ', pse.seuil_stock_alerte' ;
335 }
336 $sql.= ', s.fk_product';
337 
338 if ($usevirtualstock)
339 {
340  $sqlCommandesCli = "(SELECT ".$db->ifsql("SUM(cd.qty) IS NULL", "0", "SUM(cd.qty)")." as qty";
341  $sqlCommandesCli.= " FROM ".MAIN_DB_PREFIX."commandedet as cd";
342  $sqlCommandesCli.= " LEFT JOIN ".MAIN_DB_PREFIX."commande as c ON (c.rowid = cd.fk_commande)";
343  $sqlCommandesCli.= " WHERE c.entity IN (".getEntity('commande').")";
344  $sqlCommandesCli.= " AND cd.fk_product = p.rowid";
345  $sqlCommandesCli.= " AND c.fk_statut IN (1,2))";
346 
347  $sqlExpeditionsCli = "(SELECT ".$db->ifsql("SUM(ed.qty) IS NULL", "0", "SUM(ed.qty)")." as qty";
348  $sqlExpeditionsCli.= " FROM ".MAIN_DB_PREFIX."expedition as e";
349  $sqlExpeditionsCli.= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet as ed ON (ed.fk_expedition = e.rowid)";
350  $sqlExpeditionsCli.= " LEFT JOIN ".MAIN_DB_PREFIX."commandedet as cd ON (cd.rowid = ed.fk_origin_line)";
351  $sqlExpeditionsCli.= " LEFT JOIN ".MAIN_DB_PREFIX."commande as c ON (c.rowid = cd.fk_commande)";
352  $sqlExpeditionsCli.= " WHERE e.entity IN (".getEntity('expedition').")";
353  $sqlExpeditionsCli.= " AND cd.fk_product = p.rowid";
354  $sqlExpeditionsCli.= " AND c.fk_statut IN (1,2))";
355 
356  $sqlCommandesFourn = "(SELECT ".$db->ifsql("SUM(cd.qty) IS NULL", "0", "SUM(cd.qty)")." as qty";
357  $sqlCommandesFourn.= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as cd";
358  $sqlCommandesFourn.= ", ".MAIN_DB_PREFIX."commande_fournisseur as c";
359  $sqlCommandesFourn.= " WHERE c.rowid = cd.fk_commande";
360  $sqlCommandesFourn.= " AND c.entity IN (".getEntity('supplier_order').")";
361  $sqlCommandesFourn.= " AND cd.fk_product = p.rowid";
362  $sqlCommandesFourn.= " AND c.fk_statut IN (3,4))";
363 
364  $sqlReceptionFourn = "(SELECT ".$db->ifsql("SUM(fd.qty) IS NULL", "0", "SUM(fd.qty)")." as qty";
365  $sqlReceptionFourn.= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as cf";
366  $sqlReceptionFourn.= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as fd ON (fd.fk_commande = cf.rowid)";
367  $sqlReceptionFourn.= " WHERE cf.entity IN (".getEntity('supplier_order').")";
368  $sqlReceptionFourn.= " AND fd.fk_product = p.rowid";
369  $sqlReceptionFourn.= " AND cf.fk_statut IN (3,4))";
370 
371  $sql.= ' HAVING (('.$sqldesiredtock.' >= 0 AND ('.$sqldesiredtock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')';
372  $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.')))';
373  $sql.= ' OR ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')';
374  $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.'))))';
375 
376  if ($salert == 'on') // Option to see when stock is lower than alert
377  {
378  $sql.= ' AND ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')';
379  $sql.= ' - ('.$sqlCommandesCli.' - '.$sqlExpeditionsCli.') + ('.$sqlCommandesFourn.' - '.$sqlReceptionFourn.')))';
380  $alertchecked = 'checked';
381  }
382 } else {
383  $sql.= ' HAVING (('.$sqldesiredtock.' >= 0 AND ('.$sqldesiredtock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))';
384  $sql.= ' OR ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").'))))';
385 
386  if ($salert == 'on') // Option to see when stock is lower than alert
387  {
388  $sql.= ' AND ('.$sqlalertstock.' >= 0 AND ('.$sqlalertstock.' > SUM('.$db->ifsql("s.reel IS NULL", "0", "s.reel").')))';
389  $alertchecked = 'checked';
390  }
391 }
392 
393 $sql.= $db->order($sortfield,$sortorder);
394 $sql.= $db->plimit($limit + 1, $offset);
395 
396 //print $sql;
397 $resql = $db->query($sql);
398 if (empty($resql))
399 {
400  dol_print_error($db);
401  exit;
402 }
403 
404 $num = $db->num_rows($resql);
405 $i = 0;
406 
407 $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|';
408 $helpurl .= 'ES:M&oacute;dulo_Stocks';
409 
410 llxHeader('', $title, $helpurl, '');
411 
412 $head = array();
413 $head[0][0] = DOL_URL_ROOT.'/product/stock/replenish.php';
414 $head[0][1] = $title;
415 $head[0][2] = 'replenish';
416 $head[1][0] = DOL_URL_ROOT.'/product/stock/replenishorders.php';
417 $head[1][1] = $langs->trans("ReplenishmentOrders");
418 $head[1][2] = 'replenishorders';
419 
420 
421 print load_fiche_titre($langs->trans('Replenishment'), '', 'title_generic.png');
422 
423 dol_fiche_head($head, 'replenish', '', -1, '');
424 
425 print $langs->trans("ReplenishmentStatusDesc").'<br>'."\n";
426 if ($usevirtualstock == 1)
427 {
428  print $langs->trans("CurentSelectionMode").': ';
429  print $langs->trans("CurentlyUsingVirtualStock").' - ';
430  print '<a href="'.$_SERVER["PHP_SELF"].'?mode=physical&fk_supplier='.$fk_supplier.'&fk_entrepot='.$fk_entrepot.'">'.$langs->trans("UsePhysicalStock").'</a><br>';
431 }
432 if ($usevirtualstock == 0)
433 {
434  print $langs->trans("CurentSelectionMode").': ';
435  print $langs->trans("CurentlyUsingPhysicalStock").' - ';
436  print '<a href="'.$_SERVER["PHP_SELF"].'?mode=virtual&fk_supplier='.$fk_supplier.'&fk_entrepot='.$fk_entrepot.'">'.$langs->trans("UseVirtualStock").'</a><br>';
437 }
438 print '<br>'."\n";
439 
440 print '<form name="formFilterWarehouse" method="GET" action="">';
441 print '<input type="hidden" name="action" value="filter">';
442 print '<input type="hidden" name="sref" value="'.$sref.'">';
443 print '<input type="hidden" name="snom" value="'.$snom.'">';
444 print '<input type="hidden" name="salert" value="'.$salert.'">';
445 print '<input type="hidden" name="draftorder" value="'.$draftorder.'">';
446 print '<input type="hidden" name="mode" value="'.$mode.'">';
447 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE))
448 {
449  print '<div class="inline-block valignmiddle" style="padding-right: 20px;">';
450  print $langs->trans('Warehouse').' '.$formproduct->selectWarehouses($fk_entrepot, 'fk_entrepot', '', 1);
451  print '</div>';
452 }
453 print '<div class="inline-block valignmiddle" style="padding-right: 20px;">';
454 print $langs->trans('Supplier').' '.$form->select_company($fk_supplier, 'fk_supplier', 'fournisseur=1', 1);
455 print '</div>';
456 print '<div class="inline-block valignmiddle">';
457 print '<input class="button" type="submit" name="valid" value="'.$langs->trans('ToFilter').'">';
458 print '</div>';
459 print '</form>';
460 
461 if ($sref || $snom || $sall || $salert || $draftorder || GETPOST('search', 'alpha')) {
462  $filters = '&sref=' . $sref . '&snom=' . $snom;
463  $filters .= '&sall=' . $sall;
464  $filters .= '&salert=' . $salert;
465  $filters .= '&draftorder=' . $draftorder;
466  $filters .= '&mode=' . $mode;
467  $filters .= '&fk_supplier=' . $fk_supplier;
468  $filters .= '&fk_entrepot=' . $fk_entrepot;
470  $texte,
471  $page,
472  'replenish.php',
473  $filters,
474  $sortfield,
475  $sortorder,
476  '',
477  $num
478  );
479 } else {
480  $filters = '&sref=' . $sref . '&snom=' . $snom;
481  $filters .= '&fourn_id=' . $fourn_id;
482  $filters .= (isset($type)?'&type=' . $type:'');
483  $filters .= '&=' . $salert;
484  $filters .= '&draftorder=' . $draftorder;
485  $filters .= '&mode=' . $mode;
486  $filters .= '&fk_supplier=' . $fk_supplier;
487  $filters .= '&fk_entrepot=' . $fk_entrepot;
489  $texte,
490  $page,
491  'replenish.php',
492  $filters,
493  $sortfield,
494  $sortorder,
495  '',
496  $num
497  );
498 }
499 
500 print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
501 print '<table class="liste" width="100%">';
502 
503 $param = (isset($type)? '&type=' . $type : '');
504 $param .= '&fourn_id=' . $fourn_id . '&snom='. $snom . '&salert=' . $salert . '&draftorder='.$draftorder;
505 $param .= '&sref=' . $sref;
506 $param .= '&mode=' . $mode;
507 $param .= '&fk_supplier=' . $fk_supplier;
508 $param .= '&fk_entrepot=' . $fk_entrepot;
509 
510 $stocklabel = $langs->trans('Stock');
511 if ($usevirtualstock == 1) $stocklabel = $langs->trans('VirtualStock');
512 if ($usevirtualstock == 0) $stocklabel = $langs->trans('PhysicalStock');
513 if (!empty($conf->global->STOCK_ALLOW_ADD_LIMIT_STOCK_BY_WAREHOUSE) && $fk_entrepot > 0)
514 {
515  $stocklabel.=' ('.$langs->trans("AllWarehouses").')';
516 }
517 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">'.
518  '<input type="hidden" name="token" value="' .$_SESSION['newtoken'] . '">'.
519  '<input type="hidden" name="fk_supplier" value="' . $fk_supplier . '">'.
520  '<input type="hidden" name="fk_entrepot" value="' .$fk_entrepot . '">'.
521  '<input type="hidden" name="sortfield" value="' . $sortfield . '">'.
522  '<input type="hidden" name="sortorder" value="' . $sortorder . '">'.
523  '<input type="hidden" name="type" value="' . $type . '">'.
524  '<input type="hidden" name="linecount" value="' . $num . '">'.
525  '<input type="hidden" name="action" value="order">'.
526  '<input type="hidden" name="mode" value="' . $mode . '">';
527 
528 // Lignes des champs de filtre
529 print '<tr class="liste_titre_filter">';
530 print '<td class="liste_titre">&nbsp;</td>';
531 print '<td class="liste_titre"><input class="flat" type="text" name="sref" size="8" value="'.dol_escape_htmltag($sref).'"></td>';
532 print '<td class="liste_titre"><input class="flat" type="text" name="snom" size="8" value="'.dol_escape_htmltag($snom).'"></td>';
533 if (!empty($conf->service->enabled) && $type == 1) print '<td class="liste_titre">&nbsp;</td>';
534 print '<td class="liste_titre">&nbsp;</td>';
535 print '<td class="liste_titre" align="right">&nbsp;</td>';
536 print '<td class="liste_titre" align="right">' . $langs->trans('AlertOnly') . '&nbsp;<input type="checkbox" id="salert" name="salert" ' . (!empty($alertchecked)?$alertchecked:'') . '></td>';
537 print '<td class="liste_titre" align="right">' . $langs->trans('IncludeAlsoDraftOrders') . '&nbsp;<input type="checkbox" id="draftorder" name="draftorder" ' . (!empty($draftchecked)?$draftchecked:'') . '></td>';
538 print '<td class="liste_titre">&nbsp;</td>';
539 print '<td class="liste_titre" align="right">';
540 $searchpicto=$form->showFilterAndCheckAddButtons(0);
541 print $searchpicto;
542 print '</td>';
543 print '</tr>';
544 
545 // Lines of title
546 print '<tr class="liste_titre">';
547 print_liste_field_titre('<input type="checkbox" onClick="toggle(this)" />', $_SERVER["PHP_SELF"], '');
548 print_liste_field_titre('Ref', $_SERVER["PHP_SELF"], 'p.ref', $param, '', '', $sortfield, $sortorder);
549 print_liste_field_titre('Label', $_SERVER["PHP_SELF"], 'p.label', $param, '', '', $sortfield, $sortorder);
550 if (!empty($conf->service->enabled) && $type == 1) print_liste_field_titre('Duration', $_SERVER["PHP_SELF"], 'p.duration', $param, '', 'align="center"', $sortfield, $sortorder);
551 print_liste_field_titre('DesiredStock', $_SERVER["PHP_SELF"], 'p.desiredstock', $param, '', 'align="right"', $sortfield, $sortorder);
552 print_liste_field_titre('StockLimitShort', $_SERVER["PHP_SELF"], 'p.seuil_stock_alerte', $param, '', 'align="right"', $sortfield, $sortorder);
553 print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], 'stock_physique', $param, '', 'align="right"', $sortfield, $sortorder);
554 print_liste_field_titre('Ordered', $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder);
555 print_liste_field_titre('StockToBuy', $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder);
556 print_liste_field_titre('SupplierRef', $_SERVER["PHP_SELF"], '', $param, '', 'align="right"', $sortfield, $sortorder);
557 print "</tr>\n";
558 
559 while ($i < ($limit ? min($num, $limit) : $num))
560 {
561  $objp = $db->fetch_object($resql);
562 
563  if (! empty($conf->global->STOCK_SUPPORTS_SERVICES) || $objp->fk_product_type == 0)
564  {
565  $prod->fetch($objp->rowid);
566  $prod->load_stock('warehouseopen, warehouseinternal');
567 
568  // Multilangs
569  if (! empty($conf->global->MAIN_MULTILANGS))
570  {
571  $sql = 'SELECT label,description';
572  $sql .= ' FROM ' . MAIN_DB_PREFIX . 'product_lang';
573  $sql .= ' WHERE fk_product = ' . $objp->rowid;
574  $sql .= ' AND lang = "' . $langs->getDefaultLang() . '"';
575  $sql .= ' LIMIT 1';
576 
577  $resqlm = $db->query($sql);
578  if ($resqlm)
579  {
580  $objtp = $db->fetch_object($resqlm);
581  if (!empty($objtp->description)) $objp->description = $objtp->description;
582  if (!empty($objtp->label)) $objp->label = $objtp->label;
583  }
584  }
585 
586  if ($usevirtualstock)
587  {
588  // If option to increase/decrease is not on an object validation, virtual stock may differs from physical stock.
589  $stock = $prod->stock_theorique;
590  }
591  else
592  {
593  $stock = $prod->stock_reel;
594  }
595 
596  // Force call prod->load_stats_xxx to choose status to count (otherwise it is loaded by load_stock function)
597  if(isset($draftchecked)){
598  $result=$prod->load_stats_commande_fournisseur(0,'0,1,2,3,4');
599  }else {
600  $result=$prod->load_stats_commande_fournisseur(0,'1,2,3,4');
601  }
602 
603  $result=$prod->load_stats_reception(0,'4');
604 
605  //print $prod->stats_commande_fournisseur['qty'].'<br>'."\n";
606  //print $prod->stats_reception['qty'];
607  $ordered = $prod->stats_commande_fournisseur['qty'] - $prod->stats_reception['qty'];
608 
609  $desiredstock=($objp->desiredstockpse ? $objp->desiredstockpse : $objp->desiredstock);
610  $alertstock=($objp->seuil_stock_alertepse ? $objp->seuil_stock_alertepse : $objp->seuil_stock_alerte);
611 
612  $warning='';
613  if ($alertstock && ($stock < $alertstock))
614  {
615  $warning = img_warning($langs->trans('StockTooLow')) . ' ';
616  }
617 
618  //depending on conf, use either physical stock or
619  //virtual stock to compute the stock to buy value
620  $stocktobuy = max(max($desiredstock, $alertstock) - $stock - $ordered, 0);
621  $disabled = '';
622  if ($ordered > 0)
623  {
624  $stockforcompare = $usevirtualstock ? $stock : $stock + $ordered;
625  if ($stockforcompare >= $desiredstock)
626  {
627  $picto = img_picto('', './img/yes', '', 1);
628  $disabled = 'disabled';
629  }
630  else {
631  $picto = img_picto('', './img/no', '', 1);
632  }
633  } else {
634  //$picto = img_help('',$langs->trans("NoPendingReceptionOnSupplierOrder"));
635  $picto = img_picto($langs->trans("NoPendingReceptionOnSupplierOrder"), './img/no', '', 1);
636  }
637 
638  print '<tr class="oddeven">';
639 
640  // Select field
641  //print '<td><input type="checkbox" class="check" name="' . $i . '"' . $disabled . '></td>';
642  print '<td><input type="checkbox" class="check" name="choose'.$i.'"></td>';
643 
644  print '<td class="nowrap">'.$prod->getNomUrl(1, '').'</td>';
645 
646  print '<td>'.$objp->label ;
647  print '<input type="hidden" name="desc' . $i . '" value="' . dol_escape_htmltag($objp->description) . '">'; // TODO Remove this and make a fetch to get description when creating order instead of a GETPOST
648  print '</td>';
649 
650  if (!empty($conf->service->enabled) && $type == 1)
651  {
652  if (preg_match('/([0-9]+)y/i', $objp->duration, $regs)) {
653  $duration = $regs[1] . ' ' . $langs->trans('DurationYear');
654  } elseif (preg_match('/([0-9]+)m/i', $objp->duration, $regs)) {
655  $duration = $regs[1] . ' ' . $langs->trans('DurationMonth');
656  } elseif (preg_match('/([0-9]+)d/i', $objp->duration, $regs)) {
657  $duration = $regs[1] . ' ' . $langs->trans('DurationDay');
658  } else {
659  $duration = $objp->duration;
660  }
661  print '<td align="center">'.$duration.'</td>';
662  }
663 
664  // Desired stock
665  print '<td align="right">' . $desiredstock . '</td>';
666 
667  // Limit stock for alert
668  print '<td align="right">' . $alertstock . '</td>';
669 
670  // Current stock (all warehouses)
671  print '<td align="right">'. $warning . $stock. '</td>';
672 
673  // Already ordered
674  print '<td align="right"><a href="replenishorders.php?sproduct=' . $prod->id . '">'. $ordered . '</a> ' . $picto. '</td>';
675 
676  // To order
677  //print '<td align="right"><input type="text" name="tobuy'.$i.'" value="'.$stocktobuy.'" '.$disabled.'></td>';
678  print '<td align="right"><input type="text" size="4" name="tobuy'.$i.'" value="'.$stocktobuy.'"></td>';
679 
680  // Supplier
681  print '<td align="right">'. $form->select_product_fourn_price($prod->id, 'fourn'.$i, $fk_supplier).'</td>';
682 
683  print '</tr>';
684  }
685  $i++;
686 }
687 
688 $parameters=array('sql'=>$sql);
689 $reshook=$hookmanager->executeHooks('printFieldListFooter',$parameters); // Note that $action and $object may have been modified by hook
690 print $hookmanager->resPrint;
691 
692 print '</table>';
693 print '</div>';
694 
695 $db->free($resql);
696 
697 dol_fiche_end();
698 
699 
700 $value=$langs->trans("CreateOrders");
701 print '<div class="center"><input class="button" type="submit" name="valid" value="'.$value.'"></div>';
702 
703 
704 print '</form>';
705 
706 
707 // TODO Replace this with jquery
708 print '
709 <script type="text/javascript">
710 function toggle(source)
711 {
712  checkboxes = document.getElementsByClassName("check");
713  for (var i=0; i < checkboxes.length;i++) {
714  if (!checkboxes[i].disabled) {
715  checkboxes[i].checked = source.checked;
716  }
717  }
718 }
719 </script>';
720 
721 
722 llxFooter();
723 
724 $db->close();
img_warning($titlealt='default', $moreatt='')
Show warning logo.
llxFooter()
Empty footer.
Definition: wrapper.php:56
load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
GETPOST($paramname, $check='none', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
print
Draft customers invoices.
Definition: index.php:91
setEventMessages($mesg, $mesgs, $style='mesgs')
Set event messages in dol_events session object.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->lire) if(! empty($conf->tax->enabled) && $user->rights->tax->charges->lire) if(! empty($conf->facture->enabled) &&! empty($conf->commande->enabled) && $user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
Class to manage products or services.
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
Class with static methods for building HTML components related to products Only components common to ...
Class to manage generation of HTML components Only common components must be here.
print_barre_liste($titre, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='title_generic.png', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0)
Print a title with navigation controls for pagination.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
dol_fiche_end($notab=0)
Show tab footer of a card.
llxHeader()
Empty header.
Definition: wrapper.php:44
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
Class to manage predefined suppliers products.
restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0)
Check permissions of a user to show a page and an object.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="")
Show title line of an array.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it&#39;s its name (generic function)
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='')
Show tab header of a card.
Class to manage predefined suppliers products.
Class to manage line orders.