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