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