dolibarr 18.0.7
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
30require '../../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
32require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
35require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
36require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
37require_once './lib/replenishment.lib.php';
38
39// Load translation files required by the page
40$langs->loadLangs(array('products', 'stocks', 'orders'));
41
42// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
43$hookmanager->initHooks(array('stockatdate'));
44
45// Security check
46if ($user->socid) {
47 $socid = $user->socid;
48}
49$result = restrictedArea($user, 'produit|service');
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 = '';
59if (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');
70if (GETPOSTISARRAY('search_fk_warehouse')) {
71 $search_fk_warehouse = GETPOST('search_fk_warehouse', 'array:int');
72} else {
73 $search_fk_warehouse = array(GETPOST('search_fk_warehouse', 'int'));
74}
75// For backward compatibility
76if (GETPOST('fk_warehouse', 'int')) {
77 $search_fk_warehouse = array(GETPOST('fk_warehouse', 'int'));
78}
79// Clean value -1
80foreach ($search_fk_warehouse as $key => $val) {
81 if ($val == -1 || empty($val)) {
82 unset($search_fk_warehouse[$key]);
83 }
84}
85
86$sortfield = GETPOST('sortfield', 'aZ09comma');
87$sortorder = GETPOST('sortorder', 'aZ09comma');
88$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
89if (empty($page) || $page == -1) {
90 $page = 0;
91} // If $page is not defined, or '' or -1
92$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
93$offset = $limit * $page;
94if (!$sortfield) {
95 $sortfield = 'p.ref';
96}
97if (!$sortorder) {
98 $sortorder = 'ASC';
99}
100
101$parameters = array();
102$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
103if ($reshook < 0) {
104 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
105}
106
107$dateIsValid = true;
108if ($mode == 'future') {
109 if ($date && $date < $now) {
110 setEventMessages($langs->trans("ErrorDateMustBeInFuture"), null, 'errors');
111 $dateIsValid = false;
112 }
113} else {
114 if ($date && $date > $now) {
115 setEventMessages($langs->trans("ErrorDateMustBeBeforeToday"), null, 'errors');
116 $dateIsValid = false;
117 }
118}
119
120
121/*
122 * Actions
123 */
124
125if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // Both test are required to be compatible with all browsers
126 $date = '';
127 $productid = 0;
128 $search_fk_warehouse = array();
129 $search_ref = '';
130 $search_nom = '';
131}
132
133$warehouseStatus = array();
134if (!empty($conf->global->ENTREPOT_EXTRA_STATUS)) {
135 //$warehouseStatus[] = Entrepot::STATUS_CLOSED;
136 $warehouseStatus[] = Entrepot::STATUS_OPEN_ALL;
137 $warehouseStatus[] = Entrepot::STATUS_OPEN_INTERNAL;
138}
139
140// Get array with current stock per product, warehouse
141$stock_prod_warehouse = array();
142$stock_prod = array();
143if ($date && $dateIsValid) { // Avoid heavy sql if mandatory date is not defined
144 $sql = "SELECT ps.fk_product, ps.fk_entrepot as fk_warehouse,";
145 $sql .= " SUM(ps.reel) AS stock";
146 $sql .= " FROM ".MAIN_DB_PREFIX."product_stock as ps";
147 $sql .= ", ".MAIN_DB_PREFIX."entrepot as w";
148 $sql .= ", ".MAIN_DB_PREFIX."product as p";
149 $sql .= " WHERE w.entity IN (".getEntity('stock').")";
150 $sql .= " AND w.rowid = ps.fk_entrepot AND p.rowid = ps.fk_product";
151 if (!empty($conf->global->ENTREPOT_EXTRA_STATUS) && count($warehouseStatus)) {
152 $sql .= " AND w.statut IN (".$db->sanitize(implode(',', $warehouseStatus)).")";
153 }
154 if ($productid > 0) {
155 $sql .= " AND ps.fk_product = ".((int) $productid);
156 }
157 if (! empty($search_fk_warehouse)) {
158 $sql .= " AND ps.fk_entrepot IN (".$db->sanitize(join(",", $search_fk_warehouse)).")";
159 }
160 if ($search_ref) {
161 $sql .= natural_search("p.ref", $search_ref);
162 }
163 if ($search_nom) {
164 $sql .= natural_search("p.label", $search_nom);
165 }
166 $sql .= " GROUP BY fk_product, fk_entrepot";
167 //print $sql;
168
169 $resql = $db->query($sql);
170 if ($resql) {
171 $num = $db->num_rows($resql);
172 $i = 0;
173
174 while ($i < $num) {
175 $obj = $db->fetch_object($resql);
176
177 $tmp_fk_product = $obj->fk_product;
178 $tmp_fk_warehouse = $obj->fk_warehouse;
179 $stock = $obj->stock;
180
181 $stock_prod_warehouse[$tmp_fk_product][$tmp_fk_warehouse] = $stock;
182 $stock_prod[$tmp_fk_product] = (isset($stock_prod[$tmp_fk_product]) ? $stock_prod[$tmp_fk_product] : 0) + $stock;
183
184 $i++;
185 }
186
187 $db->free($resql);
188 } else {
189 dol_print_error($db);
190 }
191 //var_dump($stock_prod_warehouse);
192} elseif ($action == 'filter') {
193 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
194}
195
196// Get array with list of stock movements between date and now (for product/warehouse=
197$movements_prod_warehouse = array();
198$movements_prod = array();
199$movements_prod_warehouse_nb = array();
200$movements_prod_nb = array();
201if ($date && $dateIsValid) {
202 $sql = "SELECT sm.fk_product, sm.fk_entrepot, SUM(sm.value) AS stock, COUNT(sm.rowid) AS nbofmovement";
203 $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as sm";
204 $sql .= ", ".MAIN_DB_PREFIX."entrepot as w";
205 $sql .= ", ".MAIN_DB_PREFIX."product as p";
206 $sql .= " WHERE w.entity IN (".getEntity('stock').")";
207 $sql .= " AND w.rowid = sm.fk_entrepot AND p.rowid = sm.fk_product ";
208 if (!empty($conf->global->ENTREPOT_EXTRA_STATUS) && count($warehouseStatus)) {
209 $sql .= " AND w.statut IN (".$db->sanitize(implode(',', $warehouseStatus)).")";
210 }
211 if ($mode == 'future') {
212 $sql .= " AND sm.datem <= '".$db->idate($dateendofday)."'";
213 } else {
214 $sql .= " AND sm.datem >= '".$db->idate($dateendofday)."'";
215 }
216 if ($productid > 0) {
217 $sql .= " AND sm.fk_product = ".((int) $productid);
218 }
219 if (!empty($search_fk_warehouse)) {
220 $sql .= " AND sm.fk_entrepot IN (".$db->sanitize(join(",", $search_fk_warehouse)).")";
221 }
222 if ($search_ref) {
223 $sql .= " AND p.ref LIKE '%".$db->escape($search_ref)."%' ";
224 }
225 if ($search_nom) {
226 $sql .= " AND p.label LIKE '%".$db->escape($search_nom)."%' ";
227 }
228 $sql .= " GROUP BY sm.fk_product, sm.fk_entrepot";
229
230 $resql = $db->query($sql);
231
232 if ($resql) {
233 $num = $db->num_rows($resql);
234 $i = 0;
235
236 while ($i < $num) {
237 $obj = $db->fetch_object($resql);
238 $fk_product = $obj->fk_product;
239 $fk_entrepot = $obj->fk_entrepot;
240 $stock = $obj->stock;
241 $nbofmovement = $obj->nbofmovement;
242
243 // Pour llx_product_stock.reel
244 $movements_prod_warehouse[$fk_product][$fk_entrepot] = $stock;
245 $movements_prod_warehouse_nb[$fk_product][$fk_entrepot] = $nbofmovement;
246
247 // Pour llx_product.stock
248 $movements_prod[$fk_product] += $stock;
249 $movements_prod_nb[$fk_product] += $nbofmovement;
250
251 $i++;
252 }
253
254 $db->free($resql);
255 } else {
256 dol_print_error($db);
257 }
258}
259//var_dump($movements_prod_warehouse);
260//var_dump($movements_prod);
261
262
263/*
264 * View
265 */
266
267$form = new Form($db);
268$formproduct = new FormProduct($db);
269$prod = new Product($db);
270
271$num = 0;
272
273$title = $langs->trans('StockAtDate');
274
275$sql = 'SELECT p.rowid, p.ref, p.label, p.description, p.price, p.pmp,';
276$sql .= ' p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,';
277$sql .= ' p.tms as datem, p.duration, p.tobuy, p.stock, ';
278if (!empty($search_fk_warehouse)) {
279 $sql .= " SUM(p.pmp * ps.reel) as estimatedvalue, SUM(p.price * ps.reel) as sellvalue";
280 $sql .= ', SUM(ps.reel) as stock_reel';
281} else {
282 $sql .= " SUM(p.pmp * p.stock) as estimatedvalue, SUM(p.price * p.stock) as sellvalue";
283}
284// Add fields from hooks
285$parameters = array();
286$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
287$sql .= $hookmanager->resPrint;
288
289$sql .= ' FROM '.MAIN_DB_PREFIX.'product as p';
290if (!empty($search_fk_warehouse)) {
291 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'product_stock as ps ON p.rowid = ps.fk_product AND ps.fk_entrepot IN ('.$db->sanitize(join(",", $search_fk_warehouse)).")";
292}
293// Add fields from hooks
294$parameters = array();
295$reshook = $hookmanager->executeHooks('printFieldListJoin', $parameters); // Note that $action and $object may have been modified by hook
296$sql .= $hookmanager->resPrint;
297$sql .= ' WHERE p.entity IN ('.getEntity('product').')';
298if ($productid > 0) {
299 $sql .= " AND p.rowid = ".((int) $productid);
300}
301if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
302 $sql .= " AND p.fk_product_type = 0";
303}
304if (!empty($canvas)) {
305 $sql .= " AND p.canvas = '".$db->escape($canvas)."'";
306}
307if ($search_ref) {
308 $sql .= natural_search('p.ref', $search_ref);
309}
310if ($search_nom) {
311 $sql .= natural_search('p.label', $search_nom);
312}
313$sql .= ' GROUP BY p.rowid, p.ref, p.label, p.description, p.price, p.pmp, p.price_ttc, p.price_base_type, p.fk_product_type, p.desiredstock, p.seuil_stock_alerte,';
314$sql .= ' p.tms, p.duration, p.tobuy, p.stock';
315// Add where from hooks
316$parameters = array();
317$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
318$sql .= $hookmanager->resPrint;
319
320if ($sortfield == 'stock_reel' && empty($search_fk_warehouse)) {
321 $sortfield = 'stock';
322}
323if ($sortfield == 'stock' && !empty($search_fk_warehouse)) {
324 $sortfield = 'stock_reel';
325}
326$sql .= $db->order($sortfield, $sortorder);
327
328$nbtotalofrecords = '';
329if ($date && $dateIsValid) { // We avoid a heavy sql if mandatory parameter date not yet defined
330 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
331 $result = $db->query($sql);
332 $nbtotalofrecords = $db->num_rows($result);
333 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0
334 $page = 0;
335 $offset = 0;
336 }
337 }
338
339 $sql .= $db->plimit($limit + 1, $offset);
340
341 //print $sql;
342 $resql = $db->query($sql);
343 if (empty($resql)) {
344 dol_print_error($db);
345 exit;
346 }
347
348 $num = $db->num_rows($resql);
349}
350
351$i = 0;
352
353$helpurl = 'EN:Module_Stocks_En|FR:Module_Stock|';
354$helpurl .= 'ES:M&oacute;dulo_Stocks';
355
356llxHeader('', $title, $helpurl, '');
357
358$head = array();
359
360$head[0][0] = DOL_URL_ROOT.'/product/stock/stockatdate.php';
361$head[0][1] = $langs->trans("StockAtDateInPast");
362$head[0][2] = 'stockatdatepast';
363
364$head[1][0] = DOL_URL_ROOT.'/product/stock/stockatdate.php?mode=future';
365$head[1][1] = $langs->trans("StockAtDateInFuture");
366$head[1][2] = 'stockatdatefuture';
367
368
369print load_fiche_titre($langs->trans('StockAtDate'), '', 'stock');
370
371print dol_get_fiche_head($head, ($mode == 'future' ? 'stockatdatefuture' : 'stockatdatepast'), '', -1, '');
372
373$desc = $langs->trans("StockAtDatePastDesc");
374if ($mode == 'future') {
375 $desc = $langs->trans("StockAtDateFutureDesc");
376}
377print '<span class="opacitymedium">'.$desc.'</span><br>'."\n";
378print '<br>'."\n";
379
380print '<form name="formFilterWarehouse" method="POST" action="'.$_SERVER["PHP_SELF"].'">';
381print '<input type="hidden" name="token" value="'.newToken().'">';
382print '<input type="hidden" name="action" value="filter">';
383print '<input type="hidden" name="mode" value="'.$mode.'">';
384
385print '<div class="inline-block valignmiddle" style="padding-right: 20px;">';
386print '<span class="fieldrequired">'.$langs->trans('Date').'</span> '.$form->selectDate(($date ? $date : -1), 'date');
387
388print ' <span class="clearbothonsmartphone marginleftonly paddingleftonly marginrightonly paddingrightonly">&nbsp;</span> ';
389print img_picto('', 'product', 'class="pictofiwedwidth"').' ';
390print '</span> ';
391print $form->select_produits($productid, 'productid', '', 0, 0, -1, 2, '', 0, array(), 0, $langs->trans('Product'), 0, 'maxwidth300', 0, '', null, 1);
392
393if ($mode != 'future') {
394 // A virtual stock in future has no sense on a per warehouse view, so no filter on warehouse is available for stock at date in future
395 print ' <span class="clearbothonsmartphone marginleftonly paddingleftonly marginrightonly paddingrightonly">&nbsp;</span> ';
396 print img_picto('', 'stock', 'class="pictofixedwidth"').$langs->trans("Warehouse").' :';
397 print '</span> ';
398 $selected = ((GETPOSTISSET('search_fk_warehouse') || GETPOSTISSET('fk_warehouse')) ? $search_fk_warehouse : 'ifonenodefault');
399 print $formproduct->selectWarehouses($selected, 'search_fk_warehouse', '', 1, 0, 0, $langs->trans('Warehouse'), 0, 0, null, 'minwidth200', null, 1, false, 'e.ref', 1);
400}
401
402print '</div>';
403
404$parameters = array();
405$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
406if (empty($reshook)) {
407 print $hookmanager->resPrint;
408}
409
410print '<div class="inline-block valignmiddle">';
411print '<input type="submit" class="button" name="valid" value="'.$langs->trans('Refresh').'">';
412print '</div>';
413
414//print '</form>';
415
416$param = '';
417if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
418 $param .= '&contextpage='.urlencode($contextpage);
419}
420if ($limit > 0 && $limit != $conf->liste_limit) {
421 $param .= '&limit='.((int) $limit);
422}
423$param .= '&mode='.$mode;
424if (!empty($search_fk_warehouse)) {
425 foreach ($search_fk_warehouse as $val) {
426 $param .= '&search_fk_warehouse[]='.$val;
427 }
428}
429if ($productid > 0) {
430 $param .= '&productid='.(int) $productid;
431}
432if (GETPOST('dateday', 'int') > 0) {
433 $param .= '&dateday='.GETPOST('dateday', 'int');
434}
435if (GETPOST('datemonth', 'int') > 0) {
436 $param .= '&datemonth='.GETPOST('datemonth', 'int');
437}
438if (GETPOST('dateyear', 'int') > 0) {
439 $param .= '&dateyear='.GETPOST('dateyear', 'int');
440}
441
442// TODO Move this into the title line ?
443print_barre_liste('', $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'stock', 0, '', '', $limit, 0, 0, 1);
444
445print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
446print '<table class="liste centpercent">';
447
448$stocklabel = $langs->trans('StockAtDate');
449if ($mode == 'future') {
450 $stocklabel = $langs->trans("VirtualStockAtDate");
451}
452
453print '<input type="hidden" name="token" value="'.newToken().'">';
454print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
455print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
456print '<input type="hidden" name="type" value="'.$type.'">';
457print '<input type="hidden" name="mode" value="'.$mode.'">';
458
459// Fields title search
460print '<tr class="liste_titre_filter">';
461// Action column
462if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
463 print '<td class="liste_titre center maxwidthsearch">';
464 $searchpicto = $form->showFilterButtons('left');
465 print $searchpicto;
466 print '</td>';
467}
468print '<td class="liste_titre"><input class="flat" type="text" name="search_ref" size="8" value="'.dol_escape_htmltag($search_ref).'"></td>';
469print '<td class="liste_titre"><input class="flat" type="text" name="search_nom" size="8" value="'.dol_escape_htmltag($search_nom).'"></td>';
470print '<td class="liste_titre"></td>';
471print '<td class="liste_titre"></td>';
472print '<td class="liste_titre"></td>';
473if ($mode == 'future') {
474 print '<td class="liste_titre"></td>';
475} else {
476 print '<td class="liste_titre"></td>';
477 print '<td class="liste_titre"></td>';
478}
479// Fields from hook
480$parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
481$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
482print $hookmanager->resPrint;
483
484// Action column
485if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
486 print '<td class="liste_titre center maxwidthsearch">';
487 $searchpicto = $form->showFilterButtons();
488 print $searchpicto;
489 print '</td>';
490}
491print '</tr>';
492
493$fieldtosortcurrentstock = 'stock';
494if (!empty($search_fk_warehouse)) {
495 $fieldtosortcurrentstock = 'stock_reel';
496}
497
498// Lines of title
499print '<tr class="liste_titre">';
500// Action column
501if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
502 print_liste_field_titre('', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'left ');
503}
504print_liste_field_titre('ProductRef', $_SERVER["PHP_SELF"], 'p.ref', $param, '', '', $sortfield, $sortorder);
505print_liste_field_titre('Label', $_SERVER["PHP_SELF"], 'p.label', $param, '', '', $sortfield, $sortorder);
506
507if ($mode == 'future') {
508 print_liste_field_titre('CurrentStock', $_SERVER["PHP_SELF"], $fieldtosortcurrentstock, $param, '', '', $sortfield, $sortorder, 'right ');
509 print_liste_field_titre('', $_SERVER["PHP_SELF"]);
510 print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockAtDateDesc');
511 print_liste_field_titre('VirtualStock', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ', 'VirtualStockDesc');
512} else {
513 print_liste_field_titre($stocklabel, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ');
514 print_liste_field_titre("EstimatedStockValue", $_SERVER["PHP_SELF"], "estimatedvalue", '', $param, '', $sortfield, $sortorder, 'right ', $langs->trans("AtDate"), 1);
515 print_liste_field_titre("EstimatedStockValueSell", $_SERVER["PHP_SELF"], "", '', $param, '', $sortfield, $sortorder, 'right ', $langs->trans("AtDate"), 1);
516 print_liste_field_titre('', $_SERVER["PHP_SELF"]);
517 print_liste_field_titre('CurrentStock', $_SERVER["PHP_SELF"], $fieldtosortcurrentstock, $param, '', '', $sortfield, $sortorder, 'right ');
518}
519
520// Hook fields
521$parameters = array('param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
522$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
523print $hookmanager->resPrint;
524
525// Action column
526if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
527 print_liste_field_titre('', $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right ');
528}
529
530print "</tr>\n";
531
532$totalbuyingprice = 0;
533$totalcurrentstock = 0;
534$totalvirtualstock = 0;
535
536$i = 0;
537while ($i < ($limit ? min($num, $limit) : $num)) {
538 $objp = $db->fetch_object($resql);
539
540 if (!empty($conf->global->STOCK_SUPPORTS_SERVICES) || $objp->fk_product_type == 0) {
541 $prod->fetch($objp->rowid);
542
543 // Multilangs
544 /*if (getDolGlobalInt('MAIN_MULTILANGS'))
545 {
546 $sql = 'SELECT label,description';
547 $sql .= ' FROM '.MAIN_DB_PREFIX.'product_lang';
548 $sql .= ' WHERE fk_product = '.((int) $objp->rowid);
549 $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
550 $sql .= ' LIMIT 1';
551
552 $resqlm = $db->query($sql);
553 if ($resqlm)
554 {
555 $objtp = $db->fetch_object($resqlm);
556 if (!empty($objtp->description)) $objp->description = $objtp->description;
557 if (!empty($objtp->label)) $objp->label = $objtp->label;
558 }
559 }*/
560
561 $currentstock = '';
562 if (!empty($search_fk_warehouse)) {
563 //if ($productid > 0) {
564 foreach ($search_fk_warehouse as $val) {
565 if (!is_numeric($currentstock)) {
566 $currentstock = 0;
567 }
568 $currentstock += $stock_prod_warehouse[$objp->rowid][$val];
569 }
570 //} else {
571 // $currentstock = $objp->stock_reel;
572 //}
573 } else {
574 //if ($productid > 0) {
575 $currentstock = $stock_prod[$objp->rowid];
576 //} else {
577 // $currentstock = $objp->stock;
578 //}
579 }
580
581 if ($mode == 'future') {
582 $prod->load_stock('warehouseopen,warehouseinternal,nobatch', 0, $dateendofday);
583 $stock = $prod->stock_theorique; // virtual stock at a date
584 $prod->load_stock('warehouseopen,warehouseinternal,nobatch', 0);
585 $virtualstock = $prod->stock_theorique; // virtual stock in infinite future
586 } else {
587 $stock = $currentstock;
588 $nbofmovement = 0;
589 if (!empty($search_fk_warehouse)) {
590 foreach ($search_fk_warehouse as $val) {
591 $stock -= $movements_prod_warehouse[$objp->rowid][$val];
592 $nbofmovement += $movements_prod_warehouse_nb[$objp->rowid][$val];
593 }
594 } else {
595 $stock -= $movements_prod[$objp->rowid];
596 $nbofmovement += $movements_prod_nb[$objp->rowid];
597 }
598 }
599
600
601 print '<tr class="oddeven">';
602
603 // Action column
604 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
605 print '<td class="left"></td>';
606 }
607
608 // Product ref
609 print '<td class="nowrap">'.$prod->getNomUrl(1, '').'</td>';
610
611 // Product label
612 print '<td>';
613 print dol_escape_htmltag($objp->label);
614 print '</td>';
615
616 if ($mode == 'future') {
617 // Current stock
618 print '<td class="right">'.$currentstock.'</td>';
619 $totalcurrentstock += $currentstock;
620
621 print '<td class="right"></td>';
622
623 // Virtual stock at date
624 print '<td class="right">'.$stock.'</td>';
625
626 // Final virtual stock
627 print '<td class="right">'.$virtualstock.'</td>';
628 $totalvirtualstock += $virtualstock;
629 } else {
630 // Stock at date
631 print '<td class="right">'.($stock ? $stock : '<span class="opacitymedium">'.$stock.'</span>').'</td>';
632
633 // PMP value
634 print '<td class="right">';
635 if (price2num($stock * $objp->pmp, 'MT')) {
636 print '<span class="amount">'.price(price2num($stock * $objp->pmp, 'MT'), 1).'</span>';
637 } else {
638 print '';
639 }
640 $totalbuyingprice += $stock * $objp->pmp;
641 print '</td>';
642
643 // Selling value
644 print '<td class="right">';
645 if (empty($conf->global->PRODUIT_MULTIPRICES)) {
646 print price(price2num($objp->sellvalue, 'MT'), 1);
647 } else {
648 $htmltext = $langs->trans("OptionMULTIPRICESIsOn");
649 print $form->textwithtooltip('<span class="opacitymedium">'.$langs->trans("Variable").'</span>', $htmltext);
650 }
651 print'</td>';
652
653 print '<td class="right">';
654 if ($nbofmovement > 0) {
655 print '<a href="'.DOL_URL_ROOT.'/product/stock/movement_list.php?idproduct='.$objp->rowid;
656 foreach ($search_fk_warehouse as $val) {
657 print ($val > 0 ? '&search_warehouse='.$val : '');
658 }
659 print '">'.$langs->trans("Movements").'</a>';
660 print ' <span class="tabs"><span class="badge">'.$nbofmovement.'</span></span>';
661 }
662 print '</td>';
663
664 // Current stock
665 print '<td class="right">'.($currentstock ? $currentstock : '<span class="opacitymedium">0</span>').'</td>';
666 $totalcurrentstock += $currentstock;
667 }
668
669 // Fields from hook
670 $parameters = array('objp'=>$objp);
671 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters); // Note that $action and $object may have been modified by hook
672 print $hookmanager->resPrint;
673
674 // Action column
675 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
676 print '<td class="right"></td>';
677 }
678
679 print '</tr>'."\n";
680 }
681 $i++;
682}
683
684$parameters = array('sql'=>$sql);
685$reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters); // Note that $action and $object may have been modified by hook
686print $hookmanager->resPrint;
687
688$colspan = 8;
689if ($mode == 'future') {
690 $colspan++;
691}
692
693
694if (empty($date) || !$dateIsValid) {
695 print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("EnterADateCriteria").'</span></td></tr>';
696} else {
697 print '<tr class="liste_total">';
698 print '<td>'.$langs->trans("Totalforthispage").'</td>';
699 print '<td></td>';
700 if ($mode == 'future') {
701 print '<td class="right">'.price(price2num($totalcurrentstock, 'MS')).'</td>';
702 print '<td></td>';
703 print '<td></td>';
704 print '<td class="right">'.price(price2num($totalvirtualstock, 'MS')).'</td>';
705 } else {
706 print '<td></td>';
707 print '<td class="right">'.price(price2num($totalbuyingprice, 'MT')).'</td>';
708 print '<td></td>';
709 print '<td></td>';
710 print '<td class="right">'.($productid > 0 ? price(price2num($totalcurrentstock, 'MS')) : '').'</td>';
711 }
712 print '<td></td>';
713 print '</tr>';
714}
715
716print '</table>';
717print '</div>';
718
719if (!empty($resql)) {
720 $db->free($resql);
721}
722
723print dol_get_fiche_end();
724
725print '</form>';
726
727llxFooter();
728
729$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 only operations for stock transfers/corrections allowed (not for customer shipping...
const STATUS_OPEN_ALL
Warehouse open and any operations are allowed (customer shipping, supplier dispatch,...
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.
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='', $dragdropfile=0)
Show tabs of a record.
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.
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...
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.
GETPOSTISARRAY($paramname, $method=0)
Return true if the parameter $paramname is submit from a POST OR GET as an array.
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
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.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
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.