dolibarr  19.0.0-dev
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_project=GETPOST("search_fk_project", '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_project = "";
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_project) && $search_fk_project != '-1') {
694  $sql .= natural_search('m.fk_projet', $search_fk_project);
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 if ($search_fk_project != '' && $search_fk_project != '-1') {
1012  $param .= '&search_fk_project='.urlencode($search_fk_project);
1013 }
1014 // Add $param from extra fields
1015 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
1016 // Add $param from hooks
1017 $parameters = array();
1018 $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1019 $param .= $hookmanager->resPrint;
1020 
1021 // List of mass actions available
1022 $arrayofmassactions = array();
1023 if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
1024  $arrayofmassactions['builddoc'] = img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("GeneratePDF");
1025 }
1026 // By default, we should never accept deletion of stock movement
1027 if (!empty($conf->global->STOCK_ALLOW_DELETE_OF_MOVEMENT) && $permissiontodelete) {
1028  $arrayofmassactions['predelete'] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("Delete");
1029 }
1030 if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) {
1031  $arrayofmassactions = array();
1032 }
1033 $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
1034 
1035 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'."\n";
1036 if ($optioncss != '') {
1037  print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
1038 }
1039 print '<input type="hidden" name="token" value="'.newToken().'">';
1040 print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
1041 print '<input type="hidden" name="action" value="list">';
1042 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
1043 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
1044 print '<input type="hidden" name="type" value="'.$type.'">';
1045 print '<input type="hidden" name="page" value="'.$page.'">';
1046 print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
1047 print '<input type="hidden" name="page_y" value="">';
1048 print '<input type="hidden" name="mode" value="'.$mode.'">';
1049 if ($id > 0) {
1050  print '<input type="hidden" name="id" value="'.$id.'">';
1051 }
1052 
1053 
1054 $newcardbutton = '';
1055 
1056 if ($id > 0) {
1057  print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1);
1058 } else {
1059  print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1);
1060 }
1061 
1062 // Add code for pre mass action (confirmation or email presend form)
1063 $topicmail = "SendStockMovement";
1064 $modelmail = "movementstock";
1065 $objecttmp = new MouvementStock($db);
1066 $trackid = 'mov'.$object->id;
1067 include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
1068 
1069 if ($search_all) {
1070  $setupstring = '';
1071  foreach ($fieldstosearchall as $key => $val) {
1072  $fieldstosearchall[$key] = $langs->trans($val);
1073  $setupstring .= $key."=".$val.";";
1074  }
1075  print '<!-- Search done like if STOCK_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
1076  print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>'."\n";
1077 }
1078 
1079 $moreforfilter = '';
1080 
1081 $parameters = array('arrayfields'=>&$arrayfields);
1082 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1083 if (empty($reshook)) {
1084  $moreforfilter .= $hookmanager->resPrint;
1085 } else {
1086  $moreforfilter = $hookmanager->resPrint;
1087 }
1088 
1089 if (!empty($moreforfilter)) {
1090  print '<div class="liste_titre liste_titre_bydiv centpercent">';
1091  print $moreforfilter;
1092  print '</div>';
1093 }
1094 
1095 $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
1096 $selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields
1097 $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
1098 
1099 print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
1100 print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
1101 
1102 // Fields title search
1103 // --------------------------------------------------------------------
1104 print '<tr class="liste_titre">';
1105 // Action column
1106 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1107  print '<td class="liste_titre center maxwidthsearch">';
1108  $searchpicto = $form->showFilterButtons('left');
1109  print $searchpicto;
1110  print '</td>';
1111 }
1112 if (!empty($arrayfields['m.rowid']['checked'])) {
1113  // Ref
1114  print '<td class="liste_titre left">';
1115  print '<input class="flat maxwidth25" type="text" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
1116  print '</td>';
1117 }
1118 if (!empty($arrayfields['m.datem']['checked'])) {
1119  // Date
1120  print '<td class="liste_titre center">';
1121  print '<div class="nowrap">';
1122  print $form->selectDate($search_date_start?$search_date_start:-1, 'search_date_start', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('From'), 'tzuserrel');
1123  print '</div>';
1124  print '<div class="nowrap">';
1125  print $form->selectDate($search_date_end?$search_date_end:-1, 'search_date_end', 0, 0, 1, '', 1, 0, 0, '', '', '', '', 1, '', $langs->trans('to'), 'tzuserrel');
1126  print '</div>';
1127  print '</td>';
1128 }
1129 if (!empty($arrayfields['p.ref']['checked'])) {
1130  // Product Ref
1131  print '<td class="liste_titre left">';
1132  print '<input class="flat maxwidth75" type="text" name="search_product_ref" value="'.dol_escape_htmltag($idproduct ? $product->ref : $search_product_ref).'">';
1133  print '</td>';
1134 }
1135 if (!empty($arrayfields['p.label']['checked'])) {
1136  // Product label
1137  print '<td class="liste_titre left">';
1138  print '<input class="flat maxwidth100" type="text" name="search_product" value="'.dol_escape_htmltag($idproduct ? $product->label : $search_product).'">';
1139  print '</td>';
1140 }
1141 // Batch
1142 if (!empty($arrayfields['m.batch']['checked'])) {
1143  print '<td class="liste_titre center"><input class="flat maxwidth75" type="text" name="search_batch" value="'.dol_escape_htmltag($search_batch).'"></td>';
1144 }
1145 if (!empty($arrayfields['pl.eatby']['checked'])) {
1146  print '<td class="liste_titre left">';
1147  print '</td>';
1148 }
1149 if (!empty($arrayfields['pl.sellby']['checked'])) {
1150  print '<td class="liste_titre left">';
1151  print '</td>';
1152 }
1153 // Warehouse
1154 if (!empty($arrayfields['e.ref']['checked'])) {
1155  print '<td class="liste_titre maxwidthonsmartphone left">';
1156  //print '<input class="flat" type="text" size="8" name="search_warehouse" value="'.($search_warehouse).'">';
1157  print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200');
1158  print '</td>';
1159 }
1160 if (!empty($arrayfields['m.fk_user_author']['checked'])) {
1161  // Author
1162  print '<td class="liste_titre left">';
1163  print '<input class="flat" type="text" size="6" name="search_user" value="'.dol_escape_htmltag($search_user).'">';
1164  print '</td>';
1165 }
1166 if (!empty($arrayfields['m.inventorycode']['checked'])) {
1167  // Inventory code
1168  print '<td class="liste_titre left">';
1169  print '<input class="flat" type="text" size="4" name="search_inventorycode" value="'.dol_escape_htmltag($search_inventorycode).'">';
1170  print '</td>';
1171 }
1172 if (!empty($arrayfields['m.label']['checked'])) {
1173  // Label of movement
1174  print '<td class="liste_titre left">';
1175  print '<input class="flat" type="text" size="8" name="search_movement" value="'.dol_escape_htmltag($search_movement).'">';
1176  print '</td>';
1177 }
1178 if (!empty($arrayfields['origin']['checked'])) {
1179  // Origin of movement
1180  print '<td class="liste_titre left">';
1181  print '&nbsp; ';
1182  print '</td>';
1183 }
1184 if (!empty($arrayfields['m.fk_projet']['checked'])) {
1185  // fk_project
1186  print '<td class="liste_titre" align="left">';
1187  print $object->showInputField($object->fields['fk_project'], 'fk_project', $search_fk_project, '', '', 'search_', 'maxwidth125', 1);
1188  print '</td>';
1189 }
1190 if (!empty($arrayfields['m.type_mouvement']['checked'])) {
1191  // Type of movement
1192  print '<td class="liste_titre center">';
1193  //print '<input class="flat" type="text" size="3" name="search_type_mouvement" value="'.dol_escape_htmltag($search_type_mouvement).'">';
1194  print '<select id="search_type_mouvement" name="search_type_mouvement" class="maxwidth150">';
1195  print '<option value="" '.(($search_type_mouvement == "") ? 'selected="selected"' : '').'>&nbsp;</option>';
1196  print '<option value="0" '.(($search_type_mouvement == "0") ? 'selected="selected"' : '').'>'.$langs->trans('StockIncreaseAfterCorrectTransfer').'</option>';
1197  print '<option value="1" '.(($search_type_mouvement == "1") ? 'selected="selected"' : '').'>'.$langs->trans('StockDecreaseAfterCorrectTransfer').'</option>';
1198  print '<option value="2" '.(($search_type_mouvement == "2") ? 'selected="selected"' : '').'>'.$langs->trans('StockDecrease').'</option>';
1199  print '<option value="3" '.(($search_type_mouvement == "3") ? 'selected="selected"' : '').'>'.$langs->trans('StockIncrease').'</option>';
1200  print '</select>';
1201  print ajax_combobox('search_type_mouvement');
1202  // TODO: add new function $formentrepot->selectTypeOfMovement(...) like
1203  // print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200');
1204  print '</td>';
1205 }
1206 if (!empty($arrayfields['m.value']['checked'])) {
1207  // Qty
1208  print '<td class="liste_titre right">';
1209  print '<input class="flat" type="text" size="4" name="search_qty" value="'.dol_escape_htmltag($search_qty).'">';
1210  print '</td>';
1211 }
1212 if (!empty($arrayfields['m.price']['checked'])) {
1213  // Price
1214  print '<td class="liste_titre" align="left">';
1215  print '&nbsp; ';
1216  print '</td>';
1217 }
1218 
1219 // Extra fields
1220 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
1221 
1222 // Fields from hook
1223 $parameters = array('arrayfields'=>$arrayfields);
1224 $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1225 print $hookmanager->resPrint;
1226 // Date creation
1227 if (!empty($arrayfields['m.datec']['checked'])) {
1228  print '<td class="liste_titre">';
1229  print '</td>';
1230 }
1231 // Date modification
1232 if (!empty($arrayfields['m.tms']['checked'])) {
1233  print '<td class="liste_titre">';
1234  print '</td>';
1235 }
1236 // Action column
1237 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1238  print '<td class="liste_titre center maxwidthsearch">';
1239  $searchpicto = $form->showFilterButtons();
1240  print $searchpicto;
1241  print '</td>';
1242 }
1243 print '</tr>'."\n";
1244 
1245 $totalarray = array();
1246 $totalarray['nbfield'] = 0;
1247 
1248 // Fields title label
1249 // --------------------------------------------------------------------
1250 print '<tr class="liste_titre">';
1251 // Action column
1252 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1253  print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1254  $totalarray['nbfield']++;
1255 }
1256 if (!empty($arrayfields['m.rowid']['checked'])) {
1257  print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder);
1258 }
1259 if (!empty($arrayfields['m.datem']['checked'])) {
1260  print_liste_field_titre($arrayfields['m.datem']['label'], $_SERVER["PHP_SELF"], 'm.datem', '', $param, '', $sortfield, $sortorder, 'center ');
1261 }
1262 if (!empty($arrayfields['p.ref']['checked'])) {
1263  print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], 'p.ref', '', $param, '', $sortfield, $sortorder);
1264 }
1265 if (!empty($arrayfields['p.label']['checked'])) {
1266  print_liste_field_titre($arrayfields['p.label']['label'], $_SERVER["PHP_SELF"], 'p.label', '', $param, '', $sortfield, $sortorder);
1267 }
1268 if (!empty($arrayfields['m.batch']['checked'])) {
1269  print_liste_field_titre($arrayfields['m.batch']['label'], $_SERVER["PHP_SELF"], 'm.batch', '', $param, '', $sortfield, $sortorder, 'center ');
1270 }
1271 if (!empty($arrayfields['pl.eatby']['checked'])) {
1272  print_liste_field_titre($arrayfields['pl.eatby']['label'], $_SERVER["PHP_SELF"], 'pl.eatby', '', $param, '', $sortfield, $sortorder, 'center ');
1273 }
1274 if (!empty($arrayfields['pl.sellby']['checked'])) {
1275  print_liste_field_titre($arrayfields['pl.sellby']['label'], $_SERVER["PHP_SELF"], 'pl.sellby', '', $param, '', $sortfield, $sortorder, 'center ');
1276 }
1277 if (!empty($arrayfields['e.ref']['checked'])) {
1278  // We are on a specific warehouse card, no filter on other should be possible
1279  print_liste_field_titre($arrayfields['e.ref']['label'], $_SERVER["PHP_SELF"], "e.ref", "", $param, "", $sortfield, $sortorder);
1280 }
1281 if (!empty($arrayfields['m.fk_user_author']['checked'])) {
1282  print_liste_field_titre($arrayfields['m.fk_user_author']['label'], $_SERVER["PHP_SELF"], "m.fk_user_author", "", $param, "", $sortfield, $sortorder);
1283 }
1284 if (!empty($arrayfields['m.inventorycode']['checked'])) {
1285  print_liste_field_titre($arrayfields['m.inventorycode']['label'], $_SERVER["PHP_SELF"], "m.inventorycode", "", $param, "", $sortfield, $sortorder);
1286 }
1287 if (!empty($arrayfields['m.label']['checked'])) {
1288  print_liste_field_titre($arrayfields['m.label']['label'], $_SERVER["PHP_SELF"], "m.label", "", $param, "", $sortfield, $sortorder);
1289 }
1290 if (!empty($arrayfields['origin']['checked'])) {
1291  print_liste_field_titre($arrayfields['origin']['label'], $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder);
1292 }
1293 if (!empty($arrayfields['m.fk_projet']['checked'])) {
1294  print_liste_field_titre($arrayfields['m.fk_projet']['label'], $_SERVER["PHP_SELF"], "m.fk_projet", "", $param, '', $sortfield, $sortorder);
1295 }
1296 if (!empty($arrayfields['m.type_mouvement']['checked'])) {
1297  print_liste_field_titre($arrayfields['m.type_mouvement']['label'], $_SERVER["PHP_SELF"], "m.type_mouvement", "", $param, '', $sortfield, $sortorder, 'center ');
1298 }
1299 if (!empty($arrayfields['m.value']['checked'])) {
1300  print_liste_field_titre($arrayfields['m.value']['label'], $_SERVER["PHP_SELF"], "m.value", "", $param, '', $sortfield, $sortorder, 'right ');
1301 }
1302 if (!empty($arrayfields['m.price']['checked'])) {
1303  print_liste_field_titre($arrayfields['m.price']['label'], $_SERVER["PHP_SELF"], "m.price", "", $param, '', $sortfield, $sortorder, 'right ');
1304 }
1305 
1306 // Extra fields
1307 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
1308 
1309 // Hook fields
1310 $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray);
1311 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1312 print $hookmanager->resPrint;
1313 if (!empty($arrayfields['m.datec']['checked'])) {
1314  print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1315 }
1316 if (!empty($arrayfields['m.tms']['checked'])) {
1317  print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
1318 }
1319 // Action column
1320 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1321  print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
1322  $totalarray['nbfield']++;
1323 }
1324 print '</tr>'."\n";
1325 
1326 
1327 $arrayofuniqueproduct = array();
1328 
1329 
1330 // Loop on record
1331 // --------------------------------------------------------------------
1332 $i = 0;
1333 $savnbfield = $totalarray['nbfield'];
1334 $totalarray = array();
1335 $totalarray['nbfield'] = 0;
1336 $imaxinloop = ($limit ? min($num, $limit) : $num);
1337 while ($i < $imaxinloop) {
1338  $obj = $db->fetch_object($resql);
1339  if (empty($obj)) {
1340  break; // Should not happen
1341  }
1342 
1343  $userstatic->id = $obj->fk_user_author;
1344  $userstatic->login = $obj->login;
1345  $userstatic->lastname = $obj->lastname;
1346  $userstatic->firstname = $obj->firstname;
1347  $userstatic->photo = $obj->photo;
1348  $userstatic->email = $obj->user_email;
1349  $userstatic->statut = $obj->user_status;
1350 
1351  // Multilangs
1352  if (getDolGlobalInt('MAIN_MULTILANGS')) { // If multilang is enabled
1353  // TODO Use a cache
1354  $sql = "SELECT label";
1355  $sql .= " FROM ".MAIN_DB_PREFIX."product_lang";
1356  $sql .= " WHERE fk_product = ".((int) $obj->rowid);
1357  $sql .= " AND lang = '".$db->escape($langs->getDefaultLang())."'";
1358  $sql .= " LIMIT 1";
1359 
1360  $result = $db->query($sql);
1361  if ($result) {
1362  $objtp = $db->fetch_object($result);
1363  if (!empty($objtp->label)) {
1364  $obj->produit = $objtp->label;
1365  }
1366  }
1367  }
1368 
1369  $productstatic->id = $obj->rowid;
1370  $productstatic->ref = $obj->product_ref;
1371  $productstatic->label = $obj->produit;
1372  $productstatic->type = $obj->type;
1373  $productstatic->entity = $obj->entity;
1374  $productstatic->status = $obj->tosell;
1375  $productstatic->status_buy = $obj->tobuy;
1376  $productstatic->status_batch = $obj->tobatch;
1377 
1378  $productlot->id = $obj->lotid;
1379  $productlot->batch = $obj->batch;
1380  $productlot->eatby = $obj->eatby;
1381  $productlot->sellby = $obj->sellby;
1382 
1383  $warehousestatic->id = $obj->entrepot_id;
1384  $warehousestatic->ref = $obj->warehouse_ref;
1385  $warehousestatic->label = $obj->warehouse_ref;
1386  $warehousestatic->lieu = $obj->lieu;
1387  $warehousestatic->fk_parent = $obj->fk_parent;
1388  $warehousestatic->statut = $obj->statut;
1389 
1390  $movement->type = $obj->type_mouvement;
1391 
1392  $arrayofuniqueproduct[$obj->rowid] = $obj->produit;
1393  if (!empty($obj->fk_origin)) {
1394  $origin = $movement->get_origin($obj->fk_origin, $obj->origintype);
1395  } else {
1396  $origin = '';
1397  }
1398 
1399  if ($mode == 'kanban') {
1400  if ($i == 0) {
1401  print '<tr class="trkanban"><td colspan="'.$savnbfield.'">';
1402  print '<div class="box-flex-container kanban">';
1403  }
1404  // Output Kanban
1405  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1406  $selected = 0;
1407  if (in_array($object->id, $arrayofselected)) {
1408  $selected = 1;
1409  }
1410  }
1411  print $object->getKanbanView('', array('selected' => in_array($warehousestatic->id, $arrayofselected)));
1412  if ($i == ($imaxinloop - 1)) {
1413  print '</div>';
1414  print '</td></tr>';
1415  }
1416  } else {
1417  // Show here line of result
1418  $j = 0;
1419  print '<tr data-rowid="'.$object->id.'" class="oddeven">';
1420  // Action column
1421  if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1422  print '<td class="nowrap center">';
1423  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1424  $selected = 0;
1425  if (in_array($obj->mid, $arrayofselected)) {
1426  $selected = 1;
1427  }
1428  print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
1429  }
1430  print '</td>';
1431  if (!$i) {
1432  $totalarray['nbfield']++;
1433  }
1434  }
1435  // Id movement
1436  if (!empty($arrayfields['m.rowid']['checked'])) {
1437  print '<td class="nowraponall">';
1438  print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
1439  print $obj->mid;
1440  print '</td>'; // This is primary not movement id
1441  }
1442  if (!empty($arrayfields['m.datem']['checked'])) {
1443  // Date
1444  print '<td class="nowraponall center">'.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').'</td>';
1445  }
1446  if (!empty($arrayfields['p.ref']['checked'])) {
1447  // Product ref
1448  print '<td class="nowraponall">';
1449  print $productstatic->getNomUrl(1, 'stock', 16);
1450  print "</td>\n";
1451  }
1452  if (!empty($arrayfields['p.label']['checked'])) {
1453  // Product label
1454  print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($productstatic->label).'">';
1455  print $productstatic->label;
1456  print "</td>\n";
1457  }
1458  if (!empty($arrayfields['m.batch']['checked'])) {
1459  print '<td class="center nowraponall">';
1460  if ($productlot->id > 0) {
1461  print $productlot->getNomUrl(1);
1462  } else {
1463  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.
1464  }
1465  print '</td>';
1466  }
1467  if (!empty($arrayfields['pl.eatby']['checked'])) {
1468  print '<td class="center">'.dol_print_date($obj->eatby, 'day').'</td>';
1469  }
1470  if (!empty($arrayfields['pl.sellby']['checked'])) {
1471  print '<td class="center">'.dol_print_date($obj->sellby, 'day').'</td>';
1472  }
1473  // Warehouse
1474  if (!empty($arrayfields['e.ref']['checked'])) {
1475  print '<td class="tdoverflowmax100">';
1476  print $warehousestatic->getNomUrl(1);
1477  print "</td>\n";
1478  }
1479  // Author
1480  if (!empty($arrayfields['m.fk_user_author']['checked'])) {
1481  print '<td class="tdoverflowmax100">';
1482  print $userstatic->getNomUrl(-1);
1483  print "</td>\n";
1484  }
1485  if (!empty($arrayfields['m.inventorycode']['checked'])) {
1486  // Inventory code
1487  print '<td><a href="'.$_SERVER["PHP_SELF"].'?search_inventorycode='.urlencode('^'.$obj->inventorycode.'$').'&search_type_mouvement='.urlencode($obj->type_mouvement).'">'.$obj->inventorycode.'</a></td>';
1488  }
1489  if (!empty($arrayfields['m.label']['checked'])) {
1490  // Label of movement
1491  print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($obj->label).'">'.$obj->label.'</td>';
1492  }
1493  if (!empty($arrayfields['origin']['checked'])) {
1494  // Origin of movement
1495  print '<td class="nowraponall">'.$origin.'</td>';
1496  }
1497  if (!empty($arrayfields['m.fk_projet']['checked'])) {
1498  // fk_project
1499  print '<td>';
1500  if ($obj->fk_project != 0) {
1501  print $movement->get_origin($obj->fk_project, 'project');
1502  }
1503  print '</td>';
1504  }
1505  if (!empty($arrayfields['m.type_mouvement']['checked'])) {
1506  // Type of movement
1507  print '<td class="center">';
1508  print $movement->getTypeMovement();
1509  print '</td>';
1510  }
1511  if (!empty($arrayfields['m.value']['checked'])) {
1512  // Qty
1513  print '<td class="right">';
1514  if ($obj->qty > 0) {
1515  print '<span class="stockmovemententry">';
1516  print '+';
1517  print $obj->qty;
1518  print '</span>';
1519  } else {
1520  print '<span class="stockmovementexit">';
1521  print $obj->qty;
1522  print '</span>';
1523  }
1524  print '</td>';
1525  }
1526  if (!empty($arrayfields['m.price']['checked'])) {
1527  // Price
1528  print '<td class="right">';
1529  if ($obj->price != 0) {
1530  print price($obj->price);
1531  }
1532  print '</td>';
1533  }
1534 
1535  // Extra fields
1536  $object = $movement;
1537  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
1538  // Fields from hook
1539  $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
1540  $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1541  print $hookmanager->resPrint;
1542 
1543  // Action column
1544  if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
1545  print '<td class="nowrap center">';
1546  if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1547  $selected = 0;
1548  if (in_array($obj->mid, $arrayofselected)) {
1549  $selected = 1;
1550  }
1551  print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
1552  }
1553  print '</td>';
1554  if (!$i) {
1555  $totalarray['nbfield']++;
1556  }
1557  }
1558 
1559  print '</tr>'."\n";
1560  }
1561 
1562  $i++;
1563 }
1564 
1565 // If no record found
1566 if ($num == 0) {
1567  $colspan = 1;
1568  foreach ($arrayfields as $key => $val) {
1569  if (!empty($val['checked'])) {
1570  $colspan++;
1571  }
1572  }
1573  print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
1574 }
1575 
1576 $db->free($resql);
1577 
1578 $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
1579 $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1580 print $hookmanager->resPrint;
1581 
1582 print '</table>'."\n";
1583 print '</div>'."\n";
1584 
1585 print '</form>'."\n";
1586 
1587 // Add number of product when there is a filter on period
1588 if (count($arrayofuniqueproduct) == 1 && !empty($year) && is_numeric($year)) {
1589  print "<br>";
1590 
1591  $productidselected = 0;
1592  foreach ($arrayofuniqueproduct as $key => $val) {
1593  $productidselected = $key;
1594  $productlabelselected = $val;
1595  }
1596  $datebefore = dol_get_first_day($year ? $year : strftime("%Y", time()), $month ? $month : 1, true);
1597  $dateafter = dol_get_last_day($year ? $year : strftime("%Y", time()), $month ? $month : 12, true);
1598  $balancebefore = $movement->calculateBalanceForProductBefore($productidselected, $datebefore);
1599  $balanceafter = $movement->calculateBalanceForProductBefore($productidselected, $dateafter);
1600 
1601  //print '<tr class="total"><td class="liste_total">';
1602  print $langs->trans("NbOfProductBeforePeriod", $productlabelselected, dol_print_date($datebefore, 'day', 'gmt'));
1603  //print '</td>';
1604  //print '<td class="liste_total right" colspan="6">';
1605  print ': '.$balancebefore;
1606  print "<br>\n";
1607  //print '</td></tr>';
1608  //print '<tr class="total"><td class="liste_total">';
1609  print $langs->trans("NbOfProductAfterPeriod", $productlabelselected, dol_print_date($dateafter, 'day', 'gmt'));
1610  //print '</td>';
1611  //print '<td class="liste_total right" colspan="6">';
1612  print ': '.$balanceafter;
1613  print "<br>\n";
1614  //print '</td></tr>';
1615 }
1616 
1617 if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $nbtotalofrecords)) {
1618  $hidegeneratedfilelistifempty = 1;
1619  if ($massaction == 'builddoc' || $action == 'remove_file' || $show_files) {
1620  $hidegeneratedfilelistifempty = 0;
1621  }
1622 
1623  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
1624  $formfile = new FormFile($db);
1625 
1626  // Show list of available documents
1627  $urlsource = $_SERVER['PHP_SELF'].'?sortfield='.$sortfield.'&sortorder='.$sortorder;
1628  $urlsource .= str_replace('&amp;', '&', $param);
1629 
1630  $filedir = $diroutputmassaction;
1631  $genallowed = $permissiontoread;
1632  $delallowed = $permissiontoadd;
1633 
1634  print $formfile->showdocuments('massfilesarea_'.$object->module, '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
1635 }
1636 
1637 // End of page
1638 llxFooter();
1639 $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:576
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition: date.lib.php:595
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)
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