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