dolibarr 25.0.0-alpha
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-2026 MDW <mdeweerd@users.noreply.github.com>
16 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
17 * Copyright (C) 2025 Nick Fragoulis
18 * Copyright (C) 2026 Jose MARTINEZ <jose.martinez@pichinov.com>
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <https://www.gnu.org/licenses/>.
32 */
33
40// Load Dolibarr environment
41require '../main.inc.php';
50require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
51require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
52require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
53require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
54require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
55require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
56require_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
57require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
58require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
59require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
60require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
61if (isModEnabled("product") || isModEnabled("service")) {
62 require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
63}
64if (isModEnabled("propal")) {
65 require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
66}
67require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
68require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.orderline.class.php';
69require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
70if (isModEnabled('productbatch')) {
71 require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
72}
73if (isModEnabled('project')) {
74 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
75 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
76}
77
78$langs->loadLangs(array("receptions", "companies", "bills", 'orders', 'stocks', 'other', 'propal', 'sendings'));
79
80if (isModEnabled('incoterm')) {
81 $langs->load('incoterm');
82}
83if (isModEnabled('productbatch')) {
84 $langs->load('productbatch');
85}
86
87$origin = GETPOST('origin', 'alpha'); // Example: commande, propal
88$origin_id = GETPOSTINT('origin_id') ? GETPOSTINT('id') : '';
89$id = GETPOSTINT('id');
90if (empty($origin_id) && !empty($origin)) {
91 $origin_id = GETPOSTINT('origin_id'); // Id of order or propal
92}
93if (empty($origin_id) && !empty($origin)) {
94 $origin_id = GETPOSTINT('object_id'); // Id of order or propal
95}
96if (empty($origin_id) && !empty($origin)) {
97 $origin_id = GETPOSTINT('originid'); // Id of order or propal
98}
99$ref = GETPOST('ref', 'alpha');
100$line_id = GETPOSTINT('lineid') ? GETPOSTINT('lineid') : 0;
101$facid = GETPOSTINT('facid');
102$socid = GETPOSTINT('socid');
103$action = GETPOST('action', 'alpha');
104//Select mail models is same action as presend
105if (GETPOST('modelselected')) {
106 $action = 'presend';
107}
108$confirm = GETPOST('confirm', 'alpha');
109$cancel = GETPOST('cancel', 'alpha');
110$backtopage = GETPOST('backtopage', 'alpha');
111$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
112
113$contactid = GETPOSTINT('contactid');
114$projectid = GETPOSTINT('projectid');
115
116
117$cancel = GETPOST('cancel', 'alpha');
118$rank = (GETPOSTINT('rank') > 0) ? GETPOSTINT('rank') : -1;
119$lineid = GETPOSTINT('lineid');
120$backtopage = GETPOST('backtopage', 'alpha');
121//PDF
122$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
123$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
124$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
125
126$object = new Reception($db);
127$objectorder = new CommandeFournisseur($db);
128$extrafields = new ExtraFields($db);
129
130// fetch optionals attributes and labels
131$extrafields->fetch_name_optionals_label($object->table_element);
132$extrafields->fetch_name_optionals_label($object->table_element_line);
133$extrafields->fetch_name_optionals_label($objectorder->table_element_line);
134
135// Load object. Make an object->fetch
136include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
137
138// Restore $origin and $origin_id from the loaded object when the request only carried the
139// reception id (e.g. the line edit form on an existing reception posts action=updateline
140// and id=N but no origin field). Without this, the action handler below sees $origin
141// empty and silently skips both its standalone and its origin branches, so updates to
142// quantity, comment, batch and extrafields on an existing line are not persisted
143// (see issue #38386, regression from PR #36134).
144// The restore is gated on $object->origin_id > 0 so standalone receptions, which have
145// no upstream origin, are not affected: $origin stays empty and the standalone branch
146// of the updateline handler is still selected.
147if ($object->origin_id > 0) {
148 if (empty($origin)) {
149 if (!empty($object->origin_type)) {
150 $origin = $object->origin_type;
151 } elseif (is_string($object->origin) && $object->origin !== '') {
152 $origin = (string) $object->origin;
153 }
154 }
155 if (empty($origin_id)) {
156 $origin_id = $object->origin_id;
157 }
158}
159
160// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
161$hookmanager->initHooks(array('receptioncard', 'globalcard'));
162
163$date_delivery = dol_mktime(GETPOSTINT('date_deliveryhour'), GETPOSTINT('date_deliverymin'), 0, GETPOSTINT('date_deliverymonth'), GETPOSTINT('date_deliveryday'), GETPOSTINT('date_deliveryyear'));
164$date_reception = dol_mktime(GETPOSTINT('date_receptionhour'), GETPOSTINT('date_receptionmin'), 0, GETPOSTINT('date_receptionmonth'), GETPOSTINT('date_receptionday'), GETPOSTINT('date_receptionyear'));
165
166// Security check
167if ($user->socid) {
168 $socid = $user->socid;
169}
170$result = restrictedArea($user, 'reception', $object->id, '');
171// TODO Test on reception module on only
172if (isModEnabled("reception") || $origin == 'reception' || empty($origin)) {
173 $result = restrictedArea($user, 'reception', $object->id);
174} else {
175 // We do not use the reception module, so we test permission on the supplier orders
176 if ($origin == 'supplierorder' || $origin == 'order_supplier') {
177 $result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande');
178 } elseif (!$user->hasRight($origin, 'lire') && !$user->hasRight($origin, 'read')) {
180 }
181}
182
183if (isModEnabled("reception")) {
184 $permissiontoread = $user->hasRight('reception', 'lire');
185 $permissiontoadd = $user->hasRight('reception', 'creer');
186 $permissiontoedit = $user->hasRight('reception', 'creer'); // Used by the include of actions_lineupdown.inc.php
187 $permissiondellink = $user->hasRight('reception', 'creer'); // Used by the include of actions_dellink.inc.php
188 $permissiontovalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate')));
189 $permissiontodelete = $user->hasRight('reception', 'supprimer');
190} else {
191 $permissiontoread = $user->hasRight('fournisseur', 'commande', 'receptionner');
192 $permissiontoadd = $user->hasRight('fournisseur', 'commande', 'receptionner');
193 $permissiondellink = $user->hasRight('fournisseur', 'commande', 'receptionner'); // Used by the include of actions_dellink.inc.php
194 $permissiontovalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande', 'receptionner')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande_advance', 'check')));
195 $permissiontodelete = $user->hasRight('fournisseur', 'commande', 'receptionner');
196}
197$permissiontoeditextra = $permissiontoadd;
198if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
199 // For action 'update_extras' there is a specific permission set for the attribute to update
200 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
201}
202
203$editColspan = 0;
204$objectsrc = null;
205$typeobject = null;
206$ref_customer = null;
207$shipping_method_id = null;
208$warehouse_id = null;
209$note_public = null;
210$note_private = null;
211
212
213/*
214 * Actions
215 */
216
217$error = 0;
218$parameters = array();
219$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
220if ($reshook < 0) {
221 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
222}
223
224if (empty($reshook)) {
225 $backurlforlist = DOL_URL_ROOT.'/reception/list.php';
226
227 if (empty($backtopage) || ($cancel && empty($id))) {
228 if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
229 if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
230 $backtopage = $backurlforlist;
231 } else {
232 $backtopage = DOL_URL_ROOT.'/reception/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
233 }
234 }
235 }
236
237 if ($cancel) {
238 if (!empty($backtopageforcancel)) {
239 header("Location: ".$backtopageforcancel);
240 exit;
241 } elseif (!empty($backtopage)) {
242 header("Location: ".$backtopage);
243 exit;
244 }
245
246 $action = '';
247 }
248
249 if ($cancel) {
250 if (!$origin) {
251 $action = '';
252 $object->fetch($object->id); // show reception also after canceling modification
253 }
254 }
255
256 include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
257
258 // Reopen
259 if ($action == 'reopen' && $permissiontoadd) { // Test on permissions not required here
260 $result = $object->reOpen();
261 if ($result < 0) {
262 setEventMessages($object->error, $object->errors, 'errors');
263 }
264 }
265
266 // Confirm back to draft status
267 if ($action == 'modif' && $permissiontoadd) {
268 $result = $object->setDraft($user);
269 if ($result >= 0) {
270 // Define output language
271 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
272 $outputlangs = $langs;
273 $newlang = '';
274 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
275 $newlang = GETPOST('lang_id', 'aZ09');
276 }
277 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
278 $newlang = $object->thirdparty->default_lang;
279 }
280 if (!empty($newlang)) {
281 $outputlangs = new Translate("", $conf);
282 $outputlangs->setDefaultLang($newlang);
283 }
284 $model = $object->model_pdf;
285 $ret = $object->fetch($id); // Reload to get new records
286 $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
287 }
288 } else {
289 setEventMessages($object->error, $object->errors, 'errors');
290 }
291 }
292
293 // Set incoterm
294 if ($action == 'set_incoterms' && isModEnabled('incoterm') && $permissiontoadd) {
295 $result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
296 }
297
298 if ($action == 'setref_supplier' && $permissiontoadd) {
299 if ($result < 0) {
300 setEventMessages($object->error, $object->errors, 'errors');
301 }
302
303 $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'RECEPTION_MODIFY');
304 if ($result < 0) {
305 setEventMessages($object->error, $object->errors, 'errors');
306 $action = 'editref_supplier';
307 } else {
308 header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
309 exit;
310 }
311 }
312
313 if ($action == 'update_extras' && $permissiontoeditextra) {
314 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
315
316 $attribute_name = GETPOST('attribute', 'aZ09');
317
318 // Fill array 'array_options' with data from update form
319 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
320 if ($ret < 0) {
321 $error++;
322 }
323
324 if (!$error) {
325 $result = $object->updateExtraField($attribute_name, 'RECEPTION_MODIFY');
326 if ($result < 0) {
327 setEventMessages($object->error, $object->errors, 'errors');
328 $error++;
329 }
330 }
331
332 if ($error) {
333 $action = 'edit_extras';
334 }
335 }
336
337 // Create reception
338 if ($action == 'add' && $permissiontoadd) {
339 $db->begin();
340
341 if (!$error && !$origin && getDolGlobalString('RECEPTION_STANDALONE')) {
342 if (GETPOSTINT('socid') < 1) {
343 $error++;
344 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors');
345 $action = 'create';
346 }
347
348 $object->socid = GETPOSTINT('socid');
349 $object->fetch_thirdparty();
350 $object->note = GETPOST('note', 'alpha');
351 $object->note_private = GETPOST('note', 'alpha');
352 $object->origin = $origin; // deprecated
353 $object->origin_type = $origin;
354 $object->origin_id = $origin_id;
355 $object->fk_project = GETPOSTINT('projectid');
356 $object->weight = GETPOSTINT('weight') == '' ? null : GETPOSTINT('weight');
357 $object->trueHeight = GETPOSTINT('trueHeight') == '' ? null : GETPOSTINT('trueHeight');
358 $object->trueWidth = GETPOSTINT('trueWidth') == '' ? null : GETPOSTINT('trueWidth');
359 $object->trueDepth = GETPOSTINT('trueDepth') == '' ? null : GETPOSTINT('trueDepth');
360 $object->size_units = GETPOSTINT('size_units');
361 $object->weight_units = GETPOSTINT('weight_units');
362 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
363 $object->fk_warehouse = GETPOSTINT('fk_warehouse'); // Default warehouse for the lines
364 $object->model_pdf = GETPOST('model');
365 $object->date_delivery = $date_delivery; // Date delivery planned
366 $object->date_reception = $date_reception;
367 $object->shipping_method_id = GETPOSTINT('shipping_method_id');
368 $object->tracking_number = GETPOST('tracking_number', 'alpha');
369 $object->note_private = GETPOST('note_private', 'restricthtml');
370 $object->note_public = GETPOST('note_public', 'restricthtml');
371 $object->fk_incoterms = GETPOSTINT('incoterm_id');
372 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
373
374 $product = new Product($db);
375
376 // Fill array 'array_options' with data from add form
377 $ret = $extrafields->setOptionalsFromPost(null, $object);
378 if ($ret < 0) {
379 $error++;
380 }
381
382 if (!$error) {
383 $ret = $object->create($user);
384 if ($ret <= 0) {
385 setEventMessages($object->error, $object->errors, 'errors');
386 $error++;
387 }
388 }
389 }
390 if ($origin && $origin_id > 0) {
391 $object->note = GETPOST('note', 'alpha');
392 $object->note_private = GETPOST('note', 'alpha');
393 $object->origin = $origin;
394 $object->origin_type = $origin;
395 $object->origin_id = $origin_id;
396 $object->fk_project = GETPOSTINT('projectid');
397 $object->weight = GETPOST('weight') == '' ? null : GETPOSTINT('weight');
398 $object->trueHeight = GETPOST('trueHeight') == '' ? null : GETPOSTINT('trueHeight');
399 $object->trueWidth = GETPOST('trueWidth') == '' ? null : GETPOSTINT('trueWidth');
400 $object->trueDepth = GETPOST('trueDepth') == '' ? null : GETPOSTINT('trueDepth');
401 $object->size_units = GETPOSTINT('size_units');
402 $object->weight_units = GETPOSTINT('weight_units');
403
404 $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
405 $object->fk_warehouse = GETPOSTINT('fk_warehouse'); // Default warehouse for the lines
406 $object->model_pdf = GETPOST('model');
407 $object->date_delivery = $date_delivery; // Date delivery planned
408 $object->date_reception = $date_reception;
409 $object->shipping_method_id = GETPOSTINT('shipping_method_id');
410 $object->tracking_number = GETPOST('tracking_number', 'alpha');
411 $object->note_private = GETPOST('note_private', 'restricthtml');
412 $object->note_public = GETPOST('note_public', 'restricthtml');
413 $object->fk_incoterms = GETPOSTINT('incoterm_id');
414 $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
415
416 if ($object->origin == "supplierorder") {
417 $object->origin = 'order_supplier';
418 $object->origin_type = 'order_supplier';
419 $classname = 'CommandeFournisseur';
420 } else {
421 $classname = ucfirst($object->origin_type);
422 }
423 $objectsrc = new $classname($db);
424 $objectsrc->fetch($object->origin_id);
425
426 $object->socid = $objectsrc->socid;
427
428 $product = new Product($db);
429 $batch_line = array();
430 $stockLine = array();
431 $array_options = array();
432
433 $totalqty = 0;
434
435 $num = 0;
436 foreach ($_POST as $key => $value) {
437 // without batch module enabled
438
439 if (strpos($key, 'qtyasked') !== false) {
440 $num++;
441 }
442 }
443
444 // Loop lines to calculate $totalqty
445 for ($i = 1; $i <= $num; $i++) {
446 $idl = "idl".$i; // id line source
447
448 //$sub_qty = array();
449 //$subtotalqty = 0;
450
451 //$j = 0;
452 //$batch = "batchl".$i."_0";
453 //$stockLocation = "ent1".$i."_0";
454 $qty = "qtyl".$i; // qty
455
456 //reception line for product with no batch management and no multiple stock location
457 if (GETPOST($qty, 'alpha') > 0) {
458 $totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
459 }
460
461 // Extrafields
462 $array_options[$i] = $extrafields->getOptionalsFromPost($object->table_element_line, (string) $i);
463 }
464
465
466 if ($totalqty > 0) { // There is at least one thing to ship
467 for ($i = 1; $i <= $num; $i++) {
468 $idl = "idl".$i; // id line source
469 $lineToTest = '';
470 $lineId = GETPOSTINT($idl);
471 foreach ($objectsrc->lines as $linesrc) {
472 if ($linesrc->id == $lineId) {
473 $lineToTest = $linesrc;
474 break;
475 }
476 }
477 if (empty($lineToTest)) {
478 continue;
479 }
480 $qty = "qtyl".$i;
481 $comment = "comment".$i;
482 // EATBY <-> DLUO and SELLBY <-> DLC, see productbatch.class.php
483 $eatby = "dluo".$i;
484 $sellby = "dlc".$i;
485 $batch = "batch".$i;
486 $cost_price = "cost_price".$i;
487
488 //var_dump(GETPOST("productl".$i, 'int').' '.GETPOST('entl'.$i, 'int').' '.GETPOST($idl, 'int').' '.GETPOST($qty, 'int').' '.GETPOST($batch, 'alpha'));
489
490 //if (GETPOST($qty, 'int') > 0 || (GETPOST($qty, 'int') == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS')) || (GETPOST($qty, 'int') < 0 && getDolGlobalString('RECEPTION_ALLOW_NEGATIVE_QTY'))) {
491 if (GETPOSTFLOAT($qty) > 0 || (GETPOSTFLOAT($qty) == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS'))) {
492 $ent = "entl".$i;
493 $idl = "idl".$i;
494
495 $entrepot_id = is_numeric(GETPOST($ent)) ? GETPOSTINT($ent) : GETPOSTINT('entrepot_id');
496
497 /*
498 if (!empty($lineToTest)) {
499 $fk_product = $lineToTest->fk_product;
500 } else {
501 $fk_product = $linesrc->fk_product;
502 }*/
503 $fk_product = GETPOSTINT("productl".$i);
504
505 if ($entrepot_id < 0) {
506 $entrepot_id = '';
507 }
508 if (!($fk_product > 0) && !getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
509 $entrepot_id = 0;
510 }
511
512 $eatby = GETPOST($eatby, 'alpha');
513 $sellby = GETPOST($sellby, 'alpha');
514 $eatbydate = str_replace('/', '-', $eatby);
515 $sellbydate = str_replace('/', '-', $sellby);
516
517 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
518 $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'));
519 } else {
520 $ret = $object->addline($entrepot_id, GETPOSTINT($idl), (float) price2num(GETPOST($qty), 'MS'), $array_options[$i], GETPOST($comment), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch));
521 }
522 if ($ret < 0) {
523 setEventMessages($object->error, $object->errors, 'errors');
524 $error++;
525 }
526 }
527 }
528
529 // Fill array 'array_options' with data from add form
530 $ret = $extrafields->setOptionalsFromPost(null, $object);
531 if ($ret < 0) {
532 $error++;
533 }
534 if (!$error) {
535 $ret = $object->create($user); // This create reception (like Odoo picking) and line of receptions. Stock movement will when validating reception.
536
537 if ($ret <= 0) {
538 setEventMessages($object->error, $object->errors, 'errors');
539 $error++;
540 } else {
541 // Define output language
542 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
543 $object->fetch_thirdparty();
544 $outputlangs = $langs;
545 $newlang = '';
546 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
547 $newlang = GETPOST('lang_id', 'aZ09');
548 }
549 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
550 $newlang = $object->thirdparty->default_lang;
551 }
552 if (!empty($newlang)) {
553 $outputlangs = new Translate("", $conf);
554 $outputlangs->setDefaultLang($newlang);
555 }
556 $model = $object->model_pdf;
557 $ret = $object->fetch($object->id); // Reload to get new records
558
559 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
560 if ($result < 0) {
561 dol_print_error($db, $object->error, $object->errors);
562 }
563 }
564 }
565 }
566 } else {
567 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("QtyToReceive").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
568 $error++;
569 }
570 }
571 if (!$error) {
572 $db->commit();
573 header("Location: card.php?id=" . $object->id);
574 exit;
575 } else {
576 $db->rollback();
577 //$_GET["commande_id"] = GETPOSTINT('commande_id');
578 $action = 'create';
579 }
580 } elseif ($action == 'confirm_valid' && $confirm == 'yes' && $permissiontovalidate) {
581 $object->fetch_thirdparty();
582
583 $result = $object->valid($user);
584
585 if ($result < 0) {
586 $langs->load("errors");
587 setEventMessages($langs->trans($object->error), null, 'errors');
588 } else {
589 // Define output language
590 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
591 $outputlangs = $langs;
592 $newlang = '';
593 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
594 $newlang = GETPOST('lang_id', 'aZ09');
595 }
596 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
597 $newlang = $object->thirdparty->default_lang;
598 }
599 if (!empty($newlang)) {
600 $outputlangs = new Translate("", $conf);
601 $outputlangs->setDefaultLang($newlang);
602 }
603 $model = $object->model_pdf;
604 $ret = $object->fetch($id); // Reload to get new records
605
606 $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
607 if ($result < 0) {
608 dol_print_error($db, $object->error, $object->errors);
609 }
610 }
611 }
612 } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
613 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
614 $result = $object->delete($user);
615 if ($result > 0) {
616 header("Location: ".DOL_URL_ROOT.'/reception/index.php');
617 exit;
618 } else {
619 setEventMessages($object->error, $object->errors, 'errors');
620 }
621
622 // TODO add alternative status
623 /*} elseif ($action == 'reopen' && ($user->hasRights('reception', 'creer') || $user->hasRights('reception', 'reception_advance', 'validate'))) {
624 $result = $object->setStatut(Reception::STATUS_DRAFT);
625 if ($result < 0) {
626 setEventMessages($object->error, $object->errors, 'errors');
627 }*/
628 } elseif ($action == 'setdate_livraison' && $permissiontoadd) {
629 $datedelivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
630
631 $object->fetch($id);
632 $result = $object->setDeliveryDate($user, $datedelivery);
633 if ($result < 0) {
634 setEventMessages($object->error, $object->errors, 'errors');
635 }
636 } elseif ($action == 'setdate_reception' && $user->hasRight('reception', 'creer')) {
637 $datereception = dol_mktime(GETPOSTINT('recep_hour'), GETPOSTINT('recep_min'), 0, GETPOSTINT('recep_month'), GETPOSTINT('recep_day'), GETPOSTINT('recep_year'));
638
639 $object->fetch($id);
640 $result = $object->setReceptionDate($user, $datereception);
641 if ($result < 0) {
642 setEventMessages($object->error, $object->errors, 'errors');
643 }
644 } elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $permissiontoadd) {
645 // Remove a product line
646 $result = $object->deleteLine($user, $lineid);
647 if ($result > 0) {
648 // reorder lines
649 $object->line_order(true);
650 // Define output language
651 $outputlangs = $langs;
652 $newlang = '';
653 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
654 $newlang = GETPOST('lang_id', 'aZ09');
655 }
656 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
657 $newlang = $object->thirdparty->default_lang;
658 }
659 if (!empty($newlang)) {
660 $outputlangs = new Translate("", $conf);
661 $outputlangs->setDefaultLang($newlang);
662 }
663 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
664 $ret = $object->fetch($object->id); // Reload to get new records
665 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
666 }
667
668 header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
669 exit;
670 } else {
671 setEventMessages($object->error, $object->errors, 'errors');
672 }
673 } elseif (in_array($action, array('setwarehouse', 'settracking_number', 'settracking_url', 'settrueWeight', 'settrueWidth', 'settrueHeight', 'settrueDepth', 'setshipping_method_id')) && $permissiontoadd) {
674 // Action update
675 $error = 0;
676
677 if ($action == 'setwarehouse') { // Test on permission already done. Default warehouse for the lines
678 // Note: setValueFrom() casts the value to int, so it can not store an empty warehouse.
679 // We use update() to keep a NULL, because a line without warehouse must not move stock.
680 $object->fk_warehouse = (GETPOSTINT('warehouse_id') > 0 ? GETPOSTINT('warehouse_id') : null);
681 if ($object->update($user) < 0) {
682 $error++;
683 setEventMessages($object->error, $object->errors, 'errors');
684 }
685 }
686
687 if ($action == 'settracking_number') { // Test on permission already done
688 $object->tracking_number = trim(GETPOST('tracking_number', 'alpha'));
689 }
690 if ($action == 'settracking_url') { // Test on permission already done
691 $object->tracking_url = trim(GETPOST('tracking_url', 'restricthtml'));
692 }
693 if ($action == 'settrueWeight') { // Test on permission already done
694 $object->trueWeight = GETPOST('trueWeight');
695 $object->weight_units = GETPOSTINT('weight_units');
696 }
697 if ($action == 'settrueWidth') { // Test on permission already done
698 $object->trueWidth = GETPOST('trueWidth');
699 }
700 if ($action == 'settrueHeight') { // Test on permission already done
701 $object->trueHeight = GETPOST('trueHeight');
702 $object->size_units = GETPOSTINT('size_units');
703 }
704 if ($action == 'settrueDepth') { // Test on permission already done
705 $object->trueDepth = GETPOST('trueDepth');
706 }
707 if ($action == 'setshipping_method_id') { // Test on permission already done
708 $object->shipping_method_id = GETPOSTINT('shipping_method_id');
709 }
710
711 if ($object->update($user) >= 0) {
712 header("Location: card.php?id=" . $object->id);
713 exit;
714 }
715 setEventMessages($object->error, $object->errors, 'errors');
716
717 $action = "";
718 } elseif ($action == 'builddoc' && $permissiontoread) {
719 // Build document
720 // En get ou en post
721 // Save last template used to generate document
722 if (GETPOST('model')) {
723 $object->setDocModel($user, GETPOST('model', 'alpha'));
724 }
725
726 // Define output language
727 $outputlangs = $langs;
728 $newlang = '';
729 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
730 $newlang = GETPOST('lang_id', 'aZ09');
731 }
732 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
733 $newlang = $object->thirdparty->default_lang;
734 }
735 if (!empty($newlang)) {
736 $outputlangs = new Translate("", $conf);
737 $outputlangs->setDefaultLang($newlang);
738 }
739 $result = $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
740 if ($result <= 0) {
741 setEventMessages($object->error, $object->errors, 'errors');
742 $action = '';
743 }
744 } elseif ($action == 'remove_file' && $permissiontoadd) {
745 // Delete file in doc form
746 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
747
748 $upload_dir = $conf->reception->dir_output;
749 $file = $upload_dir.'/'.GETPOST('file');
750 $ret = dol_delete_file($file, 1, 0, 0, $object);
751 if ($ret) {
752 setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
753 } else {
754 setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
755 }
756 } elseif ($action == 'classifybilled' && $permissiontoadd) {
757 $result = $object->setBilled();
758 if ($result >= 0) {
759 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
760 exit();
761 } else {
762 setEventMessages($object->error, $object->errors, 'errors');
763 $action = '';
764 }
765 } elseif ($action == 'classifyclosed' && $permissiontoread) {
766 $result = $object->setClosed();
767 if ($result >= 0) {
768 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
769 exit();
770 } else {
771 setEventMessages($object->error, $object->errors, 'errors');
772 $action = '';
773 }
774 } elseif ($action == 'deleteline' && !empty($line_id) && $permissiontoread) {
775 // delete a line
776 $lines = $object->lines;
777 $line = new CommandeFournisseurDispatch($db);
778
779 $num_prod = count($lines);
780 for ($i = 0; $i < $num_prod; $i++) {
781 if ($lines[$i]->id == $line_id) {
782 // delete single warehouse line
783 $line->id = $line_id;
784 if (!$error && $line->delete($user) < 0) {
785 $error++;
786 }
787 }
788 unset($_POST["lineid"]);
789 }
790
791 if (!$error) {
792 header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
793 exit();
794 } else {
795 setEventMessages($line->error, $line->errors, 'errors');
796 }
797 } elseif ($action == 'updateline' && GETPOST('save') && $permissiontoadd) {
798 if (!$origin && getDolGlobalString('RECEPTION_STANDALONE')) {
799 // Update a line
800 // Clean parameters
801
802 if (!$object->fetch($id) > 0) {
803 dol_print_error($db);
804 }
805 $object->fetch_thirdparty();
806
807 $qty = GETPOST('qty', 'alpha');
808 $description = '';
809 $element_type = 'reception';
810 $fk_unit = '';
811 $fk_product = 0;
812 $rang = 0;
813
814 // Extrafields
815 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
816 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
817 // Unset extrafield
818 if (is_array($extralabelsline)) {
819 // Get extra fields
820 foreach ($extralabelsline as $key => $value) {
821 unset($_POST["options_" . $key]);
822 }
823 }
824
825 $receptionline = new ReceptionLineBatch($db);
826 $receptionline->fetch(GETPOSTINT('lineid'));
827
828
829 if (!$error) {
830 // Warehouse: the empty choice of the select posts -1, which means "clear the warehouse" (0),
831 // while an absent field means "do not change" (-1)
832 $wh_line = GETPOSTISSET('entrepot_id') ? max(0, GETPOSTINT('entrepot_id')) : -1;
833 $result = $object->updatelinefree(GETPOSTINT('lineid'), (float) $qty, $element_type, $fk_product, GETPOSTINT('units'), $rang, $description, 0, $array_options, GETPOSTISSET('cost_price') ? price2num(GETPOST('cost_price', 'alpha')) : null, GETPOSTISSET('fourn_ref') ? GETPOST('fourn_ref', 'alphanohtml') : null, $wh_line, GETPOSTISSET('batch') ? GETPOST('batch', 'alphanohtml') : null);
834
835 if ($result >= 0) {
836 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
837 // Define output language
838 $outputlangs = $langs;
839 $newlang = '';
840 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
841 $newlang = GETPOST('lang_id', 'aZ09');
842 }
843 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
844 $newlang = $object->thirdparty->default_lang;
845 }
846 if (!empty($newlang)) {
847 $outputlangs = new Translate("", $conf);
848 $outputlangs->setDefaultLang($newlang);
849 $outputlangs->load('products');
850 }
851
852 $ret = $object->fetch($object->id); // Reload to get new records
853 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
854 }
855 unset($_POST['qty']);
856 unset($_POST['units']);
857 } else {
858 setEventMessages($object->error, $object->errors, 'errors');
859 }
860 }
861 } elseif ($origin && $origin_id > 0) {
862 // Update a line
863 // Clean parameters
864 $qty = 0;
865 $entrepot_id = 0;
866 $batch_id = 0;
867
868 $lines = $object->lines;
869 $num_prod = count($lines);
870 for ($i = 0; $i < $num_prod; $i++) {
871 if ($lines[$i]->id == $line_id) { // we have found line to update
872 $line = new CommandeFournisseurDispatch($db);
873 $line->fetch($line_id);
874 // Extrafields Lines
875 $extrafields->fetch_name_optionals_label($object->table_element_line);
876 $line->array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
877
878 $line->fk_product = $lines[$i]->fk_product;
879
880 if ($lines[$i]->fk_product > 0) {
881 // single warehouse reception line
882 $stockLocation = "entl".$line_id;
883 $qty = "qtyl".$line_id;
884 $comment = "comment".$line_id;
885
886 $line->id = $line_id;
887 $line->fk_entrepot = GETPOSTINT($stockLocation);
888 $line->qty = GETPOSTFLOAT($qty, 'MS');
889 $line->comment = GETPOST($comment, 'alpha');
890
891 if (isModEnabled('productbatch')) {
892 $batch = "batch".$line_id;
893 $dlc = "dlc".$line_id;
894 $dluo = "dluo".$line_id;
895 // EATBY <-> DLUO
896 $eatby = GETPOST($dluo, 'alpha');
897 $eatbydate = str_replace('/', '-', $eatby);
898 // SELLBY <-> DLC
899 $sellby = GETPOST($dlc, 'alpha');
900 $sellbydate = str_replace('/', '-', $sellby);
901 $line->batch = GETPOST($batch, 'alpha');
902 $line->eatby = strtotime($eatbydate);
903 $line->sellby = strtotime($sellbydate);
904 }
905
906 if ($line->update($user) < 0) {
907 setEventMessages($line->error, $line->errors, 'errors');
908 $error++;
909 }
910 } else { // Product no predefined
911 $qty = "qtyl".$line_id;
912 $line->id = $line_id;
913 $line->qty = GETPOSTFLOAT($qty, 'MS');
914 $line->fk_entrepot = 0;
915 if ($line->update($user) < 0) {
916 setEventMessages($line->error, $line->errors, 'errors');
917 $error++;
918 }
919 unset($_POST[$qty]);
920 }
921 }
922 }
923
924 unset($_POST["lineid"]);
925
926 if (!$error) {
927 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
928 // Define output language
929 $outputlangs = $langs;
930 $newlang = '';
931 if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
932 $newlang = GETPOST('lang_id', 'aZ09');
933 }
934 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
935 $newlang = $object->thirdparty->default_lang;
936 }
937 if (!empty($newlang)) {
938 $outputlangs = new Translate("", $conf);
939 $outputlangs->setDefaultLang($newlang);
940 }
941
942 $ret = $object->fetch($object->id); // Reload to get new records
943 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
944 }
945
946 // Redirect after the successful save so the page leaves edit mode and the
947 // updated values are read back from DB, matching the cancel path below
948 // and the header-data save handlers (see issue #38386).
949 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id);
950 exit();
951 } else {
952 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
953 exit();
954 }
955 }
956 } elseif ($action == 'updateline' && $permissiontoadd && GETPOST('cancel', 'alpha') == $langs->trans("Cancel")) {
957 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
958 exit();
959 } elseif ($action == 'addline' && !$origin && getDolGlobalString('RECEPTION_STANDALONE') && $permissiontoadd) { // Add a new line
960 $langs->load('errors');
961 $error = 0;
962 $line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
963 $predef = '';
964 $description = '';
965 $fk_elementdet = '';
966 $element_type = 'reception';
967 $fk_unit = GETPOSTINT('units');
968 $idprod = 0;
969 $fk_product = 0;
970 $fk_entrepot = '';
971 $rang = '';
972 $prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09');
973 $cost_price_from_pfp = 0;
974 $reffourn_from_pfp = '';
975 if ($prod_entry_mode == 'free') {
976 $idprod = 0;
977 } else {
978 $idprod = GETPOSTINT('idprod');
979 if (empty($idprod) && GETPOSTISSET('idprodfournprice')) {
980 // The supplier product combo posts idprodfournprice (id of supplier price, or 'idprod_x' if product has no supplier price)
981 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
982 $ipfp = GETPOST('idprodfournprice', 'alpha');
983 $reg = array();
984 if (preg_match('/^idprod_([0-9]+)$/', $ipfp, $reg)) {
985 $idprod = (int) $reg[1];
986 } elseif ((int) $ipfp > 0) {
987 $productsupplier = new ProductFournisseur($db);
988 $idprod = $productsupplier->get_buyprice((int) $ipfp, (float) price2num(GETPOST('qty', 'alpha'), 'MS'));
989 if ($idprod > 0) {
990 $cost_price_from_pfp = price2num($productsupplier->fourn_unitprice);
991 $reffourn_from_pfp = $productsupplier->ref_supplier;
992 }
993 }
994 }
995 if ($prod_entry_mode != 'free' && $idprod <= 0) {
996 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
997 $error++;
998 }
999 if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
1000 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
1001 $error++;
1002 }
1003 }
1004
1005 $qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
1006
1007 // Extrafields
1008 $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
1009 $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
1010 // Unset extrafield
1011 if (is_array($extralabelsline)) {
1012 // Get extra fields
1013 foreach ($extralabelsline as $key => $value) {
1014 unset($_POST["options_".$key]);
1015 }
1016 }
1017
1018 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
1019 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
1020 $error++;
1021 }
1022
1023 if ($qty == '') {
1024 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1025 $error++;
1026 }
1027 if ($qty < 0) {
1028 setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
1029 $error++;
1030 }
1031 if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($line_desc)) {
1032 setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
1033 $error++;
1034 }
1035
1036 if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
1037 if ($combinations = GETPOST('combinations', 'array')) {
1038 // Check if there is a product with the given combination
1039 $prodcomb = new ProductCombination($db);
1040
1041 if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
1042 $idprod = $res->fk_product_child;
1043 $fk_product = $idprod; // Update $fk_product with the fetched child product
1044 } else {
1045 setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
1046 $error++;
1047 }
1048 }
1049 }
1050
1051 if (!$error && ($qty >= 0) && (!empty($line_desc) || (!empty($idprod) && $idprod > 0))) {
1052 // Clean parameters
1053 if (!empty($idprod) && $idprod > 0) {
1054 $prod = new Product($db);
1055 $prod->fetch($idprod);
1056 $desc = $prod->label;
1057 $description = $desc;
1058 // Define output language
1059 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1060 $outputlangs = $langs;
1061 $newlang = '';
1062 if (GETPOST('lang_id', 'aZ09')) {
1063 $newlang = GETPOST('lang_id', 'aZ09');
1064 }
1065 if (empty($newlang)) {
1066 $newlang = $object->thirdparty->default_lang;
1067 }
1068 if (!empty($newlang)) {
1069 $outputlangs = new Translate("", $conf);
1070 $outputlangs->setDefaultLang($newlang);
1071 }
1072
1073 $description = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
1074 } else {
1075 $description = $prod->description;
1076 }
1077 if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
1078 $description = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
1079 } else {
1080 $description = $line_desc;
1081 }
1082
1083 // Add custom code and origin country into description
1084 if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
1085 $tmptxt = '(';
1086 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
1087 $outputlangs = $langs;
1088 $newlang = '';
1089 if (GETPOST('lang_id', 'alpha')) {
1090 $newlang = GETPOST('lang_id', 'alpha');
1091 }
1092 if (empty($newlang)) {
1093 $newlang = $object->thirdparty->default_lang;
1094 }
1095 if (!empty($newlang)) {
1096 $outputlangs = new Translate("", $conf);
1097 $outputlangs->setDefaultLang($newlang);
1098 $outputlangs->load('products');
1099 }
1100 if (!empty($prod->customcode)) {
1101 $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
1102 }
1103 if (!empty($prod->customcode) && !empty($prod->country_code)) {
1104 $tmptxt .= ' - ';
1105 }
1106 if (!empty($prod->country_code)) {
1107 $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $outputlangs, 0);
1108 }
1109 } else {
1110 if (!empty($prod->customcode)) {
1111 $tmptxt .= $langs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
1112 }
1113 if (!empty($prod->customcode) && !empty($prod->country_code)) {
1114 $tmptxt .= ' - ';
1115 }
1116 if (!empty($prod->country_code)) {
1117 $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $langs, 0);
1118 }
1119 }
1120 $tmptxt .= ')';
1121 $description = dol_concatdesc($desc, $tmptxt);
1122 }
1123 $type = $prod->type;
1124 $fk_unit = $prod->fk_unit;
1125 } else {
1126 $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
1127 $desc = $line_desc;
1128 $type = GETPOST('type');
1129 $fk_unit = GETPOST('units', 'alpha');
1130 $description = $desc;
1131 $fk_elementdet = '';
1132 }
1133 $desc = dol_htmlcleanlastbr($desc);
1134
1135 if (!$error) {
1136 // Insert line
1137 // Buying price: typed value first (field of the supplier add-line block), then known supplier price
1138 $typedcost = price2num(GETPOST('cost_price', 'alpha'));
1139 if (!(float) $typedcost) {
1140 $typedcost = price2num(GETPOST('price_ht', 'alpha'));
1141 }
1142 $finalcost = ((float) $typedcost > 0) ? (float) $typedcost : (float) $cost_price_from_pfp;
1143 $reffourn_line = GETPOST('fourn_ref', 'alphanohtml');
1144 if ($reffourn_line === '' && !empty($reffourn_from_pfp)) {
1145 $reffourn_line = $reffourn_from_pfp;
1146 }
1147 $wh_line = max(0, GETPOSTINT('entrepot_id')); // Empty choice of the select posts -1: store 0 (a line without warehouse deliberately generates no stock movement)
1148 $result = $object->addlinefree((float) $qty, $element_type, $idprod, $fk_unit, min($rank, count($object->lines) + 1), $description, $array_options, (float) $finalcost, $reffourn_line, $wh_line, GETPOST('batch', 'alphanohtml'));
1149
1150 if ($result > 0) {
1151 $ret = $object->fetch($object->id); // Reload to get new records
1152 $object->fetch_thirdparty();
1153 if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
1154 // Define output language
1155 $outputlangs = $langs;
1156 $newlang = GETPOST('lang_id', 'alpha');
1157 if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
1158 $newlang = $object->thirdparty->default_lang;
1159 }
1160 if (!empty($newlang)) {
1161 $outputlangs = new Translate("", $conf);
1162 $outputlangs->setDefaultLang($newlang);
1163 }
1164 $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
1165 }
1166 } else {
1167 header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To redisplay the form being edited
1168 exit();
1169 }
1170 }
1171 }
1172 }
1173
1174 include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
1175
1176 // Actions to send emails
1177 if (empty($id)) {
1178 $id = $facid;
1179 }
1180 $triggersendname = 'RECEPTION_SENTBYMAIL';
1181 $paramname = 'id';
1182 $mode = 'emailfromreception';
1183 $autocopy = 'MAIN_MAIL_AUTOCOPY_RECEPTION_TO';
1184 $trackid = 'rec'.$object->id;
1185 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
1186}
1187
1188
1189/*
1190 * View
1191 */
1192
1193$title = $object->ref.' - '.$langs->trans('Reception');
1194if ($action == 'create') {
1195 $title = $langs->trans("NewReception");
1196}
1197llxHeader('', $title, 'Reception', '', 0, 0, '', '', '', 'mod-reception page-card');
1198
1199$form = new Form($db);
1200$formfile = new FormFile($db);
1201$formproduct = new FormProduct($db);
1202$formproject = null;
1203if (isModEnabled('project')) {
1204 $formproject = new FormProjets($db);
1205} else {
1206 $formproject = null;
1207}
1208
1209$product_static = new Product($db);
1210$reception_static = new Reception($db);
1211$warehousestatic = new Entrepot($db);
1212
1213if ($action == 'create' && $origin != 'supplierorder' && !getDolGlobalString('RECEPTION_STANDALONE')) {
1214 print load_fiche_titre($langs->trans("CreateReception"), '', 'dollyrevert');
1215
1216 print '<br>'.$langs->trans("ReceptionCreationIsDoneFromOrder");
1217 $action = '';
1218 $id = '';
1219 $ref = '';
1220}
1221
1222// Mode creation.
1223if ($action == 'create' && $permissiontoadd) {
1224 $recept = new Reception($db);
1225
1226 print load_fiche_titre($langs->trans("NewReception"), '', 'dollyrevert');
1227 if (empty($origin) && getDolGlobalString('RECEPTION_STANDALONE')) {
1228 $soc = new Societe($db);
1229 if ($socid > 0) {
1230 $res = $soc->fetch($socid);
1231 }
1232
1233 $note_private = $object->getDefaultCreateValueFor('note_private');
1234 $note_public = $object->getDefaultCreateValueFor('note_public');
1235
1236 print '<form name="crea_reception" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
1237 print '<input type="hidden" name="token" value="' . newToken() . '">';
1238 print '<input type="hidden" name="action" value="add">';
1239 print '<input type="hidden" name="changecompany" value="0">'; // will be set to 1 by javascript so we know post is done after a company change
1240 print '<input type="hidden" name="originid" value="' . $id . '">';
1241 print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
1242
1243 print dol_get_fiche_head([]);
1244
1245 print '<table class="border centpercent">';
1246
1247
1248 // Thirdparty
1249 print '<tr>';
1250 print '<td class="fieldrequired">' . $langs->trans('ThirdParty') . '</td>';
1251 if ($socid > 0) {
1252 print '<td>';
1253 print $soc->getNomUrl(1);
1254 print '<input type="hidden" name="socid" value="' . $soc->id . '">';
1255 print '</td>';
1256 } else {
1257 print '<td class="valuefieldcreate">';
1258 print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', '', 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
1259 // reload page to retrieve customer information
1260 if (!getDolGlobalString('RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED')) {
1261 print '<script>
1262 $(document).ready(function() {
1263 $("#socid").change(function() {
1264 console.log("We have changed the company - Reload page");
1265 var socid = $(this).val();
1266 // reload page
1267 $("input[name=action]").val("create");
1268 $("input[name=changecompany]").val("1");
1269 $("form[name=crea_reception]").submit();
1270 });
1271 });
1272 </script>';
1273 }
1274 print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
1275 print '</td>';
1276 }
1277 print '</tr>'."\n";
1278
1279 // Default warehouse for the lines
1280 if (isModEnabled('stock')) {
1281 $langs->load('stocks');
1282 print '<tr><td>'.$langs->trans('Warehouse').'</td>';
1283 print '<td>';
1284 print img_picto('', 'stock', 'class="pictofixedwidth"');
1285 print $formproduct->selectWarehouses(GETPOSTINT('fk_warehouse') > 0 ? GETPOSTINT('fk_warehouse') : 'ifone', 'fk_warehouse', '', 1, 0, 0, '', 1, 0, array(), 'minwidth200');
1286 print '</td></tr>'."\n";
1287 }
1288
1289 // Project
1290 if (isModEnabled('project') && is_object($formproject)) {
1291 $projectid = GETPOSTINT('projectid');
1292 if (empty($projectid) && !empty($object->fk_project)) {
1293 $projectid = (int) $object->fk_project;
1294 }
1295 $langs->load("projects");
1296 print '<tr>';
1297 print '<td>' . $langs->trans("Project") . '</td><td colspan="2">';
1298 print img_picto('', 'project', 'class="pictofixedwidth"');
1299 print $formproject->select_projects($soc->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 1, 0, 'widthcentpercentminusxx');
1300 print ' <a class="paddingleft" 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"></span></a>';
1301 print '</td>';
1302 print '</tr>';
1303 }
1304
1305 // Reception Date
1306 print '<tr><td>'.$langs->trans("DateReception").'</td>';
1307 print '<td colspan="3">';
1308 print img_picto('', 'action', 'class="pictofixedwidth"');
1309 $date_reception = ($date_reception ? $date_reception : $object->date_reception); // $date_reception comes from GETPOST
1310 print $form->selectDate($date_reception ? $date_reception : -1, 'date_reception', 1, 1, 1);
1311 print "</td>\n";
1312 print '</tr>';
1313
1314 // Date delivery planned
1315 print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
1316 print '<td colspan="3">';
1317 print img_picto('', 'action', 'class="pictofixedwidth"');
1318 $date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date); // $date_delivery comes from GETPOST
1319 print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
1320 print "</td>\n";
1321 print '</tr>';
1322
1323 // Weight
1324 print '<tr><td>';
1325 print $langs->trans("Weight");
1326 print '</td><td colspan="3">';
1327 print img_picto('', 'fa-balance-scale', 'class="pictofixedwidth"');
1328 print '<input name="weight" size="4" value="'.GETPOST('weight').'"> ';
1329 $text = $formproduct->selectMeasuringUnits("weight_units", "weight", (string) GETPOSTINT('weight_units'), 0, 2);
1330 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
1331 print $form->textwithpicto($text, $htmltext);
1332 print '</td></tr>';
1333
1334 // Dim
1335 print '<tr><td>';
1336 print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
1337 print ' </td><td colspan="3">';
1338 print img_picto('', 'fa-ruler', 'class="pictofixedwidth"');
1339 print '<input name="sizeW" size="4" value="'.GETPOST('sizeW').'">';
1340 print ' x <input name="sizeH" size="4" value="'.GETPOST('sizeH').'">';
1341 print ' x <input name="sizeS" size="4" value="'.GETPOST('sizeS').'">';
1342 print ' ';
1343 $text = $formproduct->selectMeasuringUnits("size_units", "size", (string) GETPOSTINT('size_units'), 0, 2);
1344 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
1345 print $form->textwithpicto($text, $htmltext);
1346 print '</td></tr>';
1347
1348 // Delivery method
1349 print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
1350 print '<td colspan="3">';
1351 $recept->fetch_delivery_methods();
1352 print $form->selectarray("shipping_method_id", $recept->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1);
1353 if ($user->admin) {
1354 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1355 }
1356 print "</td></tr>\n";
1357
1358 // Tracking number
1359 print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
1360 print '<td colspan="3">';
1361 print img_picto('', 'barcode', 'class="pictofixedwidth"');
1362 print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
1363 print "</td></tr>\n";
1364
1365 // Here $object can be of an object Reception
1366 $extrafields->fetch_name_optionals_label($object->table_element);
1367 if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
1368 if ($object->fetch_optionals() > 0) {
1369 $recept->array_options = array_merge($recept->array_options, $object->array_options);
1370 }
1371 print $recept->showOptionals($extrafields, 'create', $parameters);
1372 }
1373
1374 // Incoterms
1375 if (isModEnabled('incoterm')) {
1376 print '<tr>';
1377 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->label_incoterms, 1).'</label></td>';
1378 print '<td colspan="3" class="maxwidthonsmartphone">';
1379 print img_picto('', 'incoterm', 'class="pictofixedwidth"');
1380 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''));
1381 print '</td></tr>';
1382 }
1383
1384 // Template to use by default
1386 if (is_countable($list) && count($list) > 0) {
1387 print '<tr><td>'.$langs->trans('Model').'</td>';
1388 print '<td colspan="2">';
1389 print img_picto('', 'pdf', 'class="pictofixedwidth"');
1390 include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
1391 print $form->selectarray('model', $list, getDolGlobalString('RECEPTION_ADDON_PDF'), 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
1392 print "</td></tr>";
1393 }
1394
1395 // Note Public
1396 $htmltext = '';
1397 print '<tr>';
1398 print '<td class="tdtop">';
1399 print $form->textwithpicto($langs->trans('NotePublic'), $htmltext);
1400 print '</td>';
1401 print '<td valign="top" colspan="2">';
1402 $doleditor = new DolEditor('note_public', (string) $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
1403 print $doleditor->Create(1);
1404
1405 // Note Private
1406 if (!$user->socid) {
1407 print '<tr>';
1408 print '<td class="tdtop">';
1409 print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext);
1410 print '</td>';
1411 print '<td valign="top" colspan="2">';
1412 $doleditor = new DolEditor('note_private', (string) $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
1413 print $doleditor->Create(1);
1414 print "</td></tr>";
1415 }
1416
1417 print "</table>\n";
1418
1419 print dol_get_fiche_end();
1420
1421 print $form->buttonsSaveCancel("CreateDraft");
1422
1423 print "</form>\n";
1424 } elseif ($origin) {
1425 if ($origin == 'supplierorder') {
1426 $classname = 'CommandeFournisseur';
1427 } else {
1428 $classname = ucfirst($origin);
1429 }
1430
1431 $objectsrc = new $classname($db);
1432 if ($objectsrc->fetch($origin_id)) { // This include the fetch_lines
1433 $soc = new Societe($db);
1434 $soc->fetch($objectsrc->socid);
1435
1436 $author = new User($db);
1437 $author->fetch($objectsrc->user_author_id);
1438
1439 if (isModEnabled('stock')) {
1440 $entrepot = new Entrepot($db);
1441 }
1442
1443 print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
1444 print '<input type="hidden" name="token" value="'.newToken().'">';
1445 print '<input type="hidden" name="action" value="add">';
1446 print '<input type="hidden" name="origin" value="'.$origin.'">';
1447 print '<input type="hidden" name="origin_id" value="'.$objectsrc->id.'">';
1448 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
1449 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
1450 if (GETPOSTINT('entrepot_id')) {
1451 print '<input type="hidden" name="entrepot_id" value="'.GETPOSTINT('entrepot_id').'">';
1452 }
1453
1454 print dol_get_fiche_head();
1455
1456 print '<table class="border centpercent">';
1457
1458 // Ref
1459 print '<tr><td class="titlefieldcreate fieldrequired">';
1460 if ($origin == 'supplierorder' && isModEnabled("supplier_order")) {
1461 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;
1462 }
1463 if ($origin == 'propal' && isModEnabled("propal")) {
1464 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;
1465 }
1466 print '</a></td>';
1467 print "</tr>\n";
1468
1469 // Ref client
1470 print '<tr><td>';
1471 if ($origin == 'supplier_order') {
1472 print $langs->trans('SupplierOrder');
1473 } else {
1474 print $langs->trans('RefSupplier');
1475 }
1476 print '</td><td colspan="3">';
1477 print '<input type="text" name="ref_supplier" value="'.$objectsrc->ref_supplier.'" />';
1478 print '</td>';
1479 print '</tr>';
1480
1481 // Thirdparty provider
1482 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Company').'</td>';
1483 print '<td colspan="3">'.$soc->getNomUrl(1).'</td>';
1484 print '</tr>';
1485
1486 // Project
1487 if (isModEnabled('project') && $formproject !== null) {
1488 $projectid = GETPOSTINT('projectid') ? GETPOSTINT('projectid') : 0;
1489 if (empty($projectid) && !empty($objectsrc->fk_project)) {
1490 $projectid = $objectsrc->fk_project;
1491 }
1492 if ($origin == 'project') {
1493 $projectid = ($origin_id ? $origin_id : 0);
1494 }
1495
1496 $langs->load("projects");
1497 print '<tr>';
1498 print '<td>'.$langs->trans("Project").'</td><td colspan="2">';
1499 print img_picto('', 'project', 'class="paddingright"');
1500 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');
1501 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>';
1502 print '</td>';
1503 print '</tr>';
1504 }
1505
1506 // Reception Date
1507 print '<tr><td>'.$langs->trans("DateReception").'</td>';
1508 print '<td colspan="3">';
1509 print img_picto('', 'action', 'class="pictofixedwidth"');
1510 $date_reception = ($date_reception ? $date_reception : $object->date_reception); // $date_reception comes from GETPOST
1511 print $form->selectDate($date_reception ? $date_reception : -1, 'date_reception', 1, 1, 1);
1512 print "</td>\n";
1513 print '</tr>';
1514
1515 // Date delivery planned
1516 print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
1517 print '<td colspan="3">';
1518 print img_picto('', 'action', 'class="pictofixedwidth"');
1519 $date_delivery = ($date_delivery ? $date_delivery : $objectsrc->delivery_date); // $date_delivery comes from GETPOST
1520 print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
1521 print "</td>\n";
1522 print '</tr>';
1523
1524 // Note Public
1525 print '<tr><td>'.$langs->trans("NotePublic").'</td>';
1526 print '<td colspan="3">';
1527 $doleditor = new DolEditor('note_public', $objectsrc->note_public, '', 60, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
1528 print $doleditor->Create(1);
1529 print "</td></tr>";
1530
1531 // Note Private
1532 if ($objectsrc->note_private && !$user->socid) {
1533 print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
1534 print '<td colspan="3">';
1535 $doleditor = new DolEditor('note_private', $objectsrc->note_private, '', 60, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
1536 print $doleditor->Create(1);
1537 print "</td></tr>";
1538 }
1539
1540 // Weight
1541 print '<tr><td>';
1542 print $langs->trans("Weight");
1543 print '</td><td colspan="3"><input name="weight" size="4" value="'.GETPOST('weight').'"> ';
1544 $text = $formproduct->selectMeasuringUnits("weight_units", "weight", (string) GETPOSTINT('weight_units'), 0, 2);
1545 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
1546 print $form->textwithpicto($text, $htmltext);
1547 print '</td></tr>';
1548 // Dim
1549 print '<tr><td>';
1550 print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
1551 print ' </td><td colspan="3"><input name="trueWidth" size="4" value="'.GETPOST('trueWidth').'">';
1552 print ' x <input name="trueHeight" size="4" value="'.GETPOST('trueHeight').'">';
1553 print ' x <input name="trueDepth" size="4" value="'.GETPOST('trueDepth').'">';
1554 print ' ';
1555 $text = $formproduct->selectMeasuringUnits("size_units", "size", (string) GETPOSTINT('size_units'), 0, 2);
1556 $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
1557 print $form->textwithpicto($text, $htmltext);
1558 print '</td></tr>';
1559
1560 // Delivery method
1561 print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
1562 print '<td colspan="3">';
1563 $recept->fetch_delivery_methods();
1564 print $form->selectarray("shipping_method_id", $recept->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1);
1565 if ($user->admin) {
1566 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1567 }
1568 print "</td></tr>\n";
1569
1570 // Tracking number
1571 print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
1572 print '<td colspan="3">';
1573 print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
1574 print "</td></tr>\n";
1575
1576 // Other attributes
1577 $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3', 'socid' => $socid);
1578 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $recept, $action); // Note that $action and $objectsrc may have been modified by hook
1579 print $hookmanager->resPrint;
1580
1581 // Here $object can be of an object Reception
1582 $extrafields->fetch_name_optionals_label($object->table_element);
1583 if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
1584 // copy from order
1585 if ($objectsrc->fetch_optionals() > 0) {
1586 $recept->array_options = array_merge($recept->array_options, $objectsrc->array_options);
1587 }
1588 print $recept->showOptionals($extrafields, 'create', $parameters);
1589 }
1590
1591 // Incoterms
1592 if (isModEnabled('incoterm')) {
1593 print '<tr>';
1594 print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->label_incoterms, 1).'</label></td>';
1595 print '<td colspan="3" class="maxwidthonsmartphone">';
1596 print $form->select_incoterms((!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : ''), (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : ''));
1597 print '</td></tr>';
1598 }
1599
1600 // Document model
1601 include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
1603
1604 if (is_array($list) && count($list) > 1) {
1605 print "<tr><td>".$langs->trans("DefaultModel")."</td>";
1606 print '<td colspan="3">';
1607 print $form->selectarray('model', $list, getDolGlobalString('RECEPTION_ADDON_PDF'));
1608 print "</td></tr>\n";
1609 }
1610
1611 print "</table>";
1612
1613 print dol_get_fiche_end();
1614
1615 // Number of lines show on the reception card
1616 $numAsked = 0;
1617
1622 $suffix2numAsked = array();
1623 $dispatchLines = array();
1624
1625 foreach ($_POST as $key => $value) {
1626 // If create form is coming from the button "Create Reception" of previous page
1627
1628 // without batch module enabled or product with no lot/serial
1629 $reg = array();
1630 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
1631 $numAsked++;
1632 $paramSuffix = $reg[1] . '_' . $reg[2];
1633 $suffix2numAsked[$paramSuffix] = $numAsked;
1634
1635 // $numline=$reg[2] + 1; // line of product
1636 $numline = $numAsked;
1637
1638 $prod = "product_" . $paramSuffix;
1639 $qty = "qty_" . $paramSuffix;
1640 $ent = "entrepot_" . $paramSuffix;
1641 $pu = "pu_" . $paramSuffix; // This is unit price including discount
1642 $fk_commandefourndet = "fk_commandefourndet_" . $paramSuffix;
1643 $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));
1644 }
1645
1646 // with batch module enabled and product with lot/serial
1647 if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
1648 $numAsked++;
1649 $paramSuffix = $reg[1] . '_' . $reg[2];
1650 $suffix2numAsked[$paramSuffix] = $numAsked;
1651
1652 // eat-by date dispatch
1653 // $numline=$reg[2] + 1; // line of product
1654 $numline = $numAsked;
1655
1656 $prod = 'product_batch_' . $paramSuffix;
1657 $qty = 'qty_' . $paramSuffix;
1658 $ent = 'entrepot_' . $paramSuffix;
1659 $pu = 'pu_' . $paramSuffix;
1660 $lot = 'lot_number_' . $paramSuffix;
1661 $dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo_'.$paramSuffix.'month'), GETPOSTINT('dluo_'.$paramSuffix.'day'), GETPOSTINT('dluo_'.$paramSuffix.'year'));
1662 $dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc_'.$paramSuffix.'month'), GETPOSTINT('dlc_'.$paramSuffix.'day'), GETPOSTINT('dlc_'.$paramSuffix.'year'));
1663 $fk_commandefourndet = 'fk_commandefourndet_'.$paramSuffix;
1664 $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));
1665 }
1666
1667 // If create form is coming from same page, it means that post was sent but an error occurred
1668 if (preg_match('/^productl([0-9]+)$/i', $key, $reg)) {
1669 $numAsked++;
1670 $paramSuffix = $reg[1];
1671 $suffix2numAsked[$paramSuffix] = $numAsked;
1672
1673 // eat-by date dispatch
1674 // $numline=$reg[2] + 1; // line of product
1675 $numline = $numAsked;
1676
1677 $prod = 'productid'.$paramSuffix;
1678 $comment = 'comment'.$paramSuffix;
1679 $qty = 'qtyl'.$paramSuffix;
1680 $ent = 'entl'.$paramSuffix;
1681 $pu = 'pul'.$paramSuffix;
1682 $lot = 'batch'.$paramSuffix;
1683 $dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo'.$paramSuffix.'month'), GETPOSTINT('dluo'.$paramSuffix.'day'), GETPOSTINT('dluo'.$paramSuffix.'year'));
1684 $dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc'.$paramSuffix.'month'), GETPOSTINT('dlc'.$paramSuffix.'day'), GETPOSTINT('dlc'.$paramSuffix.'year'));
1685 $fk_commandefourndet = 'fk_commandefournisseurdet'.$paramSuffix;
1686 $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));
1687 }
1688 }
1689
1690 // If extrafield values are passed in the HTTP query, assign them to the correct dispatch line
1691 // Note that if an extrafield with the same name exists in the origin supplier order line, the value
1692 // from the HTTP query will be ignored
1693 foreach ($suffix2numAsked as $suffix => $n) {
1694 $dispatchLines[$n]['array_options'] = $extrafields->getOptionalsFromPost('receptiondet_batch', '_' . $suffix, '');
1695 }
1696
1697 $reshook = $hookmanager->executeHooks('dataProcessing', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1698 if ($reshook < 0) {
1699 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1700 } elseif (empty($reshook)) {
1701 // Only merge if resArray is a valid, non-empty array
1702 if (is_array($hookmanager->resArray) && !empty($hookmanager->resArray)) {
1703 // Check if the merge would overwrite valid data with NULL
1704 $tempMerged = array_merge($dispatchLines, $hookmanager->resArray);
1705
1706 // Sanity check: ensure our existing keys are still valid arrays
1707 $corrupted = false;
1708 foreach ($dispatchLines as $idx => $val) {
1709 if (!is_array($tempMerged[$idx]) || !isset($tempMerged[$idx]['fk_commandefourndet'])) {
1710 $corrupted = true;
1711 break;
1712 }
1713 }
1714
1715 if (!$corrupted) {
1716 $dispatchLines = $tempMerged;
1717 } else {
1718 // If merge corrupted data, ignore the hook result and keep original
1719 error_log("WARNING: Hook dataProcessing returned invalid data, ignoring merge.");
1720 }
1721 }
1722 } elseif ($reshook > 0) {
1723 // $resArray starts from [0], we need $dispatchLines to start from [1], so we shift it
1724 $dispatchLines = $hookmanager->resArray;
1725 array_unshift($dispatchLines, null);
1726 unset($dispatchLines[0]);
1727 $numAsked = count($dispatchLines);
1728 }
1729
1730 print '<script type="text/javascript">
1731 jQuery(document).ready(function() {
1732 jQuery("#autofill").click(function(event) {
1733 event.preventDefault();';
1734 $i = 1;
1735 while ($i <= $numAsked) {
1736 print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1737 $i++;
1738 }
1739 print '});
1740 jQuery("#autoreset").click(function(event) {
1741 event.preventDefault();';
1742 $i = 1;
1743 while ($i <= $numAsked) {
1744 print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1745 $i++;
1746 }
1747 print '});
1748 });
1749 </script>';
1750
1751 print '<br>';
1752
1753 print '<table class="noborder centpercent">';
1754
1755 // Load receptions already done for same order
1756 $objectsrc->loadReceptions();
1757
1758 if ($numAsked) {
1759 print '<tr class="liste_titre">';
1760 print '<td>'.$langs->trans("Description").'</td>';
1761 print '<td>'.$langs->trans("Comment").'</td>';
1762 print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1763 print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1764 print '<td class="center">'.$langs->trans("QtyToReceive");
1765 if (getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1766 print '<td>'.$langs->trans("BuyingPrice").'</td>';
1767 }
1768 if (!isModEnabled('productbatch')) {
1769 print ' <br><center><a href="#" id="autofill"><span class="fas fa-fill pictofixedwidth" style=""></span> '.$langs->trans("Fill").'</a>';
1770 print ' &nbsp; &nbsp; <a href="#" id="autoreset"><span class="fas fa-eraser pictofixedwidth" style=""></span>'.$langs->trans("Reset").'</a></center><br>';
1771 }
1772 print '</td>';
1773 if (isModEnabled('stock')) {
1774 print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1775 }
1776 if (isModEnabled('productbatch')) {
1777 print '<td class="left">'.$langs->trans("batch_number").'</td>';
1778 if (!getDolGlobalInt('PRODUCT_DISABLE_SELLBY')) {
1779 print '<td class="left">'.$langs->trans("SellByDate").'</td>';
1780 }
1781 if (!getDolGlobalInt('PRODUCT_DISABLE_EATBY')) {
1782 print '<td class="left">'.$langs->trans("EatByDate").'</td>';
1783 }
1784 }
1785
1786 $parameters = array();
1787 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1788 if ($reshook < 0) {
1789 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1790 } else {
1791 print $hookmanager->resPrint;
1792 }
1793 print "</tr>\n";
1794 }
1795
1796 // $objectsrc->lines contains the line of the purchase order
1797 // $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.
1798
1799 $arrayofpurchaselinealreadyoutput = array();
1800
1801 // $_POST contains fk_commandefourndet_X_Y where Y is num of product line and X is number of split lines
1802 $indiceAsked = 1;
1803 while ($indiceAsked <= $numAsked) { // Loop on $dispatchLines. Warning: $dispatchLines must be sorted by fk_commandefourndet (it is a regroupment key on output)
1804 $product = new Product($db);
1805 $line = new CommandeFournisseurLigne($db); // By default
1806
1807 // We search the purchase order line that is linked to the dispatchLines
1808 foreach ($objectsrc->lines as $supplierLine) {
1809 if ($dispatchLines[$indiceAsked]['fk_commandefourndet'] == $supplierLine->id) {
1810 $line = $supplierLine;
1811 break;
1812 }
1813 }
1814
1815 // Now $line can be CommandeFournisseurLigne but could be other type of line.
1816
1817 // Show product and description
1818 $type = $line->product_type ? $line->product_type : $line->fk_product_type;
1819 // Try to enhance type detection using date_start and date_end for free lines where type was not saved.
1820 if (!empty($line->date_start)) {
1821 $type = 1;
1822 }
1823 if (!empty($line->date_end)) {
1824 $type = 1;
1825 }
1826
1827 print '<!-- line fk_commandefourndet='.$line->id.' for product='.$line->fk_product.' -->'."\n";
1828 print '<tr class="oddeven">'."\n";
1829
1830 // Product label
1831 if ($line->fk_product > 0) { // If predefined product
1832 $product->fetch($line->fk_product);
1833 $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
1834 //var_dump($product->stock_warehouse[1]);
1835 //var_dump($dispatchLines[$indiceAsked]);
1836
1837 print '<td>';
1838 print '<a name="'.$line->id.'"></a>'; // Anchor to return to the line
1839
1840 print '<input type="hidden" name="productl'.$indiceAsked.'" value="'.$line->fk_product.'">';
1841
1842 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1843 print '<input type="hidden" name="productid'.$indiceAsked.'" value="'.$line->fk_product.'">';
1844
1845 // Show product and description
1846 $product_static = $product;
1847
1848 $text = $product_static->getNomUrl(1);
1849 $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
1850 $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($line->desc));
1851 print $form->textwithtooltip($text, $description, 3, 0, '', (string) $i);
1852
1853 // Show range
1854 print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1855
1856 // Add description in form
1857 if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1858 print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
1859 }
1860 }
1861 print '</td>';
1862 } else {
1863 print "<td>";
1864 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1865 if ($type == 1) {
1866 $text = img_object($langs->trans('Service'), 'service');
1867 } else {
1868 $text = img_object($langs->trans('Product'), 'product');
1869 }
1870
1871 if (!empty($line->label)) {
1872 $text .= ' <strong>'.$line->label.'</strong>';
1873 print $form->textwithtooltip($text, $line->desc, 3, 0, '', (string) $i);
1874 } else {
1875 print $text.' '.nl2br($line->desc);
1876 }
1877
1878 // Show range
1879 print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1880 }
1881 print "</td>\n";
1882 }
1883
1884 // Comment
1885 //$defaultcomment = 'Line create from order line id '.$line->id;
1886 $defaultcomment = $dispatchLines[$indiceAsked]['comment'];
1887 print '<td>';
1888 print '<input type="text" class="maxwidth100" name="comment'.$indiceAsked.'" value="'.$defaultcomment.'">';
1889 print '</td>';
1890
1891 // Qty in source purchase order line
1892 print '<td class="center">';
1893 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1894 print $line->qty;
1895 }
1896 print '<input type="hidden" name="fk_commandefournisseurdet'.$indiceAsked.'" value="'.$line->id.'">';
1897 print '<input type="hidden" name="pul'.$indiceAsked.'" value="'.$line->subprice.'">';
1898 print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
1899 print '</td>';
1900 $qtyProdCom = $line->qty;
1901
1902 // Qty already received
1903 print '<td class="center">';
1904 $quantityDelivered = isset($objectsrc->receptions[$line->id]) ? $objectsrc->receptions[$line->id] : 0;
1905 if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1906 print $quantityDelivered;
1907 }
1908 print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
1909 print '</td>';
1910
1911
1912 if ($line->product_type == 1 && !getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1913 $quantityToBeDelivered = 0;
1914 } else {
1915 $quantityToBeDelivered = $dispatchLines[$indiceAsked]['qty'];
1916 }
1917 $warehouse_id = $dispatchLines[$indiceAsked]['ent'];
1918
1919
1920 $warehouseObject = null;
1921 if (isModEnabled('stock')) {
1922 // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1923 print '<!-- Case warehouse already known or product not a predefined product -->';
1924 if (array_key_exists($dispatchLines[$indiceAsked]['ent'], $product->stock_warehouse)) {
1925 $stock = +$product->stock_warehouse[$dispatchLines[$indiceAsked]['ent']]->real; // Convert to number
1926 }
1927 $deliverableQty = $dispatchLines[$indiceAsked]['qty'];
1928 $cost_price = $dispatchLines[$indiceAsked]['pu'];
1929
1930 // Quantity to send
1931 print '<td class="center">';
1932 if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
1933 if (GETPOSTINT('qtyl'.$indiceAsked)) {
1934 $defaultqty = GETPOSTINT('qtyl'.$indiceAsked);
1935 }
1936 print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1937 print '<input class="right" name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1938 } else {
1939 print $langs->trans("NA");
1940 }
1941 print '</td>';
1942
1943 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1944 print '<td>';
1945 print '<input class="width75 right" name="cost_price'.$indiceAsked.'" id="cost_price'.$indiceAsked.'" value="'.price($cost_price).'">';
1946 print '</td>';
1947 }
1948
1949 // Stock
1950 if (isModEnabled('stock')) {
1951 print '<td class="left">';
1952 if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) { // Type of product need stock change ?
1953 // Show warehouse combo list
1954 $ent = "entl".$indiceAsked;
1955 $idl = "idl".$indiceAsked;
1956 $tmpentrepot_id = is_numeric(GETPOST($ent)) ? GETPOSTINT($ent) : $warehouse_id;
1957 if ($line->fk_product > 0) {
1958 print '<!-- Show warehouse selection -->';
1959 print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 0, 0, $line->fk_product, '', 1);
1960 }
1961 } else {
1962 print $langs->trans("Service");
1963 }
1964 print '</td>';
1965 }
1966
1967 if (isModEnabled('productbatch')) {
1968 if (!empty($product->status_batch)) {
1969 print '<td><input name="batch'.$indiceAsked.'" value="'.$dispatchLines[$indiceAsked]['lot'].'"></td>';
1970 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
1971 print '<td class="nowraponall">';
1972 print $form->selectDate($dispatchLines[$indiceAsked]['DLC'], 'dlc'.$indiceAsked, 0, 0, 1, "");
1973 print '</td>';
1974 }
1975 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
1976 print '<td class="nowraponall">';
1977 print $form->selectDate($dispatchLines[$indiceAsked]['DLUO'], 'dluo'.$indiceAsked, 0, 0, 1, "");
1978 print '</td>';
1979 }
1980 } else {
1981 print '<td colspan="3"></td>';
1982 }
1983 }
1984
1985 $parameters = array();
1986 $parameters['dispatchLine'] = $dispatchLines[$indiceAsked];
1987 $parameters['indiceAsked'] = $indiceAsked;
1988 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
1989 if ($reshook < 0) {
1990 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1991 } else {
1992 print $hookmanager->resPrint;
1993 }
1994 }
1995
1996 $arrayofpurchaselinealreadyoutput[$line->id] = $line->id;
1997
1998 print "</tr>\n";
1999
2000 // Display lines for extrafields of the Reception line
2001 // $line is a 'CommandeFournisseurLigne', $dispatchLines contains values of Reception lines so properties of CommandeFournisseurDispatch
2002 if (!empty($extrafields)) {
2003 $colspan = 5;
2004 if (isModEnabled('productbatch')) {
2005 $colspan += 2;
2006 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
2007 $colspan += 1;
2008 }
2009 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
2010 $colspan += 1;
2011 }
2012 }
2013 $recLine = new CommandeFournisseurDispatch($db);
2014
2015 $srcLine = new CommandeFournisseurLigne($db);
2016 $srcLine->id = $line->id;
2017 $srcLine->fetch_optionals(); // fetch extrafields also available in orderline
2018
2019 if (empty($recLine->array_options) && !empty($dispatchLines[$indiceAsked]['array_options'])) {
2020 $recLine->array_options = $dispatchLines[$indiceAsked]['array_options'];
2021 }
2022 $recLine->array_options = array_merge($recLine->array_options, $srcLine->array_options);
2023
2024 print $recLine->showOptionals($extrafields, 'edit', array('style' => 'class="oddeven"', 'colspan' => $colspan), (string) $indiceAsked, '', '1');
2025 }
2026
2027 $indiceAsked++;
2028 }
2029
2030 print "</table>";
2031
2032 print '<br>';
2033
2034 print $form->buttonsSaveCancel("Create");
2035
2036 print '</form>';
2037
2038 print '<br>';
2039 } else {
2040 dol_print_error($db);
2041 }
2042 }
2043} elseif ($object->id > 0) {
2044 /* *************************************************************************** */
2045 /* */
2046 /* Edit and view mode */
2047 /* */
2048 /* *************************************************************************** */
2049 $lines = $object->lines;
2050
2051 $num_prod = count($lines);
2052 $indiceAsked = 0;
2053
2054 if ($object->id <= 0) {
2055 print $langs->trans("NoRecordFound");
2056 llxFooter();
2057 exit;
2058 }
2059
2060 $typeobject = '';
2061 if (!empty($object->origin) && $object->origin_id > 0) {
2062 $typeobject = $object->origin;
2063 $origin = $object->origin;
2064 $origin_id = $object->origin_id;
2065 $object->fetch_origin(); // Load property $object->origin_object, $object->commande, $object->propal, ...
2066 }
2067
2068 $soc = new Societe($db);
2069 $soc->fetch($object->socid);
2070
2071 $res = $object->fetch_optionals();
2072
2073 $head = reception_prepare_head($object);
2074 print dol_get_fiche_head($head, 'reception', $langs->trans("Reception"), -1, 'dollyrevert', 0, '', '', 0, '', 1);
2075
2076 $formconfirm = '';
2077
2078 // Confirm deletion
2079 if ($action == 'delete') {
2080 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeleteReception'), $langs->trans("ConfirmDeleteReception", $object->ref), 'confirm_delete', '', 0, 1);
2081 }
2082
2083 // Confirmation validation
2084 if ($action == 'valid') {
2085 $objectref = substr($object->ref, 1, 4);
2086 if ($objectref == 'PROV') {
2087 $numref = $object->getNextNumRef($soc);
2088 } else {
2089 $numref = (string) $object->ref;
2090 }
2091
2092 $text = $langs->trans("ConfirmValidateReception", $numref);
2093 if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')) {
2094 $text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementWillBeRecorded").'.';
2095 } elseif (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
2096 $text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementNotYetRecorded").'.';
2097 }
2098
2099 if (isModEnabled('notification')) {
2100 require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
2101 $notify = new Notify($db);
2102 $text .= '<br>';
2103 $text .= $notify->confirmMessage('RECEPTION_VALIDATE', $object->socid, $object);
2104 }
2105
2106 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateReception'), $text, 'confirm_valid', '', 0, 1, 250);
2107 }
2108
2109 // Confirm cancellation
2110 if ($action == 'annuler') {
2111 $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelReception'), $langs->trans("ConfirmCancelReception", $object->ref), 'confirm_cancel', '', 0, 1);
2112 }
2113
2114 if (!$formconfirm) {
2115 $parameters = array('formConfirm' => $formconfirm);
2116 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2117 if (empty($reshook)) {
2118 $formconfirm .= $hookmanager->resPrint;
2119 } elseif ($reshook > 0) {
2120 $formconfirm = $hookmanager->resPrint;
2121 }
2122 }
2123
2124 // Print form confirm
2125 print $formconfirm;
2126
2127
2128 // Calculate totalWeight and totalVolume for all products
2129 // by adding weight and volume of each product line.
2130 $tmparray = $object->getTotalWeightVolume();
2131 $totalWeight = $tmparray['weight'];
2132 $totalVolume = $tmparray['volume'];
2133
2134
2135 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
2136 $objectsrc = new Commande($db);
2137 $objectsrc->fetch($object->origin_object->id);
2138 }
2139 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
2140 $objectsrc = new Propal($db);
2141 $objectsrc->fetch($object->origin_object->id);
2142 }
2143 if (($typeobject == 'supplier_order' || $typeobject == 'CommandeFournisseur') && $object->origin_object->id && isModEnabled("supplier_order")) {
2144 $objectsrc = new CommandeFournisseur($db);
2145 $objectsrc->fetch($object->origin_object->id);
2146 }
2147 // Reception card
2148 $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
2149 $morehtmlref = '<div class="refidno">';
2150 // Ref customer reception
2151
2152 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', 0, 1);
2153 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', null, null, '', 1);
2154
2155 // Thirdparty
2156 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
2157 // Project
2158 if ($origin && $origin_id > 0) {
2159 if (isModEnabled('project')) {
2160 $langs->load("projects");
2161 $morehtmlref .= '<br>';
2162 if (0) { // @phpstan-ignore-line Do not change on shipment
2163 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2164 if ($action != 'classify') {
2165 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
2166 }
2167 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $objectsrc->socid, (string) $objectsrc->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2168 } else {
2169 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
2170 $proj = new Project($db);
2171 $proj->fetch($objectsrc->fk_project);
2172 $morehtmlref .= $proj->getNomUrl(1);
2173 if ($proj->title) {
2174 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
2175 }
2176 }
2177 }
2178 }
2179 } elseif (!$origin && getDolGlobalString('RECEPTION_STANDALONE')) {
2180 // Project
2181 if (isModEnabled('project')) {
2182 $langs->load("projects");
2183 $morehtmlref .= '<br>';
2184 if ($permissiontoadd) {
2185 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
2186 if ($action != 'classify') {
2187 $morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> ';
2188 }
2189 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
2190 } else {
2191 if (!empty($object->fk_project)) {
2192 $proj = new Project($db);
2193 $proj->fetch($object->fk_project);
2194 $morehtmlref .= $proj->getNomUrl(1);
2195 if ($proj->title) {
2196 $morehtmlref .= '<span class="opacitymedium"> - ' . dol_escape_htmltag($proj->title) . '</span>';
2197 }
2198 }
2199 }
2200 }
2201 }
2202 $morehtmlref .= '</div>';
2203
2204 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
2205
2206
2207 print '<div class="fichecenter">';
2208 print '<div class="fichehalfleft">';
2209 print '<div class="underbanner clearboth"></div>';
2210
2211 print '<table class="border centpercent tableforfield">';
2212
2213 // Linked documents
2214 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
2215 print '<tr><td>';
2216 print $langs->trans("RefOrder").'</td>';
2217 print '<td colspan="3">';
2218 print $objectsrc->getNomUrl(1, 'commande');
2219 print "</td>\n";
2220 print '</tr>';
2221 }
2222 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
2223 print '<tr><td>';
2224 print $langs->trans("RefProposal").'</td>';
2225 print '<td colspan="3">';
2226 print $objectsrc->getNomUrl(1, 'reception');
2227 print "</td>\n";
2228 print '</tr>';
2229 }
2230 if (($typeobject == 'supplier_order' || $typeobject == 'CommandeFournisseur') && $object->origin_object->id && isModEnabled("propal")) {
2231 print '<tr><td>';
2232 print $langs->trans("SupplierOrder").'</td>';
2233 print '<td colspan="3">';
2234 print $objectsrc->getNomUrl(1, 'reception');
2235 print "</td>\n";
2236 print '</tr>';
2237 }
2238
2239 // Date creation
2240 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
2241 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
2242 print '</tr>';
2243
2244 // Reception Date
2245 print '<tr><td height="10">';
2246 print '<table class="nobordernopadding centpercent"><tr><td>';
2247 print $langs->trans('DateReception');
2248 print '</td>';
2249 if ($action != 'editdate_reception') {
2250 print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editdate_reception&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->trans('SetReceptionDate'), 1) . '</a></td>';
2251 }
2252 print '</tr></table>';
2253 print '</td><td>';
2254 if ($action == 'editdate_reception') {
2255 print '<form name="setdate_reception" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
2256 print '<input type="hidden" name="token" value="' . newToken() . '">';
2257 print '<input type="hidden" name="action" value="setdate_reception">';
2258 print $form->selectDate($object->date_reception ? $object->date_reception : -1, 'recep_', 1, 1, 0, "setdate_reception", 1, 0);
2259 print '<input type="submit" class="button button-edit smallpaddingimp" value="' . $langs->trans('Modify') . '">';
2260 print '</form>';
2261 } else {
2262 print $object->date_reception ? dol_print_date($object->date_reception, 'dayhour') : '&nbsp;';
2263 }
2264 print '</td>';
2265 print '</tr>';
2266
2267 // Delivery date planned
2268 print '<tr><td height="10">';
2269 print '<table class="nobordernopadding" width="100%"><tr><td>';
2270 print $langs->trans('DateDeliveryPlanned');
2271 print '</td>';
2272
2273 if ($action != 'editdate_livraison' && $permissiontoadd) {
2274 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>';
2275 }
2276 print '</tr></table>';
2277 print '</td><td colspan="2">';
2278 if ($action == 'editdate_livraison') {
2279 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2280 print '<input type="hidden" name="token" value="'.newToken().'">';
2281 print '<input type="hidden" name="action" value="setdate_livraison">';
2282 print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
2283 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2284 print '</form>';
2285 } else {
2286 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
2287 }
2288 print '</td>';
2289 print '</tr>';
2290
2291 // Weight
2292 print '<tr><td>';
2293 print $form->editfieldkey("Weight", 'trueWeight', (string) $object->trueWeight, $object, $user->hasRight('reception', 'creer'));
2294 print '</td><td colspan="3">';
2295
2296 if ($action == 'edittrueWeight') {
2297 print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
2298 print '<input name="action" value="settrueWeight" type="hidden">';
2299 print '<input name="id" value="'.$object->id.'" type="hidden">';
2300 print '<input type="hidden" name="token" value="'.newToken().'">';
2301 print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
2302 print $formproduct->selectMeasuringUnits("weight_units", "weight", (string) $object->weight_units, 0, 2);
2303 print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
2304 print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
2305 print '</form>';
2306 } else {
2307 print $object->trueWeight;
2308 print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : '';
2309 }
2310
2311 // Calculated
2312 if ($totalWeight > 0) {
2313 if (!empty($object->trueWeight)) {
2314 print ' ('.$langs->trans("SumOfProductWeights").': ';
2315 }
2316 print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, getDolGlobalInt('MAIN_WEIGHT_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_WEIGHT_DEFAULT_UNIT', 'no'));
2317 if (!empty($object->trueWeight)) {
2318 print ')';
2319 }
2320 }
2321 print '</td></tr>';
2322
2323 // Width
2324 print '<tr><td>'.$form->editfieldkey("Width", 'trueWidth', (string) $object->trueWidth, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
2325 print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->hasRight('reception', 'creer'));
2326 print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : '';
2327 print '</td></tr>';
2328
2329 // Height
2330 print '<tr><td>'.$form->editfieldkey("Height", 'trueHeight', (string) $object->trueHeight, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
2331 if ($action == 'edittrueHeight') {
2332 print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
2333 print '<input name="action" value="settrueHeight" type="hidden">';
2334 print '<input name="id" value="'.$object->id.'" type="hidden">';
2335 print '<input type="hidden" name="token" value="'.newToken().'">';
2336 print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
2337 print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
2338 print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
2339 print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
2340 print '</form>';
2341 } else {
2342 print $object->trueHeight;
2343 print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : '';
2344 }
2345
2346 print '</td></tr>';
2347
2348 // Depth
2349 print '<tr><td>'.$form->editfieldkey("Depth", 'trueDepth', (string) $object->trueDepth, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
2350 print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->hasRight('reception', 'creer'));
2351 print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : '';
2352 print '</td></tr>';
2353
2354 // Default warehouse for the lines
2355 if (isModEnabled('stock')) {
2356 $langs->load('stocks');
2357 print '<tr><td><table class="nobordernopadding centpercent"><tr><td>';
2358 print $langs->trans('Warehouse');
2359 print '</td>';
2360 if ($action != 'editwarehouse' && $object->statut == Reception::STATUS_DRAFT && $user->hasRight('reception', 'creer')) {
2361 print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editwarehouse&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetWarehouse'), 1).'</a></td>';
2362 }
2363 print '</tr></table></td><td colspan="3">';
2364 if ($action == 'editwarehouse' && $permissiontoadd) {
2365 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_warehouse, 'warehouse_id', 1);
2366 } else {
2367 $formproduct->formSelectWarehouses($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_warehouse, 'none');
2368 }
2369 print '</td></tr>';
2370 }
2371
2372 // Volume
2373 print '<tr><td>';
2374 print $langs->trans("Volume");
2375 print '</td>';
2376 print '<td colspan="3">';
2377 $calculatedVolume = 0;
2378 $volumeUnit = 0;
2379 if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
2380 $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
2381 $volumeUnit = $object->size_units * 3;
2382 }
2383 // If reception volume not defined we use sum of products
2384 if ($calculatedVolume > 0) {
2385 if ($volumeUnit < 50) {
2386 print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString("MAIN_VOLUME_DEFAULT_UNIT", 'no'));
2387 } else {
2388 print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit);
2389 }
2390 }
2391 if ($totalVolume > 0) {
2392 if ($calculatedVolume) {
2393 print ' ('.$langs->trans("SumOfProductVolumes").': ';
2394 }
2395 print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_VOLUME_DEFAULT_UNIT', 'no'));
2396 //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
2397 if ($calculatedVolume) {
2398 print ')';
2399 }
2400 }
2401 print "</td>\n";
2402 print '</tr>';
2403
2404 // Other attributes
2405 $cols = 2;
2406
2407 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
2408
2409 print '</table>';
2410
2411 print '</div>';
2412 print '<div class="fichehalfright">';
2413 print '<div class="underbanner clearboth"></div>';
2414
2415 print '<table class="border centpercent tableforfield">';
2416
2417 // Reception method
2418 print '<tr><td height="10">';
2419 print '<table class="nobordernopadding centpercent"><tr><td>';
2420 print $langs->trans('ReceptionMethod');
2421 print '</td>';
2422
2423 if ($action != 'editshipping_method_id' && $permissiontoadd) {
2424 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>';
2425 }
2426 print '</tr></table>';
2427 print '</td><td colspan="2">';
2428 if ($action == 'editshipping_method_id') {
2429 print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
2430 print '<input type="hidden" name="token" value="'.newToken().'">';
2431 print '<input type="hidden" name="action" value="setshipping_method_id">';
2432 $object->fetch_delivery_methods();
2433 print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1);
2434 if ($user->admin) {
2435 print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
2436 }
2437 print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
2438 print '</form>';
2439 } else {
2440 if ($object->shipping_method_id > 0) {
2441 // Get code using getLabelFromKey
2442 $code = $langs->getLabelFromKey($db, (string) $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
2443 print $langs->trans("SendingMethod".strtoupper($code));
2444 }
2445 }
2446 print '</td>';
2447 print '</tr>';
2448
2449 // Tracking Number
2450 print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
2451 print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->hasRight('reception', 'creer'), 'safehtmlstring', $object->tracking_number);
2452 print '</td></tr>';
2453
2454 // Incoterms
2455 if (isModEnabled('incoterm')) {
2456 print '<tr><td>';
2457 print '<table width="100%" class="nobordernopadding"><tr><td>';
2458 print $langs->trans('IncotermLabel');
2459 print '<td><td class="right">';
2460 if ($user->hasRight('reception', 'creer')) {
2461 print '<a class="editfielda" href="'.DOL_URL_ROOT.'/reception/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
2462 } else {
2463 print '&nbsp;';
2464 }
2465 print '</td></tr></table>';
2466 print '</td>';
2467 print '<td colspan="3">';
2468 if ($action != 'editincoterm') {
2469 print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
2470 } else {
2471 print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2472 }
2473 print '</td></tr>';
2474 }
2475
2476 print "</table>";
2477
2478 print '</div>';
2479 print '</div>';
2480
2481 print '<div class="clearboth"></div>';
2482
2483 /*
2484 * Lines of simple reception
2485 */
2486 if (!$origin_id && getDolGlobalString('RECEPTION_STANDALONE')) {
2487 if (!empty($object->table_element_line)) {
2488 // Show object lines
2489 $result = $object->getLinesArray();
2490
2491 print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '' : '#line_'.GETPOSTINT('lineid')).'" method="POST">
2492 <input type="hidden" name="token" value="' . newToken().'">
2493 <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
2494 <input type="hidden" name="mode" value="">
2495 <input type="hidden" name="page_y" value="">
2496 <input type="hidden" name="id" value="' . $object->id.'">
2497 ';
2498
2499 if (!empty($conf->use_javascript_ajax) && $object->status == $object::STATUS_DRAFT) {
2500 include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
2501 }
2502
2503 print '<div class="div-table-responsive-no-min">';
2504 if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
2505 print '<table id="tablelines" class="noborder noshadow" width="100%">';
2506 }
2507
2508 if (!empty($object->lines)) {
2509 $object->printObjectLines($action, $mysoc, null, GETPOSTINT('lineid'), 0, '/reception/tpl');
2510 }
2511
2512 // Form to add new line
2513 if ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines') {
2514 if ($action != 'editline') {
2515 // Add products/services form
2516
2517 $parameters = array();
2518 $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2519 if ($reshook < 0) {
2520 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2521 }
2522 if (empty($reshook)) {
2523 $senderissupplier = 2; // Use the same add-line block as supplier orders; 2 = also list products without supplier price for this supplier
2524 $object->formAddObjectLine(0, $mysoc, $soc);
2525 }
2526 }
2527 }
2528
2529 if (!empty($object->lines) || ($object->status == Reception::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
2530 print '</table>';
2531 }
2532 print '</div>';
2533
2534 print "</form>\n";
2535 }
2536 } elseif (!empty($object->origin) && $object->origin_id > 0) {
2537 // Lines of products of origin
2538 if ($action == 'editline') {
2539 print '<form name="updateline" id="updateline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;lineid='.$line_id.'" method="POST">
2540 <input type="hidden" name="token" value="' . newToken().'">
2541 <input type="hidden" name="action" value="updateline">
2542 <input type="hidden" name="mode" value="">
2543 <input type="hidden" name="id" value="' . $object->id.'">';
2544 }
2545 print '<br><br>';
2546
2547 print '<div class="div-table-responsive-no-min">';
2548 print '<table id="tablelines" class="noborder centpercent">';
2549 print '<thead>';
2550 print '<tr class="liste_titre">';
2551 // #
2552 if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
2553 print '<td width="5" class="center">&nbsp;</td>';
2554 }
2555 // Product/Service
2556 print '<td>'.$langs->trans("Products").'</td>';
2557 // Comment
2558 print '<td>'.$langs->trans("Comment").'</td>';
2559 // Qty
2560 print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
2561 if ($origin && $origin_id > 0) {
2562 print '<td class="center">'.$langs->trans("QtyInOtherReceptions").'</td>';
2563 }
2564
2565 $editColspan = 3;
2566 if ($action == 'editline') {
2567 if (!isModEnabled('stock')) {
2568 $editColspan--;
2569 }
2570 if (empty($conf->productbatch->enabled)) {
2571 $editColspan--;
2572 }
2573 print '<td class="center" colspan="'.$editColspan.'">';
2574 if ($object->statut <= 1) {
2575 print $langs->trans("QtyToReceive").' - ';
2576 } else {
2577 print $langs->trans("QtyReceived").' - ';
2578 }
2579 if (isModEnabled('stock')) {
2580 print $langs->trans("WarehouseTarget").' - ';
2581 }
2582 if (isModEnabled('productbatch')) {
2583 print $langs->trans("Batch");
2584 }
2585 print '</td>';
2586
2587 $parameters = array();
2588 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2589 if ($reshook < 0) {
2590 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2591 } else {
2592 print $hookmanager->resPrint;
2593 }
2594 } else {
2595 $statusreceived = $object::STATUS_CLOSED;
2596 if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) {
2597 $statusreceived = $object::STATUS_VALIDATED;
2598 }
2599 if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) {
2600 $statusreceived = $object::STATUS_CLOSED;
2601 }
2602 if ($object->statut < $statusreceived) {
2603 print '<td class="center">'.$langs->trans("QtyToReceive").'</td>';
2604 } else {
2605 print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
2606 }
2607 if (isModEnabled('stock')) {
2608 print '<td class="left">'.$langs->trans("WarehouseTarget").'</td>';
2609 }
2610
2611 if (isModEnabled('productbatch')) {
2612 print '<td class="left">'.$langs->trans("Batch").'</td>';
2613 }
2614
2615 $parameters = array();
2616 $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2617 if ($reshook < 0) {
2618 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2619 } else {
2620 print $hookmanager->resPrint;
2621 }
2622 }
2623 print '<td class="center">'.$langs->trans("CalculatedWeight").'</td>';
2624 print '<td class="center">'.$langs->trans("CalculatedVolume").'</td>';
2625 //print '<td class="center">'.$langs->trans("Size").'</td>';
2626 if ($object->statut == 0) {
2627 print '<td class="linecoledit"></td>';
2628 print '<td class="linecoldelete" width="10"></td>';
2629 }
2630 print "</tr>\n";
2631 print '</thead>';
2632
2633 $var = false;
2634
2635 $outputlangs = $langs;
2636 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
2637 $object->fetch_thirdparty();
2638 $newlang = '';
2639 if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
2640 $newlang = GETPOST('lang_id', 'aZ09');
2641 }
2642 if (empty($newlang)) {
2643 $newlang = $object->thirdparty->default_lang;
2644 }
2645 if (!empty($newlang)) {
2646 $outputlangs = new Translate("", $conf);
2647 $outputlangs->setDefaultLang($newlang);
2648 }
2649 }
2650
2651 // Get list of products already sent for same source object into $alreadysent
2652 $alreadysent = array();
2653
2654 $origin = (string) $origin;
2655
2656 // The origin may arrive as 'order_supplier' from some callers, while the table name below is
2657 // built from 'supplier_order'. Normalise it or the query targets a table that does not exist.
2658 if (empty($origin) || $origin == 'order_supplier') {
2659 $origin = 'supplier_order';
2660 }
2661
2662 // List of allowed value of $origin
2663 if (!in_array($origin, array('supplier_proposal', 'supplier_order', 'commande_fournisseur', 'facture_fourn', 'propal', 'commande', 'facture'))) {
2664 dol_print_error($db, 'Bad value for parameter origin in reception/card.php');
2665 exit;
2666 }
2667
2668 if ($origin_id > 0) {
2669 $tablenametouse = (($origin == 'supplier_order') ? 'commande_fournisseur' : (($origin == 'facture_fourn') ? 'facture_fourn_' : $origin));
2670
2671 $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";
2672 $sql .= ", ed.rowid as receptionline_id, ed.qty, ed.fk_reception as reception_id, ed.fk_entrepot";
2673 $sql .= ", e.rowid as reception_id, e.ref as reception_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_reception";
2674 $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
2675 $sql .= ', p.description as product_desc';
2676 $sql .= " FROM ".MAIN_DB_PREFIX."receptiondet_batch as ed";
2677 $sql .= ", ".MAIN_DB_PREFIX."reception as e";
2678 $sql .= ", ".MAIN_DB_PREFIX.$db->sanitize($tablenametouse)."det as obj";
2679 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
2680 $sql .= " WHERE e.entity IN (".getEntity('reception').")";
2681 $sql .= " AND obj.fk_commande = ".((int) $origin_id);
2682 $sql .= " AND obj.rowid = ed.fk_elementdet";
2683 $sql .= " AND ed.fk_reception = e.rowid";
2684 $sql .= " AND ed.fk_reception !=".((int) $object->id);
2685 $sql .= " ORDER BY obj.fk_product";
2686
2687 dol_syslog("get list of reception lines", LOG_DEBUG);
2688 $resql = $db->query($sql);
2689 if ($resql) {
2690 $num = $db->num_rows($resql);
2691 $i = 0;
2692
2693 while ($i < $num) {
2694 $obj = $db->fetch_object($resql);
2695 if ($obj) {
2696 // $obj->rowid is rowid in $origin."det" table
2697 $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);
2698 }
2699 $i++;
2700 }
2701 }
2702 //var_dump($alreadysent);
2703 }
2704
2705 $arrayofpurchaselinealreadyoutput = array();
2706
2707 // Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output)
2708 print '<tbody>';
2709 for ($i = 0; $i < $num_prod; $i++) {
2710 print '<!-- origin line id = '.(!empty($lines[$i]->origin_line_id) ? $lines[$i]->origin_line_id : 0).' -->'; // id of order line
2711 print '<tr class="oddeven" id="row-'.$lines[$i]->id.'" data-id="'.$lines[$i]->id.'" data-element="'.$lines[$i]->element.'">';
2712
2713 // #
2714 if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
2715 print '<td class="center">'.($i + 1).'</td>';
2716 }
2717
2718 // Predefined product or service
2719 if ($lines[$i]->fk_product > 0) {
2720 // Define output language
2721 if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
2722 $prod = new Product($db);
2723 $prod->fetch($lines[$i]->fk_product);
2724 $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product->label;
2725 } else {
2726 $label = (!empty($lines[$i]->product->label) ? $lines[$i]->product->label : $lines[$i]->product->product_label);
2727 }
2728
2729 print '<td class="linecoldescription">';
2730 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
2731 $text = $lines[$i]->product->getNomUrl(1);
2732 $text .= ' - '.$label;
2733 $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->description));
2734 print $form->textwithtooltip($text, $description, 3, 0, '', (string) $i);
2735 print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : 0, !empty($lines[$i]->date_end) ? $lines[$i]->date_end : 0);
2736 if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
2737 print (!empty($lines[$i]->description) && $lines[$i]->description != $label) ? '<br>'.dol_htmlentitiesbr($lines[$i]->description) : '';
2738 }
2739 }
2740 print "</td>\n";
2741 } else {
2742 print '<td class="linecoldescription">';
2743 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
2744 if ($lines[$i]->product_type == Product::TYPE_SERVICE) {
2745 $text = img_object($langs->trans('Service'), 'service');
2746 } else {
2747 $text = img_object($langs->trans('Product'), 'product');
2748 }
2749
2750 if (!empty($lines[$i]->label)) {
2751 $text .= ' <strong>'.$lines[$i]->label.'</strong>';
2752 print $form->textwithtooltip($text, $lines[$i]->description, 3, 0, '', (string) $i);
2753 } else {
2754 print $text.' '.nl2br($lines[$i]->description);
2755 }
2756
2757 print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
2758 }
2759 print "</td>\n";
2760 }
2761
2762 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2763 print '<td><input name="comment'.$line_id.'" id="comment'.$line_id.'" value="'.dol_escape_htmltag($lines[$i]->comment).'"></td>';
2764 } else {
2765 print '<td style="white-space: pre-wrap; max-width: 200px;">'.dol_escape_htmltag($lines[$i]->comment).'</td>';
2766 }
2767
2768
2769 // Qty ordered
2770 print '<td class="center linecolqty">';
2771 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
2772 print $lines[$i]->qty_asked;
2773 }
2774 print '</td>';
2775
2776 // Qty in other receptions (with reception and warehouse used)
2777 // Note: here $origin is always a non-empty string (normalized above), so only $origin_id needs to be tested
2778 if ($origin_id > 0) {
2779 print '<td class="center nowrap linecolqtyinotherreceptions">';
2780 $htmltooltip = '';
2781 $qtyalreadyreceived = 0;
2782 if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
2783 foreach ($alreadysent as $key => $val) {
2784 if ($lines[$i]->fk_commandefourndet == $key) {
2785 $j = 0;
2786 foreach ($val as $receptionline_id => $receptionline_var) {
2787 if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) {
2788 continue; // We want to show only "other receptions"
2789 }
2790
2791 $j++;
2792 if ($j > 1) {
2793 $htmltooltip .= '<br>';
2794 }
2795 if (empty($conf->cache['reception'][$receptionline_var['reception_id']])) {
2796 $reception_static = new Reception($db);
2797 $reception_static->fetch($receptionline_var['reception_id']);
2798 $conf->cache['reception'][$receptionline_var['reception_id']] = $reception_static;
2799 } else {
2800 $reception_static = $conf->cache['reception'][$receptionline_var['reception_id']];
2801 }
2802 $htmltooltip .= $reception_static->getNomUrl(1, 'nolink', 0, 0, 1);
2803 $htmltooltip .= ' - '.$receptionline_var['qty'];
2804
2805 $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour'));
2806 if (isModEnabled('stock') && $receptionline_var['warehouse'] > 0) {
2807 if (empty($conf->cache['warehouse'][$receptionline_var['warehouse']])) {
2808 $warehousestatic = new Entrepot($db);
2809 $warehousestatic->fetch($receptionline_var['warehouse']);
2810 $conf->cache['warehouse'][$receptionline_var['warehouse']] = $warehousestatic;
2811 } else {
2812 $warehousestatic = $conf->cache['warehouse'][$receptionline_var['warehouse']];
2813 }
2814 $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
2815 }
2816 $htmltooltip .= ' '.$form->textwithpicto('', $htmltext, 1);
2817
2818 $qtyalreadyreceived += $receptionline_var['qty'];
2819 }
2820 if ($j) {
2821 $htmltooltip = $langs->trans("QtyInOtherReceptions").'...<br><br>'.$htmltooltip.'<br><input type="submit" name="dummyhiddenbuttontogetfocus" style="display:none" autofocus>';
2822 }
2823 }
2824 }
2825 }
2826 print $form->textwithpicto((string) $qtyalreadyreceived, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id);
2827 print '</td>';
2828 }
2829
2830 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2831 // edit mode
2832 print '<td colspan="'.$editColspan.'" class="center"><table class="nobordernopadding">';
2833 if (isModEnabled('stock')) {
2834 if ($lines[$i]->fk_product > 0) {
2835 print '<!-- case edit 1 -->';
2836 print '<tr>';
2837 // Qty to receive or received
2838 print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
2839 // Warehouse source
2840 print '<td>'.$formproduct->selectWarehouses($lines[$i]->fk_entrepot, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).'</td>';
2841 // Batch number management
2842 if ($conf->productbatch->enabled && !empty($lines[$i]->product->status_batch)) {
2843 print '<td class="nowraponall left"><input name="batch'.$line_id.'" id="batch'.$line_id.'" type="text" value="'.$lines[$i]->batch.'"><br>';
2844 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
2845 print $langs->trans('SellByDate').' : ';
2846 print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, 0, 0, 1, "").'<br>';
2847 }
2848 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
2849 print $langs->trans('EatByDate').' : ';
2850 print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, 0, 0, 1, "");
2851 }
2852 print '</td>';
2853 }
2854 print '</tr>';
2855 } else {
2856 print '<!-- case edit 2 -->';
2857 print '<tr>';
2858 // Qty to receive or received
2859 print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
2860 // Warehouse source
2861 print '<td></td>';
2862 // Batch number management
2863 print '<td></td>';
2864 print '</tr>';
2865 }
2866 }
2867 print '</table></td>';
2868
2869 $parameters = array();
2870 $parameters['line'] = $lines[$i];
2871 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2872 if ($reshook < 0) {
2873 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2874 } else {
2875 print $hookmanager->resPrint;
2876 }
2877 } else {
2878 // Qty to receive or received
2879 print '<td class="center linecolqtytoreceive">'.$lines[$i]->qty.'</td>';
2880
2881 // Warehouse source
2882 if (isModEnabled('stock')) {
2883 if ($lines[$i]->fk_entrepot > 0) {
2884 $entrepot = new Entrepot($db);
2885 $entrepot->fetch($lines[$i]->fk_entrepot);
2886
2887 print '<td class="left tdoverflowmax150" title="'.dol_escape_htmltag($entrepot->label).'">';
2888 print $entrepot->getNomUrl(1);
2889 print '</td>';
2890 } else {
2891 print '<td></td>';
2892 }
2893 }
2894
2895 // Batch number management
2896 if (isModEnabled('productbatch')) {
2897 if (isset($lines[$i]->batch)) {
2898 print '<!-- Detail of lot -->';
2899 print '<td class="linecolbatch nowrap">';
2900 $detail = $langs->trans("NA");
2901 if ($lines[$i]->product->status_batch > 0 && $lines[$i]->fk_product > 0) {
2902 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
2903 $productlot = new Productlot($db);
2904 $reslot = $productlot->fetch(0, $lines[$i]->fk_product, $lines[$i]->batch);
2905 if ($reslot > 0) {
2906 $detail = $productlot->getNomUrl(1);
2907 } else {
2908 // lot is not created and info is only in reception lines
2909 $batchinfo = $langs->trans("Batch").': '.$lines[$i]->batch;
2910 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
2911 $batchinfo .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($lines[$i]->sellby, "day");
2912 }
2913 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
2914 $batchinfo .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($lines[$i]->eatby, "day");
2915 }
2916 $detail = $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $batchinfo);
2917 }
2918 }
2919 print $detail . '</td>';
2920 } else {
2921 print '<td></td>';
2922 }
2923 }
2924
2925 $parameters = array();
2926 $parameters['line'] = $lines[$i];
2927 $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2928 if ($reshook < 0) {
2929 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2930 } else {
2931 print $hookmanager->resPrint;
2932 }
2933 }
2934
2935 // Weight
2936 print '<td class="center linecolweight">';
2937 if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2938 print $lines[$i]->product->weight * $lines[$i]->qty.' '.measuringUnitString(0, "weight", $lines[$i]->product->weight_units);
2939 } else {
2940 print '&nbsp;';
2941 }
2942 print '</td>';
2943
2944 // Volume
2945 print '<td class="center linecolvolume">';
2946 if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2947 print $lines[$i]->product->volume * $lines[$i]->qty.' '.measuringUnitString(0, "volume", $lines[$i]->product->volume_units);
2948 } else {
2949 print '&nbsp;';
2950 }
2951 print '</td>';
2952
2953
2954 if ($action == 'editline' && $lines[$i]->id == $line_id) {
2955 print '<td class="center valignmiddle" colspan="2">';
2956 print '<input type="submit" class="button small button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'"><br>';
2957 print '<input type="submit" class="button small button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'"><br>';
2958 print '</td>';
2959 } elseif ($object->statut == Reception::STATUS_DRAFT) {
2960 // edit-delete buttons
2961 print '<td class="linecoledit center">';
2962 print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_edit().'</a>';
2963 print '</td>';
2964 print '<td class="linecoldelete" width="10">';
2965 print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_delete().'</a>';
2966 print '</td>';
2967
2968 // Display lines extrafields
2969 if (isset($rowExtrafieldsStart, $rowExtrafieldsView, $rowEnd)) { // @phan-suppress-current-line PhanPluginUndeclaredVariableIsset
2970 print $rowExtrafieldsStart;
2971 print $rowExtrafieldsView;
2972 print $rowEnd;
2973 }
2974 }
2975 print "</tr>";
2976
2977 $arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet;
2978
2979 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
2980 if ($reshook < 0) {
2981 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
2982 } else {
2983 print $hookmanager->resPrint;
2984 }
2985
2986 // Display lines extrafields
2987 $extralabelslines = $extrafields->attributes[$lines[$i]->table_element];
2988 if (!empty($extralabelslines) && is_array($extralabelslines) && count($extralabelslines) > 0) {
2989 $colspan = 8;
2990 if (isModEnabled('stock')) {
2991 $colspan++;
2992 }
2993 if (isModEnabled('productbatch')) {
2994 $colspan++;
2995 }
2996
2997 $line = new CommandeFournisseurDispatch($db);
2998 $line->id = $lines[$i]->id;
2999 $line->fetch_optionals();
3000
3001 if ($action == 'editline' && $lines[$i]->id == $line_id) {
3002 print $line->showOptionals($extrafields, 'edit', array('colspan' => $colspan), '');
3003 } else {
3004 print $line->showOptionals($extrafields, 'view', array('colspan' => $colspan), '');
3005 }
3006 }
3007 }
3008 print '</tbody>';
3009
3010 // TODO Show also lines ordered but not delivered
3011
3012 print "</table>\n";
3013 print '</div>';
3014
3015
3016 print dol_get_fiche_end();
3017
3018
3019 $object->fetchObjectLinked($object->id, $object->element);
3020 }
3021
3022 /*
3023 * Button actions
3024 */
3025
3026 if (($user->socid == 0) && ($action != 'presend') && ($action != 'editline')) {
3027 print '<div class="tabsAction">';
3028
3029 $parameters = array();
3030 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
3031 if (empty($reshook)) {
3032 if ($object->statut == Reception::STATUS_DRAFT && $num_prod > 0) {
3033 if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer'))
3034 || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate'))) {
3035 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'">'.$langs->trans("Validate").'</a>';
3036 } else {
3037 print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
3038 }
3039 }
3040 // Back to draft
3041 if ($object->statut == Reception::STATUS_VALIDATED && $user->hasRight('reception', 'creer')) {
3042 print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('SetToDraft').'</a></div>';
3043 }
3044
3045 // TODO add alternative status
3046 // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
3047 if ($object->statut == Reception::STATUS_CLOSED && $user->hasRight('reception', 'creer')) {
3048 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
3049 }
3050
3051 // Send mail
3052 if (empty($user->socid)) {
3053 if ($object->statut > 0) {
3054 if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('reception', 'reception_advance', 'send')) {
3055 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
3056 } else {
3057 print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
3058 }
3059 }
3060 }
3061
3062 // Create bill
3063 if (isModEnabled("supplier_invoice") && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED) && !getDolGlobalString('RECEPTION_STANDALONE')) {
3064 if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer')) {
3065 if (getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
3066 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>';
3067 }
3068 }
3069 }
3070
3071
3072 // Set Billed and Closed
3073 if ($object->statut == Reception::STATUS_VALIDATED) {
3074 if ($user->hasRight('reception', 'creer') && $object->statut > 0) {
3075 if (!$object->billed && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
3076 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans('ClassifyBilled').'</a>';
3077 }
3078 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifyclosed&token='.newToken().'">'.$langs->trans("Close").'</a>';
3079 }
3080 }
3081
3082 if ($user->hasRight('reception', 'supprimer')) {
3083 print dolGetButtonAction($langs->trans("Delete"), $langs->trans("Delete"), 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), '', true, array('attr' => array('class' => 'reposition')))."\n";
3084 }
3085 }
3086
3087 print '</div>';
3088 }
3089
3090
3091 /*
3092 * Documents generated
3093 */
3094
3095 if ($action != 'presend' && $action != 'editline') {
3096 print '<div class="fichecenter"><div class="fichehalfleft">';
3097
3098 $objectref = dol_sanitizeFileName((string) $object->ref);
3099 $filedir = $conf->reception->dir_output."/".$objectref;
3100
3101 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
3102
3103 $genallowed = $user->hasRight('reception', 'lire');
3104 $delallowed = $user->hasRight('reception', 'creer');
3105
3106 print $formfile->showdocuments('reception', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
3107
3108 // Show links to link elements
3109 //$tmparray = $form->showLinkToObjectBlock($object, null, array('order'), 1);
3110 $somethingshown = $form->showLinkedObjectBlock($object, '');
3111
3112 print '</div><div class="fichehalfright">';
3113
3114 print '</div></div>';
3115 }
3116
3117 // Presend form
3118 $modelmail = 'reception_send';
3119 $defaulttopic = 'SendReceptionRef';
3120 $diroutput = $conf->reception->dir_output;
3121 $trackid = 'rec'.$object->id;
3122
3123 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
3124}
3125
3126llxFooter();
3127
3128$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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 ProductCombination Used to represent the relation between a product and one of its variants.
Class to manage predefined suppliers products.
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 table commandefournisseurdispatch.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
getCountry($searchkey, $withcode='', $dbtouse=null, $outputlangs=null, $entconv=1, $searchlabel='')
Return country label, code or id from an id, code or label.
global $mysoc
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.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
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...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
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.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
print_date_range($date_start, $date_end, $format='', $outputlangs=null)
Format output for start and end date.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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.
Definition html.lib.php:540
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:738
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
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, $nodie=0, $mode='')
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.