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