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