dolibarr  13.0.2
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 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->projet->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)) $langs->load("productbatch");
49 
50 // Security check
51 $result = restrictedArea($user, 'stock');
52 
53 $id = GETPOST('id', 'int');
54 $ref = GETPOST('ref', 'alpha');
55 $msid = GETPOST('msid', 'int');
56 $product_id = GETPOST("product_id", 'int');
57 $action = GETPOST('action', 'aZ09');
58 $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
59 $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
60 $cancel = GETPOST('cancel', 'alpha');
61 $contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'movementlist';
62 $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
63 
64 // Security check
65 //$result=restrictedArea($user, 'stock', $id, 'entrepot&stock');
66 $result = restrictedArea($user, 'stock');
67 
68 $idproduct = GETPOST('idproduct', 'int');
69 $year = GETPOST("year");
70 $month = GETPOST("month");
71 $search_ref = GETPOST('search_ref', 'alpha');
72 $search_movement = GETPOST("search_movement");
73 $search_product_ref = trim(GETPOST("search_product_ref"));
74 $search_product = trim(GETPOST("search_product"));
75 $search_warehouse = trim(GETPOST("search_warehouse"));
76 $search_inventorycode = trim(GETPOST("search_inventorycode"));
77 $search_user = trim(GETPOST("search_user"));
78 $search_batch = trim(GETPOST("search_batch"));
79 $search_qty = trim(GETPOST("search_qty"));
80 $search_type_mouvement = GETPOST('search_type_mouvement', 'int');
81 
82 $limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
83 $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
84 $sortfield = GETPOST("sortfield", 'alpha');
85 $sortorder = GETPOST("sortorder", 'alpha');
86 if (empty($page) || $page == -1) { $page = 0; } // If $page is not defined, or '' or -1
87 $offset = $limit * $page;
88 if (!$sortfield) $sortfield = "m.datem";
89 if (!$sortorder) $sortorder = "DESC";
90 
91 $pdluoid = GETPOST('pdluoid', 'int');
92 
93 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
94 $object = new MouvementStock($db);
95 $hookmanager->initHooks(array('movementlist'));
96 $extrafields = new ExtraFields($db);
97 $formfile = new FormFile($db);
98 
99 // fetch optionals attributes and labels
100 $extrafields->fetch_name_optionals_label($object->table_element);
101 
102 $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
103 
104 $arrayfields = array(
105  'm.rowid'=>array('label'=>$langs->trans("Ref"), 'checked'=>1),
106  'm.datem'=>array('label'=>$langs->trans("Date"), 'checked'=>1),
107  'p.ref'=>array('label'=>$langs->trans("ProductRef"), 'checked'=>1, 'css'=>'maxwidth100'),
108  'p.label'=>array('label'=>$langs->trans("ProductLabel"), 'checked'=>1),
109  'm.batch'=>array('label'=>$langs->trans("BatchNumberShort"), 'checked'=>1, 'enabled'=>(!empty($conf->productbatch->enabled))),
110  'pl.eatby'=>array('label'=>$langs->trans("EatByDate"), 'checked'=>0, 'enabled'=>(!empty($conf->productbatch->enabled))),
111  'pl.sellby'=>array('label'=>$langs->trans("SellByDate"), 'checked'=>0, 'position'=>10, 'enabled'=>(!empty($conf->productbatch->enabled))),
112  'e.ref'=>array('label'=>$langs->trans("Warehouse"), 'checked'=>1, 'enabled'=>(!$id > 0)), // If we are on specific warehouse, we hide it
113  'm.fk_user_author'=>array('label'=>$langs->trans("Author"), 'checked'=>0),
114  'm.inventorycode'=>array('label'=>$langs->trans("InventoryCodeShort"), 'checked'=>1),
115  'm.label'=>array('label'=>$langs->trans("MovementLabel"), 'checked'=>1),
116  'm.type_mouvement'=>array('label'=>$langs->trans("TypeMovement"), 'checked'=>1),
117  'origin'=>array('label'=>$langs->trans("Origin"), 'checked'=>1),
118  'm.value'=>array('label'=>$langs->trans("Qty"), 'checked'=>1),
119  'm.price'=>array('label'=>$langs->trans("UnitPurchaseValue"), 'checked'=>0),
120  'm.fk_projet'=>array('label'=>$langs->trans('Project'), 'checked'=>0)
121  //'m.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
122  //'m.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500)
123 );
124 if (!empty($conf->global->PRODUCT_DISABLE_EATBY)) {
125  unset($arrayfields['pl.eatby']);
126 }
127 if (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
128  unset($arrayfields['pl.sellby']);
129 }
130 
131 // Security check
132 if (!$user->rights->stock->mouvement->lire) {
133  accessforbidden();
134 }
135 
136 $permissiontoread = $user->rights->stock->mouvement->lire;
137 $permissiontoadd = $user->rights->stock->mouvement->creer;
138 $permissiontodelete = $user->rights->stock->mouvement->creer; // There is no deletion permission for stock movement as we shoul dnever delete
139 
140 $usercanread = $user->rights->stock->mouvement->lire;
141 $usercancreate = $user->rights->stock->mouvement->creer;
142 $usercandelete = $user->rights->stock->mouvement->creer;
143 
144 $error = 0;
145 
146 
147 /*
148  * Actions
149  */
150 
151 if (GETPOST('cancel', 'alpha')) { $action = 'list'; $massaction = ''; }
152 if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction = ''; }
153 
154 $parameters = array();
155 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
156 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
157 
158 if (empty($reshook))
159 {
160  include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
161 
162  // Do we click on purge search criteria ?
163  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
164  {
165  $year = '';
166  $month = '';
167  $search_ref = '';
168  $search_movement = "";
169  $search_type_mouvement = "";
170  $search_inventorycode = "";
171  $search_product_ref = "";
172  $search_product = "";
173  $search_warehouse = "";
174  $search_user = "";
175  $search_batch = "";
176  $search_qty = '';
177  $sall = "";
178  $toselect = '';
179  $search_array_options = array();
180  }
181 
182  // Mass actions
183  $objectclass = 'MouvementStock';
184  $objectlabel = 'MouvementStock';
185  $uploaddir = $conf->stock->dir_output;
186  include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
187 }
188 
189 if ($action == 'update_extras') {
190  $tmpwarehouse = new Entrepot($db);
191  $tmpwarehouse->fetch($id);
192 
193  $tmpwarehouse->oldcopy = dol_clone($tmpwarehouse);
194 
195  // Fill array 'array_options' with data from update form
196  $ret = $extrafields->setOptionalsFromPost(null, $tmpwarehouse, GETPOST('attribute', 'restricthtml'));
197  if ($ret < 0) $error++;
198  if (!$error) {
199  $result = $tmpwarehouse->insertExtraFields();
200  if ($result < 0) {
201  setEventMessages($tmpwarehouse->error, $tmpwarehouse->errors, 'errors');
202  $error++;
203  }
204  }
205  if ($error) $action = 'edit_extras';
206 }
207 
208 // Correct stock
209 if ($action == "correct_stock")
210 {
211  $product = new Product($db);
212  if (!empty($product_id)) $result = $product->fetch($product_id);
213 
214  $error = 0;
215 
216  if (empty($product_id))
217  {
218  $error++;
219  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
220  $action = 'correction';
221  }
222  if (!is_numeric($_POST["nbpiece"]))
223  {
224  $error++;
225  setEventMessages($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentitiesnoconv("NumberOfUnit")), null, 'errors');
226  $action = 'correction';
227  }
228 
229  if (!$error)
230  {
231  $origin_element = '';
232  $origin_id = null;
233 
234  if (GETPOST('projectid', 'int'))
235  {
236  $origin_element = 'project';
237  $origin_id = GETPOST('projectid', 'int');
238  }
239 
240  if ($product->hasbatch())
241  {
242  $batch = GETPOST('batch_number', 'alphanohtml');
243 
244  //$eatby=GETPOST('eatby');
245  //$sellby=GETPOST('sellby');
246  $eatby = dol_mktime(0, 0, 0, GETPOST('eatbymonth', 'int'), GETPOST('eatbyday', 'int'), GETPOST('eatbyyear', 'int'));
247  $sellby = dol_mktime(0, 0, 0, GETPOST('sellbymonth', 'int'), GETPOST('sellbyday', 'int'), GETPOST('sellbyyear', 'int'));
248 
249  $result = $product->correct_stock_batch(
250  $user,
251  $id,
252  GETPOST("nbpiece", 'int'),
253  GETPOST("mouvement"),
254  GETPOST("label", 'san_alpha'),
255  GETPOST('unitprice'),
256  $eatby, $sellby, $batch,
257  GETPOST('inventorycode', 'alphanohtml'),
258  $origin_element,
259  $origin_id
260  ); // We do not change value of stock for a correction
261  } else {
262  $result = $product->correct_stock(
263  $user,
264  $id,
265  GETPOST("nbpiece", 'int'),
266  GETPOST("mouvement"),
267  GETPOST("label", 'san_alpha'),
268  GETPOST('unitprice'),
269  GETPOST('inventorycode', 'alphanohtml'),
270  $origin_element,
271  $origin_id
272  ); // We do not change value of stock for a correction
273  }
274 
275  if ($result > 0)
276  {
277  header("Location: ".$_SERVER["PHP_SELF"]."?id=".$id);
278  exit;
279  } else {
280  $error++;
281  setEventMessages($product->error, $product->errors, 'errors');
282  $action = 'correction';
283  }
284  }
285 
286  if (!$error) $action = '';
287 }
288 
289 // Transfer stock from a warehouse to another warehouse
290 if ($action == "transfert_stock" && !$cancel)
291 {
292  $product = new Product($db);
293  if (!empty($product_id)) $result = $product->fetch($product_id);
294 
295  if (!(GETPOST("id_entrepot_destination", 'int') > 0))
296  {
297  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
298  $error++;
299  $action = 'transfert';
300  }
301  if (empty($product_id))
302  {
303  $error++;
304  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
305  $action = 'transfert';
306  }
307  if (!GETPOST("nbpiece", 'int'))
308  {
309  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("NumberOfUnit")), null, 'errors');
310  $error++;
311  $action = 'transfert';
312  }
313  if ($id == GETPOST("id_entrepot_destination", 'int'))
314  {
315  setEventMessages($langs->trans("ErrorSrcAndTargetWarehouseMustDiffers"), null, 'errors');
316  $error++;
317  $action = 'transfert';
318  }
319 
320  if (!empty($conf->productbatch->enabled))
321  {
322  $product = new Product($db);
323  $result = $product->fetch($product_id);
324 
325  if ($product->hasbatch() && !GETPOST("batch_number"))
326  {
327  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("batch_number")), null, 'errors');
328  $error++;
329  $action = 'transfert';
330  }
331  }
332 
333  if (!$error)
334  {
335  if ($id)
336  {
337  $object = new Entrepot($db);
338  $result = $object->fetch($id);
339 
340  $db->begin();
341 
342  $product->load_stock('novirtual'); // Load array product->stock_warehouse
343 
344  // Define value of products moved
345  $pricesrc = 0;
346  if (isset($product->pmp)) $pricesrc = $product->pmp;
347  $pricedest = $pricesrc;
348 
349  if ($product->hasbatch())
350  {
351  $pdluo = new Productbatch($db);
352 
353  if ($pdluoid > 0)
354  {
355  $result = $pdluo->fetch($pdluoid);
356  if ($result)
357  {
358  $srcwarehouseid = $pdluo->warehouseid;
359  $batch = $pdluo->batch;
360  $eatby = $pdluo->eatby;
361  $sellby = $pdluo->sellby;
362  } else {
363  setEventMessages($pdluo->error, $pdluo->errors, 'errors');
364  $error++;
365  }
366  } else {
367  $srcwarehouseid = $id;
368  $batch = GETPOST('batch_number', 'alphanohtml');
369  $eatby = $d_eatby;
370  $sellby = $d_sellby;
371  }
372 
373  if (!$error)
374  {
375  // Remove stock
376  $result1 = $product->correct_stock_batch(
377  $user,
378  $srcwarehouseid,
379  GETPOST("nbpiece", 'int'),
380  1,
381  GETPOST("label", 'san_alpha'),
382  $pricesrc,
383  $eatby, $sellby, $batch,
384  GETPOST('inventorycode')
385  );
386  // Add stock
387  $result2 = $product->correct_stock_batch(
388  $user,
389  GETPOST("id_entrepot_destination", 'int'),
390  GETPOST("nbpiece", 'int'),
391  0,
392  GETPOST("label", 'san_alpha'),
393  $pricedest,
394  $eatby, $sellby, $batch,
395  GETPOST('inventorycode', 'alphanohtml')
396  );
397  }
398  } else {
399  // Remove stock
400  $result1 = $product->correct_stock(
401  $user,
402  $id,
403  GETPOST("nbpiece"),
404  1,
405  GETPOST("label", 'san_alpha'),
406  $pricesrc,
407  GETPOST('inventorycode', 'alphanohtml')
408  );
409 
410  // Add stock
411  $result2 = $product->correct_stock(
412  $user,
413  GETPOST("id_entrepot_destination"),
414  GETPOST("nbpiece"),
415  0,
416  GETPOST("label", 'san_alpha'),
417  $pricedest,
418  GETPOST('inventorycode', 'alphanohtml')
419  );
420  }
421  if (!$error && $result1 >= 0 && $result2 >= 0)
422  {
423  $db->commit();
424 
425  if ($backtopage)
426  {
427  header("Location: ".$backtopage);
428  exit;
429  } else {
430  header("Location: movement_list.php?id=".$object->id);
431  exit;
432  }
433  } else {
434  setEventMessages($product->error, $product->errors, 'errors');
435  $db->rollback();
436  $action = 'transfert';
437  }
438  }
439  }
440 }
441 
442 
443 /*
444  * View
445  */
446 
447 $productlot = new ProductLot($db);
448 $productstatic = new Product($db);
449 $warehousestatic = new Entrepot($db);
450 $movement = new MouvementStock($db);
451 $userstatic = new User($db);
452 $form = new Form($db);
453 $formother = new FormOther($db);
454 $formproduct = new FormProduct($db);
455 if (!empty($conf->projet->enabled)) $formproject = new FormProjets($db);
456 
457 $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,";
458 $sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,";
459 $sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,";
460 $sql .= " m.batch, m.price,";
461 $sql .= " m.type_mouvement,";
462 $sql .= " m.fk_projet as fk_project,";
463 $sql .= " pl.rowid as lotid, pl.eatby, pl.sellby,";
464 $sql .= " u.login, u.photo, u.lastname, u.firstname";
465 // Add fields from extrafields
466 if (!empty($extrafields->attributes[$object->table_element]['label'])) {
467  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql .= ($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? ", ef.".$key.' as options_'.$key : '');
468 }
469 // Add fields from hooks
470 $parameters = array();
471 $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook
472 $sql .= $hookmanager->resPrint;
473 $sql .= " FROM ".MAIN_DB_PREFIX."entrepot as e,";
474 $sql .= " ".MAIN_DB_PREFIX."product as p,";
475 $sql .= " ".MAIN_DB_PREFIX."stock_mouvement as m";
476 if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (m.rowid = ef.fk_object)";
477 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u ON m.fk_user_author = u.rowid";
478 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product_lot as pl ON m.batch = pl.batch AND m.fk_product = pl.fk_product";
479 $sql .= " WHERE m.fk_product = p.rowid";
480 if ($msid > 0) $sql .= " AND m.rowid = ".$msid;
481 $sql .= " AND m.fk_entrepot = e.rowid";
482 $sql .= " AND e.entity IN (".getEntity('stock').")";
483 if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) $sql .= " AND p.fk_product_type = 0";
484 if ($id > 0) $sql .= " AND e.rowid ='".$id."'";
485 $sql .= dolSqlDateFilter('m.datem', 0, $month, $year);
486 if ($idproduct > 0) $sql .= " AND p.rowid = ".((int) $idproduct);
487 if (!empty($search_ref)) $sql .= natural_search('m.rowid', $search_ref, 1);
488 if (!empty($search_movement)) $sql .= natural_search('m.label', $search_movement);
489 if (!empty($search_inventorycode)) $sql .= natural_search('m.inventorycode', $search_inventorycode);
490 if (!empty($search_product_ref)) $sql .= natural_search('p.ref', $search_product_ref);
491 if (!empty($search_product)) $sql .= natural_search('p.label', $search_product);
492 if ($search_warehouse != '' && $search_warehouse != '-1') $sql .= natural_search('e.rowid', $search_warehouse, 2);
493 if (!empty($search_user)) $sql .= natural_search('u.login', $search_user);
494 if (!empty($search_batch)) $sql .= natural_search('m.batch', $search_batch);
495 if (!empty($product_id)) $sql .= natural_search('p.rowid', $product_id);
496 if ($search_qty != '') $sql .= natural_search('m.value', $search_qty, 1);
497 if ($search_type_mouvement != '' && $search_type_mouvement != '-1') $sql .= natural_search('m.type_mouvement', $search_type_mouvement, 2);
498 // Add where from extra fields
499 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
500 // Add where from hooks
501 $parameters = array();
502 $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook
503 $sql .= $hookmanager->resPrint;
504 $sql .= $db->order($sortfield, $sortorder);
505 
506 $nbtotalofrecords = '';
507 if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST))
508 {
509  $result = $db->query($sql);
510  $nbtotalofrecords = $db->num_rows($result);
511  if (($page * $limit) > $nbtotalofrecords) // if total resultset is smaller then paging size (filtering), goto and load page 0
512  {
513  $page = 0;
514  $offset = 0;
515  }
516 }
517 
518 if (empty($search_inventorycode))
519 {
520  $sql .= $db->plimit($limit + 1, $offset);
521 } else {
522  $limit = 0;
523 }
524 
525 //print $sql;
526 
527 $resql = $db->query($sql);
528 
529 if (!empty($search_inventorycode)) $limit = $db->num_rows($resql);
530 
531 if ($resql)
532 {
533  $product = new Product($db);
534  $object = new Entrepot($db);
535 
536  if ($idproduct > 0)
537  {
538  $product->fetch($idproduct);
539  }
540  if ($id > 0 || $ref)
541  {
542  $result = $object->fetch($id, $ref);
543  if ($result < 0)
544  {
545  dol_print_error($db);
546  }
547  }
548 
549  $num = $db->num_rows($resql);
550 
551  $arrayofselected = is_array($toselect) ? $toselect : array();
552 
553 
554  $i = 0;
555  $help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:M&oacute;dulo_Stocks';
556  if ($msid) $texte = $langs->trans('StockMovementForId', $msid);
557  else {
558  $texte = $langs->trans("ListOfStockMovements");
559  if ($id) $texte .= ' ('.$langs->trans("ForThisWarehouse").')';
560  }
561  llxHeader("", $texte, $help_url);
562 
563  /*
564  * Show tab only if we ask a particular warehouse
565  */
566  if ($object->id > 0)
567  {
568  $head = stock_prepare_head($object);
569 
570  print dol_get_fiche_head($head, 'movements', $langs->trans("Warehouse"), -1, 'stock');
571 
572 
573  $linkback = '<a href="'.DOL_URL_ROOT.'/product/stock/list.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
574 
575  $morehtmlref = '<div class="refidno">';
576  $morehtmlref .= $langs->trans("LocationSummary").' : '.$object->lieu;
577  $morehtmlref .= '</div>';
578 
579  $shownav = 1;
580  if ($user->socid && !in_array('stock', explode(',', $conf->global->MAIN_MODULES_FOR_EXTERNAL))) $shownav = 0;
581 
582  dol_banner_tab($object, 'ref', $linkback, $shownav, 'ref', 'ref', $morehtmlref);
583 
584 
585  print '<div class="fichecenter">';
586  print '<div class="fichehalfleft">';
587  print '<div class="underbanner clearboth"></div>';
588 
589  print '<table class="border centpercent tableforfield">';
590 
591  print '<tr>';
592 
593  // Description
594  print '<td class="titlefield tdtop">'.$langs->trans("Description").'</td><td>'.dol_htmlentitiesbr($object->description).'</td></tr>';
595 
596  $calcproductsunique = $object->nb_different_products();
597  $calcproducts = $object->nb_products();
598 
599  // Total nb of different products
600  print '<tr><td>'.$langs->trans("NumberOfDifferentProducts").'</td><td>';
601  print empty($calcproductsunique['nb']) ? '0' : $calcproductsunique['nb'];
602  print "</td></tr>";
603 
604  // Nb of products
605  print '<tr><td>'.$langs->trans("NumberOfProducts").'</td><td>';
606  $valtoshow = price2num($calcproducts['nb'], 'MS');
607  print empty($valtoshow) ? '0' : $valtoshow;
608  print "</td></tr>";
609 
610  print '</table>';
611 
612  print '</div>';
613  print '<div class="fichehalfright">';
614  print '<div class="ficheaddleft">';
615  print '<div class="underbanner clearboth"></div>';
616 
617  print '<table class="border centpercent tableforfield">';
618 
619  // Value
620  print '<tr><td class="titlefield">'.$langs->trans("EstimatedStockValueShort").'</td><td>';
621  print price((empty($calcproducts['value']) ? '0' : price2num($calcproducts['value'], 'MT')), 0, $langs, 0, -1, -1, $conf->currency);
622  print "</td></tr>";
623 
624  // Last movement
625  $sql = "SELECT MAX(m.datem) as datem";
626  $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement as m";
627  $sql .= " WHERE m.fk_entrepot = ".((int) $object->id);
628  $resqlbis = $db->query($sql);
629  if ($resqlbis)
630  {
631  $objbis = $db->fetch_object($resqlbis);
632  $lastmovementdate = $db->jdate($objbis->datem);
633  } else {
634  dol_print_error($db);
635  }
636 
637  print '<tr><td>'.$langs->trans("LastMovement").'</td><td>';
638  if ($lastmovementdate)
639  {
640  print dol_print_date($lastmovementdate, 'dayhour');
641  } else {
642  print $langs->trans("None");
643  }
644  print "</td></tr>";
645 
646  // Other attributes
647  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
648 
649  // Categories
650  if ($conf->categorie->enabled) {
651  print '<tr><td valign="middle">'.$langs->trans("Categories").'</td><td colspan="3">';
652  print $form->showCategories($object->id, Categorie::TYPE_WAREHOUSE, 1);
653  print "</td></tr>";
654  }
655 
656  print "</table>";
657 
658  print '</div>';
659  print '</div>';
660  print '</div>';
661 
662  print '<div class="clearboth"></div>';
663 
665  }
666 
667 
668  /*
669  * Correct stock
670  */
671  if ($action == "correction")
672  {
673  include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stockcorrection.tpl.php';
674  print '<br>';
675  }
676 
677  /*
678  * Transfer of units
679  */
680  if ($action == "transfert")
681  {
682  include DOL_DOCUMENT_ROOT.'/product/stock/tpl/stocktransfer.tpl.php';
683  print '<br>';
684  }
685 
686 
687  /* ************************************************************************** */
688  /* */
689  /* Barre d'action */
690  /* */
691  /* ************************************************************************** */
692 
693  if ((empty($action) || $action == 'list') && $id > 0)
694  {
695  print "<div class=\"tabsAction\">\n";
696 
697  if ($user->rights->stock->mouvement->creer)
698  {
699  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=correction">'.$langs->trans("CorrectStock").'</a>';
700  }
701 
702  if ($user->rights->stock->mouvement->creer)
703  {
704  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$id.'&action=transfert">'.$langs->trans("TransferStock").'</a>';
705  }
706 
707  print '</div><br>';
708  }
709 
710  $param = '';
711  if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param .= '&contextpage='.urlencode($contextpage);
712  if ($limit > 0 && $limit != $conf->liste_limit) $param .= '&limit='.urlencode($limit);
713  if ($id > 0) $param .= '&id='.urlencode($id);
714  if ($search_movement) $param .= '&search_movement='.urlencode($search_movement);
715  if ($search_inventorycode) $param .= '&search_inventorycode='.urlencode($search_inventorycode);
716  if ($search_type_mouvement) $param .= '&search_type_mouvement='.urlencode($search_type_mouvement);
717  if ($search_product_ref) $param .= '&search_product_ref='.urlencode($search_product_ref);
718  if ($search_product) $param .= '&search_product='.urlencode($search_product);
719  if ($search_batch) $param .= '&search_batch='.urlencode($search_batch);
720  if ($search_warehouse > 0) $param .= '&search_warehouse='.urlencode($search_warehouse);
721  if ($search_user) $param .= '&search_user='.urlencode($search_user);
722  if ($idproduct > 0) $param .= '&idproduct='.urlencode($idproduct);
723  // Add $param from extra fields
724  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
725 
726  // List of mass actions available
727  $arrayofmassactions = array(
728  // 'presend'=>$langs->trans("SendByMail"),
729  // 'builddoc'=>$langs->trans("PDFMerge"),
730  );
731  // By default, we should never accept deletion of stock movement.
732  if (!empty($conf->global->STOCK_ALLOW_DELETE_OF_MOVEMENT) && $permissiontodelete) $arrayofmassactions['predelete'] = '<span class="fa fa-trash paddingrightonly"></span>'.$langs->trans("Delete");
733  if (GETPOST('nomassaction', 'int') || in_array($massaction, array('presend', 'predelete'))) $arrayofmassactions = array();
734  $massactionbutton = $form->selectMassAction('', $arrayofmassactions);
735 
736  print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
737  if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
738  print '<input type="hidden" name="token" value="'.newToken().'">';
739  print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
740  print '<input type="hidden" name="action" value="list">';
741  print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
742  print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
743  print '<input type="hidden" name="type" value="'.$type.'">';
744  print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
745  if ($id > 0) print '<input type="hidden" name="id" value="'.$id.'">';
746 
747  if ($id > 0) print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'stock', 0, '', '', $limit, 0, 0, 1);
748  else print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'stock', 0, '', '', $limit, 0, 0, 1);
749 
750  // Add code for pre mass action (confirmation or email presend form)
751  $topicmail = "SendStockMovement";
752  $modelmail = "movementstock";
753  $objecttmp = new MouvementStock($db);
754  $trackid = 'mov'.$object->id;
755  include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
756 
757  if ($sall)
758  {
759  foreach ($fieldstosearchall as $key => $val) $fieldstosearchall[$key] = $langs->trans($val);
760  print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'</div>';
761  }
762 
763  $moreforfilter = '';
764 
765  $parameters = array();
766  $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook
767  if (empty($reshook)) $moreforfilter .= $hookmanager->resPrint;
768  else $moreforfilter = $hookmanager->resPrint;
769 
770  if (!empty($moreforfilter))
771  {
772  print '<div class="liste_titre liste_titre_bydiv centpercent">';
773  print $moreforfilter;
774  print '</div>';
775  }
776 
777  $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
778  $selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields
779 
780  print '<div class="div-table-responsive">';
781  print '<table class="tagtable liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
782 
783  // Fields title search
784  print '<tr class="liste_titre_filter">';
785  if (!empty($arrayfields['m.rowid']['checked']))
786  {
787  // Ref
788  print '<td class="liste_titre left">';
789  print '<input class="flat maxwidth25" type="text" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
790  print '</td>';
791  }
792  if (!empty($arrayfields['m.datem']['checked']))
793  {
794  // Date
795  print '<td class="liste_titre nowraponall">';
796  print '<input class="flat" type="text" size="2" maxlength="2" placeholder="'.dol_escape_htmltag($langs->trans("Month")).'" name="month" value="'.$month.'">';
797  if (empty($conf->productbatch->enabled)) print '&nbsp;';
798  //else print '<br>';
799  $syear = $year ? $year : -1;
800  print '<input class="flat maxwidth50" type="text" maxlength="4" placeholder="'.dol_escape_htmltag($langs->trans("Year")).'" name="year" value="'.($syear > 0 ? $syear : '').'">';
801  //print $formother->selectyear($syear,'year',1, 20, 5);
802  print '</td>';
803  }
804  if (!empty($arrayfields['p.ref']['checked']))
805  {
806  // Product Ref
807  print '<td class="liste_titre left">';
808  print '<input class="flat maxwidth75" type="text" name="search_product_ref" value="'.dol_escape_htmltag($idproduct ? $product->ref : $search_product_ref).'">';
809  print '</td>';
810  }
811  if (!empty($arrayfields['p.label']['checked']))
812  {
813  // Product label
814  print '<td class="liste_titre left">';
815  print '<input class="flat maxwidth100" type="text" name="search_product" value="'.dol_escape_htmltag($idproduct ? $product->label : $search_product).'">';
816  print '</td>';
817  }
818  // Batch
819  if (!empty($arrayfields['m.batch']['checked']))
820  {
821  print '<td class="liste_titre center"><input class="flat maxwidth75" type="text" name="search_batch" value="'.dol_escape_htmltag($search_batch).'"></td>';
822  }
823  if (!empty($arrayfields['pl.eatby']['checked']))
824  {
825  print '<td class="liste_titre left">';
826  print '</td>';
827  }
828  if (!empty($arrayfields['pl.sellby']['checked']))
829  {
830  print '<td class="liste_titre left">';
831  print '</td>';
832  }
833  // Warehouse
834  if (!empty($arrayfields['e.ref']['checked']))
835  {
836  print '<td class="liste_titre maxwidthonsmartphone left">';
837  //print '<input class="flat" type="text" size="8" name="search_warehouse" value="'.($search_warehouse).'">';
838  print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200');
839  print '</td>';
840  }
841  if (!empty($arrayfields['m.fk_user_author']['checked']))
842  {
843  // Author
844  print '<td class="liste_titre left">';
845  print '<input class="flat" type="text" size="6" name="search_user" value="'.dol_escape_htmltag($search_user).'">';
846  print '</td>';
847  }
848  if (!empty($arrayfields['m.inventorycode']['checked']))
849  {
850  // Inventory code
851  print '<td class="liste_titre left">';
852  print '<input class="flat" type="text" size="4" name="search_inventorycode" value="'.dol_escape_htmltag($search_inventorycode).'">';
853  print '</td>';
854  }
855  if (!empty($arrayfields['m.label']['checked']))
856  {
857  // Label of movement
858  print '<td class="liste_titre left">';
859  print '<input class="flat" type="text" size="8" name="search_movement" value="'.dol_escape_htmltag($search_movement).'">';
860  print '</td>';
861  }
862  if (!empty($arrayfields['m.type_mouvement']['checked']))
863  {
864  // Type of movement
865  print '<td class="liste_titre center">';
866  //print '<input class="flat" type="text" size="3" name="search_type_mouvement" value="'.dol_escape_htmltag($search_type_mouvement).'">';
867  print '<select id="search_type_mouvement" name="search_type_mouvement" class="maxwidth150">';
868  print '<option value="" '.(($search_type_mouvement == "") ? 'selected="selected"' : '').'></option>';
869  print '<option value="0" '.(($search_type_mouvement == "0") ? 'selected="selected"' : '').'>'.$langs->trans('StockIncreaseAfterCorrectTransfer').'</option>';
870  print '<option value="1" '.(($search_type_mouvement == "1") ? 'selected="selected"' : '').'>'.$langs->trans('StockDecreaseAfterCorrectTransfer').'</option>';
871  print '<option value="2" '.(($search_type_mouvement == "2") ? 'selected="selected"' : '').'>'.$langs->trans('StockDecrease').'</option>';
872  print '<option value="3" '.(($search_type_mouvement == "3") ? 'selected="selected"' : '').'>'.$langs->trans('StockIncrease').'</option>';
873  print '</select>';
874  print ajax_combobox('search_type_mouvement');
875  // TODO: add new function $formentrepot->selectTypeOfMovement(...) like
876  // print $formproduct->selectWarehouses($search_warehouse, 'search_warehouse', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, null, 'maxwidth200');
877  print '</td>';
878  }
879  if (!empty($arrayfields['origin']['checked']))
880  {
881  // Origin of movement
882  print '<td class="liste_titre left">';
883  print '&nbsp; ';
884  print '</td>';
885  }
886  if (!empty($arrayfields['m.value']['checked']))
887  {
888  // Qty
889  print '<td class="liste_titre right">';
890  print '<input class="flat" type="text" size="4" name="search_qty" value="'.dol_escape_htmltag($search_qty).'">';
891  print '</td>';
892  }
893  if (!empty($arrayfields['m.price']['checked']))
894  {
895  // Price
896  print '<td class="liste_titre" align="left">';
897  print '&nbsp; ';
898  print '</td>';
899  }
900  if (!empty($arrayfields['m.fk_projet']['checked']))
901  {
902  // fk_project
903  print '<td class="liste_titre" align="left">';
904  print '&nbsp; ';
905  print '</td>';
906  }
907 
908 
909  // Extra fields
910  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
911 
912  // Fields from hook
913  $parameters = array('arrayfields'=>$arrayfields);
914  $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
915  print $hookmanager->resPrint;
916  // Date creation
917  if (!empty($arrayfields['m.datec']['checked']))
918  {
919  print '<td class="liste_titre">';
920  print '</td>';
921  }
922  // Date modification
923  if (!empty($arrayfields['m.tms']['checked']))
924  {
925  print '<td class="liste_titre">';
926  print '</td>';
927  }
928  // Actions
929  print '<td class="liste_titre maxwidthsearch">';
930  $searchpicto = $form->showFilterAndCheckAddButtons(0);
931  print $searchpicto;
932  print '</td>';
933  print "</tr>\n";
934 
935  print '<tr class="liste_titre">';
936  if (!empty($arrayfields['m.rowid']['checked'])) {
937  print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder);
938  }
939  if (!empty($arrayfields['m.datem']['checked'])) {
940  print_liste_field_titre($arrayfields['m.datem']['label'], $_SERVER["PHP_SELF"], 'm.datem', '', $param, '', $sortfield, $sortorder);
941  }
942  if (!empty($arrayfields['p.ref']['checked'])) {
943  print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], 'p.ref', '', $param, '', $sortfield, $sortorder);
944  }
945  if (!empty($arrayfields['p.label']['checked'])) {
946  print_liste_field_titre($arrayfields['p.label']['label'], $_SERVER["PHP_SELF"], 'p.label', '', $param, '', $sortfield, $sortorder);
947  }
948  if (!empty($arrayfields['m.batch']['checked'])) {
949  print_liste_field_titre($arrayfields['m.batch']['label'], $_SERVER["PHP_SELF"], 'm.batch', '', $param, '', $sortfield, $sortorder, 'center ');
950  }
951  if (!empty($arrayfields['pl.eatby']['checked'])) {
952  print_liste_field_titre($arrayfields['pl.eatby']['label'], $_SERVER["PHP_SELF"], 'pl.eatby', '', $param, '', $sortfield, $sortorder, 'center ');
953  }
954  if (!empty($arrayfields['pl.sellby']['checked'])) {
955  print_liste_field_titre($arrayfields['pl.sellby']['label'], $_SERVER["PHP_SELF"], 'pl.sellby', '', $param, '', $sortfield, $sortorder, 'center ');
956  }
957  if (!empty($arrayfields['e.ref']['checked'])) {
958  // We are on a specific warehouse card, no filter on other should be possible
959  print_liste_field_titre($arrayfields['e.ref']['label'], $_SERVER["PHP_SELF"], "e.ref", "", $param, "", $sortfield, $sortorder);
960  }
961  if (!empty($arrayfields['m.fk_user_author']['checked'])) {
962  print_liste_field_titre($arrayfields['m.fk_user_author']['label'], $_SERVER["PHP_SELF"], "m.fk_user_author", "", $param, "", $sortfield, $sortorder);
963  }
964  if (!empty($arrayfields['m.inventorycode']['checked'])) {
965  print_liste_field_titre($arrayfields['m.inventorycode']['label'], $_SERVER["PHP_SELF"], "m.inventorycode", "", $param, "", $sortfield, $sortorder);
966  }
967  if (!empty($arrayfields['m.label']['checked'])) {
968  print_liste_field_titre($arrayfields['m.label']['label'], $_SERVER["PHP_SELF"], "m.label", "", $param, "", $sortfield, $sortorder);
969  }
970  if (!empty($arrayfields['m.type_mouvement']['checked'])) {
971  print_liste_field_titre($arrayfields['m.type_mouvement']['label'], $_SERVER["PHP_SELF"], "m.type_mouvement", "", $param, '', $sortfield, $sortorder, 'center ');
972  }
973  if (!empty($arrayfields['origin']['checked'])) {
974  print_liste_field_titre($arrayfields['origin']['label'], $_SERVER["PHP_SELF"], "", "", $param, "", $sortfield, $sortorder);
975  }
976  if (!empty($arrayfields['m.value']['checked'])) {
977  print_liste_field_titre($arrayfields['m.value']['label'], $_SERVER["PHP_SELF"], "m.value", "", $param, '', $sortfield, $sortorder, 'right ');
978  }
979  if (!empty($arrayfields['m.price']['checked'])) {
980  print_liste_field_titre($arrayfields['m.price']['label'], $_SERVER["PHP_SELF"], "m.price", "", $param, '', $sortfield, $sortorder, 'right ');
981  }
982  if (!empty($arrayfields['m.fk_projet']['checked'])) {
983  print_liste_field_titre($arrayfields['m.fk_projet']['label'], $_SERVER["PHP_SELF"], "m.fk_projet", "", $param, 'align="right"', $sortfield, $sortorder);
984  }
985 
986  // Extra fields
987  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
988 
989  // Hook fields
990  $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder);
991  $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters); // Note that $action and $object may have been modified by hook
992  print $hookmanager->resPrint;
993  if (!empty($arrayfields['m.datec']['checked'])) {
994  print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
995  }
996  if (!empty($arrayfields['m.tms']['checked'])) {
997  print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
998  }
999  print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
1000  print "</tr>\n";
1001 
1002 
1003  $arrayofuniqueproduct = array();
1004 
1005  $i = 0;
1006  $totalarray = array();
1007  while ($i < min($num, $limit))
1008  {
1009  $objp = $db->fetch_object($resql);
1010 
1011  $userstatic->id = $objp->fk_user_author;
1012  $userstatic->login = $objp->login;
1013  $userstatic->lastname = $objp->lastname;
1014  $userstatic->firstname = $objp->firstname;
1015  $userstatic->photo = $objp->photo;
1016 
1017  $productstatic->id = $objp->rowid;
1018  $productstatic->ref = $objp->product_ref;
1019  $productstatic->label = $objp->produit;
1020  $productstatic->type = $objp->type;
1021  $productstatic->entity = $objp->entity;
1022  $productstatic->status = $objp->tosell;
1023  $productstatic->status_buy = $objp->tobuy;
1024  $productstatic->status_batch = $objp->tobatch;
1025 
1026  $productlot->id = $objp->lotid;
1027  $productlot->batch = $objp->batch;
1028  $productlot->eatby = $objp->eatby;
1029  $productlot->sellby = $objp->sellby;
1030 
1031  $warehousestatic->id = $objp->entrepot_id;
1032  $warehousestatic->ref = $objp->warehouse_ref;
1033  $warehousestatic->label = $objp->warehouse_ref;
1034  $warehousestatic->lieu = $objp->lieu;
1035  $warehousestatic->fk_parent = $objp->fk_parent;
1036  $warehousestatic->statut = $objp->statut;
1037 
1038  $arrayofuniqueproduct[$objp->rowid] = $objp->produit;
1039  if (!empty($objp->fk_origin)) {
1040  $origin = $movement->get_origin($objp->fk_origin, $objp->origintype);
1041  } else {
1042  $origin = '';
1043  }
1044 
1045  print '<tr class="oddeven">';
1046  // Id movement
1047  if (!empty($arrayfields['m.rowid']['checked']))
1048  {
1049  print '<td>'.$objp->mid.'</td>'; // This is primary not movement id
1050  }
1051  if (!empty($arrayfields['m.datem']['checked']))
1052  {
1053  // Date
1054  print '<td class="nowraponall">'.dol_print_date($db->jdate($objp->datem), 'dayhour', 'tzuserrel').'</td>';
1055  }
1056  if (!empty($arrayfields['p.ref']['checked']))
1057  {
1058  // Product ref
1059  print '<td class="nowraponall">';
1060  print $productstatic->getNomUrl(1, 'stock', 16);
1061  print "</td>\n";
1062  }
1063  if (!empty($arrayfields['p.label']['checked']))
1064  {
1065  // Product label
1066  print '<td>';
1067  /*$productstatic->id=$objp->rowid;
1068  $productstatic->ref=$objp->produit;
1069  $productstatic->type=$objp->type;
1070  print $productstatic->getNomUrl(1,'',16);*/
1071  print $productstatic->label;
1072  print "</td>\n";
1073  }
1074  if (!empty($arrayfields['m.batch']['checked']))
1075  {
1076  print '<td class="center nowraponall">';
1077  if ($productlot->id > 0) print $productlot->getNomUrl(1);
1078  else 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.
1079  print '</td>';
1080  }
1081  if (!empty($arrayfields['pl.eatby']['checked']))
1082  {
1083  print '<td class="center">'.dol_print_date($objp->eatby, 'day').'</td>';
1084  }
1085  if (!empty($arrayfields['pl.sellby']['checked']))
1086  {
1087  print '<td class="center">'.dol_print_date($objp->sellby, 'day').'</td>';
1088  }
1089  // Warehouse
1090  if (!empty($arrayfields['e.ref']['checked']))
1091  {
1092  print '<td>';
1093  print $warehousestatic->getNomUrl(1);
1094  print "</td>\n";
1095  }
1096  // Author
1097  if (!empty($arrayfields['m.fk_user_author']['checked']))
1098  {
1099  print '<td class="tdoverflowmax100">';
1100  print $userstatic->getNomUrl(-1);
1101  print "</td>\n";
1102  }
1103  if (!empty($arrayfields['m.inventorycode']['checked']))
1104  {
1105  // Inventory code
1106  print '<td><a href="'
1107  .DOL_URL_ROOT.'/product/stock/movement_card.php?id='.urlencode($objp->entrepot_id)
1108  .'&search_inventorycode='.urlencode($objp->inventorycode)
1109  .'&search_type_mouvement='.urlencode($objp->type_mouvement)
1110  .'">'.$objp->inventorycode.'</a></td>';
1111  }
1112  if (!empty($arrayfields['m.label']['checked']))
1113  {
1114  // Label of movement
1115  print '<td class="tdoverflowmax100aaa">'.$objp->label.'</td>';
1116  }
1117  if (!empty($arrayfields['m.type_mouvement']['checked']))
1118  {
1119  // Type of movement
1120  switch ($objp->type_mouvement) {
1121  case "0":
1122  print '<td class="center">'.$langs->trans('StockIncreaseAfterCorrectTransfer').'</td>';
1123  break;
1124  case "1":
1125  print '<td class="center">'.$langs->trans('StockDecreaseAfterCorrectTransfer').'</td>';
1126  break;
1127  case "2":
1128  print '<td class="center">'.$langs->trans('StockDecrease').'</td>';
1129  break;
1130  case "3":
1131  print '<td class="center">'.$langs->trans('StockIncrease').'</td>';
1132  break;
1133  }
1134  }
1135  if (!empty($arrayfields['origin']['checked']))
1136  {
1137  // Origin of movement
1138  print '<td class="nowraponall">'.$origin.'</td>';
1139  }
1140  if (!empty($arrayfields['m.value']['checked']))
1141  {
1142  // Qty
1143  print '<td class="right">';
1144  if ($objp->qt > 0) print '+';
1145  print $objp->qty;
1146  print '</td>';
1147  }
1148  if (!empty($arrayfields['m.price']['checked']))
1149  {
1150  // Price
1151  print '<td class="right">';
1152  if ($objp->price != 0) print price($objp->price);
1153  print '</td>';
1154  }
1155  if (!empty($arrayfields['m.fk_projet']['checked']))
1156  {
1157  // fk_project
1158  print '<td align="right">';
1159  if ($objp->fk_project != 0) print $movement->get_origin($objp->fk_project, 'project');
1160  print '</td>';
1161  }
1162  // Action column
1163  print '<td class="nowrap center">';
1164  if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
1165  {
1166  $selected = 0;
1167  if (in_array($objp->mid, $arrayofselected)) $selected = 1;
1168  print '<input id="cb'.$objp->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$objp->mid.'"'.($selected ? ' checked="checked"' : '').'>';
1169  }
1170  print '</td>';
1171  if (!$i) $totalarray['nbfield']++;
1172 
1173  print "</tr>\n";
1174  $i++;
1175  }
1176  $db->free($resql);
1177 
1178  print "</table>";
1179  print '</div>';
1180  print "</form>";
1181 
1182  // Add number of product when there is a filter on period
1183  if (count($arrayofuniqueproduct) == 1 && is_numeric($year))
1184  {
1185  print "<br>";
1186 
1187  $productidselected = 0;
1188  foreach ($arrayofuniqueproduct as $key => $val)
1189  {
1190  $productidselected = $key;
1191  $productlabelselected = $val;
1192  }
1193  $datebefore = dol_get_first_day($year ? $year : strftime("%Y", time()), $month ? $month : 1, true);
1194  $dateafter = dol_get_last_day($year ? $year : strftime("%Y", time()), $month ? $month : 12, true);
1195  $balancebefore = $movement->calculateBalanceForProductBefore($productidselected, $datebefore);
1196  $balanceafter = $movement->calculateBalanceForProductBefore($productidselected, $dateafter);
1197 
1198  //print '<tr class="total"><td class="liste_total">';
1199  print $langs->trans("NbOfProductBeforePeriod", $productlabelselected, dol_print_date($datebefore, 'day', 'gmt'));
1200  //print '</td>';
1201  //print '<td class="liste_total right" colspan="6">';
1202  print ': '.$balancebefore;
1203  print "<br>\n";
1204  //print '</td></tr>';
1205  //print '<tr class="total"><td class="liste_total">';
1206  print $langs->trans("NbOfProductAfterPeriod", $productlabelselected, dol_print_date($dateafter, 'day', 'gmt'));
1207  //print '</td>';
1208  //print '<td class="liste_total right" colspan="6">';
1209  print ': '.$balanceafter;
1210  print "<br>\n";
1211  //print '</td></tr>';
1212  }
1213 } else {
1214  dol_print_error($db);
1215 }
1216 
1217 
1218 // End of page
1219 llxFooter();
1220 $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.
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...
Class to manage products or services.
Class to manage Dolibarr users.
Definition: user.class.php:44
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for properties) With native = 0: P...
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete= 'resolve')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:391
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:481
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 ...
llxHeader()
Empty header.
Definition: wrapper.php:45
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.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
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.
Classe permettant la generation de composants html autre Only common components are here...
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=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 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...
dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $excludefirstand=0)
Generate a SQL string to make a filter into a range (for second of date until last second of date) ...
Definition: date.lib.php:281
Class to offer components to list and upload files.
print $_SERVER["PHP_SELF"]
Edit parameters.
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:498
Manage record for batch number management.
print
Draft customers invoices.
Definition: index.php:89
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
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.
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:59
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
Class to manage warehouses.