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