dolibarr 18.0.6
massstockmove.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2022 Laurent Destaileur <ely@users.sourceforge.net>
3 * Copyright (C) 2014 Regis Houssin <regis.houssin@inodbox.com>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
26// Load Dolibarr environment
27require '../../main.inc.php';
28require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
29require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
30require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
31require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
32require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
33require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
34require_once DOL_DOCUMENT_ROOT.'/core/modules/import/import_csv.modules.php';
35require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
36require_once DOL_DOCUMENT_ROOT.'/core/lib/import.lib.php';
37
38$confirm = GETPOST('confirm', 'alpha');
39$filetoimport = GETPOST('filetoimport');
40
41// Load translation files required by the page
42$langs->loadLangs(array('products', 'stocks', 'orders', 'productbatch'));
43
44//init Hook
45$hookmanager->initHooks(array('massstockmove'));
46
47// Security check
48if ($user->socid) {
49 $socid = $user->socid;
50}
51$result = restrictedArea($user, 'produit|service');
52
53//checks if a product has been ordered
54
55$action = GETPOST('action', 'aZ09');
56$id_product = GETPOST('productid', 'int');
57$id_sw = GETPOST('id_sw', 'int');
58$id_tw = GETPOST('id_tw', 'int');
59$batch = GETPOST('batch');
60$qty = GETPOST('qty');
61$idline = GETPOST('idline');
62
63$sortfield = GETPOST('sortfield', 'aZ09comma');
64$sortorder = GETPOST('sortorder', 'aZ09comma');
65$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
66if (empty($page) || $page == -1) {
67 $page = 0;
68} // If $page is not defined, or '' or -1
69
70if (!$sortfield) {
71 $sortfield = 'p.ref';
72}
73
74if (!$sortorder) {
75 $sortorder = 'ASC';
76}
77$limit = GETPOST('limit', 'int') ?GETPOST('limit', 'int') : $conf->liste_limit;
78$offset = $limit * $page;
79
80if (GETPOST('init')) {
81 unset($_SESSION['massstockmove']);
82}
83$listofdata = array();
84if (!empty($_SESSION['massstockmove'])) {
85 $listofdata = json_decode($_SESSION['massstockmove'], true);
86}
87
88
89/*
90 * Actions
91 */
92
93if ($action == 'addline' && !empty($user->rights->stock->mouvement->creer)) {
94 if (!($id_sw > 0)) {
95 //$error++;
96 //setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WarehouseSource")), null, 'errors');
97 if ($id_sw < 0) {
98 $id_sw = 0;
99 }
100 }
101 if (!($id_tw > 0)) {
102 $error++;
103 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WarehouseTarget")), null, 'errors');
104 }
105 if ($id_sw > 0 && $id_tw == $id_sw) {
106 $error++;
107 $langs->load("errors");
108 setEventMessages($langs->trans("ErrorWarehouseMustDiffers"), null, 'errors');
109 }
110 if (!($id_product > 0)) {
111 $error++;
112 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
113 }
114 if (!$qty) {
115 $error++;
116 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Qty")), null, 'errors');
117 }
118
119 // Check a batch number is provided if product need it
120 if (!$error) {
121 $producttmp = new Product($db);
122 $producttmp->fetch($id_product);
123 if ($producttmp->hasbatch()) {
124 if (empty($batch)) {
125 $error++;
126 $langs->load("errors");
127 setEventMessages($langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData", $producttmp->ref), null, 'errors');
128 }
129 }
130 }
131
132 // TODO Check qty is ok for stock move. Note qty may not be enough yet, but we make a check now to report a warning.
133 // What is more important is to have qty when doing action 'createmovements'
134 if (!$error) {
135 // Warning, don't forget lines already added into the $_SESSION['massstockmove']
136 if ($producttmp->hasbatch()) {
137 } else {
138 }
139 }
140
141 //var_dump($_SESSION['massstockmove']);exit;
142 if (!$error) {
143 if (count(array_keys($listofdata)) > 0) {
144 $id = max(array_keys($listofdata)) + 1;
145 } else {
146 $id = 1;
147 }
148 $listofdata[$id] = array('id'=>$id, 'id_product'=>$id_product, 'qty'=>$qty, 'id_sw'=>$id_sw, 'id_tw'=>$id_tw, 'batch'=>$batch);
149 $_SESSION['massstockmove'] = json_encode($listofdata);
150
151 //unset($id_sw);
152 //unset($id_tw);
153 unset($id_product);
154 unset($batch);
155 unset($qty);
156 }
157}
158
159if ($action == 'delline' && $idline != '' && !empty($user->rights->stock->mouvement->creer)) {
160 if (!empty($listofdata[$idline])) {
161 unset($listofdata[$idline]);
162 }
163 if (count($listofdata) > 0) {
164 $_SESSION['massstockmove'] = json_encode($listofdata);
165 } else {
166 unset($_SESSION['massstockmove']);
167 }
168}
169
170if ($action == 'createmovements' && !empty($user->rights->stock->mouvement->creer)) {
171 $error = 0;
172
173 if (!GETPOST("label")) {
174 $error++;
175 setEventMessages($langs->trans("ErrorFieldRequired"), $langs->transnoentitiesnoconv("MovementLabel"), null, 'errors');
176 }
177
178 $db->begin();
179
180 if (!$error) {
181 $product = new Product($db);
182
183 foreach ($listofdata as $key => $val) { // Loop on each movement to do
184 $id = $val['id'];
185 $id_product = $val['id_product'];
186 $id_sw = $val['id_sw'];
187 $id_tw = $val['id_tw'];
188 $qty = price2num($val['qty']);
189 $batch = $val['batch'];
190 $dlc = -1; // They are loaded later from serial
191 $dluo = -1; // They are loaded later from serial
192
193 if (!$error && $id_sw <> $id_tw && is_numeric($qty) && $id_product) {
194 $result = $product->fetch($id_product);
195
196 $product->load_stock('novirtual'); // Load array product->stock_warehouse
197
198 // Define value of products moved
199 $pricesrc = 0;
200 if (!empty($product->pmp)) {
201 $pricesrc = $product->pmp;
202 }
203 $pricedest = $pricesrc;
204
205 //print 'price src='.$pricesrc.', price dest='.$pricedest;exit;
206
207 if (empty($conf->productbatch->enabled) || !$product->hasbatch()) { // If product does not need lot/serial
208 // Remove stock if source warehouse defined
209 if ($id_sw > 0) {
210 $result1 = $product->correct_stock(
211 $user,
212 $id_sw,
213 $qty,
214 1,
215 GETPOST("label"),
216 $pricesrc,
217 GETPOST("codemove")
218 );
219 if ($result1 < 0) {
220 $error++;
221 setEventMessages($product->error, $product->errors, 'errors');
222 }
223 }
224
225 // Add stock
226 $result2 = $product->correct_stock(
227 $user,
228 $id_tw,
229 $qty,
230 0,
231 GETPOST("label"),
232 $pricedest,
233 GETPOST("codemove")
234 );
235 if ($result2 < 0) {
236 $error++;
237 setEventMessages($product->error, $product->errors, 'errors');
238 }
239 } else {
240 $arraybatchinfo = $product->loadBatchInfo($batch);
241 if (count($arraybatchinfo) > 0) {
242 $firstrecord = array_shift($arraybatchinfo);
243 $dlc = $firstrecord['eatby'];
244 $dluo = $firstrecord['sellby'];
245 //var_dump($batch);
246 //var_dump($arraybatchinfo);
247 //var_dump($firstrecord);
248 //var_dump($dlc);
249 //var_dump($dluo); exit;
250 } else {
251 $dlc = '';
252 $dluo = '';
253 }
254
255 // Remove stock
256 if ($id_sw > 0) {
257 $result1 = $product->correct_stock_batch(
258 $user,
259 $id_sw,
260 $qty,
261 1,
262 GETPOST("label"),
263 $pricesrc,
264 $dlc,
265 $dluo,
266 $batch,
267 GETPOST("codemove")
268 );
269 if ($result1 < 0) {
270 $error++;
271 setEventMessages($product->error, $product->errors, 'errors');
272 }
273 }
274
275 // Add stock
276 $result2 = $product->correct_stock_batch(
277 $user,
278 $id_tw,
279 $qty,
280 0,
281 GETPOST("label"),
282 $pricedest,
283 $dlc,
284 $dluo,
285 $batch,
286 GETPOST("codemove")
287 );
288 if ($result2 < 0) {
289 $error++;
290 setEventMessages($product->error, $product->errors, 'errors');
291 }
292 }
293 } else {
294 // dol_print_error('',"Bad value saved into sessions");
295 $error++;
296 }
297 }
298 }
299 //var_dump($_SESSION['massstockmove']);exit;
300
301 if (!$error) {
302 unset($_SESSION['massstockmove']);
303
304 $db->commit();
305 setEventMessages($langs->trans("StockMovementRecorded"), null, 'mesgs');
306 header("Location: ".DOL_URL_ROOT.'/product/stock/index.php'); // Redirect to avoid pb when using back
307 exit;
308 } else {
309 $db->rollback();
310 setEventMessages($langs->trans("Error"), null, 'errors');
311 }
312}
313
314if ($action == 'importCSV' && !empty($user->rights->stock->mouvement->creer)) {
315 dol_mkdir($conf->stock->dir_temp);
316 $nowyearmonth = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
317
318 $fullpath = $conf->stock->dir_temp."/".$user->id.'-csvfiletotimport.csv';
319 if (dol_move_uploaded_file($_FILES['userfile']['tmp_name'], $fullpath, 1) > 0) {
320 dol_syslog("File ".$fullpath." was added for import");
321 } else {
322 $error++;
323 $langs->load("errors");
324 setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
325 }
326
327 if (!$error) {
328 $importcsv = new ImportCsv($db, 'massstocklist');
329 //print $importcsv->separator;
330
331 $nblinesrecord = $importcsv->import_get_nb_of_lines($fullpath)-1;
332 $importcsv->import_open_file($fullpath);
333 $labelsrecord = $importcsv->import_read_record();
334
335 if ($nblinesrecord < 1) {
336 setEventMessages($langs->trans("BadNumberOfLinesMustHaveAtLeastOneLinePlusTitle"), null, 'errors');
337 } else {
338 $i=0;
339 $data = array();
340 $productstatic = new Product($db);
341 $warehousestatics = new Entrepot($db);
342 $warehousestatict = new Entrepot($db);
343
344 // Loop on each line in CSV file
345 while (($i < $nblinesrecord) && !$error) {
346 $newrecord = $importcsv->import_read_record();
347
348 $data[$i] = $newrecord;
349 if (count($data[$i]) == 1) {
350 // Only 1 empty line
351 unset($data[$i]);
352 $i++;
353 continue;
354 }
355
356 $tmp_id_sw = $data[$i][0]['val'];
357 $tmp_id_tw = $data[$i][1]['val'];
358 $tmp_id_product = $data[$i][2]['val'];
359 $tmp_qty = $data[$i][3]['val'];
360 $tmp_batch = $data[$i][4]['val'];
361
362 $errorforproduct = 0;
363 $isidorref = 'ref';
364 if (!is_numeric($tmp_id_product) && $tmp_id_product != '' && preg_match('/^id:/i', $tmp_id_product)) {
365 $isidorref = 'id';
366 }
367 $tmp_id_product = preg_replace('/^(id|ref):/i', '', $tmp_id_product);
368
369 if ($isidorref === 'ref') {
370 $tmp_id_product = preg_replace('/^ref:/', '', $tmp_id_product);
371 $result = fetchref($productstatic, $tmp_id_product);
372 if ($result === -2) {
373 $error++;
374 $errorforproduct = 1;
375 $langs->load("errors");
376 setEventMessages($langs->trans("ErrorMultipleRecordFoundFromRef", $tmp_id_product), null, 'errors');
377 } elseif ($result <= 0) {
378 $error++;
379 $errorforproduct = 1;
380 $langs->load("errors");
381 setEventMessages($langs->trans("ErrorRefNotFound", $tmp_id_product), null, 'errors');
382 }
383 $tmp_id_product = $result;
384 }
385 $data[$i][2]['val'] = $tmp_id_product;
386 if (!$errorforproduct && !($tmp_id_product > 0)) {
387 $error++;
388 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Product")), null, 'errors');
389 }
390
391 if ($tmp_id_sw !== '') {
392 // For source, we allow empty value
393 $errorforwarehouses = 0;
394 $isidorref = 'ref';
395 if (!is_numeric($tmp_id_sw) && $tmp_id_sw != '' && preg_match('/^id:/i', $tmp_id_sw)) {
396 $isidorref = 'id';
397 }
398 $tmp_id_sw = preg_replace('/^(id|ref):/i', '', $tmp_id_sw);
399 if ($isidorref === 'ref') {
400 $tmp_id_sw = preg_replace('/^ref:/', '', $tmp_id_sw);
401 $result = fetchref($warehousestatics, $tmp_id_sw);
402 if ($result === -2) {
403 $error++;
404 $errorforwarehouses = 1;
405 $langs->load("errors");
406 setEventMessages($langs->trans("ErrorMultipleRecordFoundFromRef", $tmp_id_sw), null, 'errors');
407 } elseif ($result <= 0) {
408 $error++;
409 $errorforwarehouses = 1;
410 $langs->load("errors");
411 setEventMessages($langs->trans("ErrorRefNotFound", $tmp_id_sw), null, 'errors');
412 }
413 $tmp_id_sw = $result;
414 }
415 $data[$i][0]['val'] = $tmp_id_sw;
416 if (!$errorforwarehouses && !($tmp_id_sw > 0)) {
417 $error++;
418 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WarehouseSource")), null, 'errors');
419 }
420 }
421
422 $errorforwarehouset = 0;
423 $isidorref = 'ref';
424 if (!is_numeric($tmp_id_tw) && $tmp_id_tw != '' && preg_match('/^id:/i', $tmp_id_tw)) {
425 $isidorref = 'id';
426 }
427 $tmp_id_tw = preg_replace('/^(id|ref):/i', '', $tmp_id_tw);
428 if ($isidorref === 'ref') {
429 $tmp_id_tw = preg_replace('/^ref:/', '', $tmp_id_tw);
430 $result = fetchref($warehousestatict, $tmp_id_tw);
431 if ($result === -2) {
432 $error++;
433 $errorforwarehouset = 1;
434 $langs->load("errors");
435 setEventMessages($langs->trans("ErrorMultipleRecordFoundFromRef", $tmp_id_tw), null, 'errors');
436 } elseif ($result <= 0) {
437 $error++;
438 $errorforwarehouset = 1;
439 $langs->load("errors");
440 setEventMessages($langs->trans("ErrorRefNotFound", $tmp_id_tw), null, 'errors');
441 }
442 $tmp_id_tw = $result;
443 }
444 $data[$i][1]['val'] = $tmp_id_tw;
445 if (!$errorforwarehouset && !($tmp_id_tw > 0)) {
446 $error++;
447 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("WarehouseTarget")), null, 'errors');
448 }
449
450 // If a source is provided and same than target
451 if ($tmp_id_sw > 0 && $tmp_id_tw == $tmp_id_sw) {
452 $error++;
453 $langs->load("errors");
454 setEventMessages($langs->trans("ErrorWarehouseMustDiffers"), null, 'errors');
455 }
456 if (!$tmp_qty) {
457 $error++;
458 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Qty")), null, 'errors');
459 }
460
461 // Check a batch number is provided if product need it
462 if (!$error) {
463 $producttmp = new Product($db);
464 $producttmp->fetch($tmp_id_product);
465 if ($producttmp->hasbatch()) {
466 if (empty($tmp_batch)) {
467 $error++;
468 $langs->load("errors");
469 setEventMessages($langs->trans("ErrorTryToMakeMoveOnProductRequiringBatchData", $producttmp->ref), null, 'errors');
470 }
471 }
472 }
473
474 $i++;
475 }
476
477 if (!$error) {
478 foreach ($data as $key => $value) {
479 if (count(array_keys($listofdata)) > 0) {
480 $id = max(array_keys($listofdata)) + 1;
481 } else {
482 $id = 1;
483 }
484 $tmp_id_sw = $data[$key][0]['val'];
485 $tmp_id_tw = $data[$key][1]['val'];
486 $tmp_id_product = $data[$key][2]['val'];
487 $tmp_qty = $data[$key][3]['val'];
488 $tmp_batch = $data[$key][4]['val'];
489 $listofdata[$key] = array('id'=>$key, 'id_sw'=>$tmp_id_sw, 'id_tw'=>$tmp_id_tw, 'id_product'=>$tmp_id_product, 'qty'=>$tmp_qty, 'batch'=>$tmp_batch);
490 }
491 }
492 }
493 }
494 if ($error) {
495 $listofdata = array();
496 }
497
498 $_SESSION['massstockmove'] = json_encode($listofdata);
499}
500
501if ($action == 'confirm_deletefile' && $confirm == 'yes') {
502 $langs->load("other");
503
504 $param = '&datatoimport='.urlencode($datatoimport).'&format='.urlencode($format);
505 if ($excludefirstline) {
506 $param .= '&excludefirstline='.urlencode($excludefirstline);
507 }
508 if ($endatlinenb) {
509 $param .= '&endatlinenb='.urlencode($endatlinenb);
510 }
511
512 $file = $conf->stock->dir_temp.'/'.GETPOST('urlfile'); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP).
513 $ret = dol_delete_file($file);
514 if ($ret) {
515 setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
516 } else {
517 setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
518 }
519 Header('Location: '.$_SERVER["PHP_SELF"]);
520 exit;
521}
522
523
524/*
525 * View
526 */
527
528$now = dol_now();
529$error = 0;
530
531$form = new Form($db);
532$formproduct = new FormProduct($db);
533$productstatic = new Product($db);
534$warehousestatics = new Entrepot($db);
535$warehousestatict = new Entrepot($db);
536
537$help_url = 'EN:Module_Stocks_En|FR:Module_Stock|ES:Módulo_Stocks|DE:Modul_Bestände';
538
539$title = $langs->trans('MassMovement');
540
541llxHeader('', $title, $help_url);
542
543print load_fiche_titre($langs->trans("MassStockTransferShort"), '', 'stock');
544
545$titletoadd = $langs->trans("Select");
546$buttonrecord = $langs->trans("RecordMovements");
547$titletoaddnoent = $langs->transnoentitiesnoconv("Select");
548$buttonrecordnoent = $langs->transnoentitiesnoconv("RecordMovements");
549print '<span class="opacitymedium">'.$langs->trans("SelectProductInAndOutWareHouse", $titletoaddnoent, $buttonrecordnoent).'</span>';
550
551print '<br>';
552//print '<br>';
553
554// Form to upload a file
555print '<form name="userfile" action="'.$_SERVER["PHP_SELF"].'" enctype="multipart/form-data" METHOD="POST">';
556print '<input type="hidden" name="token" value="'.newToken().'">';
557print '<input type="hidden" name="action" value="importCSV">';
558if (!empty($conf->dol_optimize_smallscreen)) {
559 print '<br>';
560}
561print '<span class="opacitymedium">';
562print $langs->trans("or");
563print ' ';
564$importcsv = new ImportCsv($db, 'massstocklist');
565print $form->textwithpicto($langs->trans('SelectAStockMovementFileToImport'), $langs->transnoentitiesnoconv("InfoTemplateImport", $importcsv->separator));
566print '</span>';
567
568$maxfilesizearray = getMaxFileSizeArray();
569$maxmin = $maxfilesizearray['maxmin'];
570if ($maxmin > 0) {
571 print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
572}
573print '<input type="file" name="userfile" size="20" maxlength="80"> &nbsp; &nbsp; ';
574$out = (empty($conf->global->MAIN_UPLOAD_DOC) ? ' disabled' : '');
575print '<input type="submit" class="button small smallpaddingimp" value="'.$langs->trans("ImportFromCSV").'"'.$out.' name="sendit">';
576$out = '';
577if (!empty($conf->global->MAIN_UPLOAD_DOC)) {
578 $max = $conf->global->MAIN_UPLOAD_DOC; // In Kb
579 $maxphp = @ini_get('upload_max_filesize'); // In unknown
580 if (preg_match('/k$/i', $maxphp)) {
581 $maxphp = preg_replace('/k$/i', '', $maxphp);
582 $maxphp = $maxphp * 1;
583 }
584 if (preg_match('/m$/i', $maxphp)) {
585 $maxphp = preg_replace('/m$/i', '', $maxphp);
586 $maxphp = $maxphp * 1024;
587 }
588 if (preg_match('/g$/i', $maxphp)) {
589 $maxphp = preg_replace('/g$/i', '', $maxphp);
590 $maxphp = $maxphp * 1024 * 1024;
591 }
592 if (preg_match('/t$/i', $maxphp)) {
593 $maxphp = preg_replace('/t$/i', '', $maxphp);
594 $maxphp = $maxphp * 1024 * 1024 * 1024;
595 }
596 $maxphp2 = @ini_get('post_max_size'); // In unknown
597 if (preg_match('/k$/i', $maxphp2)) {
598 $maxphp2 = preg_replace('/k$/i', '', $maxphp2);
599 $maxphp2 = $maxphp2 * 1;
600 }
601 if (preg_match('/m$/i', $maxphp2)) {
602 $maxphp2 = preg_replace('/m$/i', '', $maxphp2);
603 $maxphp2 = $maxphp2 * 1024;
604 }
605 if (preg_match('/g$/i', $maxphp2)) {
606 $maxphp2 = preg_replace('/g$/i', '', $maxphp2);
607 $maxphp2 = $maxphp2 * 1024 * 1024;
608 }
609 if (preg_match('/t$/i', $maxphp2)) {
610 $maxphp2 = preg_replace('/t$/i', '', $maxphp2);
611 $maxphp2 = $maxphp2 * 1024 * 1024 * 1024;
612 }
613 // Now $max and $maxphp and $maxphp2 are in Kb
614 $maxmin = $max;
615 $maxphptoshow = $maxphptoshowparam = '';
616 if ($maxphp > 0) {
617 $maxmin = min($max, $maxphp);
618 $maxphptoshow = $maxphp;
619 $maxphptoshowparam = 'upload_max_filesize';
620 }
621 if ($maxphp2 > 0) {
622 $maxmin = min($max, $maxphp2);
623 if ($maxphp2 < $maxphp) {
624 $maxphptoshow = $maxphp2;
625 $maxphptoshowparam = 'post_max_size';
626 }
627 }
628
629 $langs->load('other');
630 $out .= ' ';
631 $out .= info_admin($langs->trans("ThisLimitIsDefinedInSetup", $max, $maxphptoshow), 1);
632} else {
633 $out .= ' ('.$langs->trans("UploadDisabled").')';
634}
635print $out;
636
637print '</form>';
638
639print '<br><br>';
640
641// Form to add a line
642print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire">';
643print '<input type="hidden" name="token" value="'.newToken().'">';
644print '<input type="hidden" name="action" value="addline">';
645
646
647print '<div class="div-table-responsive-no-min">';
648print '<table class="liste centpercent">';
649
650$param = '';
651
652print '<tr class="liste_titre">';
653print getTitleFieldOfList($langs->trans('WarehouseSource'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
654print getTitleFieldOfList($langs->trans('WarehouseTarget'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
655print getTitleFieldOfList($langs->trans('Product'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
656if (isModEnabled('productbatch')) {
657 print getTitleFieldOfList($langs->trans('Batch'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'tagtd maxwidthonsmartphone ');
658}
659print getTitleFieldOfList($langs->trans('Qty'), 0, $_SERVER["PHP_SELF"], '', $param, '', '', $sortfield, $sortorder, 'right tagtd maxwidthonsmartphone ');
660print getTitleFieldOfList('', 0);
661print '</tr>';
662
663print '<tr class="oddeven">';
664// From warehouse
665print '<td class="nowraponall">';
666print img_picto($langs->trans("WarehouseSource"), 'stock', 'class="paddingright"').$formproduct->selectWarehouses($id_sw, 'id_sw', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp maxwidth200');
667print '</td>';
668// To warehouse
669print '<td class="nowraponall">';
670print img_picto($langs->trans("WarehouseTarget"), 'stock', 'class="paddingright"').$formproduct->selectWarehouses($id_tw, 'id_tw', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth200imp maxwidth200');
671print '</td>';
672// Product
673print '<td class="nowraponall">';
674$filtertype = 0;
675if (!empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
676 $filtertype = '';
677}
678if ($conf->global->PRODUIT_LIMIT_SIZE <= 0) {
679 $limit = '';
680} else {
681 $limit = $conf->global->PRODUIT_LIMIT_SIZE;
682}
683
684print img_picto($langs->trans("Product"), 'product', 'class="paddingright"');
685print $form->select_produits($id_product, 'productid', $filtertype, $limit, 0, -1, 2, '', 1, array(), 0, '1', 0, 'minwidth200imp maxwidth300', 1, '', null, 1);
686print '</td>';
687// Batch number
688if (isModEnabled('productbatch')) {
689 print '<td class="nowraponall">';
690 print img_picto($langs->trans("LotSerial"), 'lot', 'class="paddingright"');
691 print '<input type="text" name="batch" class="flat maxwidth75" value="'.dol_escape_htmltag($batch).'">';
692 print '</td>';
693}
694// Qty
695print '<td class="right"><input type="text" class="flat maxwidth50 right" name="qty" value="'.price2num((float) $qty, 'MS').'"></td>';
696// Button to add line
697print '<td class="right"><input type="submit" class="button" name="addline" value="'.dol_escape_htmltag($titletoadd).'"></td>';
698
699print '</tr>';
700
701foreach ($listofdata as $key => $val) {
702 $productstatic->id = 0;
703 $productstatic->fetch($val['id_product']);
704
705 $warehousestatics->id = 0;
706 if ($val['id_sw'] > 0) {
707 $warehousestatics->fetch($val['id_sw']);
708 }
709 $warehousestatict->id = 0;
710 if ($val['id_tw'] > 0) {
711 $warehousestatict->fetch($val['id_tw']);
712 }
713
714 if ($productstatic->id <= 0) {
715 $error++;
716 setEventMessages($langs->trans("ObjectNotFound", $langs->transnoentitiesnoconv("Product").' (id='.$val['id_product'].')'), null, 'errors');
717 }
718 if ($warehousestatics->id < 0) { // We accept 0 for source warehouse id
719 $error++;
720 setEventMessages($langs->trans("ObjectNotFound", $langs->transnoentitiesnoconv("WarehouseSource").' (id='.$val['id_sw'].')'), null, 'errors');
721 }
722 if ($warehousestatict->id <= 0) {
723 $error++;
724 setEventMessages($langs->trans("ObjectNotFound", $langs->transnoentitiesnoconv("WarehouseTarget").' (id='.$val['id_tw'].')'), null, 'errors');
725 }
726
727 if (!$error) {
728 print '<tr class="oddeven">';
729 print '<td>';
730 if ($warehousestatics->id > 0) {
731 print $warehousestatics->getNomUrl(1);
732 } else {
733 print '<span class="opacitymedium">';
734 print $langs->trans("None");
735 print '</span>';
736 }
737 print '</td>';
738 print '<td>';
739 print $warehousestatict->getNomUrl(1);
740 print '</td>';
741 print '<td>';
742 print $productstatic->getNomUrl(1).' - '.dol_escape_htmltag($productstatic->label);
743 print '</td>';
744 if (isModEnabled('productbatch')) {
745 print '<td>';
746 print dol_escape_htmltag($val['batch']);
747 print '</td>';
748 }
749 print '<td class="right">'.price2num((float) $val['qty'], 'MS').'</td>';
750 print '<td class="right"><a href="'.$_SERVER["PHP_SELF"].'?action=delline&token='.newToken().'&idline='.$val['id'].'">'.img_delete($langs->trans("Remove")).'</a></td>';
751 print '</tr>';
752 }
753}
754
755print '</table>';
756print '</div>';
757
758print '</form>';
759
760print '<br>';
761
762// Form to validate all movements
763if (count($listofdata)) {
764 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="formulaire2" class="formconsumeproduce">';
765 print '<input type="hidden" name="token" value="'.newToken().'">';
766 print '<input type="hidden" name="action" value="createmovements">';
767
768 // Button to record mass movement
769 $codemove = (GETPOSTISSET("codemove") ? GETPOST("codemove", 'alpha') : dol_print_date(dol_now(), '%Y%m%d%H%M%S'));
770 $labelmovement = GETPOST("label") ? GETPOST('label') : $langs->trans("MassStockTransferShort").' '.dol_print_date($now, '%Y-%m-%d %H:%M');
771
772 print '<div class="center">';
773 print '<span class="fieldrequired">'.$langs->trans("InventoryCode").':</span> ';
774 print '<input type="text" name="codemove" class="maxwidth300" value="'.dol_escape_htmltag($codemove).'"> &nbsp; ';
775 print '<span class="clearbothonsmartphone"></span>';
776 print $langs->trans("MovementLabel").': ';
777 print '<input type="text" name="label" class="minwidth300" value="'.dol_escape_htmltag($labelmovement).'"><br>';
778 print '<br>';
779
780 print '<div class="center"><input type="submit" class="button" name="valid" value="'.dol_escape_htmltag($buttonrecord).'"></div>';
781
782 print '<br>';
783 print '</div>';
784
785 print '</form>';
786}
787
788if ($action == 'delete') {
789 print $form->formconfirm($_SERVER["PHP_SELF"].'?urlfile='.urlencode(GETPOST('urlfile')).'&step=3'.$param, $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', 0, 1);
790}
791
792// End of page
793llxFooter();
794$db->close();
795
796
804function startsWith($haystack, $needle)
805{
806 $length = strlen($needle);
807 return substr($haystack, 0, $length) === $needle;
808}
809
817function fetchref($static_object, $tmp_ref)
818{
819 if (startsWith($tmp_ref, 'ref:')) {
820 $tmp_ref = str_replace('ref:', '', $tmp_ref);
821 }
822 $static_object->id = 0;
823 $static_object->fetch('', $tmp_ref);
824 return $static_object->id;
825}
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 generation of HTML components Only common components must be here.
Class with static methods for building HTML components related to products Only components common to ...
Class to import CSV files.
Class to manage products or services.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles='addedfile', $upload_dir='')
Make control on an uploaded file from an GUI page and move it to final destination.
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip='', $forcenowrapcolumntitle=0)
Get title line of an array.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
startsWith($haystack, $needle)
Verify if $haystack startswith $needle.
fetchref($static_object, $tmp_ref)
Fetch object with ref.
getMaxFileSizeArray()
Return the max allowed for file upload.
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.