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