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