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