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