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