dolibarr 22.0.5
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Simon TOSSER <simon@kornog-computing.com>
5 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
6 * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8 * Copyright (C) 2013 Marcos García <marcosgdf@gmail.com>
9 * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
10 * Copyright (C) 2014-2017 Francis Appels <francis.appels@yahoo.com>
11 * Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
12 * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
13 * Copyright (C) 2016 Yasser Carreón <yacasia@gmail.com>
14 * Copyright (C) 2018 Quentin Vial-Gouteyron <quentin.vial-gouteyron@atm-consulting.fr>
15 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
16 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 3 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <https://www.gnu.org/licenses/>.
30 */
31
38// Load Dolibarr environment
39require '../main.inc.php';
40require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
41require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
42require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
44require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
45require_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
46require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
47require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
48require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
49require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
50if (isModEnabled("product") || isModEnabled("service")) {
51 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
52}
53if (isModEnabled("propal")) {
54 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
55}
56require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
57require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.orderline.class.php';
58require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
59if (isModEnabled('productbatch')) {
60 require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
61}
62if (isModEnabled('project')) {
63 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
64 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
65}
74$langs->loadLangs(array("receptions", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal', 'sendings'));
75
76if (isModEnabled('incoterm')) {
77 $langs->load('incoterm');
78}
79if (isModEnabled('productbatch')) {
80 $langs->load('productbatch');
81}
82
83$origin = GETPOST('origin', 'alpha') ? GETPOST('origin', 'alpha') : 'reception'; // Example: commande, propal
84$origin_id = GETPOSTINT('id') ? GETPOSTINT('id') : '';
85$id = $origin_id;
86if (empty($origin_id)) {
87 $origin_id = GETPOSTINT('origin_id'); // Id of order or propal
88}
89if (empty($origin_id)) {
90 $origin_id = GETPOSTINT('object_id'); // Id of order or propal
91}
92if (empty($origin_id)) {
93 $origin_id = GETPOSTINT('originid'); // Id of order or propal
94}
95$ref = GETPOST('ref', 'alpha');
96$line_id = GETPOSTINT('lineid') ? GETPOSTINT('lineid') : 0;
97$facid = GETPOSTINT('facid');
98
99$action = GETPOST('action', 'alpha');
100//Select mail models is same action as presend
101if (GETPOST('modelselected')) {
102 $action = 'presend';
103}
104$confirm = GETPOST('confirm', 'alpha');
105$cancel = GETPOST('cancel', 'alpha');
106$backtopage = GETPOST('backtopage', 'alpha');
107$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
108
109//PDF
110$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
111$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
112$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
113
114$object = new Reception($db);
115$objectorder = new CommandeFournisseur($db);
116$extrafields = new ExtraFields($db);
117
118// fetch optionals attributes and labels
119$extrafields->fetch_name_optionals_label($object->table_element);
120$extrafields->fetch_name_optionals_label($object->table_element_line);
121$extrafields->fetch_name_optionals_label($objectorder->table_element_line);
122
123// Load object. Make an object->fetch
124include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
125
126// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
127$hookmanager->initHooks(array('receptioncard', 'globalcard'));
128
129$date_delivery = dol_mktime(GETPOSTINT('date_deliveryhour'), GETPOSTINT('date_deliverymin'), 0, GETPOSTINT('date_deliverymonth'), GETPOSTINT('date_deliveryday'), GETPOSTINT('date_deliveryyear'));
130
131if ($id > 0 || !empty($ref)) {
132 $object->fetch($id, $ref);
133 $object->fetch_thirdparty();
134
135 $typeobject = '';
136 if (!empty($object->origin)) {
137 $origin = $object->origin;
138 $typeobject = $object->origin;
139
140 $object->fetch_origin();
141 }
142
143 // Set $origin_id and $objectsrc
144 if (($origin == 'order_supplier' || $origin == 'supplier_order') && is_object($object->origin_object) && isModEnabled("supplier_order")) {
145 $origin_id = $object->origin_object->id;
146 $objectsrc = $object->origin_object;
147 }
148}
149
150// Security check
151$socid = '';
152if ($user->socid) {
153 $socid = $user->socid;
154}
155
156// TODO Test on reception module on only
157if (isModEnabled("reception") || $origin == 'reception' || empty($origin)) {
158 $result = restrictedArea($user, 'reception', $object->id);
159} else {
160 // We do not use the reception module, so we test permission on the supplier orders
161 if ($origin == 'supplierorder' || $origin == 'order_supplier') {
162 $result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande');
163 } elseif (!$user->hasRight($origin, 'lire') && !$user->hasRight($origin, 'read')) {
165 }
166}
167
168if (isModEnabled("reception")) {
169 $permissiontoread = $user->hasRight('reception', 'lire');
170 $permissiontoadd = $user->hasRight('reception', 'creer');
171 $permissiondellink = $user->hasRight('reception', 'creer'); // Used by the include of actions_dellink.inc.php
172 $permissiontovalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate')));
173 $permissiontodelete = $user->hasRight('reception', 'supprimer');
174} else {
175 $permissiontoread = $user->hasRight('fournisseur', 'commande', 'receptionner');
176 $permissiontoadd = $user->hasRight('fournisseur', 'commande', 'receptionner');
177 $permissiondellink = $user->hasRight('fournisseur', 'commande', 'receptionner'); // Used by the include of actions_dellink.inc.php
178 $permissiontovalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande', 'receptionner')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande_advance', 'check')));
179 $permissiontodelete = $user->hasRight('fournisseur', 'commande', 'receptionner');
180}
181$permissiontoeditextra = $permissiontoadd;
182if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
183 // For action 'update_extras', is there a specific permission set for the attribute to update
184 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
185}
186
187$error = 0;
188
189
190/*
191 * Actions
192 */
193
194$parameters = array();
195$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
196if ($reshook < 0) {
197 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
198}
199
200if (empty($reshook)) {
201 /*
202 $backurlforlist = DOL_URL_ROOT.'/reception/list.php';
203
204 if (empty($backtopage) || ($cancel && empty($id))) {
205 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
206 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
207 $backtopage = $backurlforlist;
208 } else {
209 $backtopage = dol_buildpath('/mymodule/myobject_card.php', 1).'?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
210 }
211 }
212 }
213 */
214
215 if ($cancel) {
216 if (!empty($backtopageforcancel)) {
217 header("Location: ".$backtopageforcancel);
218 exit;
219 } elseif (!empty($backtopage)) {
220 header("Location: ".$backtopage);
221 exit;
222 }
223
224 $action = '';
225 }
226
227 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
228
229 // Reopen
230 if ($action == 'reopen' && $permissiontoadd) { // Test on permissions not required here
231 $result = $object->reOpen();
232 }
233
234 // Confirm back to draft status
235 if ($action == 'modif' && $permissiontoadd) {
236 $result = $object->setDraft($user);
237 if ($result >= 0) {
238 // Define output language
239 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
240 $outputlangs = $langs;
241 $newlang = '';
242 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
243 $newlang = GETPOST('lang_id', 'aZ09');
244 }
245 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
246 $newlang = $object->thirdparty->default_lang;
247 }
248 if (!empty($newlang)) {
249 $outputlangs = new Translate("", $conf);
250 $outputlangs->setDefaultLang($newlang);
251 }
252 $model = $object->model_pdf;
253 $ret = $object->fetch($id); // Reload to get new records
254 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
255 }
256 } else {
257 setEventMessages($object->error, $object->errors, 'errors');
258 }
259 }
260
261 // Set incoterm
262 if ($action == 'set_incoterms' && isModEnabled('incoterm') && $permissiontoadd) {
263 $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
264 }
265
266 if ($action == 'setref_supplier' && $permissiontoadd) {
267 if ($result < 0) {
268 setEventMessages($object->error, $object->errors, 'errors');
269 }
270
271 $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'RECEPTION_MODIFY');
272 if ($result < 0) {
273 setEventMessages($object->error, $object->errors, 'errors');
274 $action = 'editref_supplier';
275 } else {
276 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
277 exit;
278 }
279 }
280
281 if ($action == 'update_extras' && $permissiontoeditextra) {
282 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
283
284 $attribute_name = GETPOST('attribute', 'aZ09');
285
286 // Fill array 'array_options' with data from update form
287 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
288 if ($ret < 0) {
289 $error++;
290 }
291
292 if (!$error) {
293 $result = $object->updateExtraField($attribute_name, 'RECEPTION_MODIFY');
294 if ($result < 0) {
295 setEventMessages($object->error, $object->errors, 'errors');
296 $error++;
297 }
298 }
299
300 if ($error) {
301 $action = 'edit_extras';
302 }
303 }
304
305 // Create reception
306 if ($action == 'add' && $permissiontoadd) {
307 $error = 0;
308
309 $db->begin();
310
311 $object->note = GETPOST('note', 'alpha');
312 $object->note_private = GETPOST('note', 'alpha');
313 $object->origin = $origin;
314 $object->origin_id = $origin_id;
315 $object->fk_project = GETPOSTINT('projectid');
316 $object->weight = GETPOST('weight') == '' ? null : GETPOSTINT('weight');
317 $object->trueHeight = GETPOST('trueHeight') == '' ? null : GETPOSTINT('trueHeight');
318 $object->trueWidth = GETPOST('trueWidth') == '' ? null : GETPOSTINT('trueWidth');
319 $object->trueDepth = GETPOST('trueDepth') == '' ? null : GETPOSTINT('trueDepth');
320 $object->size_units = GETPOSTINT('size_units');
321 $object->weight_units = GETPOSTINT('weight_units');
322
323 // On va boucler sur chaque ligne du document d'origine pour completer object reception
324 // avec info diverses + qte a livrer
325
326 if ($object->origin == "supplierorder") {
327 $object->origin = 'order_supplier';
328 $classname = 'CommandeFournisseur';
329 } else {
330 $classname = ucfirst($object->origin);
331 }
332 $objectsrc = new $classname($db);
333 $objectsrc->fetch($object->origin_id);
334
335 $object->socid = $objectsrc->socid;
336 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
337 $object->model_pdf = GETPOST('model');
338 $object->date_delivery = $date_delivery; // Date delivery planned
339 $object->fk_delivery_address = $objectsrc->fk_delivery_address;
340 $object->shipping_method_id = GETPOSTINT('shipping_method_id');
341 $object->tracking_number = GETPOST('tracking_number', 'alpha');
342 $object->note_private = GETPOST('note_private', 'restricthtml');
343 $object->note_public = GETPOST('note_public', 'restricthtml');
344 $object->fk_incoterms = GETPOSTINT('incoterm_id');
345 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
346
347 $batch_line = array();
348 $stockLine = array();
349 $array_options = array();
350
351 $totalqty = 0;
352
353 $num = 0;
354 foreach ($_POST as $key => $value) {
355 // without batch module enabled
356
357 if (strpos($key, 'qtyasked') !== false) {
358 $num++;
359 }
360 }
361
362 // Loop lines to calculate $totalqty
363 for ($i = 1; $i <= $num; $i++) {
364 $idl = "idl".$i; // id line source
365
366 //$sub_qty = array();
367 //$subtotalqty = 0;
368
369 //$j = 0;
370 //$batch = "batchl".$i."_0";
371 //$stockLocation = "ent1".$i."_0";
372 $qty = "qtyl".$i; // qty
373
374 //reception line for product with no batch management and no multiple stock location
375 if (GETPOST($qty, 'alpha') > 0) {
376 $totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
377 }
378
379 // Extrafields
380 $array_options[$i] = $extrafields->getOptionalsFromPost($object->table_element_line, (string) $i);
381 }
382
383
384 if ($totalqty > 0) { // There is at least one thing to ship
385 for ($i = 1; $i <= $num; $i++) {
386 $idl = "idl".$i; // id line source
387 $lineToTest = '';
388 $lineId = GETPOSTINT($idl);
389 foreach ($objectsrc->lines as $linesrc) {
390 if ($linesrc->id == $lineId) {
391 $lineToTest = $linesrc;
392 break;
393 }
394 }
395 if (empty($lineToTest)) {
396 continue;
397 }
398 $qty = "qtyl".$i;
399 $comment = "comment".$i;
400 // EATBY <-> DLUO and SELLBY <-> DLC, see productbatch.class.php
401 $eatby = "dluo".$i;
402 $sellby = "dlc".$i;
403 $batch = "batch".$i;
404 $cost_price = "cost_price".$i;
405
406 //var_dump(GETPOST("productl".$i, 'int').' '.GETPOST('entl'.$i, 'int').' '.GETPOST($idl, 'int').' '.GETPOST($qty, 'int').' '.GETPOST($batch, 'alpha'));
407
408 //if (GETPOST($qty, 'int') > 0 || (GETPOST($qty, 'int') == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS')) || (GETPOST($qty, 'int') < 0 && getDolGlobalString('RECEPTION_ALLOW_NEGATIVE_QTY'))) {
409 if (GETPOSTFLOAT($qty) > 0 || (GETPOSTFLOAT($qty) == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS'))) {
410 $ent = "entl".$i;
411 $idl = "idl".$i;
412
413 $entrepot_id = is_numeric(GETPOST($ent)) ? GETPOSTINT($ent) : GETPOSTINT('entrepot_id');
414
415 /*
416 if (!empty($lineToTest)) {
417 $fk_product = $lineToTest->fk_product;
418 } else {
419 $fk_product = $linesrc->fk_product;
420 }*/
421 $fk_product = GETPOSTINT("productl".$i);
422
423 if ($entrepot_id < 0) {
424 $entrepot_id = '';
425 }
426 if (!($fk_product > 0) && !getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
427 $entrepot_id = 0;
428 }
429
430 $eatby = GETPOST($eatby, 'alpha');
431 $sellby = GETPOST($sellby, 'alpha');
432 $eatbydate = str_replace('/', '-', $eatby);
433 $sellbydate = str_replace('/', '-', $sellby);
434
435 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
436 $ret = $object->addline($entrepot_id, GETPOSTINT($idl), (float) price2num(GETPOST($qty), 'MS'), $array_options[$i], GETPOST($comment), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch), GETPOSTFLOAT($cost_price, 'MU'));
437 } else {
438 $ret = $object->addline($entrepot_id, GETPOSTINT($idl), (float) price2num(GETPOST($qty), 'MS'), $array_options[$i], GETPOST($comment), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch));
439 }
440 if ($ret < 0) {
441 setEventMessages($object->error, $object->errors, 'errors');
442 $error++;
443 }
444 }
445 }
446
447 // Fill array 'array_options' with data from add form
448 $ret = $extrafields->setOptionalsFromPost(null, $object);
449 if ($ret < 0) {
450 $error++;
451 }
452 if (!$error) {
453 $ret = $object->create($user); // This create reception (like Odoo picking) and line of receptions. Stock movement will when validating reception.
454
455 if ($ret <= 0) {
456 setEventMessages($object->error, $object->errors, 'errors');
457 $error++;
458 } else {
459 // Define output language
460 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
461 $object->fetch_thirdparty();
462 $outputlangs = $langs;
463 $newlang = '';
464 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
465 $newlang = GETPOST('lang_id', 'aZ09');
466 }
467 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
468 $newlang = $object->thirdparty->default_lang;
469 }
470 if (!empty($newlang)) {
471 $outputlangs = new Translate("", $conf);
472 $outputlangs->setDefaultLang($newlang);
473 }
474 $model = $object->model_pdf;
475 $ret = $object->fetch($object->id); // Reload to get new records
476
477 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
478 if ($result < 0) {
479 dol_print_error($db, $object->error, $object->errors);
480 }
481 }
482 }
483 }
484 } else {
485 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("QtyToReceive").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
486 $error++;
487 }
488
489 if (!$error) {
490 $db->commit();
491 header("Location: card.php?id=".$object->id);
492 exit;
493 } else {
494 $db->rollback();
495 //$_GET["commande_id"] = GETPOSTINT('commande_id');
496 $action = 'create';
497 }
498 } elseif ($action == 'confirm_valid' && $confirm == 'yes' && $permissiontovalidate) {
499 $object->fetch_thirdparty();
500
501 $result = $object->valid($user);
502
503 if ($result < 0) {
504 $langs->load("errors");
505 setEventMessages($langs->trans($object->error), null, 'errors');
506 } else {
507 // Define output language
508 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
509 $outputlangs = $langs;
510 $newlang = '';
511 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
512 $newlang = GETPOST('lang_id', 'aZ09');
513 }
514 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
515 $newlang = $object->thirdparty->default_lang;
516 }
517 if (!empty($newlang)) {
518 $outputlangs = new Translate("", $conf);
519 $outputlangs->setDefaultLang($newlang);
520 }
521 $model = $object->model_pdf;
522 $ret = $object->fetch($id); // Reload to get new records
523
524 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
525 if ($result < 0) {
526 dol_print_error($db, $object->error, $object->errors);
527 }
528 }
529 }
530 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
531 $result = $object->delete($user);
532 if ($result > 0) {
533 header("Location: ".DOL_URL_ROOT.'/reception/index.php');
534 exit;
535 } else {
536 setEventMessages($object->error, $object->errors, 'errors');
537 }
538
539 // TODO add alternative status
540 /*} elseif ($action == 'reopen' && ($user->hasRights('reception', 'creer') || $user->hasRights('reception', 'reception_advance', 'validate'))) {
541 $result = $object->setStatut(0);
542 if ($result < 0) {
543 setEventMessages($object->error, $object->errors, 'errors');
544 }*/
545 } elseif ($action == 'setdate_livraison' && $permissiontoadd) {
546 $datedelivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
547
548 $object->fetch($id);
549 $result = $object->setDeliveryDate($user, $datedelivery);
550 if ($result < 0) {
551 setEventMessages($object->error, $object->errors, 'errors');
552 }
553 } elseif (in_array($action, array('settracking_number', 'settracking_url', 'settrueWeight', 'settrueWidth', 'settrueHeight', 'settrueDepth', 'setshipping_method_id')) && $permissiontoadd) {
554 // Action update
555 $error = 0;
556
557 if ($action == 'settracking_number') { // Test on permission already done
558 $object->tracking_number = trim(GETPOST('tracking_number', 'alpha'));
559 }
560 if ($action == 'settracking_url') { // Test on permission already done
561 $object->tracking_url = trim(GETPOST('tracking_url', 'restricthtml'));
562 }
563 if ($action == 'settrueWeight') { // Test on permission already done
564 $object->trueWeight = GETPOST('trueWeight');
565 $object->weight_units = GETPOSTINT('weight_units');
566 }
567 if ($action == 'settrueWidth') { // Test on permission already done
568 $object->trueWidth = GETPOST('trueWidth');
569 }
570 if ($action == 'settrueHeight') { // Test on permission already done
571 $object->trueHeight = GETPOST('trueHeight');
572 $object->size_units = GETPOSTINT('size_units');
573 }
574 if ($action == 'settrueDepth') { // Test on permission already done
575 $object->trueDepth = GETPOST('trueDepth');
576 }
577 if ($action == 'setshipping_method_id') { // Test on permission already done
578 $object->shipping_method_id = GETPOSTINT('shipping_method_id');
579 }
580
581 if (!$error) {
582 if ($object->update($user) >= 0) {
583 header("Location: card.php?id=".$object->id);
584 exit;
585 }
586 setEventMessages($object->error, $object->errors, 'errors');
587 }
588
589 $action = "";
590 } elseif ($action == 'builddoc' && $permissiontoread) {
591 // Build document
592 // En get ou en post
593 // Save last template used to generate document
594 if (GETPOST('model')) {
595 $object->setDocModel($user, GETPOST('model', 'alpha'));
596 }
597
598 // Define output language
599 $outputlangs = $langs;
600 $newlang = '';
601 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
602 $newlang = GETPOST('lang_id', 'aZ09');
603 }
604 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
605 $newlang = $reception->thirdparty->default_lang;
606 }
607 if (!empty($newlang)) {
608 $outputlangs = new Translate("", $conf);
609 $outputlangs->setDefaultLang($newlang);
610 }
611 $result = $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
612 if ($result <= 0) {
613 setEventMessages($object->error, $object->errors, 'errors');
614 $action = '';
615 }
616 } elseif ($action == 'remove_file' && $permissiontoadd) {
617 // Delete file in doc form
618 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
619
620 $upload_dir = $conf->reception->dir_output;
621 $file = $upload_dir.'/'.GETPOST('file');
622 $ret = dol_delete_file($file, 0, 0, 0, $object);
623 if ($ret) {
624 setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
625 } else {
626 setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
627 }
628 } elseif ($action == 'classifybilled' && $permissiontoadd) {
629 $result = $object->setBilled();
630 if ($result >= 0) {
631 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
632 exit();
633 } else {
634 setEventMessages($object->error, $object->errors, 'errors');
635 $action = '';
636 }
637 } elseif ($action == 'classifyclosed' && $permissiontoread) {
638 $result = $object->setClosed();
639 if ($result >= 0) {
640 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
641 exit();
642 } else {
643 setEventMessages($object->error, $object->errors, 'errors');
644 $action = '';
645 }
646 } elseif ($action == 'deleteline' && !empty($line_id) && $permissiontoread) {
647 // delete a line
648 $lines = $object->lines;
649 $line = new CommandeFournisseurDispatch($db);
650
651 $num_prod = count($lines);
652 for ($i = 0; $i < $num_prod; $i++) {
653 if ($lines[$i]->id == $line_id) {
654 // delete single warehouse line
655 $line->id = $line_id;
656 if (!$error && $line->delete($user) < 0) {
657 $error++;
658 }
659 }
660 unset($_POST["lineid"]);
661 }
662
663 if (!$error) {
664 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
665 exit();
666 } else {
667 setEventMessages($line->error, $line->errors, 'errors');
668 }
669 } elseif ($action == 'updateline' && GETPOST('save') && $permissiontoadd) {
670 // Update a line
671 // Clean parameters
672 $qty = 0;
673 $entrepot_id = 0;
674 $batch_id = 0;
675
676 $lines = $object->lines;
677 $num_prod = count($lines);
678 for ($i = 0; $i < $num_prod; $i++) {
679 if ($lines[$i]->id == $line_id) { // we have found line to update
680 $line = new CommandeFournisseurDispatch($db);
681 $line->fetch($line_id);
682 // Extrafields Lines
683 $extrafields->fetch_name_optionals_label($object->table_element_line);
684 $line->array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
685
686
687 $line->fk_product = $lines[$i]->fk_product;
688
689
690 if ($lines[$i]->fk_product > 0) {
691 // single warehouse reception line
692 $stockLocation = "entl".$line_id;
693 $qty = "qtyl".$line_id;
694 $comment = "comment".$line_id;
695
696
697 $line->id = $line_id;
698 $line->fk_entrepot = GETPOSTINT($stockLocation);
699 $line->qty = GETPOSTFLOAT($qty, 'MS');
700 $line->comment = GETPOST($comment, 'alpha');
701
702 if (isModEnabled('productbatch')) {
703 $batch = "batch".$line_id;
704 $dlc = "dlc".$line_id;
705 $dluo = "dluo".$line_id;
706 // EATBY <-> DLUO
707 $eatby = GETPOST($dluo, 'alpha');
708 $eatbydate = str_replace('/', '-', $eatby);
709 // SELLBY <-> DLC
710 $sellby = GETPOST($dlc, 'alpha');
711 $sellbydate = str_replace('/', '-', $sellby);
712 $line->batch = GETPOST($batch, 'alpha');
713 $line->eatby = strtotime($eatbydate);
714 $line->sellby = strtotime($sellbydate);
715 }
716
717 if ($line->update($user) < 0) {
718 setEventMessages($line->error, $line->errors, 'errors');
719 $error++;
720 }
721 } else { // Product no predefined
722 $qty = "qtyl".$line_id;
723 $line->id = $line_id;
724 $line->qty = GETPOSTFLOAT($qty, 'MS');
725 $line->fk_entrepot = 0;
726 if ($line->update($user) < 0) {
727 setEventMessages($line->error, $line->errors, 'errors');
728 $error++;
729 }
730 unset($_POST[$qty]);
731 }
732 }
733 }
734
735 unset($_POST["lineid"]);
736
737 if (!$error) {
738 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
739 // Define output language
740 $outputlangs = $langs;
741 $newlang = '';
742 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
743 $newlang = GETPOST('lang_id', 'aZ09');
744 }
745 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
746 $newlang = $object->thirdparty->default_lang;
747 }
748 if (!empty($newlang)) {
749 $outputlangs = new Translate("", $conf);
750 $outputlangs->setDefaultLang($newlang);
751 }
752
753 $ret = $object->fetch($object->id); // Reload to get new records
754 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
755 }
756 } else {
757 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
758 exit();
759 }
760 } elseif ($action == 'updateline' && $permissiontoadd && GETPOST('cancel', 'alpha') == $langs->trans("Cancel")) {
761 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
762 exit();
763 }
764
765 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
766
767 // Actions to send emails
768 if (empty($id)) {
769 $id = $facid;
770 }
771 $triggersendname = 'RECEPTION_SENTBYMAIL';
772 $paramname = 'id';
773 $mode = 'emailfromreception';
774 $autocopy = 'MAIN_MAIL_AUTOCOPY_RECEPTION_TO';
775 $trackid = 'rec'.$object->id;
776 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
777}
778
779
780/*
781 * View
782 */
783
784$title = $object->ref.' - '.$langs->trans('Reception');
785
786llxHeader('', $title, 'Reception', '', 0, 0, '', '', '', 'mod-reception page-card');
787
788$form = new Form($db);
789$formfile = new FormFile($db);
790$formproduct = new FormProduct($db);
791$formproject = null;
792if (isModEnabled('project')) {
793 $formproject = new FormProjets($db);
794}
795
796$product_static = new Product($db);
797$reception_static = new Reception($db);
798$warehousestatic = new Entrepot($db);
799
800if ($action == 'create2') {
801 print load_fiche_titre($langs->trans("CreateReception"), '', 'dollyrevert');
802
803 print '<br>'.$langs->trans("ReceptionCreationIsDoneFromOrder");
804 $action = '';
805 $id = '';
806 $ref = '';
807}
808
809// Mode creation.
810if ($action == 'create') {
811 $recept = new Reception($db);
812
813 print load_fiche_titre($langs->trans("CreateReception"));
814 if (!$origin) {
815 setEventMessages($langs->trans("ErrorBadParameters"), null, 'errors');
816 }
817
818 if ($origin) {
819 if ($origin == 'supplierorder') {
820 $classname = 'CommandeFournisseur';
821 } else {
822 $classname = ucfirst($origin);
823 }
824
825 $objectsrc = new $classname($db);
826 if ($objectsrc->fetch($origin_id)) { // This include the fetch_lines
827 $soc = new Societe($db);
828 $soc->fetch($objectsrc->socid);
829
830 $author = new User($db);
831 $author->fetch($objectsrc->user_author_id);
832
833 if (isModEnabled('stock')) {
834 $entrepot = new Entrepot($db);
835 }
836
837 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
838 print '<input type="hidden" name="token" value="'.newToken().'">';
839 print '<input type="hidden" name="action" value="add">';
840 print '<input type="hidden" name="origin" value="'.$origin.'">';
841 print '<input type="hidden" name="origin_id" value="'.$objectsrc->id.'">';
842 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
843 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
844 if (GETPOSTINT('entrepot_id')) {
845 print '<input type="hidden" name="entrepot_id" value="'.GETPOSTINT('entrepot_id').'">';
846 }
847
848 print dol_get_fiche_head();
849
850 print '<table class="border centpercent">';
851
852 // Ref
853 print '<tr><td class="titlefieldcreate fieldrequired">';
854 if ($origin == 'supplierorder' && isModEnabled("supplier_order")) {
855 print $langs->trans("RefOrder").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$objectsrc->id.'">'.img_object($langs->trans("ShowOrder"), 'order').' '.$objectsrc->ref;
856 }
857 if ($origin == 'propal' && isModEnabled("propal")) {
858 print $langs->trans("RefProposal").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/comm/card.php?id='.$objectsrc->id.'">'.img_object($langs->trans("ShowProposal"), 'propal').' '.$objectsrc->ref;
859 }
860 print '</a></td>';
861 print "</tr>\n";
862
863 // Ref client
864 print '<tr><td>';
865 if ($origin == 'supplier_order') {
866 print $langs->trans('SupplierOrder');
867 } else {
868 print $langs->trans('RefSupplier');
869 }
870 print '</td><td colspan="3">';
871 print '<input type="text" name="ref_supplier" value="'.$objectsrc->ref_supplier.'" />';
872 print '</td>';
873 print '</tr>';
874
875 // Tiers
876 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Company').'</td>';
877 print '<td colspan="3">'.$soc->getNomUrl(1).'</td>';
878 print '</tr>';
879
880 // Project
881 if (isModEnabled('project') && $formproject !== null) {
882 $projectid = GETPOSTINT('projectid') ? GETPOSTINT('projectid') : 0;
883 if (empty($projectid) && !empty($objectsrc->fk_project)) {
884 $projectid = $objectsrc->fk_project;
885 }
886 if ($origin == 'project') {
887 $projectid = ($originid ? $originid : 0);
888 }
889
890 $langs->load("projects");
891 print '<tr>';
892 print '<td>'.$langs->trans("Project").'</td><td colspan="2">';
893 print img_picto('', 'project', 'class="paddingright"');
894 print $formproject->select_projects((!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $soc->id : -1), (string) $projectid, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500');
895 print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$soc->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
896 print '</td>';
897 print '</tr>';
898 }
899
900 // Date delivery planned
901 print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
902 print '<td colspan="3">';
903 $date_delivery = ($date_delivery ? $date_delivery : $objectsrc->delivery_date); // $date_delivery comes from GETPOST
904 print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
905 print "</td>\n";
906 print '</tr>';
907
908 // Note Public
909 print '<tr><td>'.$langs->trans("NotePublic").'</td>';
910 print '<td colspan="3">';
911 $doleditor = new DolEditor('note_public', $objectsrc->note_public, '', 60, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
912 print $doleditor->Create(1);
913 print "</td></tr>";
914
915 // Note Private
916 if ($objectsrc->note_private && !$user->socid) {
917 print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
918 print '<td colspan="3">';
919 $doleditor = new DolEditor('note_private', $objectsrc->note_private, '', 60, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
920 print $doleditor->Create(1);
921 print "</td></tr>";
922 }
923
924 // Weight
925 print '<tr><td>';
926 print $langs->trans("Weight");
927 print '</td><td colspan="3"><input name="weight" size="4" value="'.GETPOST('weight').'"> ';
928 $text = $formproduct->selectMeasuringUnits("weight_units", "weight", (string) GETPOSTINT('weight_units'), 0, 2);
929 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
930 print $form->textwithpicto($text, $htmltext);
931 print '</td></tr>';
932 // Dim
933 print '<tr><td>';
934 print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
935 print ' </td><td colspan="3"><input name="trueWidth" size="4" value="'.GETPOST('trueWidth').'">';
936 print ' x <input name="trueHeight" size="4" value="'.GETPOST('trueHeight').'">';
937 print ' x <input name="trueDepth" size="4" value="'.GETPOST('trueDepth').'">';
938 print ' ';
939 $text = $formproduct->selectMeasuringUnits("size_units", "size", (string) GETPOSTINT('size_units'), 0, 2);
940 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
941 print $form->textwithpicto($text, $htmltext);
942 print '</td></tr>';
943
944 // Delivery method
945 print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
946 print '<td colspan="3">';
947 $recept->fetch_delivery_methods();
948 print $form->selectarray("shipping_method_id", $recept->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1);
949 if ($user->admin) {
950 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
951 }
952 print "</td></tr>\n";
953
954 // Tracking number
955 print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
956 print '<td colspan="3">';
957 print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
958 print "</td></tr>\n";
959
960 // Other attributes
961 $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3', 'socid' => $socid);
962 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $recept, $action); // Note that $action and $objectsrc may have been modified by hook
963 print $hookmanager->resPrint;
964
965 // Here $object can be of an object Reception
966 $extrafields->fetch_name_optionals_label($object->table_element);
967 if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
968 // copy from order
969 if ($objectsrc->fetch_optionals() > 0) {
970 $recept->array_options = array_merge($recept->array_options, $objectsrc->array_options);
971 }
972 print $recept->showOptionals($extrafields, 'create', $parameters);
973 }
974
975 // Incoterms
976 if (isModEnabled('incoterm')) {
977 print '<tr>';
978 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->label_incoterms, 1).'</label></td>';
979 print '<td colspan="3" class="maxwidthonsmartphone">';
980 print $form->select_incoterms((!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : ''), (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : ''));
981 print '</td></tr>';
982 }
983
984 // Document model
985 include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
987
988 if (is_array($list) && count($list) > 1) {
989 print "<tr><td>".$langs->trans("DefaultModel")."</td>";
990 print '<td colspan="3">';
991 print $form->selectarray('model', $list, getDolGlobalString('RECEPTION_ADDON_PDF'));
992 print "</td></tr>\n";
993 }
994
995 print "</table>";
996
997 print dol_get_fiche_end();
998
999 // Number of lines show on the reception card
1000 $numAsked = 0;
1001
1006 $suffix2numAsked = array();
1007 $dispatchLines = array();
1008
1009 foreach ($_POST as $key => $value) {
1010 // If create form is coming from the button "Create Reception" of previous page
1011
1012 // without batch module enabled or product with no lot/serial
1013 $reg = array();
1014 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
1015 $numAsked++;
1016 $paramSuffix = $reg[1] . '_' . $reg[2];
1017 $suffix2numAsked[$paramSuffix] = $numAsked;
1018
1019 // $numline=$reg[2] + 1; // line of product
1020 $numline = $numAsked;
1021
1022 $prod = "product_" . $paramSuffix;
1023 $qty = "qty_" . $paramSuffix;
1024 $ent = "entrepot_" . $paramSuffix;
1025 $pu = "pu_" . $paramSuffix; // This is unit price including discount
1026 $fk_commandefourndet = "fk_commandefourndet_" . $paramSuffix;
1027 $dispatchLines[$numAsked] = array('paramSuffix' => $paramSuffix, 'prod' => GETPOSTINT($prod), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOSTINT($ent), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST('comment'), 'fk_commandefourndet' => GETPOSTINT($fk_commandefourndet));
1028 }
1029
1030 // with batch module enabled and product with lot/serial
1031 if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
1032 $numAsked++;
1033 $paramSuffix = $reg[1] . '_' . $reg[2];
1034 $suffix2numAsked[$paramSuffix] = $numAsked;
1035
1036 // eat-by date dispatch
1037 // $numline=$reg[2] + 1; // line of product
1038 $numline = $numAsked;
1039
1040 $prod = 'product_batch_' . $paramSuffix;
1041 $qty = 'qty_' . $paramSuffix;
1042 $ent = 'entrepot_' . $paramSuffix;
1043 $pu = 'pu_' . $paramSuffix;
1044 $lot = 'lot_number_' . $paramSuffix;
1045 $dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo_'.$paramSuffix.'month'), GETPOSTINT('dluo_'.$paramSuffix.'day'), GETPOSTINT('dluo_'.$paramSuffix.'year'));
1046 $dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc_'.$paramSuffix.'month'), GETPOSTINT('dlc_'.$paramSuffix.'day'), GETPOSTINT('dlc_'.$paramSuffix.'year'));
1047 $fk_commandefourndet = 'fk_commandefourndet_'.$paramSuffix;
1048 $dispatchLines[$numAsked] = array('paramSuffix' => $paramSuffix, 'prod' => GETPOSTINT($prod), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOSTINT($ent), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST('comment'), 'fk_commandefourndet' => GETPOSTINT($fk_commandefourndet), 'DLC' => $dDLC, 'DLUO' => $dDLUO, 'lot' => GETPOST($lot));
1049 }
1050
1051 // If create form is coming from same page, it means that post was sent but an error occurred
1052 if (preg_match('/^productl([0-9]+)$/i', $key, $reg)) {
1053 $numAsked++;
1054 $paramSuffix = $reg[1];
1055 $suffix2numAsked[$paramSuffix] = $numAsked;
1056
1057 // eat-by date dispatch
1058 // $numline=$reg[2] + 1; // line of product
1059 $numline = $numAsked;
1060
1061 $prod = 'productid'.$paramSuffix;
1062 $comment = 'comment'.$paramSuffix;
1063 $qty = 'qtyl'.$paramSuffix;
1064 $ent = 'entl'.$paramSuffix;
1065 $pu = 'pul'.$paramSuffix;
1066 $lot = 'batch'.$paramSuffix;
1067 $dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo'.$paramSuffix.'month'), GETPOSTINT('dluo'.$paramSuffix.'day'), GETPOSTINT('dluo'.$paramSuffix.'year'));
1068 $dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc'.$paramSuffix.'month'), GETPOSTINT('dlc'.$paramSuffix.'day'), GETPOSTINT('dlc'.$paramSuffix.'year'));
1069 $fk_commandefourndet = 'fk_commandefournisseurdet'.$paramSuffix;
1070 $dispatchLines[$numAsked] = array('prod' => GETPOSTINT($prod), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOSTINT($ent), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST($comment), 'fk_commandefourndet' => GETPOSTINT($fk_commandefourndet), 'DLC' => $dDLC, 'DLUO' => $dDLUO, 'lot' => GETPOSTINT($lot));
1071 }
1072 }
1073
1074 // If extrafield values are passed in the HTTP query, assign them to the correct dispatch line
1075 // Note that if an extrafield with the same name exists in the origin supplier order line, the value
1076 // from the HTTP query will be ignored
1077 foreach ($suffix2numAsked as $suffix => $n) {
1078 $dispatchLines[$n]['array_options'] = $extrafields->getOptionalsFromPost('receptiondet_batch', '_' . $suffix, '');
1079 }
1080
1081 print '<script type="text/javascript">
1082 jQuery(document).ready(function() {
1083 jQuery("#autofill").click(function(event) {
1084 event.preventDefault();';
1085 $i = 1;
1086 while ($i <= $numAsked) {
1087 print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1088 $i++;
1089 }
1090 print '});
1091 jQuery("#autoreset").click(function(event) {
1092 event.preventDefault();';
1093 $i = 1;
1094 while ($i <= $numAsked) {
1095 print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1096 $i++;
1097 }
1098 print '});
1099 });
1100 </script>';
1101
1102 print '<br>';
1103
1104 print '<table class="noborder centpercent">';
1105
1106 // Load receptions already done for same order
1107 $objectsrc->loadReceptions();
1108
1109 if ($numAsked) {
1110 print '<tr class="liste_titre">';
1111 print '<td>'.$langs->trans("Description").'</td>';
1112 print '<td>'.$langs->trans("Comment").'</td>';
1113 print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1114 print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1115 print '<td class="center">'.$langs->trans("QtyToReceive");
1116 if (getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1117 print '<td>'.$langs->trans("BuyingPrice").'</td>';
1118 }
1119 if (!isModEnabled('productbatch')) {
1120 print ' <br><center><a href="#" id="autofill"><span class="fas fa-fill pictofixedwidth" style=""></span> '.$langs->trans("Fill").'</a>';
1121 print ' &nbsp; &nbsp; <a href="#" id="autoreset"><span class="fas fa-eraser pictofixedwidth" style=""></span>'.$langs->trans("Reset").'</a></center><br>';
1122 }
1123 print '</td>';
1124 if (isModEnabled('stock')) {
1125 print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1126 }
1127 if (isModEnabled('productbatch')) {
1128 print '<td class="left">'.$langs->trans("batch_number").'</td>';
1129 if (!getDolGlobalInt('PRODUCT_DISABLE_SELLBY')) {
1130 print '<td class="left">'.$langs->trans("SellByDate").'</td>';
1131 }
1132 if (!getDolGlobalInt('PRODUCT_DISABLE_EATBY')) {
1133 print '<td class="left">'.$langs->trans("EatByDate").'</td>';
1134 }
1135 }
1136 print "</tr>\n";
1137 }
1138
1139 // $objectsrc->lines contains the line of the purchase order
1140 // $dispatchLines is an array with dispatching detail (with product, qty, warehouse and fk_commandefourndet). One purchase order line may have n of this dispatch lines.
1141
1142 $arrayofpurchaselinealreadyoutput = array();
1143
1144 // $_POST contains fk_commandefourndet_X_Y where Y is num of product line and X is number of split lines
1145 $indiceAsked = 1;
1146 while ($indiceAsked <= $numAsked) { // Loop on $dispatchLines. Warning: $dispatchLines must be sorted by fk_commandefourndet (it is a regroupment key on output)
1147 $product = new Product($db);
1148 $line = new CommandeFournisseurLigne($db); // By default
1149
1150 // We search the purchase order line that is linked to the dispatchLines
1151 foreach ($objectsrc->lines as $supplierLine) {
1152 if ($dispatchLines[$indiceAsked]['fk_commandefourndet'] == $supplierLine->id) {
1153 $line = $supplierLine;
1154 break;
1155 }
1156 }
1157
1158 // Now $line can be CommandeFournisseurLigne but could be other type of line.
1159
1160 // Show product and description
1161 $type = $line->product_type ? $line->product_type : $line->fk_product_type;
1162 // Try to enhance type detection using date_start and date_end for free lines where type was not saved.
1163 if (!empty($line->date_start)) {
1164 $type = 1;
1165 }
1166 if (!empty($line->date_end)) {
1167 $type = 1;
1168 }
1169
1170 print '<!-- line fk_commandefourndet='.$line->id.' for product='.$line->fk_product.' -->'."\n";
1171 print '<tr class="oddeven">'."\n";
1172
1173 // Product label
1174 if ($line->fk_product > 0) { // If predefined product
1175 $product->fetch($line->fk_product);
1176 $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
1177 //var_dump($product->stock_warehouse[1]);
1178 //var_dump($dispatchLines[$indiceAsked]);
1179
1180 print '<td>';
1181 print '<a name="'.$line->id.'"></a>'; // ancre pour retourner sur la ligne
1182
1183 print '<input type="hidden" name="productl'.$indiceAsked.'" value="'.$line->fk_product.'">';
1184
1185 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1186 print '<input type="hidden" name="productid'.$indiceAsked.'" value="'.$line->fk_product.'">';
1187
1188 // Show product and description
1189 $product_static = $product;
1190
1191 $text = $product_static->getNomUrl(1);
1192 $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
1193 $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($line->desc));
1194 print $form->textwithtooltip($text, $description, 3, 0, '', (string) $i);
1195
1196 // Show range
1197 print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1198
1199 // Add description in form
1200 if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1201 print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
1202 }
1203 }
1204 print '</td>';
1205 } else {
1206 print "<td>";
1207 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1208 if ($type == 1) {
1209 $text = img_object($langs->trans('Service'), 'service');
1210 } else {
1211 $text = img_object($langs->trans('Product'), 'product');
1212 }
1213
1214 if (!empty($line->label)) {
1215 $text .= ' <strong>'.$line->label.'</strong>';
1216 print $form->textwithtooltip($text, $line->desc, 3, 0, '', (string) $i);
1217 } else {
1218 print $text.' '.nl2br($line->desc);
1219 }
1220
1221 // Show range
1222 print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1223 }
1224 print "</td>\n";
1225 }
1226
1227 // Comment
1228 //$defaultcomment = 'Line create from order line id '.$line->id;
1229 $defaultcomment = $dispatchLines[$indiceAsked]['comment'];
1230 print '<td>';
1231 print '<input type="text" class="maxwidth100" name="comment'.$indiceAsked.'" value="'.$defaultcomment.'">';
1232 print '</td>';
1233
1234 // Qty in source purchase order line
1235 print '<td class="center">';
1236 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1237 print $line->qty;
1238 }
1239 print '<input type="hidden" name="fk_commandefournisseurdet'.$indiceAsked.'" value="'.$line->id.'">';
1240 print '<input type="hidden" name="pul'.$indiceAsked.'" value="'.$line->pu_ht.'">';
1241 print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
1242 print '</td>';
1243 $qtyProdCom = $line->qty;
1244
1245 // Qty already received
1246 print '<td class="center">';
1247 $quantityDelivered = isset($objectsrc->receptions[$line->id]) ? $objectsrc->receptions[$line->id] : 0;
1248 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1249 print $quantityDelivered;
1250 }
1251 print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
1252 print '</td>';
1253
1254
1255 if ($line->product_type == 1 && !getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1256 $quantityToBeDelivered = 0;
1257 } else {
1258 $quantityToBeDelivered = $dispatchLines[$indiceAsked]['qty'];
1259 }
1260 $warehouse_id = $dispatchLines[$indiceAsked]['ent'];
1261
1262
1263 $warehouseObject = null;
1264 if (isModEnabled('stock')) {
1265 // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1266 print '<!-- Case warehouse already known or product not a predefined product -->';
1267 if (array_key_exists($dispatchLines[$indiceAsked]['ent'], $product->stock_warehouse)) {
1268 $stock = +$product->stock_warehouse[$dispatchLines[$indiceAsked]['ent']]->real; // Convert to number
1269 }
1270 $deliverableQty = $dispatchLines[$indiceAsked]['qty'];
1271 $cost_price = $dispatchLines[$indiceAsked]['pu'];
1272
1273 // Quantity to send
1274 print '<td class="center">';
1275 if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1276 if (GETPOSTINT('qtyl'.$indiceAsked)) {
1277 $defaultqty = GETPOSTINT('qtyl'.$indiceAsked);
1278 }
1279 print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1280 print '<input class="right" name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1281 } else {
1282 print $langs->trans("NA");
1283 }
1284 print '</td>';
1285
1286 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1287 print '<td>';
1288 print '<input class="width75 right" name="cost_price'.$indiceAsked.'" id="cost_price'.$indiceAsked.'" value="'.price($cost_price).'">';
1289 print '</td>';
1290 }
1291
1292 // Stock
1293 if (isModEnabled('stock')) {
1294 print '<td class="left">';
1295 if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) { // Type of product need stock change ?
1296 // Show warehouse combo list
1297 $ent = "entl".$indiceAsked;
1298 $idl = "idl".$indiceAsked;
1299 $tmpentrepot_id = is_numeric(GETPOST($ent)) ? GETPOSTINT($ent) : $warehouse_id;
1300 if ($line->fk_product > 0) {
1301 print '<!-- Show warehouse selection -->';
1302 print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 0, 0, $line->fk_product, '', 1);
1303 }
1304 } else {
1305 print $langs->trans("Service");
1306 }
1307 print '</td>';
1308 }
1309
1310 if (isModEnabled('productbatch')) {
1311 if (!empty($product->status_batch)) {
1312 print '<td><input name="batch'.$indiceAsked.'" value="'.$dispatchLines[$indiceAsked]['lot'].'"></td>';
1313 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1314 print '<td class="nowraponall">';
1315 print $form->selectDate($dispatchLines[$indiceAsked]['DLC'], 'dlc'.$indiceAsked, 0, 0, 1, "");
1316 print '</td>';
1317 }
1318 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1319 print '<td class="nowraponall">';
1320 print $form->selectDate($dispatchLines[$indiceAsked]['DLUO'], 'dluo'.$indiceAsked, 0, 0, 1, "");
1321 print '</td>';
1322 }
1323 } else {
1324 print '<td colspan="3"></td>';
1325 }
1326 }
1327 }
1328
1329 $arrayofpurchaselinealreadyoutput[$line->id] = $line->id;
1330
1331 print "</tr>\n";
1332
1333 // Display lines for extrafields of the Reception line
1334 // $line is a 'CommandeFournisseurLigne', $dispatchLines contains values of Reception lines so properties of CommandeFournisseurDispatch
1335 if (!empty($extrafields)) {
1336 $colspan = 5;
1337 if (isModEnabled('productbatch')) {
1338 $colspan += 2;
1339 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1340 $colspan += 1;
1341 }
1342 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1343 $colspan += 1;
1344 }
1345 }
1346 $recLine = new CommandeFournisseurDispatch($db);
1347
1348 $srcLine = new CommandeFournisseurLigne($db);
1349 $srcLine->id = $line->id;
1350 $srcLine->fetch_optionals(); // fetch extrafields also available in orderline
1351
1352 if (empty($recLine->array_options) && !empty($dispatchLines[$indiceAsked]['array_options'])) {
1353 $recLine->array_options = $dispatchLines[$indiceAsked]['array_options'];
1354 }
1355 $recLine->array_options = array_merge($recLine->array_options, $srcLine->array_options);
1356
1357 print $recLine->showOptionals($extrafields, 'edit', array('style' => 'class="oddeven"', 'colspan' => $colspan), (string) $indiceAsked, '', '1');
1358 }
1359
1360 $indiceAsked++;
1361 }
1362
1363 print "</table>";
1364
1365 print '<br>';
1366
1367 print $form->buttonsSaveCancel("Create");
1368
1369 print '</form>';
1370
1371 print '<br>';
1372 } else {
1373 dol_print_error($db);
1374 }
1375 }
1376} elseif ($id || $ref) {
1377 /* *************************************************************************** */
1378 /* */
1379 /* Edit and view mode */
1380 /* */
1381 /* *************************************************************************** */
1382 $lines = $object->lines;
1383
1384 $num_prod = count($lines);
1385 $indiceAsked = 0;
1386
1387 if ($object->id <= 0) {
1388 print $langs->trans("NoRecordFound");
1389 llxFooter();
1390 exit;
1391 }
1392
1393 $typeobject = '';
1394 if (!empty($object->origin) && $object->origin_id > 0) {
1395 $object->origin = 'CommandeFournisseur';
1396 $typeobject = $object->origin;
1397 $origin = $object->origin;
1398 $origin_id = $object->origin_id;
1399 $object->fetch_origin(); // Load property $object->origin_object, $object->commande, $object->propal, ...
1400 }
1401
1402 $soc = new Societe($db);
1403 $soc->fetch($object->socid);
1404
1405 $res = $object->fetch_optionals();
1406
1408 print dol_get_fiche_head($head, 'reception', $langs->trans("Reception"), -1, 'dollyrevert');
1409
1410 $formconfirm = '';
1411
1412 // Confirm deletion
1413 if ($action == 'delete') {
1414 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeleteReception'), $langs->trans("ConfirmDeleteReception", $object->ref), 'confirm_delete', '', 0, 1);
1415 }
1416
1417 // Confirmation validation
1418 if ($action == 'valid') {
1419 $objectref = substr($object->ref, 1, 4);
1420 if ($objectref == 'PROV') {
1421 $numref = $object->getNextNumRef($soc);
1422 } else {
1423 $numref = $object->ref;
1424 }
1425
1426 $text = $langs->trans("ConfirmValidateReception", $numref);
1427 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')) {
1428 $text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementWillBeRecorded").'.';
1429 } elseif (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1430 $text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementNotYetRecorded").'.';
1431 }
1432
1433 if (isModEnabled('notification')) {
1434 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
1435 $notify = new Notify($db);
1436 $text .= '<br>';
1437 $text .= $notify->confirmMessage('RECEPTION_VALIDATE', $object->socid, $object);
1438 }
1439
1440 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateReception'), $text, 'confirm_valid', '', 0, 1, 250);
1441 }
1442
1443 // Confirm cancellation
1444 if ($action == 'annuler') {
1445 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelReception'), $langs->trans("ConfirmCancelReception", $object->ref), 'confirm_cancel', '', 0, 1);
1446 }
1447
1448 if (!$formconfirm) {
1449 $parameters = array('formConfirm' => $formconfirm);
1450 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1451 if (empty($reshook)) {
1452 $formconfirm .= $hookmanager->resPrint;
1453 } elseif ($reshook > 0) {
1454 $formconfirm = $hookmanager->resPrint;
1455 }
1456 }
1457
1458 // Print form confirm
1459 print $formconfirm;
1460
1461
1462 // Calculate totalWeight and totalVolume for all products
1463 // by adding weight and volume of each product line.
1464 $tmparray = $object->getTotalWeightVolume();
1465 $totalWeight = $tmparray['weight'];
1466 $totalVolume = $tmparray['volume'];
1467
1468
1469 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
1470 $objectsrc = new Commande($db);
1471 $objectsrc->fetch($object->origin_object->id);
1472 }
1473 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
1474 $objectsrc = new Propal($db);
1475 $objectsrc->fetch($object->origin_object->id);
1476 }
1477 if ($typeobject == 'CommandeFournisseur' && $object->origin_object->id && isModEnabled("supplier_order")) {
1478 $objectsrc = new CommandeFournisseur($db);
1479 $objectsrc->fetch($object->origin_object->id);
1480 }
1481 // Reception card
1482 $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1483 $morehtmlref = '<div class="refidno">';
1484 // Ref customer reception
1485
1486 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', 0, 1);
1487 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', null, null, '', 1);
1488
1489 // Thirdparty
1490 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
1491 // Project
1492 if (isModEnabled('project')) {
1493 $langs->load("projects");
1494 $morehtmlref .= '<br>';
1495 if (0) { // Do not change on reception
1496 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1497 if ($action != 'classify' && $permissiontoadd) {
1498 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1499 }
1500 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
1501 } else {
1502 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
1503 $proj = new Project($db);
1504 $proj->fetch($objectsrc->fk_project);
1505 $morehtmlref .= $proj->getNomUrl(1);
1506 if ($proj->title) {
1507 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
1508 }
1509 }
1510 }
1511 }
1512 $morehtmlref .= '</div>';
1513
1514 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1515
1516
1517 print '<div class="fichecenter">';
1518 print '<div class="fichehalfleft">';
1519 print '<div class="underbanner clearboth"></div>';
1520
1521 print '<table class="border centpercent tableforfield">';
1522
1523 // Linked documents
1524 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
1525 print '<tr><td>';
1526 print $langs->trans("RefOrder").'</td>';
1527 print '<td colspan="3">';
1528 print $objectsrc->getNomUrl(1, 'commande');
1529 print "</td>\n";
1530 print '</tr>';
1531 }
1532 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
1533 print '<tr><td>';
1534 print $langs->trans("RefProposal").'</td>';
1535 print '<td colspan="3">';
1536 print $objectsrc->getNomUrl(1, 'reception');
1537 print "</td>\n";
1538 print '</tr>';
1539 }
1540 if ($typeobject == 'CommandeFournisseur' && $object->origin_object->id && isModEnabled("propal")) {
1541 print '<tr><td>';
1542 print $langs->trans("SupplierOrder").'</td>';
1543 print '<td colspan="3">';
1544 print $objectsrc->getNomUrl(1, 'reception');
1545 print "</td>\n";
1546 print '</tr>';
1547 }
1548
1549 // Date creation
1550 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1551 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
1552 print '</tr>';
1553
1554 // Delivery date planned
1555 print '<tr><td height="10">';
1556 print '<table class="nobordernopadding" width="100%"><tr><td>';
1557 print $langs->trans('DateDeliveryPlanned');
1558 print '</td>';
1559
1560 if ($action != 'editdate_livraison' && $permissiontoadd) {
1561 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'), 1).'</a></td>';
1562 }
1563 print '</tr></table>';
1564 print '</td><td colspan="2">';
1565 if ($action == 'editdate_livraison') {
1566 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1567 print '<input type="hidden" name="token" value="'.newToken().'">';
1568 print '<input type="hidden" name="action" value="setdate_livraison">';
1569 print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
1570 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1571 print '</form>';
1572 } else {
1573 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
1574 }
1575 print '</td>';
1576 print '</tr>';
1577
1578 // Weight
1579 print '<tr><td>';
1580 print $form->editfieldkey("Weight", 'trueWeight', (string) $object->trueWeight, $object, $user->hasRight('reception', 'creer'));
1581 print '</td><td colspan="3">';
1582
1583 if ($action == 'edittrueWeight') {
1584 print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1585 print '<input name="action" value="settrueWeight" type="hidden">';
1586 print '<input name="id" value="'.$object->id.'" type="hidden">';
1587 print '<input type="hidden" name="token" value="'.newToken().'">';
1588 print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1589 print $formproduct->selectMeasuringUnits("weight_units", "weight", (string) $object->weight_units, 0, 2);
1590 print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1591 print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1592 print '</form>';
1593 } else {
1594 print $object->trueWeight;
1595 print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : '';
1596 }
1597
1598 // Calculated
1599 if ($totalWeight > 0) {
1600 if (!empty($object->trueWeight)) {
1601 print ' ('.$langs->trans("SumOfProductWeights").': ';
1602 }
1603 print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, getDolGlobalInt('MAIN_WEIGHT_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_WEIGHT_DEFAULT_UNIT', 'no'));
1604 if (!empty($object->trueWeight)) {
1605 print ')';
1606 }
1607 }
1608 print '</td></tr>';
1609
1610 // Width
1611 print '<tr><td>'.$form->editfieldkey("Width", 'trueWidth', (string) $object->trueWidth, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
1612 print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->hasRight('reception', 'creer'));
1613 print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : '';
1614 print '</td></tr>';
1615
1616 // Height
1617 print '<tr><td>'.$form->editfieldkey("Height", 'trueHeight', (string) $object->trueHeight, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
1618 if ($action == 'edittrueHeight') {
1619 print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1620 print '<input name="action" value="settrueHeight" type="hidden">';
1621 print '<input name="id" value="'.$object->id.'" type="hidden">';
1622 print '<input type="hidden" name="token" value="'.newToken().'">';
1623 print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1624 print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
1625 print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1626 print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1627 print '</form>';
1628 } else {
1629 print $object->trueHeight;
1630 print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : '';
1631 }
1632
1633 print '</td></tr>';
1634
1635 // Depth
1636 print '<tr><td>'.$form->editfieldkey("Depth", 'trueDepth', (string) $object->trueDepth, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
1637 print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->hasRight('reception', 'creer'));
1638 print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : '';
1639 print '</td></tr>';
1640
1641 // Volume
1642 print '<tr><td>';
1643 print $langs->trans("Volume");
1644 print '</td>';
1645 print '<td colspan="3">';
1646 $calculatedVolume = 0;
1647 $volumeUnit = 0;
1648 if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
1649 $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
1650 $volumeUnit = $object->size_units * 3;
1651 }
1652 // If reception volume not defined we use sum of products
1653 if ($calculatedVolume > 0) {
1654 if ($volumeUnit < 50) {
1655 print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString("MAIN_VOLUME_DEFAULT_UNIT", 'no'));
1656 } else {
1657 print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit);
1658 }
1659 }
1660 if ($totalVolume > 0) {
1661 if ($calculatedVolume) {
1662 print ' ('.$langs->trans("SumOfProductVolumes").': ';
1663 }
1664 print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_VOLUME_DEFAULT_UNIT', 'no'));
1665 //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1666 if ($calculatedVolume) {
1667 print ')';
1668 }
1669 }
1670 print "</td>\n";
1671 print '</tr>';
1672
1673 // Other attributes
1674 $cols = 2;
1675
1676 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1677
1678 print '</table>';
1679
1680 print '</div>';
1681 print '<div class="fichehalfright">';
1682 print '<div class="underbanner clearboth"></div>';
1683
1684 print '<table class="border centpercent tableforfield">';
1685
1686 // Reception method
1687 print '<tr><td height="10">';
1688 print '<table class="nobordernopadding centpercent"><tr><td>';
1689 print $langs->trans('ReceptionMethod');
1690 print '</td>';
1691
1692 if ($action != 'editshipping_method_id' && $permissiontoadd) {
1693 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editshipping_method_id&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetReceptionMethod'), 1).'</a></td>';
1694 }
1695 print '</tr></table>';
1696 print '</td><td colspan="2">';
1697 if ($action == 'editshipping_method_id') {
1698 print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1699 print '<input type="hidden" name="token" value="'.newToken().'">';
1700 print '<input type="hidden" name="action" value="setshipping_method_id">';
1701 $object->fetch_delivery_methods();
1702 print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1);
1703 if ($user->admin) {
1704 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1705 }
1706 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1707 print '</form>';
1708 } else {
1709 if ($object->shipping_method_id > 0) {
1710 // Get code using getLabelFromKey
1711 $code = $langs->getLabelFromKey($db, (string) $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1712 print $langs->trans("SendingMethod".strtoupper($code));
1713 }
1714 }
1715 print '</td>';
1716 print '</tr>';
1717
1718 // Tracking Number
1719 print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
1720 print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->hasRight('reception', 'creer'), 'safehtmlstring', $object->tracking_number);
1721 print '</td></tr>';
1722
1723 // Incoterms
1724 if (isModEnabled('incoterm')) {
1725 print '<tr><td>';
1726 print '<table width="100%" class="nobordernopadding"><tr><td>';
1727 print $langs->trans('IncotermLabel');
1728 print '<td><td class="right">';
1729 if ($user->hasRight('reception', 'creer')) {
1730 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/reception/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
1731 } else {
1732 print '&nbsp;';
1733 }
1734 print '</td></tr></table>';
1735 print '</td>';
1736 print '<td colspan="3">';
1737 if ($action != 'editincoterm') {
1738 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
1739 } else {
1740 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
1741 }
1742 print '</td></tr>';
1743 }
1744
1745 print "</table>";
1746
1747 print '</div>';
1748 print '</div>';
1749
1750 print '<div class="clearboth"></div>';
1751
1752
1753 // Lines of products
1754 if ($action == 'editline') {
1755 print '<form name="updateline" id="updateline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;lineid='.$line_id.'" method="POST">
1756 <input type="hidden" name="token" value="' . newToken().'">
1757 <input type="hidden" name="action" value="updateline">
1758 <input type="hidden" name="mode" value="">
1759 <input type="hidden" name="id" value="' . $object->id.'">';
1760 }
1761 print '<br><br>';
1762
1763 print '<div class="div-table-responsive-no-min">';
1764 print '<table id="tablelines" class="noborder centpercent">';
1765 print '<thead>';
1766 print '<tr class="liste_titre">';
1767 // #
1768 if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
1769 print '<td width="5" class="center">&nbsp;</td>';
1770 }
1771 // Product/Service
1772 print '<td>'.$langs->trans("Products").'</td>';
1773 // Comment
1774 print '<td>'.$langs->trans("Comment").'</td>';
1775 // Qty
1776 print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1777 if ($origin && $origin_id > 0) {
1778 print '<td class="center">'.$langs->trans("QtyInOtherReceptions").'</td>';
1779 }
1780
1781 $editColspan = 3;
1782 if ($action == 'editline') {
1783 if (!isModEnabled('stock')) {
1784 $editColspan--;
1785 }
1786 if (empty($conf->productbatch->enabled)) {
1787 $editColspan--;
1788 }
1789 print '<td class="center" colspan="'.$editColspan.'">';
1790 if ($object->statut <= 1) {
1791 print $langs->trans("QtyToReceive").' - ';
1792 } else {
1793 print $langs->trans("QtyReceived").' - ';
1794 }
1795 if (isModEnabled('stock')) {
1796 print $langs->trans("WarehouseTarget").' - ';
1797 }
1798 if (isModEnabled('productbatch')) {
1799 print $langs->trans("Batch");
1800 }
1801 print '</td>';
1802 } else {
1803 $statusreceived = $object::STATUS_CLOSED;
1804 if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) {
1805 $statusreceived = $object::STATUS_VALIDATED;
1806 }
1807 if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) {
1808 $statusreceived = $object::STATUS_CLOSED;
1809 }
1810 if ($object->statut < $statusreceived) {
1811 print '<td class="center">'.$langs->trans("QtyToReceive").'</td>';
1812 } else {
1813 print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1814 }
1815 if (isModEnabled('stock')) {
1816 print '<td class="left">'.$langs->trans("WarehouseTarget").'</td>';
1817 }
1818
1819 if (isModEnabled('productbatch')) {
1820 print '<td class="left">'.$langs->trans("Batch").'</td>';
1821 }
1822 }
1823 print '<td class="center">'.$langs->trans("CalculatedWeight").'</td>';
1824 print '<td class="center">'.$langs->trans("CalculatedVolume").'</td>';
1825 //print '<td class="center">'.$langs->trans("Size").'</td>';
1826 if ($object->statut == 0) {
1827 print '<td class="linecoledit"></td>';
1828 print '<td class="linecoldelete" width="10"></td>';
1829 }
1830 print "</tr>\n";
1831 print '</thead>';
1832
1833 $var = false;
1834
1835 $outputlangs = $langs;
1836 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1837 $object->fetch_thirdparty();
1838 $newlang = '';
1839 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
1840 $newlang = GETPOST('lang_id', 'aZ09');
1841 }
1842 if (empty($newlang)) {
1843 $newlang = $object->thirdparty->default_lang;
1844 }
1845 if (!empty($newlang)) {
1846 $outputlangs = new Translate("", $conf);
1847 $outputlangs->setDefaultLang($newlang);
1848 }
1849 }
1850
1851 // Get list of products already sent for same source object into $alreadysent
1852 $alreadysent = array();
1853
1854 $origin = 'commande_fournisseur';
1855
1856 if ($origin && $origin_id > 0) {
1857 $sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.date_start, obj.date_end";
1858 $sql .= ", ed.rowid as receptionline_id, ed.qty, ed.fk_reception as reception_id, ed.fk_entrepot";
1859 $sql .= ", e.rowid as reception_id, e.ref as reception_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_reception";
1860 //if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
1861 $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
1862 $sql .= ', p.description as product_desc';
1863 $sql .= " FROM ".MAIN_DB_PREFIX."receptiondet_batch as ed";
1864 $sql .= ", ".MAIN_DB_PREFIX."reception as e";
1865 $sql .= ", ".MAIN_DB_PREFIX.$origin."det as obj";
1866 //if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.fk_reception = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."deliverydet as ld ON ld.fk_delivery = l.rowid AND obj.rowid = ld.fk_origin_line";
1867 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
1868 $sql .= " WHERE e.entity IN (".getEntity('reception').")";
1869 $sql .= " AND obj.fk_commande = ".((int) $origin_id);
1870 $sql .= " AND obj.rowid = ed.fk_elementdet";
1871 $sql .= " AND ed.fk_reception = e.rowid";
1872 $sql .= " AND ed.fk_reception !=".((int) $object->id);
1873 //if ($filter) $sql.= $filter;
1874 $sql .= " ORDER BY obj.fk_product";
1875
1876 dol_syslog("get list of reception lines", LOG_DEBUG);
1877 $resql = $db->query($sql);
1878 if ($resql) {
1879 $num = $db->num_rows($resql);
1880 $i = 0;
1881
1882 while ($i < $num) {
1883 $obj = $db->fetch_object($resql);
1884 if ($obj) {
1885 // $obj->rowid is rowid in $origin."det" table
1886 $alreadysent[$obj->rowid][$obj->receptionline_id] = array('reception_ref' => $obj->reception_ref, 'reception_id' => $obj->reception_id, 'warehouse' => $obj->fk_entrepot, 'qty' => $obj->qty, 'date_valid' => $obj->date_valid, 'date_delivery' => $obj->date_delivery);
1887 }
1888 $i++;
1889 }
1890 }
1891 //var_dump($alreadysent);
1892 }
1893
1894 $arrayofpurchaselinealreadyoutput = array();
1895
1896 // Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output)
1897 print '<tbody>';
1898 for ($i = 0; $i < $num_prod; $i++) {
1899 print '<!-- origin line id = '.(!empty($lines[$i]->origin_line_id) ? $lines[$i]->origin_line_id : 0).' -->'; // id of order line
1900 print '<tr class="oddeven" id="row-'.$lines[$i]->id.'" data-id="'.$lines[$i]->id.'" data-element="'.$lines[$i]->element.'">';
1901
1902 // #
1903 if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
1904 print '<td class="center">'.($i + 1).'</td>';
1905 }
1906
1907 // Predefined product or service
1908 if ($lines[$i]->fk_product > 0) {
1909 // Define output language
1910 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1911 $prod = new Product($db);
1912 $prod->fetch($lines[$i]->fk_product);
1913 $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product->label;
1914 } else {
1915 $label = (!empty($lines[$i]->product->label) ? $lines[$i]->product->label : $lines[$i]->product->product_label);
1916 }
1917
1918 print '<td class="linecoldescription">';
1919 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1920 $text = $lines[$i]->product->getNomUrl(1);
1921 $text .= ' - '.$label;
1922 $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->product->description));
1923 print $form->textwithtooltip($text, $description, 3, 0, '', (string) $i);
1924 print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : 0, !empty($lines[$i]->date_end) ? $lines[$i]->date_end : 0);
1925 if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1926 print (!empty($lines[$i]->product->description) && $lines[$i]->description != $lines[$i]->product->description) ? '<br>'.dol_htmlentitiesbr($lines[$i]->description) : '';
1927 }
1928 }
1929 print "</td>\n";
1930 } else {
1931 print '<td class="linecoldescription">';
1932 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1933 if ($lines[$i]->product_type == Product::TYPE_SERVICE) {
1934 $text = img_object($langs->trans('Service'), 'service');
1935 } else {
1936 $text = img_object($langs->trans('Product'), 'product');
1937 }
1938
1939 if (!empty($lines[$i]->label)) {
1940 $text .= ' <strong>'.$lines[$i]->label.'</strong>';
1941 print $form->textwithtooltip($text, $lines[$i]->description, 3, 0, '', (string) $i);
1942 } else {
1943 print $text.' '.nl2br($lines[$i]->description);
1944 }
1945
1946 print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
1947 }
1948 print "</td>\n";
1949 }
1950
1951 if ($action == 'editline' && $lines[$i]->id == $line_id) {
1952 print '<td><input name="comment'.$line_id.'" id="comment'.$line_id.'" value="'.dol_escape_htmltag($lines[$i]->comment).'"></td>';
1953 } else {
1954 print '<td style="white-space: pre-wrap; max-width: 200px;">'.dol_escape_htmltag($lines[$i]->comment).'</td>';
1955 }
1956
1957
1958 // Qty ordered
1959 print '<td class="center linecolqty">';
1960 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1961 print $lines[$i]->qty_asked;
1962 }
1963 print '</td>';
1964
1965 // Qty in other receptions (with reception and warehouse used)
1966 if ($origin && $origin_id > 0) {
1967 print '<td class="center nowrap linecolqtyinotherreceptions">';
1968 $htmltooltip = '';
1969 $qtyalreadyreceived = 0;
1970 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1971 foreach ($alreadysent as $key => $val) {
1972 if ($lines[$i]->fk_commandefourndet == $key) {
1973 $j = 0;
1974 foreach ($val as $receptionline_id => $receptionline_var) {
1975 if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) {
1976 continue; // We want to show only "other receptions"
1977 }
1978
1979 $j++;
1980 if ($j > 1) {
1981 $htmltooltip .= '<br>';
1982 }
1983 $reception_static->fetch($receptionline_var['reception_id']);
1984 $htmltooltip .= $reception_static->getNomUrl(1, 0, 0, 0, 1);
1985 $htmltooltip .= ' - '.$receptionline_var['qty'];
1986
1987 $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour'));
1988 if (isModEnabled('stock') && $receptionline_var['warehouse'] > 0) {
1989 $warehousestatic->fetch($receptionline_var['warehouse']);
1990 $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
1991 }
1992 $htmltooltip .= ' '.$form->textwithpicto('', $htmltext, 1);
1993
1994 $qtyalreadyreceived += $receptionline_var['qty'];
1995 }
1996 if ($j) {
1997 $htmltooltip = $langs->trans("QtyInOtherReceptions").'...<br><br>'.$htmltooltip.'<br><input type="submit" name="dummyhiddenbuttontogetfocus" style="display:none" autofocus>';
1998 }
1999 }
2000 }
2001 }
2002 print $form->textwithpicto((string) $qtyalreadyreceived, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id);
2003 print '</td>';
2004 }
2005
2006 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2007 // edit mode
2008 print '<td colspan="'.$editColspan.'" class="center"><table class="nobordernopadding">';
2009 if (isModEnabled('stock')) {
2010 if ($lines[$i]->fk_product > 0) {
2011 print '<!-- case edit 1 -->';
2012 print '<tr>';
2013 // Qty to receive or received
2014 print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
2015 // Warehouse source
2016 print '<td>'.$formproduct->selectWarehouses($lines[$i]->fk_entrepot, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).'</td>';
2017 // Batch number management
2018 if ($conf->productbatch->enabled && !empty($lines[$i]->product->status_batch)) {
2019 print '<td class="nowraponall left"><input name="batch'.$line_id.'" id="batch'.$line_id.'" type="text" value="'.$lines[$i]->batch.'"><br>';
2020 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
2021 print $langs->trans('SellByDate').' : ';
2022 print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, 0, 0, 1, "").'</br>';
2023 }
2024 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
2025 print $langs->trans('EatByDate').' : ';
2026 print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, 0, 0, 1, "");
2027 }
2028 print '</td>';
2029 }
2030 print '</tr>';
2031 } else {
2032 print '<!-- case edit 2 -->';
2033 print '<tr>';
2034 // Qty to receive or received
2035 print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
2036 // Warehouse source
2037 print '<td></td>';
2038 // Batch number management
2039 print '<td></td>';
2040 print '</tr>';
2041 }
2042 }
2043 print '</table></td>';
2044 } else {
2045 // Qty to receive or received
2046 print '<td class="center linecolqtytoreceive">'.$lines[$i]->qty.'</td>';
2047
2048 // Warehouse source
2049 if (isModEnabled('stock')) {
2050 if ($lines[$i]->fk_entrepot > 0) {
2051 $entrepot = new Entrepot($db);
2052 $entrepot->fetch($lines[$i]->fk_entrepot);
2053
2054 print '<td class="left tdoverflowmax150" title="'.dol_escape_htmltag($entrepot->label).'">';
2055 print $entrepot->getNomUrl(1);
2056 print '</td>';
2057 } else {
2058 print '<td></td>';
2059 }
2060 }
2061
2062 // Batch number management
2063 if (isModEnabled('productbatch')) {
2064 if (isset($lines[$i]->batch)) {
2065 print '<!-- Detail of lot -->';
2066 print '<td class="linecolbatch nowrap">';
2067 $detail = $langs->trans("NA");
2068 if ($lines[$i]->product->status_batch > 0 && $lines[$i]->fk_product > 0) {
2069 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
2070 $productlot = new Productlot($db);
2071 $reslot = $productlot->fetch(0, $lines[$i]->fk_product, $lines[$i]->batch);
2072 if ($reslot > 0) {
2073 $detail = $productlot->getNomUrl(1);
2074 } else {
2075 // lot is not created and info is only in reception lines
2076 $batchinfo = $langs->trans("Batch").': '.$lines[$i]->batch;
2077 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
2078 $batchinfo .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($lines[$i]->sellby, "day");
2079 }
2080 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
2081 $batchinfo .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($lines[$i]->eatby, "day");
2082 }
2083 $detail = $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $batchinfo);
2084 }
2085 }
2086 print $detail . '</td>';
2087 } else {
2088 print '<td></td>';
2089 }
2090 }
2091 }
2092
2093 // Weight
2094 print '<td class="center linecolweight">';
2095 if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2096 print $lines[$i]->product->weight * $lines[$i]->qty.' '.measuringUnitString(0, "weight", $lines[$i]->product->weight_units);
2097 } else {
2098 print '&nbsp;';
2099 }
2100 print '</td>';
2101
2102 // Volume
2103 print '<td class="center linecolvolume">';
2104 if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2105 print $lines[$i]->product->volume * $lines[$i]->qty.' '.measuringUnitString(0, "volume", $lines[$i]->product->volume_units);
2106 } else {
2107 print '&nbsp;';
2108 }
2109 print '</td>';
2110
2111
2112 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2113 print '<td class="center valignmiddle" colspan="2">';
2114 print '<input type="submit" class="button small button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'"><br>';
2115 print '<input type="submit" class="button small button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'"><br>';
2116 print '</td>';
2117 } elseif ($object->statut == Reception::STATUS_DRAFT) {
2118 // edit-delete buttons
2119 print '<td class="linecoledit center">';
2120 print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_edit().'</a>';
2121 print '</td>';
2122 print '<td class="linecoldelete" width="10">';
2123 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_delete().'</a>';
2124 print '</td>';
2125
2126 // Display lines extrafields
2127 if (isset($rowExtrafieldsStart, $rowExtrafieldsView, $rowEnd)) { // @phan-suppress-current-line PhanPluginUndeclaredVariableIsset
2128 print $rowExtrafieldsStart;
2129 print $rowExtrafieldsView;
2130 print $rowEnd;
2131 }
2132 }
2133 print "</tr>";
2134
2135 $arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet;
2136
2137 // Display lines extrafields
2138 $extralabelslines = $extrafields->attributes[$lines[$i]->table_element];
2139 if (!empty($extralabelslines) && is_array($extralabelslines) && count($extralabelslines) > 0) {
2140 $colspan = 8;
2141 if (isModEnabled('stock')) {
2142 $colspan++;
2143 }
2144 if (isModEnabled('productbatch')) {
2145 $colspan++;
2146 }
2147
2148 $line = new CommandeFournisseurDispatch($db);
2149 $line->id = $lines[$i]->id;
2150 $line->fetch_optionals();
2151
2152 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2153 print $line->showOptionals($extrafields, 'edit', array('colspan' => $colspan), '');
2154 } else {
2155 print $line->showOptionals($extrafields, 'view', array('colspan' => $colspan), '');
2156 }
2157 }
2158 }
2159 print '</tbody>';
2160
2161 // TODO Show also lines ordered but not delivered
2162
2163 print "</table>\n";
2164 print '</div>';
2165
2166
2167 print dol_get_fiche_end();
2168
2169
2170 $object->fetchObjectLinked($object->id, $object->element);
2171
2172
2173 /*
2174 * Boutons actions
2175 */
2176
2177 if (($user->socid == 0) && ($action != 'presend')) {
2178 print '<div class="tabsAction">';
2179
2180 $parameters = array();
2181 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2182 if (empty($reshook)) {
2183 if ($object->statut == Reception::STATUS_DRAFT && $num_prod > 0) {
2184 if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer'))
2185 || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate'))) {
2186 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'">'.$langs->trans("Validate").'</a>';
2187 } else {
2188 print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2189 }
2190 }
2191 // Back to draft
2192 if ($object->statut == Reception::STATUS_VALIDATED && $user->hasRight('reception', 'creer')) {
2193 print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('SetToDraft').'</a></div>';
2194 }
2195
2196 // TODO add alternative status
2197 // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2198 if ($object->statut == Reception::STATUS_CLOSED && $user->hasRight('reception', 'creer')) {
2199 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
2200 }
2201
2202 // Send
2203 if (empty($user->socid)) {
2204 if ($object->statut > 0) {
2205 if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('reception', 'reception_advance', 'send')) {
2206 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
2207 } else {
2208 print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
2209 }
2210 }
2211 }
2212
2213 // Create bill
2214 if (isModEnabled("supplier_invoice") && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) {
2215 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer')) {
2216 if (getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
2217 print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
2218 }
2219 }
2220 }
2221
2222
2223 // Set Billed and Closed
2224 if ($object->statut == Reception::STATUS_VALIDATED) {
2225 if ($user->hasRight('reception', 'creer') && $object->statut > 0) {
2226 if (!$object->billed && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
2227 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans('ClassifyBilled').'</a>';
2228 }
2229 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifyclosed&token='.newToken().'">'.$langs->trans("Close").'</a>';
2230 }
2231 }
2232
2233 if ($user->hasRight('reception', 'supprimer')) {
2234 print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
2235 }
2236 }
2237
2238 print '</div>';
2239 }
2240
2241
2242 /*
2243 * Documents generated
2244 */
2245
2246 if ($action != 'presend' && $action != 'editline') {
2247 print '<div class="fichecenter"><div class="fichehalfleft">';
2248
2249 $objectref = dol_sanitizeFileName($object->ref);
2250 $filedir = $conf->reception->dir_output."/".$objectref;
2251
2252 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2253
2254 $genallowed = $user->hasRight('reception', 'lire');
2255 $delallowed = $user->hasRight('reception', 'creer');
2256
2257 print $formfile->showdocuments('reception', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
2258
2259 // Show links to link elements
2260 //$tmparray = $form->showLinkToObjectBlock($object, null, array('order'), 1);
2261 $somethingshown = $form->showLinkedObjectBlock($object, '');
2262
2263 print '</div><div class="fichehalfright">';
2264
2265 print '</div></div>';
2266 }
2267
2268 // Presend form
2269 $modelmail = 'reception_send';
2270 $defaulttopic = 'SendReceptionRef';
2271 $diroutput = $conf->reception->dir_output;
2272 $trackid = 'rec'.$object->id;
2273
2274 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2275}
2276
2277
2278llxFooter();
2279
2280$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:48
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:67
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
Class to manage table ReceptionLineBatch.
Class to manage predefined suppliers products.
Class to manage line orders.
Class to manage customers orders.
Class to manage a WYSIWYG editor.
Class to manage warehouses.
Class to manage standard extra fields.
Class to offer components to list and upload files.
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 manage building of HTML components.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
Class to manage the table of subscription to notifications.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage proposals.
Class to manage receptions.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
print $script_file $mode $langs defaultlang(is_numeric($duration_value) ? " delay=". $duration_value :"").(is_numeric($duration_value2) ? " after cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
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_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...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
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, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
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).
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
print_date_range($date_start, $date_end, $format='', $outputlangs=null)
Format output for start and end date.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='')
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_clone($object, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
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...
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0)
Clean a string to use it as a file name.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79
measuringUnitString($unitid, $measuring_style='', $unitscale=null, $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
reception_prepare_head(Reception $object)
Prepare array with list of tabs.
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.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.