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