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