dolibarr  16.0.1
stockatdate.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
3  * Copyright (C) 2013-2020 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  * Copyright (C) 2019-2021 Frédéric France <frederic.france@netlogic.fr>
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <https://www.gnu.org/licenses/>.
21  */
22 
29 require '../../main.inc.php';
30 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
36 require_once './lib/replenishment.lib.php';
37 
38 // Load translation files required by the page
39 $langs->loadLangs(array('products', 'stocks', 'orders'));
40 
41 // Security check
42 if ($user->socid) {
43  $socid = $user->socid;
44 }
45 $result = restrictedArea($user, 'produit|service');
46 
47 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
48 $hookmanager->initHooks(array('stockatdate'));
49 
50 //checks if a product has been ordered
51 
52 $action = GETPOST('action', 'aZ09');
53 $type = GETPOST('type', 'int');
54 $mode = GETPOST('mode', 'alpha');
55 
56 $date = '';
57 $dateendofday = '';
58 if (GETPOSTISSET('dateday') && GETPOSTISSET('datemonth') && GETPOSTISSET('dateyear')) {
59  $date = dol_mktime(0, 0, 0, GETPOST('datemonth', 'int'), GETPOST('dateday', 'int'), GETPOST('dateyear', 'int'));
60  $dateendofday = dol_mktime(23, 59, 59, GETPOST('datemonth', 'int'), GETPOST('dateday', 'int'), GETPOST('dateyear', 'int'));
61 }
62 
63 $search_ref = GETPOST('search_ref', 'alphanohtml');
64 $search_nom = GETPOST('search_nom', 'alphanohtml');
65 
66 $now = dol_now();
67 
68 $productid = GETPOST('productid', 'int');
69 $fk_warehouse = GETPOST('fk_warehouse', 'int');
70 
71 $sortfield = GETPOST('sortfield', 'aZ09comma');
72 $sortorder = GETPOST('sortorder', 'aZ09comma');
73 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
74 if (empty($page) || $page == -1) {
75  $page = 0;
76 } // If $page is not defined, or '' or -1
77 $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
78 $offset = $limit * $page;
79 if (!$sortfield) {
80  $sortfield = 'p.ref';
81 }
82 if (!$sortorder) {
83  $sortorder = 'ASC';
84 }
85 
86 $parameters = array();
87 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
88 if ($reshook < 0) {
89  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
90 }
91 
92 $dateIsValid = true;
93 if ($mode == 'future') {
94  if ($date && $date < $now) {
95  setEventMessages($langs->trans("ErrorDateMustBeInFuture"), null, 'errors');
96  $dateIsValid = false;
97  }
98 } else {
99  if ($date && $date > $now) {
100  setEventMessages($langs->trans("ErrorDateMustBeBeforeToday"), null, 'errors');
101  $dateIsValid = false;
102  }
103 }
104 
105 
106 /*
107  * Actions
108  */
109 
110 if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers
111  $date = '';
112  $productid = 0;
113  $fk_warehouse = 0;
114  $search_ref = '';
115  $search_nom = '';
116 }
117 
118 $warehouseStatus = array();
119 if (!empty($conf->global->ENTREPOT_EXTRA_STATUS)) {
120  //$warehouseStatus[] = Entrepot::STATUS_CLOSED;
121  $warehouseStatus[] = Entrepot::STATUS_OPEN_ALL;
122  $warehouseStatus[] = Entrepot::STATUS_OPEN_INTERNAL;
123 }
124 
125 // Get array with current stock per product, warehouse
126 $stock_prod_warehouse = array();
127 $stock_prod = array();
128 if ($date && $dateIsValid) { // Avoid heavy sql if mandatory date is not defined
129  $sql = "SELECT ps.fk_product, ps.fk_entrepot as fk_warehouse,";
130  $sql .= " SUM(ps.reel) AS stock";
131  $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps";
132  $sql .= ", ".MAIN_DB_PREFIX."entrepot as w";
133  $sql .= " WHERE w.entity IN (".getEntity('stock').")";
134  $sql .= " AND w.rowid = ps.fk_entrepot";
135  if (!empty($conf->global->ENTREPOT_EXTRA_STATUS) && count($warehouseStatus)) {
136  $sql .= " AND w.statut IN (".$db->sanitize(implode(',', $warehouseStatus)).")";
137  }
138  if ($productid > 0) {
139  $sql .= " AND ps.fk_product = ".((int) $productid);
140  }
141  if ($fk_warehouse > 0) {
142  $sql .= " AND ps.fk_entrepot = ".((int) $fk_warehouse);
143  }
144  $sql .= " GROUP BY fk_product, fk_entrepot";
145  //print $sql;
146 
147  $resql = $db->query($sql);
148  if ($resql) {
149  $num = $db->num_rows($resql);
150  $i = 0;
151 
152  while ($i < $num) {
153  $obj = $db->fetch_object($resql);
154 
155  $tmp_fk_product = $obj->fk_product;
156  $tmp_fk_warehouse = $obj->fk_warehouse;
157  $stock = $obj->stock;
158 
159  $stock_prod_warehouse[$tmp_fk_product][$tmp_fk_warehouse] = $stock;
160  $stock_prod[$tmp_fk_product] = (isset($stock_prod[$tmp_fk_product]) ? $stock_prod[$tmp_fk_product] : 0) + $stock;
161 
162  $i++;
163  }
164 
165  $db->free($resql);
166  } else {
167  dol_print_error($db);
168  }
169  //var_dump($stock_prod_warehouse);
170 } elseif ($action == 'filter') {
171  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
172 }
173 
174 // Get array with list of stock movements between date and now (for product/warehouse=
175 $movements_prod_warehouse = array();
176 $movements_prod = array();
177 $movements_prod_warehouse_nb = array();
178 $movements_prod_nb = array();
179 if ($date && $dateIsValid) {
180  $sql = "SELECT sm.fk_product, sm.fk_entrepot, SUM(sm.value) AS stock, COUNT(sm.rowid) AS nbofmovement";
181  $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as sm";
182  $sql .= ", ".MAIN_DB_PREFIX."entrepot as w";
183  $sql .= " WHERE w.entity IN (".getEntity('stock').")";
184  $sql .= " AND w.rowid = sm.fk_entrepot";
185  if (!empty($conf->global->ENTREPOT_EXTRA_STATUS) && count($warehouseStatus)) {
186  $sql .= " AND w.statut IN (".$db->sanitize(implode(',', $warehouseStatus)).")";
187  }
188  if ($mode == 'future') {
189  $sql .= " AND sm.datem <= '".$db->idate($dateendofday)."'";
190  } else {
191  $sql .= " AND sm.datem >= '".$db->idate($dateendofday)."'";
192  }
193  if ($productid > 0) {
194  $sql .= " AND sm.fk_product = ".((int) $productid);
195  }
196  if ($fk_warehouse > 0) {
197  $sql .= " AND sm.fk_entrepot = ".((int) $fk_warehouse);
198  }
199  $sql .= " GROUP BY sm.fk_product, sm.fk_entrepot";
200  $resql = $db->query($sql);
201 
202  if ($resql) {
203  $num = $db->num_rows($resql);
204  $i = 0;
205 
206  while ($i < $num) {
207  $obj = $db->fetch_object($resql);
208  $fk_product = $obj->fk_product;
209  $fk_entrepot = $obj->fk_entrepot;
210  $stock = $obj->stock;
211  $nbofmovement = $obj->nbofmovement;
212 
213  // Pour llx_product_stock.reel
214  $movements_prod_warehouse[$fk_product][$fk_entrepot] = $stock;
215  $movements_prod_warehouse_nb[$fk_product][$fk_entrepot] = $nbofmovement;
216 
217  // Pour llx_product.stock
218  $movements_prod[$fk_product] += $stock;
219  $movements_prod_nb[$fk_product] += $nbofmovement;
220 
221  $i++;
222  }
223 
224  $db->free($resql);
225  } else {
226  dol_print_error($db);
227  }
228 }
229 //var_dump($movements_prod_warehouse);
230 //var_dump($movements_prod);
231 
232 
233 /*
234  * View
235  */
236 
237 $form = new Form($db);
238 $formproduct = new FormProduct($db);
239 $prod = new Product($db);
240 
241 $num = 0;
242 
243 $title = $langs->trans('StockAtDate');
244 
245 $sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price,';
246 $sql .= ' p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,';
247 $sql .= ' p.tms as datem, p.duration, p.tobuy, p.stock, ';
248 if ($fk_warehouse > 0) {
249  $sql .= " SUM(p.pmp * ps.reel) as estimatedvalue, SUM(p.price * ps.reel) as sellvalue";
250  $sql .= ', SUM(ps.reel) as stock_reel';
251 } else {
252  $sql .= " SUM(p.pmp * p.stock) as estimatedvalue, SUM(p.price * p.stock) as sellvalue";
253 }
254 // Add fields from hooks
255 $parameters = array();
256 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
257 $sql .= $hookmanager->resPrint;
258 
259 $sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
260 if ($fk_warehouse > 0) {
261  $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON p.rowid = ps.fk_product AND ps.fk_entrepot = '.((int) $fk_warehouse);
262 }
263 // Add fields from hooks
264 $parameters = array();
265 $reshook = $hookmanager->executeHooks('printFieldListJoin', $parameters); // Note that $action and $object may have been modified by hook
266 $sql .= $hookmanager->resPrint;
267 $sql .= ' WHERE p.entity IN ('.getEntity('product').')';
268 if ($productid > 0) {
269  $sql .= " AND p.rowid = ".((int) $productid);
270 }
271 if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
272  $sql .= " AND p.fk_product_type = 0";
273 }
274 if (!empty($canvas)) {
275  $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
276 }
277 if ($fk_warehouse > 0) {
278  $sql .= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price, p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,';
279  $sql .= ' p.tms, p.duration, p.tobuy, p.stock';
280 } else {
281  $sql .= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price, p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,';
282  $sql .= ' p.tms, p.duration, p.tobuy, p.stock';
283 }
284 // Add where from hooks
285 $parameters = array();
286 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
287 $sql .= $hookmanager->resPrint;
288 
289 if ($sortfield == 'stock_reel' && $fk_warehouse <= 0) {
290  $sortfield = 'stock';
291 }
292 if ($sortfield == 'stock' && $fk_warehouse > 0) {
293  $sortfield = 'stock_reel';
294 }
295 $sql .= $db->order($sortfield, $sortorder);
296 
297 $nbtotalofrecords = 0;
298 if ($date && $dateIsValid) { // We avoid a heavy sql if mandatory parameter date not yet defined
299  if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
300  $result = $db->query($sql);
301  $nbtotalofrecords = $db->num_rows($result);
302  if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
303  $page = 0;
304  $offset = 0;
305  }
306  }
307 
308  $sql .= $db->plimit($limit + 1, $offset);
309 
310  //print $sql;
311  $resql = $db->query($sql);
312  if (empty($resql)) {
313  dol_print_error($db);
314  exit;
315  }
316 
317  $num = $db->num_rows($resql);
318 }
319 
320 $i = 0;
321 //print $sql;
322 
323 $helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|';
324 $helpurl .= 'ES:M&oacute;dulo_Stocks';
325 
326 llxHeader('', $title, $helpurl, '');
327 
328 $head = array();
329 
330 $head[0][0] = DOL_URL_ROOT.'/product/stock/stockatdate.php';
331 $head[0][1] = $langs->trans("StockAtDateInPast");
332 $head[0][2] = 'stockatdatepast';
333 
334 $head[1][0] = DOL_URL_ROOT.'/product/stock/stockatdate.php?mode=future';
335 $head[1][1] = $langs->trans("StockAtDateInFuture");
336 $head[1][2] = 'stockatdatefuture';
337 
338 
339 print load_fiche_titre($langs->trans('StockAtDate'), '', 'stock');
340 
341 print dol_get_fiche_head($head, ($mode == 'future' ? 'stockatdatefuture' : 'stockatdatepast'), '', -1, '');
342 
343 $desc = $langs->trans("StockAtDatePastDesc");
344 if ($mode == 'future') {
345  $desc = $langs->trans("StockAtDateFutureDesc");
346 }
347 print '<span class="opacitymedium">'.$desc.'</span><br>'."\n";
348 print '<br>'."\n";
349 
350 print '<form name="formFilterWarehouse" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
351 print '<input type="hidden" name="token" value="'.newToken().'">';
352 print '<input type="hidden" name="action" value="filter">';
353 print '<input type="hidden" name="mode" value="'.$mode.'">';
354 
355 print '<div class="inline-block valignmiddle" style="padding-right: 20px;">';
356 print '<span class="fieldrequired">'.$langs->trans('Date').'</span> '.$form->selectDate(($date ? $date : -1), 'date');
357 
358 print ' <span class="clearbothonsmartphone marginleftonly paddingleftonly marginrightonly paddingrightonly">&nbsp;</span> ';
359 print img_picto('', 'product', 'class="pictofiwedwidth"').' ';
360 print '</span> ';
361 print $form->select_produits($productid, 'productid', '', 0, 0, -1, 2, '', 0, array(), 0, $langs->trans('Product'), 0, 'maxwidth300', 0, '', null, 1);
362 
363 print ' <span class="clearbothonsmartphone marginleftonly paddingleftonly marginrightonly paddingrightonly">&nbsp;</span> ';
364 print img_picto('', 'stock', 'class="pictofiwedwidth"');
365 print '</span> ';
366 print $formproduct->selectWarehouses((GETPOSTISSET('fk_warehouse') ? $fk_warehouse : 'ifonenodefault'), 'fk_warehouse', '', 1, 0, 0, $langs->trans('Warehouse'), 0, 0, null, '', null, 1, false, 'e.ref');
367 print '</div>';
368 
369 $parameters = array();
370 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
371 if (empty($reshook)) {
372  print $hookmanager->resPrint;
373 }
374 
375 print '<div class="inline-block valignmiddle">';
376 print '<input type="submit" class="button" name="valid" value="'.$langs->trans('Refresh').'">';
377 print '</div>';
378 
379 //print '</form>';
380 
381 $param = '';
382 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
383  $param .= '&contextpage='.urlencode($contextpage);
384 }
385 if ($limit > 0 && $limit != $conf->liste_limit) {
386  $param .= '&limit='.urlencode($limit);
387 }
388 $param .= '&mode='.$mode;
389 if ($fk_warehouse > 0) {
390  $param .= '&fk_warehouse='.$fk_warehouse;
391 }
392 if ($productid > 0) {
393  $param .= '&productid='.$productid;
394 }
395 if (GETPOST('dateday', 'int') > 0) {
396  $param .= '&dateday='.GETPOST('dateday', 'int');
397 }
398 if (GETPOST('datemonth', 'int') > 0) {
399  $param .= '&datemonth='.GETPOST('datemonth', 'int');
400 }
401 if (GETPOST('dateyear', 'int') > 0) {
402  $param .= '&dateyear='.GETPOST('dateyear', 'int');
403 }
404 
405 // TODO Move this into the title line ?
406 print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'stock', 0, '', '', $limit, 0, 0, 1);
407 
408 print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
409 print '<table class="liste centpercent">';
410 
411 $stocklabel = $langs->trans('StockAtDate');
412 if ($mode == 'future') {
413  $stocklabel = $langs->trans("VirtualStockAtDate");
414 }
415 
416 //print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">';
417 print '<input type="hidden" name="token" value="'.newToken().'">';
418 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
419 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
420 print '<input type="hidden" name="type" value="'.$type.'">';
421 print '<input type="hidden" name="mode" value="'.$mode.'">';
422 
423 // Fields title search
424 print '<tr class="liste_titre_filter">';
425 print '<td class="liste_titre"><input class="flat" type="text" name="search_ref" size="8" value="'.dol_escape_htmltag($search_ref).'"></td>';
426 print '<td class="liste_titre"><input class="flat" type="text" name="search_nom" size="8" value="'.dol_escape_htmltag($search_nom).'"></td>';
427 print '<td class="liste_titre"></td>';
428 print '<td class="liste_titre"></td>';
429 print '<td class="liste_titre"></td>';
430 if ($mode == 'future') {
431  print '<td class="liste_titre"></td>';
432 } else {
433  print '<td class="liste_titre"></td>';
434  print '<td class="liste_titre"></td>';
435 }
436 // Fields from hook
437 $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
438 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
439 print $hookmanager->resPrint;
440 
441 print '<td class="liste_titre maxwidthsearch">';
442 $searchpicto = $form->showFilterAndCheckAddButtons(0);
443 print $searchpicto;
444 print '</td>';
445 print '</tr>';
446 
447 $fieldtosortcurrentstock = 'stock';
448 if ($fk_warehouse > 0) {
449  $fieldtosortcurrentstock = 'stock_reel';
450 }
451 
452 // Lines of title
453 print '<tr class="liste_titre">';
454 print_liste_field_titre('Ref', $_SERVER["PHP_SELF"], 'p.ref', $param, '', '', $sortfield, $sortorder);
455 print_liste_field_titre('Label', $_SERVER["PHP_SELF"], 'p.label', $param, '', '', $sortfield, $sortorder);
456 
457 if ($mode == 'future') {
458  print_liste_field_titre('CurrentStock', $_SERVER["PHP_SELF"], $fieldtosortcurrentstock, $param, '', '', $sortfield, $sortorder, 'right ');
459  print_liste_field_titre('', $_SERVER["PHP_SELF"]);
460  print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockAtDateDesc');
461  print_liste_field_titre('VirtualStock', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
462 } else {
463  print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ');
464  print_liste_field_titre("EstimatedStockValue", $_SERVER["PHP_SELF"], "estimatedvalue", '', $param, '', $sortfield, $sortorder, 'right ', $langs->trans("AtDate"), 1);
465  print_liste_field_titre("EstimatedStockValueSell", $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', $langs->trans("AtDate"), 1);
466  print_liste_field_titre('', $_SERVER["PHP_SELF"]);
467  print_liste_field_titre('CurrentStock', $_SERVER["PHP_SELF"], $fieldtosortcurrentstock, $param, '', '', $sortfield, $sortorder, 'right ');
468 }
469 print_liste_field_titre('', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ');
470 
471 // Hook fields
472 $parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
473 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
474 print $hookmanager->resPrint;
475 
476 print "</tr>\n";
477 
478 $totalbuyingprice = 0;
479 $totalcurrentstock = 0;
480 $totalvirtualstock = 0;
481 
482 $i = 0;
483 while ($i < ($limit ? min($num, $limit) : $num)) {
484  $objp = $db->fetch_object($resql);
485 
486  if (!empty($conf->global->STOCK_SUPPORTS_SERVICES) || $objp->fk_product_type == 0) {
487  $prod->fetch($objp->rowid);
488 
489  // Multilangs
490  /*if (!empty($conf->global->MAIN_MULTILANGS))
491  {
492  $sql = 'SELECT label,description';
493  $sql .= ' FROM '.MAIN_DB_PREFIX.'product_lang';
494  $sql .= ' WHERE fk_product = '.((int) $objp->rowid);
495  $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
496  $sql .= ' LIMIT 1';
497 
498  $resqlm = $db->query($sql);
499  if ($resqlm)
500  {
501  $objtp = $db->fetch_object($resqlm);
502  if (!empty($objtp->description)) $objp->description = $objtp->description;
503  if (!empty($objtp->label)) $objp->label = $objtp->label;
504  }
505  }*/
506 
507  $currentstock = '';
508  if ($fk_warehouse > 0) {
509  //if ($productid > 0) {
510  $currentstock = $stock_prod_warehouse[$objp->rowid][$fk_warehouse];
511  //} else {
512  // $currentstock = $objp->stock_reel;
513  //}
514  } else {
515  //if ($productid > 0) {
516  $currentstock = $stock_prod[$objp->rowid];
517  //} else {
518  // $currentstock = $objp->stock;
519  //}
520  }
521 
522  if ($mode == 'future') {
523  $prod->load_stock('warehouseopen, warehouseinternal', 0); // This call also ->load_virtual_stock()
524 
525  //$result = $prod->load_stats_reception(0, '4');
526  //print $prod->stats_commande_fournisseur['qty'].'<br>'."\n";
527  //print $prod->stats_reception['qty'];
528 
529  $stock = '<span class="opacitymedium">'.$langs->trans("FeatureNotYetAvailable").'</span>';
530  $virtualstock = $prod->stock_theorique;
531  } else {
532  if ($fk_warehouse > 0) {
533  $stock = $currentstock - $movements_prod_warehouse[$objp->rowid][$fk_warehouse];
534  $nbofmovement = $movements_prod_warehouse_nb[$objp->rowid][$fk_warehouse];
535  } else {
536  $stock = $currentstock - $movements_prod[$objp->rowid];
537  $nbofmovement = $movements_prod_nb[$objp->rowid];
538  }
539  }
540 
541 
542  print '<tr class="oddeven">';
543 
544  // Product ref
545  print '<td class="nowrap">'.$prod->getNomUrl(1, '').'</td>';
546 
547  // Product label
548  print '<td>'.$objp->label;
549  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
550  print '</td>';
551 
552  if ($mode == 'future') {
553  // Current stock
554  print '<td class="right">'.$currentstock.'</td>';
555  $totalcurrentstock += $currentstock;
556 
557  print '<td class="right"></td>';
558 
559  // Virtual stock at date
560  print '<td class="right">'.$stock.'</td>';
561 
562  // Final virtual stock
563  print '<td class="right">'.$virtualstock.'</td>';
564  $totalvirtualstock += $virtualstock;
565  } else {
566  // Stock at date
567  print '<td class="right">'.($stock ? $stock : '<span class="opacitymedium">'.$stock.'</span>').'</td>';
568 
569  // PMP value
570  print '<td class="right">';
571  if (price2num($objp->estimatedvalue, 'MT')) {
572  print '<span class="amount">'.price(price2num($objp->estimatedvalue, 'MT'), 1).'</span>';
573  } else {
574  print '';
575  }
576  $totalbuyingprice += $objp->estimatedvalue;
577  print '</td>';
578 
579  // Selling value
580  print '<td class="right">';
581  if (empty($conf->global->PRODUIT_MULTIPRICES)) {
582  print price(price2num($objp->sellvalue, 'MT'), 1);
583  } else {
584  $htmltext = $langs->trans("OptionMULTIPRICESIsOn");
585  print $form->textwithtooltip('<span class="opacitymedium">'.$langs->trans("Variable").'</span>', $htmltext);
586  }
587  print'</td>';
588 
589  print '<td class="right">';
590  if ($nbofmovement > 0) {
591  print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$objp->rowid.($fk_warehouse > 0 ? '&search_warehouse='.$fk_warehouse : '').'">'.$langs->trans("Movements").'</a>';
592  print ' <span class="tabs"><span class="badge">'.$nbofmovement.'</span></span>';
593  }
594  print '</td>';
595 
596  // Current stock
597  print '<td class="right">'.($currentstock ? $currentstock : '<span class="opacitymedium">0</span>').'</td>';
598  $totalcurrentstock += $currentstock;
599  }
600 
601  // Action
602  print '<td class="right"></td>';
603 
604  // Fields from hook
605  $parameters = array('objp'=>$objp);
606  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
607  print $hookmanager->resPrint;
608 
609  print '</tr>'."\n";
610  }
611  $i++;
612 }
613 
614 $parameters = array('sql'=>$sql);
615 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook
616 print $hookmanager->resPrint;
617 
618 $colspan = 8;
619 if ($mode == 'future') {
620  $colspan++;
621 }
622 
623 
624 if (empty($date) || !$dateIsValid) {
625  print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("EnterADateCriteria").'</span></td></tr>';
626 } else {
627  print '<tr class="liste_total">';
628  print '<td>'.$langs->trans("Totalforthispage").'</td>';
629  print '<td></td>';
630  if ($mode == 'future') {
631  print '<td class="right">'.price(price2num($totalcurrentstock, 'MS')).'</td>';
632  print '<td></td>';
633  print '<td></td>';
634  print '<td class="right">'.price(price2num($totalvirtualstock, 'MS')).'</td>';
635  } else {
636  print '<td></td>';
637  print '<td class="right">'.price(price2num($totalbuyingprice, 'MT')).'</td>';
638  print '<td></td>';
639  print '<td></td>';
640  print '<td class="right">'.($productid > 0 ? price(price2num($totalcurrentstock, 'MS')) : '').'</td>';
641  }
642  print '<td></td>';
643  print '</tr>';
644 }
645 
646 print '</table>';
647 print '</div>';
648 
649 if (!empty($resql)) {
650  $db->free($resql);
651 }
652 
653 print dol_get_fiche_end();
654 
655 print '</form>';
656 
657 llxFooter();
658 
659 $db->close();
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
if($cancel &&!$id) if($action== 'add'&&!$cancel) if($action== 'delete') if($id) $form
Actions.
Definition: card.php:142
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
const STATUS_OPEN_ALL
Warehouse open and operations for customer shipping, supplier dispatch, internal stock transfers/corr...
Class to manage products or services.
dol_now($mode= 'auto')
Return date for now.
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOCSRFCHECK')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:59
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
price($amount, $form=0, $outlangs= '', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code= '')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
Class with static methods for building HTML components related to products Only components common to ...
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
print_barre_liste($titre, $page, $file, $options= '', $sortfield= '', $sortorder= '', $morehtmlcenter= '', $num=-1, $totalnboflines= '', $picto= 'generic', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow= '')
Print a title with navigation controls for pagination.
Class to manage generation of HTML components Only common components must be here.
const STATUS_OPEN_INTERNAL
Warehouse open and operations for stock transfers/corrections allowed (not for customer shipping and ...
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form...
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
if(isModEnabled('facture')&&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur')&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)&&$user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice')&&$user->rights->supplier_invoice->lire)) if(isModEnabled('don')&&!empty($user->rights->don->lire)) if(isModEnabled('tax')&&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture')&&isModEnabled('commande')&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
llxFooter()
Empty footer.
Definition: wrapper.php:73