dolibarr  18.0.6
movement_list.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2001-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
5  * Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2018-2022 Ferran Marcet <fmarcet@2byte.es>
7  * Copyright (C) 2019 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.'/core/class/html.formfile.class.php';
32 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
33 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
34 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
35 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/lib/stock.lib.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
40 require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
41 require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php';
42 if (isModEnabled('project')) {
43  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
44  require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
45 }
46 
47 // Load translation files required by the page
48 $langs->loadLangs(array('products', 'stocks', 'orders'));
49 if (isModEnabled('productbatch')) {
50  $langs->load("productbatch");
51 }
52 
53 $action = GETPOST('action', 'aZ09');
54 $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
55 $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
56 $cancel = GETPOST('cancel', 'alpha');
57 $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
58 $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
59 $backtopage = GETPOST("backtopage", "alpha");
60 $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
61 $mode = GETPOST('mode', 'aZ'); // The output mode ('list', 'kanban', 'hierarchy', 'calendar', ...)
62 
63 $id = GETPOST('id', 'int');
64 $ref = GETPOST('ref', 'alpha');
65 $msid = GETPOST('msid', 'int');
66 $idproduct = GETPOST('idproduct', 'int');
67 $product_id = GETPOST("product_id", 'int');
68 
69 $search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
70 $search_date_startday = GETPOST('search_date_startday', 'int');
71 $search_date_startmonth = GETPOST('search_date_startmonth', 'int');
72 $search_date_startyear = GETPOST('search_date_startyear', 'int');
73 $search_date_endday = GETPOST('search_date_endday', 'int');
74 $search_date_endmonth = GETPOST('search_date_endmonth', 'int');
75 $search_date_endyear = GETPOST('search_date_endyear', 'int');
76 $search_date_start = dol_mktime(0, 0, 0, GETPOST('search_date_startmonth', 'int'), GETPOST('search_date_startday', 'int'), GETPOST('search_date_startyear', 'int'), 'tzuserrel');
77 $search_date_end = dol_mktime(23, 59, 59, GETPOST('search_date_endmonth', 'int'), GETPOST('search_date_endday', 'int'), GETPOST('search_date_endyear', 'int'), 'tzuserrel');
78 $search_ref = GETPOST('search_ref', 'alpha');
79 $search_movement = GETPOST("search_movement");
80 $search_product_ref = trim(GETPOST("search_product_ref"));
81 $search_product = trim(GETPOST("search_product"));
82 $search_warehouse = trim(GETPOST("search_warehouse"));
83 $search_inventorycode = trim(GETPOST("search_inventorycode"));
84 $search_user = trim(GETPOST("search_user"));
85 $search_batch = trim(GETPOST("search_batch"));
86 $search_qty = trim(GETPOST("search_qty"));
87 $search_type_mouvement = GETPOST('search_type_mouvement', 'int');
88 $search_fk_projet=GETPOST("search_fk_projet", 'int');
89 
90 $type = GETPOST("type", "int");
91 
92 // Load variable for pagination
93 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
94 $sortfield = GETPOST('sortfield', 'aZ09comma');
95 $sortorder = GETPOST('sortorder', 'aZ09comma');
96 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
97 if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
98  // If $page is not defined, or '' or -1 or if we click on clear filters
99  $page = 0;
100 }
101 $offset = $limit * $page;
102 $pageprev = $page - 1;
103 $pagenext = $page + 1;
104 
105 if (!$sortfield) {
106  $sortfield = "m.datem";
107 }
108 if (!$sortorder) {
109  $sortorder = "DESC";
110 }
111 
112 $pdluoid = GETPOST('pdluoid', 'int');
113 
114 // Initialize technical objects
115 $object = new MouvementStock($db);
116 $extrafields = new ExtraFields($db);
117 $diroutputmassaction = $conf->stock->dir_output.'/temp/massgeneration/'.$user->id;
118 $hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes
119 
120 $formfile = new FormFile($db);
121 
122 // Fetch optionals attributes and labels
123 $extrafields->fetch_name_optionals_label($object->table_element);
124 
125 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
126 
127 $arrayfields = array(
128  'm.rowid'=>array('label'=>"Ref", 'checked'=>1, 'position'=>1),
129  'm.datem'=>array('label'=>"Date", 'checked'=>1, 'position'=>2),
130  'p.ref'=>array('label'=>"ProductRef", 'checked'=>1, 'css'=>'maxwidth100', 'position'=>3),
131  'p.label'=>array('label'=>"ProductLabel", 'checked'=>0, 'position'=>5),
132  'm.batch'=>array('label'=>"BatchNumberShort", 'checked'=>1, 'position'=>8, 'enabled'=>(isModEnabled('productbatch'))),
133  'pl.eatby'=>array('label'=>"EatByDate", 'checked'=>0, 'position'=>9, 'enabled'=>(isModEnabled('productbatch'))),
134  'pl.sellby'=>array('label'=>"SellByDate", 'checked'=>0, 'position'=>10, 'enabled'=>(isModEnabled('productbatch'))),
135  'e.ref'=>array('label'=>"Warehouse", 'checked'=>1, 'position'=>100, 'enabled'=>(!($id > 0))), // If we are on specific warehouse, we hide it
136  'm.fk_user_author'=>array('label'=>"Author", 'checked'=>0, 'position'=>120),
137  'm.inventorycode'=>array('label'=>"InventoryCodeShort", 'checked'=>1, 'position'=>130),
138  'm.label'=>array('label'=>"MovementLabel", 'checked'=>1, 'position'=>140),
139  'm.type_mouvement'=>array('label'=>"TypeMovement", 'checked'=>0, 'position'=>150),
140  'origin'=>array('label'=>"Origin", 'checked'=>1, 'position'=>155),
141  'm.fk_projet'=>array('label'=>'Project', 'checked'=>0, 'position'=>180),
142  'm.value'=>array('label'=>"Qty", 'checked'=>1, 'position'=>200),
143  'm.price'=>array('label'=>"UnitPurchaseValue", 'checked'=>0, 'position'=>210, 'enabled'=>(!getDolGlobalInt('STOCK_MOVEMENT_LIST_HIDE_UNIT_PRICE')))
144  //'m.datec'=>array('label'=>"DateCreation", 'checked'=>0, 'position'=>500),
145  //'m.tms'=>array('label'=>"DateModificationShort", 'checked'=>0, 'position'=>500)
146 );
147 
148 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_array_fields.tpl.php';
149 
150 if (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
151  unset($arrayfields['pl.sellby']);
152 }
153 if (!empty($conf->global->PRODUCT_DISABLE_EATBY)) {
154  unset($arrayfields['pl.eatby']);
155 }
156 
157 
158 $tmpwarehouse = new Entrepot($db);
159 if ($id > 0 || !empty($ref)) {
160  $tmpwarehouse->fetch($id, $ref);
161  $id = $tmpwarehouse->id;
162 }
163 
164 
165 // Security check
166 //$result=restrictedArea($user, 'stock', $id, 'entrepot&stock');
167 $result = restrictedArea($user, 'stock');
168 
169 // Security check
170 if (!$user->rights->stock->mouvement->lire) {
171  accessforbidden();
172 }
173 
174 $uploaddir = $conf->stock->dir_output.'/movements';
175 
176 $permissiontoread = $user->rights->stock->mouvement->lire;
177 $permissiontoadd = $user->rights->stock->mouvement->creer;
178 $permissiontodelete = $user->rights->stock->mouvement->creer; // There is no deletion permission for stock movement as we shoul dnever delete
179 
180 $usercanread = $user->rights->stock->mouvement->lire;
181 $usercancreate = $user->rights->stock->mouvement->creer;
182 $usercandelete = $user->rights->stock->mouvement->creer;
183 
184 $error = 0;
185 
186 
187 /*
188  * Actions
189  */
190 
191 if (GETPOST('cancel', 'alpha')) {
192  $action = 'list';
193  $massaction = '';
194 }
195 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
196  $massaction = '';
197 }
198 
199 $parameters = array();
200 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
201 if ($reshook < 0) {
202  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
203 }
204 
205 if (empty($reshook)) {
206  // Selection of new fields
207  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
208 
209  // Purge search criteria
210  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
211  $search_date_startday = '';
212  $search_date_startmonth = '';
213  $search_date_startyear = '';
214  $search_date_endday = '';
215  $search_date_endmonth = '';
216  $search_date_endyear = '';
217  $search_date_start = '';
218  $search_date_end = '';
219  $search_ref = '';
220  $search_movement = "";
221  $search_type_mouvement = "";
222  $search_inventorycode = "";
223  $search_product_ref = "";
224  $search_product = "";
225  $search_warehouse = "";
226  $search_user = "";
227  $search_batch = "";
228  $search_qty = '';
229  $search_fk_projet=0;
230  $search_all = "";
231  $toselect = array();
232  $search_array_options = array();
233  }
234  if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')
235  || GETPOST('button_search_x', 'alpha') || GETPOST('button_search.x', 'alpha') || GETPOST('button_search', 'alpha')) {
236  $massaction = ''; // Protection to avoid mass action if we force a new search during a mass action confirmation
237  }
238 
239  // Mass actions
240  $objectclass = 'MouvementStock';
241  $objectlabel = 'MouvementStock';
242 
243  if (!$error && $massaction == "builddoc" && $permissiontoread && !GETPOST('button_search')) {
244  if (empty($diroutputmassaction)) {
245  dol_print_error(null, 'include of actions_massactions.inc.php is done but var $diroutputmassaction was not defined');
246  exit;
247  }
248 
249  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
250  require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php';
251  require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
252 
253  $objecttmp = new $objectclass($db);
254  $listofobjectid = array();
255  foreach ($toselect as $toselectid) {
256  $objecttmp = new $objectclass($db); // must create new instance because instance is saved into $listofobjectref array for future use
257  $result = $objecttmp->fetch($toselectid);
258  if ($result > 0) {
259  $listofobjectid[$toselectid] = $toselectid;
260  }
261  }
262 
263  $arrayofinclusion = array();
264  foreach ($listofobjectref as $tmppdf) {
265  $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'\.pdf$';
266  }
267  foreach ($listofobjectref as $tmppdf) {
268  $arrayofinclusion[] = '^'.preg_quote(dol_sanitizeFileName($tmppdf), '/').'_[a-zA-Z0-9-_]+\.pdf$'; // To include PDF generated from ODX files
269  }
270  $listoffiles = dol_dir_list($uploaddir, 'all', 1, implode('|', $arrayofinclusion), '\.meta$|\.png', 'date', SORT_DESC, 0, true);
271 
272  // Define output language (Here it is not used because we do only merging existing PDF)
273  $outputlangs = $langs;
274  $newlang = '';
275  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
276  $newlang = GETPOST('lang_id', 'aZ09');
277  }
278  //elseif (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && is_object($objecttmp->thirdparty)) { // On massaction, we can have several values for $objecttmp->thirdparty
279  // $newlang = $objecttmp->thirdparty->default_lang;
280  //}
281  if (!empty($newlang)) {
282  $outputlangs = new Translate("", $conf);
283  $outputlangs->setDefaultLang($newlang);
284  }
285 
286  // Create output dir if not exists
287  dol_mkdir($diroutputmassaction);
288 
289  // Defined name of merged file
290  $filename = strtolower(dol_sanitizeFileName($langs->transnoentities($objectlabel)));
291  $filename = preg_replace('/\s/', '_', $filename);
292 
293  // Save merged file
294  /*
295  if ($year) {
296  $filename .= '_'.$year;
297  }
298  if ($month) {
299  $filename .= '_'.$month;
300  }
301  */
302  $now = dol_now();
303  $file = $diroutputmassaction.'/'.$filename.'_'.dol_print_date($now, 'dayhourlog').'.pdf';
304 
305 
306  // Create PDF
307  // TODO Create the pdf including list of movement ids found into $listofobjectid
308  // ...
309 
310 
311  if (!$error) {
312  $langs->load("exports");
313  setEventMessages($langs->trans('FileSuccessfullyBuilt', $filename.'_'.dol_print_date($now, 'dayhourlog')), null, 'mesgs');
314  }
315 
316  $massaction = '';
317  $action = '';
318  }
319 
320  include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
321 }
322 
323 if ($action == 'update_extras') {
324  $tmpwarehouse->oldcopy = dol_clone($tmpwarehouse);
325 
326  // Fill array 'array_options' with data from update form
327  $ret = $extrafields->setOptionalsFromPost(null, $tmpwarehouse, GETPOST('attribute', 'restricthtml'));
328  if ($ret < 0) {
329  $error++;
330  }
331  if (!$error) {
332  $result = $tmpwarehouse->insertExtraFields();
333  if ($result < 0) {
334  setEventMessages($tmpwarehouse->error, $tmpwarehouse->errors, 'errors');
335  $error++;
336  }
337  }
338  if ($error) {
339  $action = 'edit_extras';
340  }
341 }
342 
343 // Correct stock
344 if ($action == "correct_stock") {
345  $product = new Product($db);
346  if (!empty($product_id)) {
347  $result = $product->fetch($product_id);
348  }
349 
350  $error = 0;
351 
352  if (empty($product_id)) {
353  $error++;
354  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
355  $action = 'correction';
356  }
357  if (!is_numeric(GETPOST("nbpiece"))) {
358  $error++;
359  setEventMessages($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentitiesnoconv("NumberOfUnit")), null, 'errors');
360  $action = 'correction';
361  }
362 
363  if (!$error) {
364  $origin_element = '';
365  $origin_id = null;
366 
367  if (GETPOST('projectid', 'int')) {
368  $origin_element = 'project';
369  $origin_id = GETPOST('projectid', 'int');
370  }
371 
372  if ($product->hasbatch()) {
373  $batch = GETPOST('batch_number', 'alphanohtml');
374 
375  //$eatby=GETPOST('eatby');
376  //$sellby=GETPOST('sellby');
377  $eatby = dol_mktime(0, 0, 0, GETPOST('eatbymonth', 'int'), GETPOST('eatbyday', 'int'), GETPOST('eatbyyear', 'int'));
378  $sellby = dol_mktime(0, 0, 0, GETPOST('sellbymonth', 'int'), GETPOST('sellbyday', 'int'), GETPOST('sellbyyear', 'int'));
379 
380  $result = $product->correct_stock_batch(
381  $user,
382  $id,
383  GETPOST("nbpiece", 'int'),
384  GETPOST("mouvement", 'int'),
385  GETPOST("label", 'alphanohtml'),
386  price2num(GETPOST('unitprice'), 'MT'),
387  $eatby,
388  $sellby,
389  $batch,
390  GETPOST('inventorycode', 'alphanohtml'),
391  $origin_element,
392  $origin_id,
393  0,
394  $extrafields
395  ); // We do not change value of stock for a correction
396  } else {
397  $result = $product->correct_stock(
398  $user,
399  $id,
400  GETPOST("nbpiece", 'int'),
401  GETPOST("mouvement", "int"),
402  GETPOST("label", 'alphanohtml'),
403  price2num(GETPOST('unitprice'), 'MT'),
404  GETPOST('inventorycode', 'alphanohtml'),
405  $origin_element,
406  $origin_id,
407  0,
408  $extrafields
409  ); // We do not change value of stock for a correction
410  }
411 
412  if ($result > 0) {
413  header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
414  exit;
415  } else {
416  $error++;
417  setEventMessages($product->error, $product->errors, 'errors');
418  $action = 'correction';
419  }
420  }
421 
422  if (!$error) {
423  $action = '';
424  }
425 }
426 
427 // Transfer stock from a warehouse to another warehouse
428 if ($action == "transfert_stock" && !$cancel) {
429  $product = new Product($db);
430  if (!empty($product_id)) {
431  $result = $product->fetch($product_id);
432  }
433 
434  if (!(GETPOST("id_entrepot_destination", 'int') > 0)) {
435  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
436  $error++;
437  $action = 'transfert';
438  }
439  if (empty($product_id)) {
440  $error++;
441  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
442  $action = 'transfert';
443  }
444  if (!GETPOST("nbpiece", 'int')) {
445  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NumberOfUnit")), null, 'errors');
446  $error++;
447  $action = 'transfert';
448  }
449  if ($id == GETPOST("id_entrepot_destination", 'int')) {
450  setEventMessages($langs->trans("ErrorSrcAndTargetWarehouseMustDiffers"), null, 'errors');
451  $error++;
452  $action = 'transfert';
453  }
454 
455  if (isModEnabled('productbatch')) {
456  $product = new Product($db);
457  $result = $product->fetch($product_id);
458 
459  if ($product->hasbatch() && !GETPOST("batch_number")) {
460  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("batch_number")), null, 'errors');
461  $error++;
462  $action = 'transfert';
463  }
464  }
465 
466  if (!$error) {
467  if ($id) {
468  $object = new Entrepot($db);
469  $result = $object->fetch($id);
470 
471  $db->begin();
472 
473  $product->load_stock('novirtual'); // Load array product->stock_warehouse
474 
475  // Define value of products moved
476  $pricesrc = 0;
477  if (isset($product->pmp)) {
478  $pricesrc = $product->pmp;
479  }
480  $pricedest = $pricesrc;
481 
482  if ($product->hasbatch()) {
483  $pdluo = new Productbatch($db);
484 
485  if ($pdluoid > 0) {
486  $result = $pdluo->fetch($pdluoid);
487  if ($result) {
488  $srcwarehouseid = $pdluo->warehouseid;
489  $batch = $pdluo->batch;
490  $eatby = $pdluo->eatby;
491  $sellby = $pdluo->sellby;
492  } else {
493  setEventMessages($pdluo->error, $pdluo->errors, 'errors');
494  $error++;
495  }
496  } else {
497  $srcwarehouseid = $id;
498  $batch = GETPOST('batch_number', 'alphanohtml');
499  $eatby = $d_eatby;
500  $sellby = $d_sellby;
501  }
502 
503  if (!$error) {
504  // Remove stock
505  $result1 = $product->correct_stock_batch(
506  $user,
507  $srcwarehouseid,
508  GETPOST("nbpiece", 'int'),
509  1,
510  GETPOST("label", 'san_alpha'),
511  $pricesrc,
512  $eatby,
513  $sellby,
514  $batch,
515  GETPOST('inventorycode'),
516  '',
517  null,
518  0,
519  $extrafields
520  );
521  // Add stock
522  $result2 = $product->correct_stock_batch(
523  $user,
524  GETPOST("id_entrepot_destination", 'int'),
525  GETPOST("nbpiece", 'int'),
526  0,
527  GETPOST("label", 'san_alpha'),
528  $pricedest,
529  $eatby,
530  $sellby,
531  $batch,
532  GETPOST('inventorycode', 'alphanohtml'),
533  '',
534  null,
535  0,
536  $extrafields
537  );
538  }
539  } else {
540  // Remove stock
541  $result1 = $product->correct_stock(
542  $user,
543  $id,
544  GETPOST("nbpiece"),
545  1,
546  GETPOST("label", 'san_alpha'),
547  $pricesrc,
548  GETPOST('inventorycode', 'alphanohtml'),
549  '',
550  null,
551  0,
552  $extrafields
553  );
554 
555  // Add stock
556  $result2 = $product->correct_stock(
557  $user,
558  GETPOST("id_entrepot_destination"),
559  GETPOST("nbpiece"),
560  0,
561  GETPOST("label", 'san_alpha'),
562  $pricedest,
563  GETPOST('inventorycode', 'alphanohtml'),
564  '',
565  null,
566  0,
567  $extrafields
568  );
569  }
570  if (!$error && $result1 >= 0 && $result2 >= 0) {
571  $db->commit();
572 
573  if ($backtopage) {
574  header("Location: ".$backtopage);
575  exit;
576  } else {
577  header("Location: movement_list.php?id=".$object->id);
578  exit;
579  }
580  } else {
581  setEventMessages($product->error, $product->errors, 'errors');
582  $db->rollback();
583  $action = 'transfert';
584  }
585  }
586  }
587 }
588 
589 
590 /*
591  * View
592  */
593 
594 $form = new Form($db);
595 $formproduct = new FormProduct($db);
596 if (isModEnabled('project')) {
597  $formproject = new FormProjets($db);
598 }
599 $productlot = new Productlot($db);
600 $productstatic = new Product($db);
601 $warehousestatic = new Entrepot($db);
602 $movement = new MouvementStock($db);
603 $userstatic = new User($db);
604 
605 $now = dol_now();
606 
607 // Build and execute select
608 // --------------------------------------------------------------------
609 $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tosell, p.tobuy, p.tobatch, p.fk_product_type as type, p.entity,";
610 $sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,";
611 $sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,";
612 $sql .= " m.batch, m.price,";
613 $sql .= " m.type_mouvement,";
614 $sql .= " m.fk_projet as fk_project,";
615 $sql .= " pl.rowid as lotid, pl.eatby, pl.sellby,";
616 $sql .= " u.login, u.photo, u.lastname, u.firstname, u.email as user_email, u.statut as user_status";
617 // Add fields from extrafields
618 if (!empty($extrafields->attributes[$object->table_element]['label'])) {
619  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
620  $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key." as options_".$key : '');
621  }
622 }
623 // Add fields from hooks
624 $parameters = array();
625 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
626 $sql .= $hookmanager->resPrint;
627 $sql = preg_replace('/,\s*$/', '', $sql);
628 
629 $sqlfields = $sql; // $sql fields to remove for count total
630 
631 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
632 $sql .= " ".MAIN_DB_PREFIX."product as p,";
633 $sql .= " ".MAIN_DB_PREFIX."stock_mouvement as m";
634 if (!empty($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) {
635  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (m.rowid = ef.fk_object)";
636 }
637 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON m.fk_user_author = u.rowid";
638 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON m.batch = pl.batch AND m.fk_product = pl.fk_product";
639 
640 // Add table from hooks
641 $parameters = array();
642 $reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
643 $sql .= $hookmanager->resPrint;
644 
645 $sql .= " WHERE m.fk_product = p.rowid";
646 if ($msid > 0) {
647  $sql .= " AND m.rowid = ".((int) $msid);
648 }
649 $sql .= " AND m.fk_entrepot = e.rowid";
650 $sql .= " AND e.entity IN (".getEntity('stock').")";
651 if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
652  $sql .= " AND p.fk_product_type = 0";
653 }
654 if ($id > 0) {
655  $sql .= " AND e.rowid = ".((int) $id);
656 }
657 if (!empty($search_date_start)) {
658  $sql .= " AND m.datem >= '" . $db->idate($search_date_start) . "'";
659 }
660 if (!empty($search_date_end)) {
661  $sql .= " AND m.datem <= '" . $db->idate($search_date_end) . "'";
662 }
663 if ($idproduct > 0) {
664  $sql .= " AND p.rowid = ".((int) $idproduct);
665 }
666 if (!empty($search_ref)) {
667  $sql .= natural_search('m.rowid', $search_ref, 1);
668 }
669 if (!empty($search_movement)) {
670  $sql .= natural_search('m.label', $search_movement);
671 }
672 if (!empty($search_inventorycode)) {
673  $sql .= natural_search('m.inventorycode', $search_inventorycode);
674 }
675 if (!empty($search_product_ref)) {
676  $sql .= natural_search('p.ref', $search_product_ref);
677 }
678 if (!empty($search_product)) {
679  $sql .= natural_search('p.label', $search_product);
680 }
681 if ($search_warehouse != '' && $search_warehouse != '-1') {
682  $sql .= natural_search('e.rowid', $search_warehouse, 2);
683 }
684 if (!empty($search_user)) {
685  $sql .= natural_search(array('u.lastname', 'u.firstname', 'u.login'), $search_user);
686 }
687 if (!empty($search_batch)) {
688  $sql .= natural_search('m.batch', $search_batch);
689 }
690 if (!empty($product_id) && $product_id != '-1') {
691  $sql .= natural_search('p.rowid', $product_id);
692 }
693 if (!empty($search_fk_projet) && $search_fk_projet != '-1') {
694  $sql .= natural_search('m.fk_projet', $search_fk_projet);
695 }
696 if ($search_qty != '') {
697  $sql .= natural_search('m.value', $search_qty, 1);
698 }
699 if ($search_type_mouvement != '' && $search_type_mouvement != '-1') {
700  $sql .= natural_search('m.type_mouvement', $search_type_mouvement, 2);
701 }
702 // Add where from extra fields
703 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
704 // Add where from hooks
705 $parameters = array();
706 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
707 $sql .= $hookmanager->resPrint;
708 
709 // Count total nb of records
710 $nbtotalofrecords = '';
711 if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) {
712  /* The fast and low memory method to get and count full list converts the sql into a sql count */
713  $sqlforcount = preg_replace('/^'.preg_quote($sqlfields, '/').'/', 'SELECT COUNT(*) as nbtotalofrecords', $sql);
714  $sqlforcount = preg_replace('/GROUP BY .*$/', '', $sqlforcount);
715  $resql = $db->query($sqlforcount);
716  if ($resql) {
717  $objforcount = $db->fetch_object($resql);
718  $nbtotalofrecords = $objforcount->nbtotalofrecords;
719  } else {
720  dol_print_error($db);
721  }
722 
723  if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
724  $page = 0;
725  $offset = 0;
726  }
727  $db->free($resql);
728 }
729 
730 // Complete request and execute it with limit
731 $sql .= $db->order($sortfield, $sortorder);
732 if ($limit) {
733  $sql .= $db->plimit($limit + 1, $offset);
734 }
735 
736 $resql = $db->query($sql);
737 if (!$resql) {
738  dol_print_error($db);
739  exit;
740 }
741 
742 $num = $db->num_rows($resql);
743 
744 
745 $product = new Product($db);
746 $object = new Entrepot($db);
747 
748 if ($idproduct > 0) {
749  $product->fetch($idproduct);
750 }
751 if ($id > 0 || $ref) {
752  $result = $object->fetch($id, $ref);
753  if ($result < 0) {
754  dol_print_error($db);
755  }
756 }
757 
758 
759 // Output page
760 // --------------------------------------------------------------------
761 
762 $i = 0;
763 $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
764 if ($msid) {
765  $title = $langs->trans('StockMovementForId', $msid);
766 } else {
767  $title = $langs->trans("ListOfStockMovements");
768  if ($id) {
769  if (!empty($object->ref)) {
770  $title .= ' ('.$object->ref.')';
771  } else {
772  $title .= ' ('.$langs->trans("ForThisWarehouse").')';
773  }
774  }
775 }
776 
777 
778 // Output page
779 // --------------------------------------------------------------------
780 
781 llxHeader('', $title, $help_url);
782 
783 /*
784  * Show tab only if we ask a particular warehouse
785  */
786 if ($object->id > 0) {
787  $head = stock_prepare_head($object);
788 
789  print dol_get_fiche_head($head, 'movements', $langs->trans("Warehouse"), -1, 'stock');
790 
791 
792  $linkback = '<a href="'.DOL_URL_ROOT.'/product/stock/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
793 
794  $morehtmlref = '<div class="refidno">';
795  $morehtmlref .= $langs->trans("LocationSummary").' : '.$object->lieu;
796 
797  // Project
798  if (isModEnabled('project')) {
799  $langs->load("projects");
800  $morehtmlref .= '<br>'.img_picto('', 'project').' '.$langs->trans('Project').' ';
801  if ($usercancreate && 1 == 2) {
802  if ($action != 'classify') {
803  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> : ';
804  }
805  if ($action == 'classify') {
806  $projectid = $object->fk_project;
807  $morehtmlref .= '<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
808  $morehtmlref .= '<input type="hidden" name="action" value="classin">';
809  $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
810  $morehtmlref .= $formproject->select_projects(($socid > 0 ? $socid : -1), $projectid, 'projectid', 0, 0, 1, 1, 0, 0, 0, '', 1, 0, 'maxwidth500');
811  $morehtmlref .= '<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
812  $morehtmlref .= '</form>';
813  } else {
814  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1, '', 'maxwidth300');
815  }
816  } else {
817  if (!empty($object->fk_project)) {
818  $proj = new Project($db);
819  $proj->fetch($object->fk_project);
820  $morehtmlref .= ' : '.$proj->getNomUrl(1);
821  if ($proj->title) {
822  $morehtmlref .= ' - '.$proj->title;
823  }
824  } else {
825  $morehtmlref .= '';
826  }
827  }
828  }
829  $morehtmlref .= '</div>';
830 
831  $shownav = 1;
832  if ($user->socid && !in_array('stock', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) {
833  $shownav = 0;
834  }
835 
836  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref', 'ref', $morehtmlref);
837 
838 
839  print '<div class="fichecenter">';
840  print '<div class="fichehalfleft">';
841  print '<div class="underbanner clearboth"></div>';
842 
843  print '<table class="border centpercent tableforfield">';
844 
845  print '<tr>';
846 
847  // Description
848  print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>'.dol_htmlentitiesbr($object->description).'</td></tr>';
849 
850  $calcproductsunique = $object->nb_different_products();
851  $calcproducts = $object->nb_products();
852 
853  // Total nb of different products
854  print '<tr><td>'.$langs->trans("NumberOfDifferentProducts").'</td><td>';
855  print empty($calcproductsunique['nb']) ? '0' : $calcproductsunique['nb'];
856  print "</td></tr>";
857 
858  // Nb of products
859  print '<tr><td>'.$langs->trans("NumberOfProducts").'</td><td>';
860  $valtoshow = price2num($calcproducts['nb'], 'MS');
861  print empty($valtoshow) ? '0' : $valtoshow;
862  print "</td></tr>";
863 
864  print '</table>';
865 
866  print '</div>';
867  print '<div class="fichehalfright">';
868  print '<div class="underbanner clearboth"></div>';
869 
870  print '<table class="border centpercent tableforfield">';
871 
872  // Value
873  print '<tr><td class="titlefield">'.$langs->trans("EstimatedStockValueShort").'</td><td>';
874  print price((empty($calcproducts['value']) ? '0' : price2num($calcproducts['value'], 'MT')), 0, $langs, 0, -1, -1, $conf->currency);
875  print "</td></tr>";
876 
877  // Last movement
878  $sql = "SELECT MAX(m.datem) as datem";
879  $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m";
880  $sql .= " WHERE m.fk_entrepot = ".((int) $object->id);
881  $resqlbis = $db->query($sql);
882  if ($resqlbis) {
883  $objbis = $db->fetch_object($resqlbis);
884  $lastmovementdate = $db->jdate($objbis->datem);
885  } else {
886  dol_print_error($db);
887  }
888 
889  print '<tr><td>'.$langs->trans("LastMovement").'</td><td>';
890  if ($lastmovementdate) {
891  print dol_print_date($lastmovementdate, 'dayhour');
892  } else {
893  print $langs->trans("None");
894  }
895  print "</td></tr>";
896 
897  // Other attributes
898  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
899 
900  // Categories
901  if (isModEnabled('categorie')) {
902  print '<tr><td valign="middle">'.$langs->trans("Categories").'</td><td colspan="3">';
903  print $form->showCategories($object->id, Categorie::TYPE_WAREHOUSE, 1);
904  print "</td></tr>";
905  }
906 
907  print "</table>";
908 
909  print '</div>';
910  print '</div>';
911 
912  print '<div class="clearboth"></div>';
913 
914  print dol_get_fiche_end();
915 }
916 
917 
918 // Correct stock
919 if ($action == "correction") {
920  include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stockcorrection.tpl.php';
921  print '<br>';
922 }
923 
924 // Transfer of units
925 if ($action == "transfert") {
926  include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stocktransfer.tpl.php';
927  print '<br>';
928 }
929 
930 
931 // Action bar
932 if ((empty($action) || $action == 'list') && $id > 0) {
933  print "<div class=\"tabsAction\">\n";
934 
935  $parameters = array();
936  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
937  // modified by hook
938  if (empty($reshook)) {
939  if ($user->rights->stock->mouvement->creer) {
940  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=correction">'.$langs->trans("CorrectStock").'</a>';
941  }
942 
943  if ($user->rights->stock->mouvement->creer) {
944  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=transfert">'.$langs->trans("TransferStock").'</a>';
945  }
946  }
947 
948  print '</div><br>';
949 }
950 
951 $arrayofselected = is_array($toselect) ? $toselect : array();
952 
953 $param = '';
954 if (!empty($mode)) {
955  $param .= '&mode='.urlencode($mode);
956 }
957 if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
958  $param .= '&contextpage='.urlencode($contextpage);
959 }
960 if ($limit > 0 && $limit != $conf->liste_limit) {
961  $param .= '&limit='.((int) $limit);
962 }
963 if ($id > 0) {
964  $param .= '&id='.urlencode($id);
965 }
966 if ($search_date_startday) {
967  $param .= '&search_date_startday='.urlencode($search_date_startday);
968 }
969 if ($search_date_startmonth) {
970  $param .= '&search_date_startmonth='.urlencode($search_date_startmonth);
971 }
972 if ($search_date_startyear) {
973  $param .= '&search_date_startyear='.urlencode($search_date_startyear);
974 }
975 if ($search_date_endday) {
976  $param .= '&search_date_endday='.urlencode($search_date_endday);
977 }
978 if ($search_date_endmonth) {
979  $param .= '&search_date_endmonth='.urlencode($search_date_endmonth);
980 }
981 if ($search_date_endyear) {
982  $param .= '&search_date_endyear='.urlencode($search_date_endyear);
983 }
984 if ($search_movement) {
985  $param .= '&search_movement='.urlencode($search_movement);
986 }
987 if ($search_inventorycode) {
988  $param .= '&search_inventorycode='.urlencode($search_inventorycode);
989 }
990 if ($search_type_mouvement) {
991  $param .= '&search_type_mouvement='.urlencode($search_type_mouvement);
992 }
993 if ($search_product_ref) {
994  $param .= '&search_product_ref='.urlencode($search_product_ref);
995 }
996 if ($search_product) {
997  $param .= '&search_product='.urlencode($search_product);
998 }
999 if ($search_batch) {
1000  $param .= '&search_batch='.urlencode($search_batch);
1001 }
1002 if ($search_warehouse > 0) {
1003  $param .= '&search_warehouse='.urlencode($search_warehouse);
1004 }
1005 if ($search_user) {
1006  $param .= '&search_user='.urlencode($search_user);
1007 }
1008 if ($idproduct > 0) {
1009  $param .= '&idproduct='.urlencode($idproduct);
1010 }
1011 // Add $param from extra fields
1012 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
1013 // Add $param from hooks
1014 $parameters = array();
1015 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1016 $param .= $hookmanager->resPrint;
1017 
1018 // List of mass actions available
1019 $arrayofmassactions = array();
1020 if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
1021  $arrayofmassactions['builddoc'] = img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("GeneratePDF");
1022 }
1023 // By default, we should never accept deletion of stock movement
1024 if (!empty($conf->global->STOCK_ALLOW_DELETE_OF_MOVEMENT) && $permissiontodelete) {
1025  $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
1026 }
1027 if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) {
1028  $arrayofmassactions = array();
1029 }
1030 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
1031 
1032 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
1033 if ($optioncss != '') {
1034  print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
1035 }
1036 print '<input type="hidden" name="token" value="'.newToken().'">';
1037 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
1038 print '<input type="hidden" name="action" value="list">';
1039 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
1040 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
1041 print '<input type="hidden" name="type" value="'.$type.'">';
1042 print '<input type="hidden" name="page" value="'.$page.'">';
1043 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
1044 print '<input type="hidden" name="page_y" value="">';
1045 print '<input type="hidden" name="mode" value="'.$mode.'">';
1046 if ($id > 0) {
1047  print '<input type="hidden" name="id" value="'.$id.'">';
1048 }
1049 
1050 
1051 $newcardbutton = '';
1052 
1053 if ($id > 0) {
1054  print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1);
1055 } else {
1056  print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1);
1057 }
1058 
1059 // Add code for pre mass action (confirmation or email presend form)
1060 $topicmail = "SendStockMovement";
1061 $modelmail = "movementstock";
1062 $objecttmp = new MouvementStock($db);
1063 $trackid = 'mov'.$object->id;
1064 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
1065 
1066 if ($search_all) {
1067  $setupstring = '';
1068  foreach ($fieldstosearchall as $key => $val) {
1069  $fieldstosearchall[$key] = $langs->trans($val);
1070  $setupstring .= $key."=".$val.";";
1071  }
1072  print '<!-- Search done like if STOCK_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
1073  print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>'."\n";
1074 }
1075 
1076 $moreforfilter = '';
1077 
1078 $parameters = array('arrayfields'=>&$arrayfields);
1079 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1080 if (empty($reshook)) {
1081  $moreforfilter .= $hookmanager->resPrint;
1082 } else {
1083  $moreforfilter = $hookmanager->resPrint;
1084 }
1085 
1086 if (!empty($moreforfilter)) {
1087  print '<div class="liste_titre liste_titre_bydiv centpercent">';
1088  print $moreforfilter;
1089  print '</div>';
1090 }
1091 
1092 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1093 $selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields
1094 $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
1095 
1096 print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
1097 print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
1098 
1099 // Fields title search
1100 // --------------------------------------------------------------------
1101 print '<tr class="liste_titre">';
1102 // Action column
1103 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1104  print '<td class="liste_titre center maxwidthsearch">';
1105  $searchpicto = $form->showFilterButtons('left');
1106  print $searchpicto;
1107  print '</td>';
1108 }
1109 if (!empty($arrayfields['m.rowid']['checked'])) {
1110  // Ref
1111  print '<td class="liste_titre left">';
1112  print '<input class="flat maxwidth40" type="text" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
1113  print '</td>';
1114 }
1115 if (!empty($arrayfields['m.datem']['checked'])) {
1116  // Date
1117  print '<td class="liste_titre center">';
1118  print '<div class="nowrap">';
1119  print $form->selectDate($search_date_start?$search_date_start:-1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'), 'tzuserrel');
1120  print '</div>';
1121  print '<div class="nowrap">';
1122  print $form->selectDate($search_date_end?$search_date_end:-1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'), 'tzuserrel');
1123  print '</div>';
1124  print '</td>';
1125 }
1126 if (!empty($arrayfields['p.ref']['checked'])) {
1127  // Product Ref
1128  print '<td class="liste_titre left">';
1129  print '<input class="flat maxwidth75" type="text" name="search_product_ref" value="'.dol_escape_htmltag($idproduct ? $product->ref : $search_product_ref).'">';
1130  print '</td>';
1131 }
1132 if (!empty($arrayfields['p.label']['checked'])) {
1133  // Product label
1134  print '<td class="liste_titre left">';
1135  print '<input class="flat maxwidth100" type="text" name="search_product" value="'.dol_escape_htmltag($idproduct ? $product->label : $search_product).'">';
1136  print '</td>';
1137 }
1138 // Batch
1139 if (!empty($arrayfields['m.batch']['checked'])) {
1140  print '<td class="liste_titre center"><input class="flat maxwidth75" type="text" name="search_batch" value="'.dol_escape_htmltag($search_batch).'"></td>';
1141 }
1142 if (!empty($arrayfields['pl.eatby']['checked'])) {
1143  print '<td class="liste_titre left">';
1144  print '</td>';
1145 }
1146 if (!empty($arrayfields['pl.sellby']['checked'])) {
1147  print '<td class="liste_titre left">';
1148  print '</td>';
1149 }
1150 // Warehouse
1151 if (!empty($arrayfields['e.ref']['checked'])) {
1152  print '<td class="liste_titre maxwidthonsmartphone left">';
1153  //print '<input class="flat" type="text" size="8" name="search_warehouse" value="'.($search_warehouse).'">';
1154  print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200');
1155  print '</td>';
1156 }
1157 if (!empty($arrayfields['m.fk_user_author']['checked'])) {
1158  // Author
1159  print '<td class="liste_titre left">';
1160  print '<input class="flat" type="text" size="6" name="search_user" value="'.dol_escape_htmltag($search_user).'">';
1161  print '</td>';
1162 }
1163 if (!empty($arrayfields['m.inventorycode']['checked'])) {
1164  // Inventory code
1165  print '<td class="liste_titre left">';
1166  print '<input class="flat" type="text" size="4" name="search_inventorycode" value="'.dol_escape_htmltag($search_inventorycode).'">';
1167  print '</td>';
1168 }
1169 if (!empty($arrayfields['m.label']['checked'])) {
1170  // Label of movement
1171  print '<td class="liste_titre left">';
1172  print '<input class="flat" type="text" size="8" name="search_movement" value="'.dol_escape_htmltag($search_movement).'">';
1173  print '</td>';
1174 }
1175 if (!empty($arrayfields['origin']['checked'])) {
1176  // Origin of movement
1177  print '<td class="liste_titre left">';
1178  print '&nbsp; ';
1179  print '</td>';
1180 }
1181 if (!empty($arrayfields['m.fk_projet']['checked'])) {
1182  // fk_project
1183  print '<td class="liste_titre" align="left">';
1184  print '&nbsp; ';
1185  print '</td>';
1186 }
1187 if (!empty($arrayfields['m.type_mouvement']['checked'])) {
1188  // Type of movement
1189  print '<td class="liste_titre center">';
1190  //print '<input class="flat" type="text" size="3" name="search_type_mouvement" value="'.dol_escape_htmltag($search_type_mouvement).'">';
1191  print '<select id="search_type_mouvement" name="search_type_mouvement" class="maxwidth150">';
1192  print '<option value="" '.(($search_type_mouvement == "") ? 'selected="selected"' : '').'>&nbsp;</option>';
1193  print '<option value="0" '.(($search_type_mouvement == "0") ? 'selected="selected"' : '').'>'.$langs->trans('StockIncreaseAfterCorrectTransfer').'</option>';
1194  print '<option value="1" '.(($search_type_mouvement == "1") ? 'selected="selected"' : '').'>'.$langs->trans('StockDecreaseAfterCorrectTransfer').'</option>';
1195  print '<option value="2" '.(($search_type_mouvement == "2") ? 'selected="selected"' : '').'>'.$langs->trans('StockDecrease').'</option>';
1196  print '<option value="3" '.(($search_type_mouvement == "3") ? 'selected="selected"' : '').'>'.$langs->trans('StockIncrease').'</option>';
1197  print '</select>';
1198  print ajax_combobox('search_type_mouvement');
1199  // TODO: add new function $formentrepot->selectTypeOfMovement(...) like
1200  // print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200');
1201  print '</td>';
1202 }
1203 if (!empty($arrayfields['m.value']['checked'])) {
1204  // Qty
1205  print '<td class="liste_titre right">';
1206  print '<input class="flat" type="text" size="4" name="search_qty" value="'.dol_escape_htmltag($search_qty).'">';
1207  print '</td>';
1208 }
1209 if (!empty($arrayfields['m.price']['checked'])) {
1210  // Price
1211  print '<td class="liste_titre" align="left">';
1212  print '&nbsp; ';
1213  print '</td>';
1214 }
1215 
1216 // Extra fields
1217 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1218 
1219 // Fields from hook
1220 $parameters = array('arrayfields'=>$arrayfields);
1221 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1222 print $hookmanager->resPrint;
1223 // Date creation
1224 if (!empty($arrayfields['m.datec']['checked'])) {
1225  print '<td class="liste_titre">';
1226  print '</td>';
1227 }
1228 // Date modification
1229 if (!empty($arrayfields['m.tms']['checked'])) {
1230  print '<td class="liste_titre">';
1231  print '</td>';
1232 }
1233 // Action column
1234 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1235  print '<td class="liste_titre center maxwidthsearch">';
1236  $searchpicto = $form->showFilterButtons();
1237  print $searchpicto;
1238  print '</td>';
1239 }
1240 print '</tr>'."\n";
1241 
1242 $totalarray = array();
1243 $totalarray['nbfield'] = 0;
1244 
1245 // Fields title label
1246 // --------------------------------------------------------------------
1247 print '<tr class="liste_titre">';
1248 // Action column
1249 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1250  print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1251  $totalarray['nbfield']++;
1252 }
1253 if (!empty($arrayfields['m.rowid']['checked'])) {
1254  print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder);
1255 }
1256 if (!empty($arrayfields['m.datem']['checked'])) {
1257  print_liste_field_titre($arrayfields['m.datem']['label'], $_SERVER["PHP_SELF"], 'm.datem', '', $param, '', $sortfield, $sortorder, 'center ');
1258 }
1259 if (!empty($arrayfields['p.ref']['checked'])) {
1260  print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], 'p.ref', '', $param, '', $sortfield, $sortorder);
1261 }
1262 if (!empty($arrayfields['p.label']['checked'])) {
1263  print_liste_field_titre($arrayfields['p.label']['label'], $_SERVER["PHP_SELF"], 'p.label', '', $param, '', $sortfield, $sortorder);
1264 }
1265 if (!empty($arrayfields['m.batch']['checked'])) {
1266  print_liste_field_titre($arrayfields['m.batch']['label'], $_SERVER["PHP_SELF"], 'm.batch', '', $param, '', $sortfield, $sortorder, 'center ');
1267 }
1268 if (!empty($arrayfields['pl.eatby']['checked'])) {
1269  print_liste_field_titre($arrayfields['pl.eatby']['label'], $_SERVER["PHP_SELF"], 'pl.eatby', '', $param, '', $sortfield, $sortorder, 'center ');
1270 }
1271 if (!empty($arrayfields['pl.sellby']['checked'])) {
1272  print_liste_field_titre($arrayfields['pl.sellby']['label'], $_SERVER["PHP_SELF"], 'pl.sellby', '', $param, '', $sortfield, $sortorder, 'center ');
1273 }
1274 if (!empty($arrayfields['e.ref']['checked'])) {
1275  // We are on a specific warehouse card, no filter on other should be possible
1276  print_liste_field_titre($arrayfields['e.ref']['label'], $_SERVER["PHP_SELF"], "e.ref", "", $param, "", $sortfield, $sortorder);
1277 }
1278 if (!empty($arrayfields['m.fk_user_author']['checked'])) {
1279  print_liste_field_titre($arrayfields['m.fk_user_author']['label'], $_SERVER["PHP_SELF"], "m.fk_user_author", "", $param, "", $sortfield, $sortorder);
1280 }
1281 if (!empty($arrayfields['m.inventorycode']['checked'])) {
1282  print_liste_field_titre($arrayfields['m.inventorycode']['label'], $_SERVER["PHP_SELF"], "m.inventorycode", "", $param, "", $sortfield, $sortorder);
1283 }
1284 if (!empty($arrayfields['m.label']['checked'])) {
1285  print_liste_field_titre($arrayfields['m.label']['label'], $_SERVER["PHP_SELF"], "m.label", "", $param, "", $sortfield, $sortorder);
1286 }
1287 if (!empty($arrayfields['origin']['checked'])) {
1288  print_liste_field_titre($arrayfields['origin']['label'], $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder);
1289 }
1290 if (!empty($arrayfields['m.fk_projet']['checked'])) {
1291  print_liste_field_titre($arrayfields['m.fk_projet']['label'], $_SERVER["PHP_SELF"], "m.fk_projet", "", $param, '', $sortfield, $sortorder);
1292 }
1293 if (!empty($arrayfields['m.type_mouvement']['checked'])) {
1294  print_liste_field_titre($arrayfields['m.type_mouvement']['label'], $_SERVER["PHP_SELF"], "m.type_mouvement", "", $param, '', $sortfield, $sortorder, 'center ');
1295 }
1296 if (!empty($arrayfields['m.value']['checked'])) {
1297  print_liste_field_titre($arrayfields['m.value']['label'], $_SERVER["PHP_SELF"], "m.value", "", $param, '', $sortfield, $sortorder, 'right ');
1298 }
1299 if (!empty($arrayfields['m.price']['checked'])) {
1300  print_liste_field_titre($arrayfields['m.price']['label'], $_SERVER["PHP_SELF"], "m.price", "", $param, '', $sortfield, $sortorder, 'right ');
1301 }
1302 
1303 // Extra fields
1304 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1305 
1306 // Hook fields
1307 $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray);
1308 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1309 print $hookmanager->resPrint;
1310 if (!empty($arrayfields['m.datec']['checked'])) {
1311  print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1312 }
1313 if (!empty($arrayfields['m.tms']['checked'])) {
1314  print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1315 }
1316 // Action column
1317 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1318  print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1319  $totalarray['nbfield']++;
1320 }
1321 print '</tr>'."\n";
1322 
1323 
1324 $arrayofuniqueproduct = array();
1325 
1326 
1327 // Loop on record
1328 // --------------------------------------------------------------------
1329 $i = 0;
1330 $savnbfield = $totalarray['nbfield'];
1331 $totalarray = array();
1332 $totalarray['nbfield'] = 0;
1333 $imaxinloop = ($limit ? min($num, $limit) : $num);
1334 while ($i < $imaxinloop) {
1335  $obj = $db->fetch_object($resql);
1336  if (empty($obj)) {
1337  break; // Should not happen
1338  }
1339 
1340  $userstatic->id = $obj->fk_user_author;
1341  $userstatic->login = $obj->login;
1342  $userstatic->lastname = $obj->lastname;
1343  $userstatic->firstname = $obj->firstname;
1344  $userstatic->photo = $obj->photo;
1345  $userstatic->email = $obj->user_email;
1346  $userstatic->statut = $obj->user_status;
1347 
1348  // Multilangs
1349  if (getDolGlobalInt('MAIN_MULTILANGS')) { // If multilang is enabled
1350  // TODO Use a cache
1351  $sql = "SELECT label";
1352  $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
1353  $sql .= " WHERE fk_product = ".((int) $obj->rowid);
1354  $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
1355  $sql .= " LIMIT 1";
1356 
1357  $result = $db->query($sql);
1358  if ($result) {
1359  $objtp = $db->fetch_object($result);
1360  if (!empty($objtp->label)) {
1361  $obj->produit = $objtp->label;
1362  }
1363  }
1364  }
1365 
1366  $productstatic->id = $obj->rowid;
1367  $productstatic->ref = $obj->product_ref;
1368  $productstatic->label = $obj->produit;
1369  $productstatic->type = $obj->type;
1370  $productstatic->entity = $obj->entity;
1371  $productstatic->status = $obj->tosell;
1372  $productstatic->status_buy = $obj->tobuy;
1373  $productstatic->status_batch = $obj->tobatch;
1374 
1375  $productlot->id = $obj->lotid;
1376  $productlot->batch = $obj->batch;
1377  $productlot->eatby = $obj->eatby;
1378  $productlot->sellby = $obj->sellby;
1379 
1380  $warehousestatic->id = $obj->entrepot_id;
1381  $warehousestatic->ref = $obj->warehouse_ref;
1382  $warehousestatic->label = $obj->warehouse_ref;
1383  $warehousestatic->lieu = $obj->lieu;
1384  $warehousestatic->fk_parent = $obj->fk_parent;
1385  $warehousestatic->statut = $obj->statut;
1386 
1387  $movement->type = $obj->type_mouvement;
1388 
1389  $arrayofuniqueproduct[$obj->rowid] = $obj->produit;
1390  if (!empty($obj->fk_origin)) {
1391  $origin = $movement->get_origin($obj->fk_origin, $obj->origintype);
1392  } else {
1393  $origin = '';
1394  }
1395 
1396  if ($mode == 'kanban') {
1397  if ($i == 0) {
1398  print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1399  print '<div class="box-flex-container kanban">';
1400  }
1401  // Output Kanban
1402  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1403  $selected = 0;
1404  if (in_array($object->id, $arrayofselected)) {
1405  $selected = 1;
1406  }
1407  }
1408  print $object->getKanbanView('', array('selected' => in_array($warehousestatic->id, $arrayofselected)));
1409  if ($i == ($imaxinloop - 1)) {
1410  print '</div>';
1411  print '</td></tr>';
1412  }
1413  } else {
1414  // Show here line of result
1415  $j = 0;
1416  print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1417  // Action column
1418  if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1419  print '<td class="nowrap center">';
1420  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1421  $selected = 0;
1422  if (in_array($obj->mid, $arrayofselected)) {
1423  $selected = 1;
1424  }
1425  print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
1426  }
1427  print '</td>';
1428  if (!$i) {
1429  $totalarray['nbfield']++;
1430  }
1431  }
1432  // Id movement
1433  if (!empty($arrayfields['m.rowid']['checked'])) {
1434  print '<td class="nowraponall">';
1435  print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
1436  print $obj->mid;
1437  print '</td>'; // This is primary not movement id
1438  }
1439  if (!empty($arrayfields['m.datem']['checked'])) {
1440  // Date
1441  print '<td class="nowraponall center">'.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').'</td>';
1442  }
1443  if (!empty($arrayfields['p.ref']['checked'])) {
1444  // Product ref
1445  print '<td class="nowraponall">';
1446  print $productstatic->getNomUrl(1, 'stock', 16);
1447  print "</td>\n";
1448  }
1449  if (!empty($arrayfields['p.label']['checked'])) {
1450  // Product label
1451  print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($productstatic->label).'">';
1452  print $productstatic->label;
1453  print "</td>\n";
1454  }
1455  if (!empty($arrayfields['m.batch']['checked'])) {
1456  print '<td class="center nowraponall">';
1457  if ($productlot->id > 0) {
1458  print $productlot->getNomUrl(1);
1459  } else {
1460  print $productlot->batch; // the id may not be defined if movement was entered when lot was not saved or if lot was removed after movement.
1461  }
1462  print '</td>';
1463  }
1464  if (!empty($arrayfields['pl.eatby']['checked'])) {
1465  print '<td class="center">'.dol_print_date($obj->eatby, 'day').'</td>';
1466  }
1467  if (!empty($arrayfields['pl.sellby']['checked'])) {
1468  print '<td class="center">'.dol_print_date($obj->sellby, 'day').'</td>';
1469  }
1470  // Warehouse
1471  if (!empty($arrayfields['e.ref']['checked'])) {
1472  print '<td class="tdoverflowmax100">';
1473  print $warehousestatic->getNomUrl(1);
1474  print "</td>\n";
1475  }
1476  // Author
1477  if (!empty($arrayfields['m.fk_user_author']['checked'])) {
1478  print '<td class="tdoverflowmax100">';
1479  print $userstatic->getNomUrl(-1);
1480  print "</td>\n";
1481  }
1482  if (!empty($arrayfields['m.inventorycode']['checked'])) {
1483  // Inventory code
1484  print '<td><a href="'.$_SERVER["PHP_SELF"].'?search_inventorycode='.urlencode('^'.$obj->inventorycode.'$').'">'.dol_escape_htmltag($obj->inventorycode).'</a></td>';
1485  }
1486  if (!empty($arrayfields['m.label']['checked'])) {
1487  // Label of movement
1488  print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($obj->label).'">'.dol_escape_htmltag($obj->label).'</td>';
1489  }
1490  if (!empty($arrayfields['origin']['checked'])) {
1491  // Origin of movement
1492  print '<td class="nowraponall">'.$origin.'</td>';
1493  }
1494  if (!empty($arrayfields['m.fk_projet']['checked'])) {
1495  // fk_project
1496  print '<td>';
1497  if ($obj->fk_project != 0) {
1498  print $movement->get_origin($obj->fk_project, 'project');
1499  }
1500  print '</td>';
1501  }
1502  if (!empty($arrayfields['m.type_mouvement']['checked'])) {
1503  // Type of movement
1504  print '<td class="center">';
1505  print $movement->getTypeMovement();
1506  print '</td>';
1507  }
1508  if (!empty($arrayfields['m.value']['checked'])) {
1509  // Qty
1510  print '<td class="right">';
1511  if ($obj->qty > 0) {
1512  print '<span class="stockmovemententry">';
1513  print '+';
1514  print $obj->qty;
1515  print '</span>';
1516  } else {
1517  print '<span class="stockmovementexit">';
1518  print $obj->qty;
1519  print '</span>';
1520  }
1521  print '</td>';
1522  }
1523  if (!empty($arrayfields['m.price']['checked'])) {
1524  // Price
1525  print '<td class="right">';
1526  if ($obj->price != 0) {
1527  print price($obj->price);
1528  }
1529  print '</td>';
1530  }
1531 
1532  // Extra fields
1533  $object = $movement;
1534  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1535  // Fields from hook
1536  $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
1537  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1538  print $hookmanager->resPrint;
1539 
1540  // Action column
1541  if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1542  print '<td class="nowrap center">';
1543  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1544  $selected = 0;
1545  if (in_array($obj->mid, $arrayofselected)) {
1546  $selected = 1;
1547  }
1548  print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
1549  }
1550  print '</td>';
1551  if (!$i) {
1552  $totalarray['nbfield']++;
1553  }
1554  }
1555 
1556  print '</tr>'."\n";
1557  }
1558 
1559  $i++;
1560 }
1561 
1562 // If no record found
1563 if ($num == 0) {
1564  $colspan = 1;
1565  foreach ($arrayfields as $key => $val) {
1566  if (!empty($val['checked'])) {
1567  $colspan++;
1568  }
1569  }
1570  print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1571 }
1572 
1573 $db->free($resql);
1574 
1575 $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
1576 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1577 print $hookmanager->resPrint;
1578 
1579 print '</table>'."\n";
1580 print '</div>'."\n";
1581 
1582 print '</form>'."\n";
1583 
1584 // Add number of product when there is a filter on period
1585 if (count($arrayofuniqueproduct) == 1 && !empty($year) && is_numeric($year)) {
1586  print "<br>";
1587 
1588  $productidselected = 0;
1589  foreach ($arrayofuniqueproduct as $key => $val) {
1590  $productidselected = $key;
1591  $productlabelselected = $val;
1592  }
1593  $datebefore = dol_get_first_day($year ? $year : strftime("%Y", time()), $month ? $month : 1, true);
1594  $dateafter = dol_get_last_day($year ? $year : strftime("%Y", time()), $month ? $month : 12, true);
1595  $balancebefore = $movement->calculateBalanceForProductBefore($productidselected, $datebefore);
1596  $balanceafter = $movement->calculateBalanceForProductBefore($productidselected, $dateafter);
1597 
1598  //print '<tr class="total"><td class="liste_total">';
1599  print $langs->trans("NbOfProductBeforePeriod", $productlabelselected, dol_print_date($datebefore, 'day', 'gmt'));
1600  //print '</td>';
1601  //print '<td class="liste_total right" colspan="6">';
1602  print ': '.$balancebefore;
1603  print "<br>\n";
1604  //print '</td></tr>';
1605  //print '<tr class="total"><td class="liste_total">';
1606  print $langs->trans("NbOfProductAfterPeriod", $productlabelselected, dol_print_date($dateafter, 'day', 'gmt'));
1607  //print '</td>';
1608  //print '<td class="liste_total right" colspan="6">';
1609  print ': '.$balanceafter;
1610  print "<br>\n";
1611  //print '</td></tr>';
1612 }
1613 
1614 if (in_array('builddoc', array_keys($arrayofmassactions)) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
1615  $hidegeneratedfilelistifempty = 1;
1616  if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
1617  $hidegeneratedfilelistifempty = 0;
1618  }
1619 
1620  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
1621  $formfile = new FormFile($db);
1622 
1623  // Show list of available documents
1624  $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
1625  $urlsource .= str_replace('&amp;', '&', $param);
1626 
1627  $filedir = $diroutputmassaction;
1628  $genallowed = $permissiontoread;
1629  $delallowed = $permissiontoadd;
1630 
1631  print $formfile->showdocuments('massfilesarea_'.$object->module, '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
1632 }
1633 
1634 // End of page
1635 llxFooter();
1636 $db->close();
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save" &&empty($cancel)) $help_url
View.
Definition: agenda.php:118
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:449
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
Class to manage warehouses.
Class to manage standard extra fields.
Class to offer components to list and upload files.
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 building of HTML components.
Class to manage stock movements.
Class to manage products or services.
Manage record for batch number management.
Class with list of lots and properties.
Class to manage projects.
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
if(isModEnabled('facture') && $user->hasRight('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') && $user->hasRight('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)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition: date.lib.php:577
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:596
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:62
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
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...
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.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
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)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get 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.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
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.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
stock_prepare_head($object)
Prepare array with list of tabs.
Definition: stock.lib.php:30