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