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