dolibarr  19.0.0-dev
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005 Simon TOSSER <simon@kornog-computing.com>
5  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
6  * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8  * Copyright (C) 2013 Marcos García <marcosgdf@gmail.com>
9  * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
10  * Copyright (C) 2014-2017 Francis Appels <francis.appels@yahoo.com>
11  * Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
12  * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
13  * Copyright (C) 2016 Yasser Carreón <yacasia@gmail.com>
14  * Copyright (C) 2018 Quentin Vial-Gouteyron <quentin.vial-gouteyron@atm-consulting.fr>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program. If not, see <https://www.gnu.org/licenses/>.
28  */
29 
36 // Load Dolibarr environment
37 require '../main.inc.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
40 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
42 require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
43 require_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
44 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
45 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
46 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
47 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
48 if (isModEnabled("product") || isModEnabled("service")) {
49  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
50 }
51 if (isModEnabled("propal")) {
52  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
53 }
54 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
55 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
56 if (isModEnabled('productbatch')) {
57  require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
58 }
59 if (isModEnabled('project')) {
60  require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
61  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
62 }
63 
64 $langs->loadLangs(array("receptions", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal', 'sendings'));
65 
66 if (isModEnabled('incoterm')) {
67  $langs->load('incoterm');
68 }
69 if (isModEnabled('productbatch')) {
70  $langs->load('productbatch');
71 }
72 
73 $origin = GETPOST('origin', 'alpha') ?GETPOST('origin', 'alpha') : 'reception'; // Example: commande, propal
74 $origin_id = GETPOST('id', 'int') ? GETPOST('id', 'int') : '';
75 $id = $origin_id;
76 if (empty($origin_id)) {
77  $origin_id = GETPOST('origin_id', 'int'); // Id of order or propal
78 }
79 if (empty($origin_id)) {
80  $origin_id = GETPOST('object_id', 'int'); // Id of order or propal
81 }
82 if (empty($origin_id)) {
83  $origin_id = GETPOST('originid', 'int'); // Id of order or propal
84 }
85 $ref = GETPOST('ref', 'alpha');
86 $line_id = GETPOST('lineid', 'int') ?GETPOST('lineid', 'int') : '';
87 $facid = GETPOST('facid', 'int');
88 
89 $action = GETPOST('action', 'alpha');
90 //Select mail models is same action as presend
91 if (GETPOST('modelselected')) {
92  $action = 'presend';
93 }
94 $confirm = GETPOST('confirm', 'alpha');
95 $cancel = GETPOST('cancel', 'alpha');
96 $backtopage = GETPOST('backtopage', 'alpha');
97 $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
98 
99 //PDF
100 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
101 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
102 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
103 
104 $object = new Reception($db);
105 $objectorder = new CommandeFournisseur($db);
106 $extrafields = new ExtraFields($db);
107 
108 // fetch optionals attributes and labels
109 $extrafields->fetch_name_optionals_label($object->table_element);
110 $extrafields->fetch_name_optionals_label($object->table_element_line);
111 $extrafields->fetch_name_optionals_label($objectorder->table_element_line);
112 
113 // Load object. Make an object->fetch
114 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
115 
116 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
117 $hookmanager->initHooks(array('receptioncard', 'globalcard'));
118 
119 $date_delivery = dol_mktime(GETPOST('date_deliveryhour', 'int'), GETPOST('date_deliverymin', 'int'), 0, GETPOST('date_deliverymonth', 'int'), GETPOST('date_deliveryday', 'int'), GETPOST('date_deliveryyear', 'int'));
120 
121 if ($id > 0 || !empty($ref)) {
122  $object->fetch($id, $ref);
123  $object->fetch_thirdparty();
124 
125  if (!empty($object->origin)) {
126  $origin = $object->origin;
127 
128  $object->fetch_origin();
129  $typeobject = $object->origin;
130  }
131 
132  // Linked documents
133  if ($origin == 'order_supplier' && $object->$typeobject->id && isModEnabled("supplier_order")) {
134  $origin_id = $object->$typeobject->id;
135  $objectsrc = new CommandeFournisseur($db);
136  $objectsrc->fetch($object->$typeobject->id);
137  }
138 }
139 
140 // Security check
141 $socid = '';
142 if ($user->socid) {
143  $socid = $user->socid;
144 }
145 
146 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 $title = $object->ref.' - '.$langs->trans('Reception');
739 
740 llxHeader('', $title, 'Reception');
741 
742 $form = new Form($db);
743 $formfile = new FormFile($db);
744 $formproduct = new FormProduct($db);
745 if (isModEnabled('project')) {
746  $formproject = new FormProjets($db);
747 }
748 
749 $product_static = new Product($db);
750 $reception_static = new Reception($db);
751 $warehousestatic = new Entrepot($db);
752 
753 if ($action == 'create2') {
754  print load_fiche_titre($langs->trans("CreateReception"), '', 'dollyrevert');
755 
756  print '<br>'.$langs->trans("ReceptionCreationIsDoneFromOrder");
757  $action = ''; $id = ''; $ref = '';
758 }
759 
760 // Mode creation.
761 if ($action == 'create') {
762  $recept = new Reception($db);
763 
764  print load_fiche_titre($langs->trans("CreateReception"));
765  if (!$origin) {
766  setEventMessages($langs->trans("ErrorBadParameters"), null, 'errors');
767  }
768 
769  if ($origin) {
770  if ($origin == 'supplierorder') {
771  $classname = 'CommandeFournisseur';
772  } else {
773  $classname = ucfirst($origin);
774  }
775 
776  $objectsrc = new $classname($db);
777  if ($objectsrc->fetch($origin_id)) { // This include the fetch_lines
778  $soc = new Societe($db);
779  $soc->fetch($objectsrc->socid);
780 
781  $author = new User($db);
782  $author->fetch($objectsrc->user_author_id);
783 
784  if (isModEnabled('stock')) {
785  $entrepot = new Entrepot($db);
786  }
787 
788  print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
789  print '<input type="hidden" name="token" value="'.newToken().'">';
790  print '<input type="hidden" name="action" value="add">';
791  print '<input type="hidden" name="origin" value="'.$origin.'">';
792  print '<input type="hidden" name="origin_id" value="'.$objectsrc->id.'">';
793  print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
794  print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
795  if (GETPOST('entrepot_id', 'int')) {
796  print '<input type="hidden" name="entrepot_id" value="'.GETPOST('entrepot_id', 'int').'">';
797  }
798 
799  print dol_get_fiche_head('');
800 
801  print '<table class="border centpercent">';
802 
803  // Ref
804  print '<tr><td class="titlefieldcreate fieldrequired">';
805  if ($origin == 'supplierorder' && isModEnabled("supplier_order")) {
806  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;
807  }
808  if ($origin == 'propal' && isModEnabled("propal")) {
809  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;
810  }
811  print '</a></td>';
812  print "</tr>\n";
813 
814  // Ref client
815  print '<tr><td>';
816  if ($origin == 'supplier_order') {
817  print $langs->trans('SupplierOrder');
818  } else {
819  print $langs->trans('RefSupplier');
820  }
821  print '</td><td colspan="3">';
822  print '<input type="text" name="ref_supplier" value="'.$objectsrc->ref_supplier.'" />';
823  print '</td>';
824  print '</tr>';
825 
826  // Tiers
827  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Company').'</td>';
828  print '<td colspan="3">'.$soc->getNomUrl(1).'</td>';
829  print '</tr>';
830 
831  // Project
832  if (isModEnabled('project')) {
833  $projectid = GETPOST('projectid', 'int') ?GETPOST('projectid', 'int') : 0;
834  if (empty($projectid) && !empty($objectsrc->fk_project)) {
835  $projectid = $objectsrc->fk_project;
836  }
837  if ($origin == 'project') {
838  $projectid = ($originid ? $originid : 0);
839  }
840 
841  $langs->load("projects");
842  print '<tr>';
843  print '<td>'.$langs->trans("Project").'</td><td colspan="2">';
844  print img_picto('', 'project', 'class="paddingright"');
845  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');
846  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>';
847  print '</td>';
848  print '</tr>';
849  }
850 
851  // Date delivery planned
852  print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
853  print '<td colspan="3">';
854  $date_delivery = ($date_delivery ? $date_delivery : $objectsrc->delivery_date); // $date_delivery comes from GETPOST
855  print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
856  print "</td>\n";
857  print '</tr>';
858 
859  // Note Public
860  print '<tr><td>'.$langs->trans("NotePublic").'</td>';
861  print '<td colspan="3">';
862  $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%');
863  print $doleditor->Create(1);
864  print "</td></tr>";
865 
866  // Note Private
867  if ($objectsrc->note_private && !$user->socid) {
868  print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
869  print '<td colspan="3">';
870  $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%');
871  print $doleditor->Create(1);
872  print "</td></tr>";
873  }
874 
875  // Weight
876  print '<tr><td>';
877  print $langs->trans("Weight");
878  print '</td><td colspan="3"><input name="weight" size="4" value="'.GETPOST('weight', 'int').'"> ';
879  $text = $formproduct->selectMeasuringUnits("weight_units", "weight", GETPOST('weight_units', 'int'), 0, 2);
880  $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
881  print $form->textwithpicto($text, $htmltext);
882  print '</td></tr>';
883  // Dim
884  print '<tr><td>';
885  print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
886  print ' </td><td colspan="3"><input name="trueWidth" size="4" value="'.GETPOST('trueWidth', 'int').'">';
887  print ' x <input name="trueHeight" size="4" value="'.GETPOST('trueHeight', 'int').'">';
888  print ' x <input name="trueDepth" size="4" value="'.GETPOST('trueDepth', 'int').'">';
889  print ' ';
890  $text = $formproduct->selectMeasuringUnits("size_units", "size", GETPOST('size_units', 'int'), 0, 2);
891  $htmltext = $langs->trans("KeepEmptyForAutoCalculation");
892  print $form->textwithpicto($text, $htmltext);
893  print '</td></tr>';
894 
895  // Delivery method
896  print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
897  print '<td colspan="3">';
898  $recept->fetch_delivery_methods();
899  print $form->selectarray("shipping_method_id", $recept->meths, GETPOST('shipping_method_id', 'int'), 1, 0, 0, "", 1);
900  if ($user->admin) {
901  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
902  }
903  print "</td></tr>\n";
904 
905  // Tracking number
906  print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
907  print '<td colspan="3">';
908  print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
909  print "</td></tr>\n";
910 
911  // Other attributes
912  $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3', 'socid'=>$socid);
913  $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $recept, $action); // Note that $action and $objectsrc may have been modified by hook
914  print $hookmanager->resPrint;
915 
916  // Here $object can be of an object Reception
917  $extrafields->fetch_name_optionals_label($object->table_element);
918  if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
919  // copy from order
920  if ($objectsrc->fetch_optionals() > 0) {
921  $recept->array_options = array_merge($recept->array_options, $objectsrc->array_options);
922  }
923  print $recept->showOptionals($extrafields, 'create', $parameters);
924  }
925 
926  // Incoterms
927  if (isModEnabled('incoterm')) {
928  print '<tr>';
929  print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->label_incoterms, 1).'</label></td>';
930  print '<td colspan="3" class="maxwidthonsmartphone">';
931  print $form->select_incoterms((!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : ''), (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : ''));
932  print '</td></tr>';
933  }
934 
935  // Document model
936  include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
938 
939  if (count($list) > 1) {
940  print "<tr><td>".$langs->trans("DefaultModel")."</td>";
941  print '<td colspan="3">';
942  print $form->selectarray('model', $list, $conf->global->RECEPTION_ADDON_PDF);
943  print "</td></tr>\n";
944  }
945 
946  print "</table>";
947 
948  print dol_get_fiche_end();
949 
950  // Number of lines show on the reception card
951  $numAsked = 0;
952 
957  $suffix2numAsked = array();
958  $dispatchLines = array();
959 
960  foreach ($_POST as $key => $value) {
961  // If create form is coming from the button "Create Reception" of previous page
962 
963  // without batch module enabled or product with no lot/serial
964  $reg = array();
965  if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
966  $numAsked++;
967  $paramSuffix = $reg[1] . '_' . $reg[2];
968  $suffix2numAsked[$paramSuffix] = $numAsked;
969 
970  // $numline=$reg[2] + 1; // line of product
971  $numline = $numAsked;
972 
973  $prod = "product_" . $paramSuffix;
974  $qty = "qty_" . $paramSuffix;
975  $ent = "entrepot_" . $paramSuffix;
976  $pu = "pu_" . $paramSuffix; // This is unit price including discount
977  $fk_commandefourndet = "fk_commandefourndet_" . $paramSuffix;
978  $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'));
979  }
980 
981  // with batch module enabled and product with lot/serial
982  if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
983  $numAsked++;
984  $paramSuffix = $reg[1] . '_' . $reg[2];
985  $suffix2numAsked[$paramSuffix] = $numAsked;
986 
987  // eat-by date dispatch
988  // $numline=$reg[2] + 1; // line of product
989  $numline = $numAsked;
990 
991  $prod = 'product_batch_' . $paramSuffix;
992  $qty = 'qty_' . $paramSuffix;
993  $ent = 'entrepot_' . $paramSuffix;
994  $pu = 'pu_' . $paramSuffix;
995  $lot = 'lot_number_' . $paramSuffix;
996  $dDLUO = dol_mktime(12, 0, 0, GETPOST('dluo_'.$paramSuffix.'month', 'int'), GETPOST('dluo_'.$paramSuffix.'day', 'int'), GETPOST('dluo_'.$paramSuffix.'year', 'int'));
997  $dDLC = dol_mktime(12, 0, 0, GETPOST('dlc_'.$paramSuffix.'month', 'int'), GETPOST('dlc_'.$paramSuffix.'day', 'int'), GETPOST('dlc_'.$paramSuffix.'year', 'int'));
998  $fk_commandefourndet = 'fk_commandefourndet_'.$paramSuffix;
999  $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'));
1000  }
1001 
1002  // If create form is coming from same page, it means that post was sent but an error occured
1003  if (preg_match('/^productl([0-9]+)$/i', $key, $reg)) {
1004  $numAsked++;
1005  $paramSuffix = $reg[1];
1006  $suffix2numAsked[$paramSuffix] = $numAsked;
1007 
1008  // eat-by date dispatch
1009  // $numline=$reg[2] + 1; // line of product
1010  $numline = $numAsked;
1011 
1012  $prod = 'productid'.$paramSuffix;
1013  $comment = 'comment'.$paramSuffix;
1014  $qty = 'qtyl'.$paramSuffix;
1015  $ent = 'entl'.$paramSuffix;
1016  $pu = 'pul'.$paramSuffix;
1017  $lot = 'batch'.$paramSuffix;
1018  $dDLUO = dol_mktime(12, 0, 0, GETPOST('dluo'.$paramSuffix.'month', 'int'), GETPOST('dluo'.$paramSuffix.'day', 'int'), GETPOST('dluo'.$paramSuffix.'year', 'int'));
1019  $dDLC = dol_mktime(12, 0, 0, GETPOST('dlc'.$paramSuffix.'month', 'int'), GETPOST('dlc'.$paramSuffix.'day', 'int'), GETPOST('dlc'.$paramSuffix.'year', 'int'));
1020  $fk_commandefourndet = 'fk_commandefournisseurdet'.$paramSuffix;
1021  $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'));
1022  }
1023  }
1024 
1025  // If extrafield values are passed in the HTTP query, assign them to the correct dispatch line
1026  // Note that if an extrafield with the same name exists in the origin supplier order line, the value
1027  // from the HTTP query will be ignored
1028  foreach ($suffix2numAsked as $suffix => $n) {
1029  $dispatchLines[$n]['array_options'] = $extrafields->getOptionalsFromPost('commande_fournisseur_dispatch', '_' . $suffix, '');
1030  }
1031 
1032  print '<script type="text/javascript">
1033  jQuery(document).ready(function() {
1034  jQuery("#autofill").click(function() {';
1035  $i = 1;
1036  while ($i <= $numAsked) {
1037  print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1038  $i++;
1039  }
1040  print '});
1041  jQuery("#autoreset").click(function() {';
1042  $i = 1;
1043  while ($i <= $numAsked) {
1044  print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1045  $i++;
1046  }
1047  print '});
1048  });
1049  </script>';
1050 
1051  print '<br>';
1052 
1053  print '<table class="noborder centpercent">';
1054 
1055  // Load receptions already done for same order
1056  $objectsrc->loadReceptions();
1057 
1058  if ($numAsked) {
1059  print '<tr class="liste_titre">';
1060  print '<td>'.$langs->trans("Description").'</td>';
1061  print '<td>'.$langs->trans("Comment").'</td>';
1062  print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1063  print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1064  print '<td class="center">'.$langs->trans("QtyToReceive");
1065  if (getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
1066  print '<td>'.$langs->trans("BuyingPrice").'</td>';
1067  }
1068  if (isModEnabled('productbatch')) {
1069  print ' <br>(<a href="#" id="autofill">'.$langs->trans("Fill").'</a>';
1070  print ' / <a href="#" id="autoreset">'.$langs->trans("Reset").'</a>)';
1071  }
1072  print '</td>';
1073  if (isModEnabled('stock')) {
1074  print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1075  }
1076  if (isModEnabled('productbatch')) {
1077  print '<td class="left">'.$langs->trans("batch_number").'</td>';
1078  if (!getDolGlobalInt('PRODUCT_DISABLE_SELLBY')) {
1079  print '<td class="left">'.$langs->trans("SellByDate").'</td>';
1080  }
1081  if (!getDolGlobalInt('PRODUCT_DISABLE_EATBY')) {
1082  print '<td class="left">'.$langs->trans("EatByDate").'</td>';
1083  }
1084  }
1085  print "</tr>\n";
1086  }
1087 
1088  // $objectsrc->lines contains the line of the purchase order
1089  // $dispatchLines is list of lines with dispatching detail (with product, qty and warehouse). One purchase order line may have n of this dispatch lines.
1090 
1091  $arrayofpurchaselinealreadyoutput= array();
1092 
1093  // $_POST contains fk_commandefourndet_X_Y where Y is num of product line and X is number of splitted line
1094  $indiceAsked = 1;
1095  while ($indiceAsked <= $numAsked) { // Loop on $dispatchLines. Warning: $dispatchLines must be sorted by fk_commandefourndet (it is a regroupment key on output)
1096  $product = new Product($db);
1097 
1098  // We search the purchase order line that is linked to the dispatchLines
1099  foreach ($objectsrc->lines as $supplierLine) {
1100  if ($dispatchLines[$indiceAsked]['fk_commandefourndet'] == $supplierLine->id) {
1101  $line = $supplierLine;
1102  break;
1103  }
1104  }
1105 
1106  // Show product and description
1107  $type = $line->product_type ? $line->product_type : $line->fk_product_type;
1108  // Try to enhance type detection using date_start and date_end for free lines where type
1109  // was not saved.
1110  if (!empty($line->date_start)) {
1111  $type = 1;
1112  }
1113  if (!empty($line->date_end)) {
1114  $type = 1;
1115  }
1116 
1117  print '<!-- line fk_commandefourndet='.$line->id.' for product='.$line->fk_product.' -->'."\n";
1118  print '<tr class="oddeven">'."\n";
1119 
1120  // Product label
1121  if ($line->fk_product > 0) { // If predefined product
1122  $product->fetch($line->fk_product);
1123  $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
1124  //var_dump($product->stock_warehouse[1]);
1125  //var_dump($dispatchLines[$indiceAsked]);
1126 
1127  print '<td>';
1128  print '<a name="'.$line->id.'"></a>'; // ancre pour retourner sur la ligne
1129 
1130  print '<input type="hidden" name="productl'.$indiceAsked.'" value="'.$line->fk_product.'">';
1131 
1132  if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1133  print '<input type="hidden" name="productid'.$indiceAsked.'" value="'.$line->fk_product.'">';
1134 
1135  // Show product and description
1136  $product_static = $product;
1137 
1138  $text = $product_static->getNomUrl(1);
1139  $text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
1140  $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($line->desc));
1141  print $form->textwithtooltip($text, $description, 3, '', '', $i);
1142 
1143  // Show range
1144  print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1145 
1146  // Add description in form
1147  if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1148  print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
1149  }
1150  }
1151  print '</td>';
1152  } else {
1153  print "<td>";
1154  if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1155  if ($type == 1) {
1156  $text = img_object($langs->trans('Service'), 'service');
1157  } else {
1158  $text = img_object($langs->trans('Product'), 'product');
1159  }
1160 
1161  if (!empty($line->label)) {
1162  $text .= ' <strong>'.$line->label.'</strong>';
1163  print $form->textwithtooltip($text, $line->desc, 3, '', '', $i);
1164  } else {
1165  print $text.' '.nl2br($line->desc);
1166  }
1167 
1168  // Show range
1169  print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
1170  }
1171  print "</td>\n";
1172  }
1173 
1174  // Comment
1175  //$defaultcomment = 'Line create from order line id '.$line->id;
1176  $defaultcomment = $dispatchLines[$indiceAsked]['comment'];
1177  print '<td>';
1178  print '<input type="text" class="maxwidth100" name="comment'.$indiceAsked.'" value="'.$defaultcomment.'">';
1179  print '</td>';
1180 
1181  // Qty in source purchase order line
1182  print '<td class="center">';
1183  if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1184  print $line->qty;
1185  }
1186  print '<input type="hidden" name="fk_commandefournisseurdet'.$indiceAsked.'" value="'.$line->id.'">';
1187  print '<input type="hidden" name="pul'.$indiceAsked.'" value="'.$line->pu_ht.'">';
1188  print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
1189  print '</td>';
1190  $qtyProdCom = $line->qty;
1191 
1192  // Qty already received
1193  print '<td class="center">';
1194  $quantityDelivered = $objectsrc->receptions[$line->id];
1195  if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
1196  print $quantityDelivered;
1197  }
1198  print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
1199  print '</td>';
1200 
1201 
1202  if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1203  $quantityToBeDelivered = 0;
1204  } else {
1205  $quantityToBeDelivered = $dispatchLines[$indiceAsked]['qty'];
1206  }
1207  $warehouse_id = $dispatchLines[$indiceAsked]['ent'];
1208 
1209 
1210  $warehouseObject = null;
1211  if (isModEnabled('stock')) {
1212  // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1213  print '<!-- Case warehouse already known or product not a predefined product -->';
1214  if (array_key_exists($dispatchLines[$indiceAsked]['ent'], $product->stock_warehouse)) {
1215  $stock = +$product->stock_warehouse[$dispatchLines[$indiceAsked]['ent']]->real; // Convert to number
1216  }
1217  $deliverableQty = $dispatchLines[$indiceAsked]['qty'];
1218  $cost_price = $dispatchLines[$indiceAsked]['pu'];
1219 
1220  // Quantity to send
1221  print '<td class="center">';
1222  if ($line->product_type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
1223  if (GETPOST('qtyl'.$indiceAsked, 'int')) {
1224  $defaultqty = GETPOST('qtyl'.$indiceAsked, 'int');
1225  }
1226  print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1227  print '<input class="right" name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1228  } else {
1229  print $langs->trans("NA");
1230  }
1231  print '</td>';
1232 
1233  if (!empty($conf->global->STOCK_CALCULATE_ON_RECEPTION) || !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) {
1234  print '<td>';
1235  print '<input class="width75 right" name="cost_price'.$indiceAsked.'" id="cost_price'.$indiceAsked.'" value="'.$cost_price.'">';
1236  print '</td>';
1237  }
1238 
1239  // Stock
1240  if (isModEnabled('stock')) {
1241  print '<td class="left">';
1242  if ($line->product_type == Product::TYPE_PRODUCT || !empty($conf->global->STOCK_SUPPORTS_SERVICES)) { // Type of product need stock change ?
1243  // Show warehouse combo list
1244  $ent = "entl".$indiceAsked;
1245  $idl = "idl".$indiceAsked;
1246  $tmpentrepot_id = is_numeric(GETPOST($ent, 'int')) ?GETPOST($ent, 'int') : $warehouse_id;
1247  if ($line->fk_product > 0) {
1248  print '<!-- Show warehouse selection -->';
1249  print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 0, 0, $line->fk_product, '', 1);
1250  }
1251  } else {
1252  print $langs->trans("Service");
1253  }
1254  print '</td>';
1255  }
1256 
1257  if (isModEnabled('productbatch')) {
1258  if (!empty($product->status_batch)) {
1259  print '<td><input name="batch'.$indiceAsked.'" value="'.$dispatchLines[$indiceAsked]['lot'].'"></td>';
1260  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1261  print '<td class="nowraponall">';
1262  print $form->selectDate($dispatchLines[$indiceAsked]['DLC'], 'dlc'.$indiceAsked, '', '', 1, "");
1263  print '</td>';
1264  }
1265  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1266  print '<td class="nowraponall">';
1267  print $form->selectDate($dispatchLines[$indiceAsked]['DLUO'], 'dluo'.$indiceAsked, '', '', 1, "");
1268  print '</td>';
1269  }
1270  } else {
1271  print '<td colspan="3"></td>';
1272  }
1273  }
1274  }
1275 
1276  $arrayofpurchaselinealreadyoutput[$line->id] = $line->id;
1277 
1278  print "</tr>\n";
1279 
1280  // Display lines for extrafields of the Reception line
1281  // $line is a 'CommandeFournisseurLigne', $dispatchLines contains values of Reception lines so properties of CommandeFournisseurDispatch
1282  if (!empty($extrafields)) {
1283  $colspan = 5;
1284  if (isModEnabled('productbatch')) {
1285  $colspan += 2;
1286  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1287  $colspan += 1;
1288  }
1289  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1290  $colspan += 1;
1291  }
1292  }
1293  $recLine = new CommandeFournisseurDispatch($db);
1294 
1295  $srcLine = new CommandeFournisseurLigne($db);
1296  $srcLine->id = $line->id;
1297  $srcLine->fetch_optionals(); // fetch extrafields also available in orderline
1298 
1299  if (empty($recLine->array_options) && !empty($dispatchLines[$indiceAsked]['array_options'])) {
1300  $recLine->array_options = $dispatchLines[$indiceAsked]['array_options'];
1301  }
1302  $recLine->array_options = array_merge($recLine->array_options, $srcLine->array_options);
1303 
1304  print $recLine->showOptionals($extrafields, 'edit', array('style'=>'class="oddeven"', 'colspan'=>$colspan), $indiceAsked, '', 1);
1305  }
1306 
1307  $indiceAsked++;
1308  }
1309 
1310  print "</table>";
1311 
1312  print '<br>';
1313 
1314  print $form->buttonsSaveCancel("Create");
1315 
1316  print '</form>';
1317 
1318  print '<br>';
1319  } else {
1320  dol_print_error($db);
1321  }
1322  }
1323 } elseif ($id || $ref) {
1324  /* *************************************************************************** */
1325  /* */
1326  /* Edit and view mode */
1327  /* */
1328  /* *************************************************************************** */
1329  $lines = $object->lines;
1330 
1331  $num_prod = count($lines);
1332  $indiceAsked = 0;
1333  if ($object->id > 0) {
1334  if (!empty($object->origin) && $object->origin_id > 0) {
1335  $object->origin = 'CommandeFournisseur';
1336  $typeobject = $object->origin;
1337  $origin = $object->origin;
1338  $origin_id = $object->origin_id;
1339  $object->fetch_origin(); // Load property $object->commande, $object->propal, ...
1340  }
1341 
1342  $soc = new Societe($db);
1343  $soc->fetch($object->socid);
1344 
1345  $res = $object->fetch_optionals();
1346 
1347  $head = reception_prepare_head($object);
1348  print dol_get_fiche_head($head, 'reception', $langs->trans("Reception"), -1, 'dollyrevert');
1349 
1350  $formconfirm = '';
1351 
1352  // Confirm deleteion
1353  if ($action == 'delete') {
1354  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeleteReception'), $langs->trans("ConfirmDeleteReception", $object->ref), 'confirm_delete', '', 0, 1);
1355  }
1356 
1357  // Confirmation validation
1358  if ($action == 'valid') {
1359  $objectref = substr($object->ref, 1, 4);
1360  if ($objectref == 'PROV') {
1361  $numref = $object->getNextNumRef($soc);
1362  } else {
1363  $numref = $object->ref;
1364  }
1365 
1366  $text = $langs->trans("ConfirmValidateReception", $numref);
1367 
1368  if (isModEnabled('notification')) {
1369  require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
1370  $notify = new Notify($db);
1371  $text .= '<br>';
1372  $text .= $notify->confirmMessage('RECEPTION_VALIDATE', $object->socid, $object);
1373  }
1374 
1375  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateReception'), $text, 'confirm_valid', '', 0, 1);
1376  }
1377 
1378  // Confirm cancelation
1379  if ($action == 'annuler') {
1380  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelReception'), $langs->trans("ConfirmCancelReception", $object->ref), 'confirm_cancel', '', 0, 1);
1381  }
1382 
1383  if (!$formconfirm) {
1384  $parameters = array('formConfirm' => $formconfirm);
1385  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1386  if (empty($reshook)) {
1387  $formconfirm .= $hookmanager->resPrint;
1388  } elseif ($reshook > 0) {
1389  $formconfirm = $hookmanager->resPrint;
1390  }
1391  }
1392 
1393  // Print form confirm
1394  print $formconfirm;
1395 
1396 
1397  // Calculate totalWeight and totalVolume for all products
1398  // by adding weight and volume of each product line.
1399  $tmparray = $object->getTotalWeightVolume();
1400  $totalWeight = $tmparray['weight'];
1401  $totalVolume = $tmparray['volume'];
1402 
1403 
1404  if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
1405  $objectsrc = new Commande($db);
1406  $objectsrc->fetch($object->$typeobject->id);
1407  }
1408  if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
1409  $objectsrc = new Propal($db);
1410  $objectsrc->fetch($object->$typeobject->id);
1411  }
1412  if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("supplier_order")) {
1413  $objectsrc = new CommandeFournisseur($db);
1414  $objectsrc->fetch($object->$typeobject->id);
1415  }
1416  // Reception card
1417  $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1418  $morehtmlref = '<div class="refidno">';
1419  // Ref customer reception
1420 
1421  $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', 0, 1);
1422  $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', null, null, '', 1);
1423 
1424  // Thirdparty
1425  $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
1426  // Project
1427  if (isModEnabled('project')) {
1428  $langs->load("projects");
1429  $morehtmlref .= '<br>';
1430  if (0) { // Do not change on reception
1431  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1432  if ($action != 'classify' && $permissiontoadd) {
1433  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1434  }
1435  $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');
1436  } else {
1437  if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
1438  $proj = new Project($db);
1439  $proj->fetch($objectsrc->fk_project);
1440  $morehtmlref .= $proj->getNomUrl(1);
1441  if ($proj->title) {
1442  $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
1443  }
1444  }
1445  }
1446  }
1447  $morehtmlref .= '</div>';
1448 
1449  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1450 
1451 
1452  print '<div class="fichecenter">';
1453  print '<div class="fichehalfleft">';
1454  print '<div class="underbanner clearboth"></div>';
1455 
1456  print '<table class="border centpercent tableforfield">';
1457 
1458  // Linked documents
1459  if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
1460  print '<tr><td>';
1461  print $langs->trans("RefOrder").'</td>';
1462  print '<td colspan="3">';
1463  print $objectsrc->getNomUrl(1, 'commande');
1464  print "</td>\n";
1465  print '</tr>';
1466  }
1467  if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
1468  print '<tr><td>';
1469  print $langs->trans("RefProposal").'</td>';
1470  print '<td colspan="3">';
1471  print $objectsrc->getNomUrl(1, 'reception');
1472  print "</td>\n";
1473  print '</tr>';
1474  }
1475  if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("propal")) {
1476  print '<tr><td>';
1477  print $langs->trans("SupplierOrder").'</td>';
1478  print '<td colspan="3">';
1479  print $objectsrc->getNomUrl(1, 'reception');
1480  print "</td>\n";
1481  print '</tr>';
1482  }
1483 
1484  // Date creation
1485  print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1486  print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
1487  print '</tr>';
1488 
1489  // Delivery date planned
1490  print '<tr><td height="10">';
1491  print '<table class="nobordernopadding" width="100%"><tr><td>';
1492  print $langs->trans('DateDeliveryPlanned');
1493  print '</td>';
1494 
1495  if ($action != 'editdate_livraison') {
1496  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>';
1497  }
1498  print '</tr></table>';
1499  print '</td><td colspan="2">';
1500  if ($action == 'editdate_livraison') {
1501  print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1502  print '<input type="hidden" name="token" value="'.newToken().'">';
1503  print '<input type="hidden" name="action" value="setdate_livraison">';
1504  print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
1505  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1506  print '</form>';
1507  } else {
1508  print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
1509  }
1510  print '</td>';
1511  print '</tr>';
1512 
1513  // Weight
1514  print '<tr><td>';
1515  print $form->editfieldkey("Weight", 'trueWeight', $object->trueWeight, $object, $user->rights->reception->creer);
1516  print '</td><td colspan="3">';
1517 
1518  if ($action == 'edittrueWeight') {
1519  print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1520  print '<input name="action" value="settrueWeight" type="hidden">';
1521  print '<input name="id" value="'.$object->id.'" type="hidden">';
1522  print '<input type="hidden" name="token" value="'.newToken().'">';
1523  print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1524  print $formproduct->selectMeasuringUnits("weight_units", "weight", $object->weight_units, 0, 2);
1525  print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1526  print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1527  print '</form>';
1528  } else {
1529  print $object->trueWeight;
1530  print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : '';
1531  }
1532 
1533  // Calculated
1534  if ($totalWeight > 0) {
1535  if (!empty($object->trueWeight)) {
1536  print ' ('.$langs->trans("SumOfProductWeights").': ';
1537  }
1538  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');
1539  if (!empty($object->trueWeight)) {
1540  print ')';
1541  }
1542  }
1543  print '</td></tr>';
1544 
1545  // Width
1546  print '<tr><td>'.$form->editfieldkey("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1547  print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->reception->creer);
1548  print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : '';
1549  print '</td></tr>';
1550 
1551  // Height
1552  print '<tr><td>'.$form->editfieldkey("Height", 'trueHeight', $object->trueHeight, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1553  if ($action == 'edittrueHeight') {
1554  print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1555  print '<input name="action" value="settrueHeight" type="hidden">';
1556  print '<input name="id" value="'.$object->id.'" type="hidden">';
1557  print '<input type="hidden" name="token" value="'.newToken().'">';
1558  print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1559  print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
1560  print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1561  print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1562  print '</form>';
1563  } else {
1564  print $object->trueHeight;
1565  print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : '';
1566  }
1567 
1568  print '</td></tr>';
1569 
1570  // Depth
1571  print '<tr><td>'.$form->editfieldkey("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1572  print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->reception->creer);
1573  print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : '';
1574  print '</td></tr>';
1575 
1576  // Volume
1577  print '<tr><td>';
1578  print $langs->trans("Volume");
1579  print '</td>';
1580  print '<td colspan="3">';
1581  $calculatedVolume = 0;
1582  $volumeUnit = 0;
1583  if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
1584  $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
1585  $volumeUnit = $object->size_units * 3;
1586  }
1587  // If reception volume not defined we use sum of products
1588  if ($calculatedVolume > 0) {
1589  if ($volumeUnit < 50) {
1590  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');
1591  } else {
1592  print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit);
1593  }
1594  }
1595  if ($totalVolume > 0) {
1596  if ($calculatedVolume) {
1597  print ' ('.$langs->trans("SumOfProductVolumes").': ';
1598  }
1599  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');
1600  //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1601  if ($calculatedVolume) {
1602  print ')';
1603  }
1604  }
1605  print "</td>\n";
1606  print '</tr>';
1607 
1608  // Other attributes
1609  $cols = 2;
1610 
1611  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1612 
1613  print '</table>';
1614 
1615  print '</div>';
1616  print '<div class="fichehalfright">';
1617  print '<div class="underbanner clearboth"></div>';
1618 
1619  print '<table class="border centpercent tableforfield">';
1620 
1621  // Reception method
1622  print '<tr><td height="10">';
1623  print '<table class="nobordernopadding centpercent"><tr><td>';
1624  print $langs->trans('ReceptionMethod');
1625  print '</td>';
1626 
1627  if ($action != 'editshipping_method_id') {
1628  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>';
1629  }
1630  print '</tr></table>';
1631  print '</td><td colspan="2">';
1632  if ($action == 'editshipping_method_id') {
1633  print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1634  print '<input type="hidden" name="token" value="'.newToken().'">';
1635  print '<input type="hidden" name="action" value="setshipping_method_id">';
1636  $object->fetch_delivery_methods();
1637  print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1);
1638  if ($user->admin) {
1639  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1640  }
1641  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1642  print '</form>';
1643  } else {
1644  if ($object->shipping_method_id > 0) {
1645  // Get code using getLabelFromKey
1646  $code = $langs->getLabelFromKey($db, $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1647  print $langs->trans("SendingMethod".strtoupper($code));
1648  }
1649  }
1650  print '</td>';
1651  print '</tr>';
1652 
1653  // Tracking Number
1654  print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1655  print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->rights->reception->creer, 'safehtmlstring', $object->tracking_number);
1656  print '</td></tr>';
1657 
1658  // Incoterms
1659  if (isModEnabled('incoterm')) {
1660  print '<tr><td>';
1661  print '<table width="100%" class="nobordernopadding"><tr><td>';
1662  print $langs->trans('IncotermLabel');
1663  print '<td><td class="right">';
1664  if ($user->rights->reception->creer) {
1665  print '<a class="editfielda" href="'.DOL_URL_ROOT.'/reception/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
1666  } else {
1667  print '&nbsp;';
1668  }
1669  print '</td></tr></table>';
1670  print '</td>';
1671  print '<td colspan="3">';
1672  if ($action != 'editincoterm') {
1673  print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
1674  } else {
1675  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
1676  }
1677  print '</td></tr>';
1678  }
1679 
1680  print "</table>";
1681 
1682  print '</div>';
1683  print '</div>';
1684 
1685  print '<div class="clearboth"></div>';
1686 
1687 
1688  // Lines of products
1689  if ($action == 'editline') {
1690  print '<form name="updateline" id="updateline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;lineid='.$line_id.'" method="POST">
1691  <input type="hidden" name="token" value="' . newToken().'">
1692  <input type="hidden" name="action" value="updateline">
1693  <input type="hidden" name="mode" value="">
1694  <input type="hidden" name="id" value="' . $object->id.'">';
1695  }
1696  print '<br><br>';
1697 
1698  print '<div class="div-table-responsive-no-min">';
1699  print '<table id="tablelines" class="noborder centpercent">';
1700  print '<thead>';
1701  print '<tr class="liste_titre">';
1702  // #
1703  if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
1704  print '<td width="5" class="center">&nbsp;</td>';
1705  }
1706  // Product/Service
1707  print '<td>'.$langs->trans("Products").'</td>';
1708  // Comment
1709  print '<td>'.$langs->trans("Comment").'</td>';
1710  // Qty
1711  print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1712  if ($origin && $origin_id > 0) {
1713  print '<td class="center">'.$langs->trans("QtyInOtherReceptions").'</td>';
1714  }
1715  if ($action == 'editline') {
1716  $editColspan = 3;
1717  if (!isModEnabled('stock')) {
1718  $editColspan--;
1719  }
1720  if (empty($conf->productbatch->enabled)) {
1721  $editColspan--;
1722  }
1723  print '<td class="center" colspan="'.$editColspan.'">';
1724  if ($object->statut <= 1) {
1725  print $langs->trans("QtyToReceive").' - ';
1726  } else {
1727  print $langs->trans("QtyReceived").' - ';
1728  }
1729  if (isModEnabled('stock')) {
1730  print $langs->trans("WarehouseTarget").' - ';
1731  }
1732  if (isModEnabled('productbatch')) {
1733  print $langs->trans("Batch");
1734  }
1735  print '</td>';
1736  } else {
1737  $statusreceived = $object::STATUS_CLOSED;
1738  if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) {
1739  $statusreceived = $object::STATUS_VALIDATED;
1740  }
1741  if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) {
1742  $statusreceived = $object::STATUS_CLOSED;
1743  }
1744  if ($object->statut < $statusreceived) {
1745  print '<td class="center">'.$langs->trans("QtyToReceive").'</td>';
1746  } else {
1747  print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1748  }
1749  if (isModEnabled('stock')) {
1750  print '<td class="left">'.$langs->trans("WarehouseTarget").'</td>';
1751  }
1752 
1753  if (isModEnabled('productbatch')) {
1754  print '<td class="left">'.$langs->trans("Batch").'</td>';
1755  }
1756  }
1757  print '<td class="center">'.$langs->trans("CalculatedWeight").'</td>';
1758  print '<td class="center">'.$langs->trans("CalculatedVolume").'</td>';
1759  //print '<td class="center">'.$langs->trans("Size").'</td>';
1760  if ($object->statut == 0) {
1761  print '<td class="linecoledit"></td>';
1762  print '<td class="linecoldelete" width="10"></td>';
1763  }
1764  print "</tr>\n";
1765  print '</thead>';
1766 
1767  $var = false;
1768 
1769  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1770  $object->fetch_thirdparty();
1771  $outputlangs = $langs;
1772  $newlang = '';
1773  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1774  $newlang = GETPOST('lang_id', 'aZ09');
1775  }
1776  if (empty($newlang)) {
1777  $newlang = $object->thirdparty->default_lang;
1778  }
1779  if (!empty($newlang)) {
1780  $outputlangs = new Translate("", $conf);
1781  $outputlangs->setDefaultLang($newlang);
1782  }
1783  }
1784 
1785  // Get list of products already sent for same source object into $alreadysent
1786  $alreadysent = array();
1787 
1788  $origin = 'commande_fournisseur';
1789 
1790  if ($origin && $origin_id > 0) {
1791  $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";
1792  $sql .= ", ed.rowid as receptionline_id, ed.qty, ed.fk_reception as reception_id, ed.fk_entrepot";
1793  $sql .= ", e.rowid as reception_id, e.ref as reception_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_reception";
1794  //if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
1795  $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
1796  $sql .= ', p.description as product_desc';
1797  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
1798  $sql .= ", ".MAIN_DB_PREFIX."reception as e";
1799  $sql .= ", ".MAIN_DB_PREFIX.$origin."det as obj";
1800  //if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.fk_reception = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."deliverydet as ld ON ld.fk_delivery = l.rowid AND obj.rowid = ld.fk_origin_line";
1801  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
1802  $sql .= " WHERE e.entity IN (".getEntity('reception').")";
1803  $sql .= " AND obj.fk_commande = ".((int) $origin_id);
1804  $sql .= " AND obj.rowid = ed.fk_commandefourndet";
1805  $sql .= " AND ed.fk_reception = e.rowid";
1806  $sql .= " AND ed.fk_reception !=".((int) $object->id);
1807  //if ($filter) $sql.= $filter;
1808  $sql .= " ORDER BY obj.fk_product";
1809 
1810  dol_syslog("get list of reception lines", LOG_DEBUG);
1811  $resql = $db->query($sql);
1812  if ($resql) {
1813  $num = $db->num_rows($resql);
1814  $i = 0;
1815 
1816  while ($i < $num) {
1817  $obj = $db->fetch_object($resql);
1818  if ($obj) {
1819  // $obj->rowid is rowid in $origin."det" table
1820  $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);
1821  }
1822  $i++;
1823  }
1824  }
1825  //var_dump($alreadysent);
1826  }
1827 
1828  $arrayofpurchaselinealreadyoutput = array();
1829 
1830  // Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output)
1831  print '<tbody>';
1832  for ($i = 0; $i < $num_prod; $i++) {
1833  print '<!-- origin line id = '.(!empty($lines[$i]->origin_line_id) ? $lines[$i]->origin_line_id : 0).' -->'; // id of order line
1834  print '<tr class="oddeven" id="row-'.$lines[$i]->id.'" data-id="'.$lines[$i]->id.'" data-element="'.$lines[$i]->element.'">';
1835 
1836  // #
1837  if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
1838  print '<td class="center">'.($i + 1).'</td>';
1839  }
1840 
1841  // Predefined product or service
1842  if ($lines[$i]->fk_product > 0) {
1843  // Define output language
1844  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1845  $prod = new Product($db);
1846  $prod->fetch($lines[$i]->fk_product);
1847  $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product->label;
1848  } else {
1849  $label = (!empty($lines[$i]->product->label) ? $lines[$i]->product->label : $lines[$i]->product->product_label);
1850  }
1851 
1852  print '<td class="linecoldescription">';
1853  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1854  $text = $lines[$i]->product->getNomUrl(1);
1855  $text .= ' - '.$label;
1856  $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->product->description));
1857  print $form->textwithtooltip($text, $description, 3, '', '', $i);
1858  print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : 0, !empty($lines[$i]->date_end) ? $lines[$i]->date_end : 0);
1859  if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1860  print (!empty($lines[$i]->product->description) && $lines[$i]->description != $lines[$i]->product->description) ? '<br>'.dol_htmlentitiesbr($lines[$i]->description) : '';
1861  }
1862  }
1863  print "</td>\n";
1864  } else {
1865  print '<td class="linecoldescription">';
1866  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1867  if ($lines[$i]->product_type == Product::TYPE_SERVICE) {
1868  $text = img_object($langs->trans('Service'), 'service');
1869  } else {
1870  $text = img_object($langs->trans('Product'), 'product');
1871  }
1872 
1873  if (!empty($lines[$i]->label)) {
1874  $text .= ' <strong>'.$lines[$i]->label.'</strong>';
1875  print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i);
1876  } else {
1877  print $text.' '.nl2br($lines[$i]->description);
1878  }
1879 
1880  print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
1881  }
1882  print "</td>\n";
1883  }
1884 
1885  if ($action == 'editline' && $lines[$i]->id == $line_id) {
1886  print '<td><input name="comment'.$line_id.'" id="comment'.$line_id.'" value="'.dol_escape_htmltag($lines[$i]->comment).'"></td>';
1887  } else {
1888  print '<td style="white-space: pre-wrap; max-width: 200px;">'.dol_escape_htmltag($lines[$i]->comment).'</td>';
1889  }
1890 
1891 
1892  // Qty ordered
1893  print '<td class="center linecolqty">';
1894  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1895  print $lines[$i]->qty_asked;
1896  }
1897  print '</td>';
1898 
1899  // Qty in other receptions (with reception and warehouse used)
1900  if ($origin && $origin_id > 0) {
1901  print '<td class="center nowrap linecolqtyinotherreceptions">';
1902  $htmltooltip = '';
1903  $qtyalreadyreceived = 0;
1904  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1905  foreach ($alreadysent as $key => $val) {
1906  if ($lines[$i]->fk_commandefourndet == $key) {
1907  $j = 0;
1908  foreach ($val as $receptionline_id => $receptionline_var) {
1909  if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) {
1910  continue; // We want to show only "other receptions"
1911  }
1912 
1913  $j++;
1914  if ($j > 1) {
1915  $htmltooltip .= '<br>';
1916  }
1917  $reception_static->fetch($receptionline_var['reception_id']);
1918  $htmltooltip .= $reception_static->getNomUrl(1, 0, 0, 0, 1);
1919  $htmltooltip .= ' - '.$receptionline_var['qty'];
1920 
1921  $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour'));
1922  if (isModEnabled('stock') && $receptionline_var['warehouse'] > 0) {
1923  $warehousestatic->fetch($receptionline_var['warehouse']);
1924  $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
1925  }
1926  $htmltooltip .= ' '.$form->textwithpicto('', $htmltext, 1);
1927 
1928  $qtyalreadyreceived += $receptionline_var['qty'];
1929  }
1930  if ($j) {
1931  $htmltooltip = $langs->trans("QtyInOtherReceptions").'...<br><br>'.$htmltooltip.'<br><input type="submit" name="dummyhiddenbuttontogetfocus" style="display:none" autofocus>';
1932  }
1933  }
1934  }
1935  }
1936  print $form->textwithpicto($qtyalreadyreceived, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id);
1937  print '</td>';
1938  }
1939 
1940  if ($action == 'editline' && $lines[$i]->id == $line_id) {
1941  // edit mode
1942  print '<td colspan="'.$editColspan.'" class="center"><table class="nobordernopadding">';
1943  if (isModEnabled('stock')) {
1944  if ($lines[$i]->fk_product > 0) {
1945  print '<!-- case edit 1 -->';
1946  print '<tr>';
1947  // Qty to receive or received
1948  print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
1949  // Warehouse source
1950  print '<td>'.$formproduct->selectWarehouses($lines[$i]->fk_entrepot, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).'</td>';
1951  // Batch number managment
1952  if ($conf->productbatch->enabled && !empty($lines[$i]->product->status_batch)) {
1953  print '<td class="nowraponall left"><input name="batch'.$line_id.'" id="batch'.$line_id.'" type="text" value="'.$lines[$i]->batch.'"><br>';
1954  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1955  print $langs->trans('SellByDate').' : ';
1956  print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, '', '', 1, "").'</br>';
1957  }
1958  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1959  print $langs->trans('EatByDate').' : ';
1960  print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, '', '', 1, "");
1961  }
1962  print '</td>';
1963  }
1964  print '</tr>';
1965  } else {
1966  print '<!-- case edit 2 -->';
1967  print '<tr>';
1968  // Qty to receive or received
1969  print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
1970  // Warehouse source
1971  print '<td></td>';
1972  // Batch number managment
1973  print '<td></td>';
1974  print '</tr>';
1975  }
1976  }
1977  print '</table></td>';
1978  } else {
1979  // Qty to receive or received
1980  print '<td class="center linecolqtytoreceive">'.$lines[$i]->qty.'</td>';
1981 
1982  // Warehouse source
1983  if (isModEnabled('stock')) {
1984  if ($lines[$i]->fk_entrepot > 0) {
1985  $entrepot = new Entrepot($db);
1986  $entrepot->fetch($lines[$i]->fk_entrepot);
1987 
1988  print '<td class="left tdoverflowmax150" title="'.dol_escape_htmltag($entrepot->label).'">';
1989  print $entrepot->getNomUrl(1);
1990  print '</td>';
1991  } else {
1992  print '<td></td>';
1993  }
1994  }
1995 
1996  // Batch number managment
1997  if (isModEnabled('productbatch')) {
1998  if (isset($lines[$i]->batch)) {
1999  print '<!-- Detail of lot -->';
2000  print '<td class="linecolbatch nowrap">';
2001  $detail = $langs->trans("NA");
2002  if ($lines[$i]->product->status_batch > 0 && $lines[$i]->fk_product > 0) {
2003  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
2004  $productlot = new Productlot($db);
2005  $reslot = $productlot->fetch(0, $lines[$i]->fk_product, $lines[$i]->batch);
2006  if ($reslot > 0) {
2007  $detail = $productlot->getNomUrl(1);
2008  } else {
2009  // lot is not created and info is only in reception lines
2010  $batchinfo = $langs->trans("Batch").': '.$lines[$i]->batch;
2011  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
2012  $batchinfo .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($lines[$i]->sellby, "day");
2013  }
2014  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
2015  $batchinfo .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($lines[$i]->eatby, "day");
2016  }
2017  $detail = $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $batchinfo);
2018  }
2019  }
2020  print $detail . '</td>';
2021  } else {
2022  print '<td></td>';
2023  }
2024  }
2025  }
2026 
2027  // Weight
2028  print '<td class="center linecolweight">';
2029  if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2030  print $lines[$i]->product->weight * $lines[$i]->qty.' '.measuringUnitString(0, "weight", $lines[$i]->product->weight_units);
2031  } else {
2032  print '&nbsp;';
2033  }
2034  print '</td>';
2035 
2036  // Volume
2037  print '<td class="center linecolvolume">';
2038  if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
2039  print $lines[$i]->product->volume * $lines[$i]->qty.' '.measuringUnitString(0, "volume", $lines[$i]->product->volume_units);
2040  } else {
2041  print '&nbsp;';
2042  }
2043  print '</td>';
2044 
2045 
2046  if ($action == 'editline' && $lines[$i]->id == $line_id) {
2047  print '<td class="center valignmiddle" colspan="2">';
2048  print '<input type="submit" class="button small button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'"><br>';
2049  print '<input type="submit" class="button small button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'"><br>';
2050  print '</td>';
2051  } elseif ($object->statut == Reception::STATUS_DRAFT) {
2052  // edit-delete buttons
2053  print '<td class="linecoledit center">';
2054  print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_edit().'</a>';
2055  print '</td>';
2056  print '<td class="linecoldelete" width="10">';
2057  print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_delete().'</a>';
2058  print '</td>';
2059 
2060  // Display lines extrafields
2061  if (!empty($rowExtrafieldsStart)) {
2062  print $rowExtrafieldsStart;
2063  print $rowExtrafieldsView;
2064  print $rowEnd;
2065  }
2066  }
2067  print "</tr>";
2068 
2069  $arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet;
2070 
2071  // Display lines extrafields
2072  $extralabelslines = $extrafields->attributes[$lines[$i]->table_element];
2073  if (!empty($extralabelslines) && is_array($extralabelslines) && count($extralabelslines) > 0) {
2074  $colspan = 8;
2075  if (isModEnabled('stock')) { $colspan++; }
2076  if (isModEnabled('productbatch')) { $colspan++; }
2077 
2078  $line = new CommandeFournisseurDispatch($db);
2079  $line->id = $lines[$i]->id;
2080  $line->fetch_optionals();
2081 
2082  if ($action == 'editline' && $lines[$i]->id == $line_id) {
2083  print $line->showOptionals($extrafields, 'edit', array('colspan'=>$colspan), $indiceAsked);
2084  } else {
2085  print $line->showOptionals($extrafields, 'view', array('colspan'=>$colspan), $indiceAsked);
2086  }
2087  }
2088  }
2089  print '</tbody>';
2090 
2091  // TODO Show also lines ordered but not delivered
2092 
2093  print "</table>\n";
2094  print '</div>';
2095  }
2096 
2097 
2098  print dol_get_fiche_end();
2099 
2100 
2101  $object->fetchObjectLinked($object->id, $object->element);
2102 
2103 
2104  /*
2105  * Boutons actions
2106  */
2107 
2108  if (($user->socid == 0) && ($action != 'presend')) {
2109  print '<div class="tabsAction">';
2110 
2111  $parameters = array();
2112  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2113  if (empty($reshook)) {
2114  if ($object->statut == Reception::STATUS_DRAFT && $num_prod > 0) {
2115  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer))
2116  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate))) {
2117  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'">'.$langs->trans("Validate").'</a>';
2118  } else {
2119  print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2120  }
2121  }
2122  // Back to draft
2123  if ($object->statut == Reception::STATUS_VALIDATED && $user->rights->reception->creer) {
2124  print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('SetToDraft').'</a></div>';
2125  }
2126 
2127  // TODO add alternative status
2128  // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2129  if ($object->statut == Reception::STATUS_CLOSED && $user->rights->reception->creer) {
2130  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 ?
2131  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ClassifyUnbilled").'</a>';
2132  } else {
2133  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
2134  }
2135  }
2136 
2137  // Send
2138  if (empty($user->socid)) {
2139  if ($object->statut > 0) {
2140  if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->reception->reception_advance->send) {
2141  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
2142  } else {
2143  print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
2144  }
2145  }
2146  }
2147 
2148  // Create bill
2149  if (isModEnabled("supplier_invoice") && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) {
2150  if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer')) {
2151  // TODO show button only if (!empty($conf->global->WORKFLOW_BILL_ON_RECEPTION))
2152  // If we do that, we must also make this option official.
2153  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>';
2154  }
2155  }
2156 
2157 
2158  // Close
2159  if ($object->statut == Reception::STATUS_VALIDATED) {
2160  if ($user->rights->reception->creer && $object->statut > 0 && !$object->billed) {
2161  $label = "Close"; $paramaction = 'classifyclosed'; // = Transferred/Received
2162  // Label here should be "Close" or "ClassifyBilled" if we decided to make bill on receptions instead of orders
2163  if (isModEnabled("supplier_order") && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2164  $label = "ClassifyBilled";
2165  $paramaction = 'classifybilled';
2166  }
2167  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$paramaction.'&token='.newToken().'">'.$langs->trans($label).'</a>';
2168  }
2169  }
2170 
2171  if ($user->rights->reception->supprimer) {
2172  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
2173  }
2174  }
2175 
2176  print '</div>';
2177  }
2178 
2179 
2180  /*
2181  * Documents generated
2182  */
2183 
2184  if ($action != 'presend' && $action != 'editline') {
2185  print '<div class="fichecenter"><div class="fichehalfleft">';
2186 
2187  $objectref = dol_sanitizeFileName($object->ref);
2188  $filedir = $conf->reception->dir_output."/".$objectref;
2189 
2190  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2191 
2192  $genallowed = $user->rights->reception->lire;
2193  $delallowed = $user->rights->reception->creer;
2194 
2195  print $formfile->showdocuments('reception', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
2196 
2197  // Show links to link elements
2198  //$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
2199  $somethingshown = $form->showLinkedObjectBlock($object, '');
2200 
2201  print '</div><div class="fichehalfright">';
2202 
2203  print '</div></div>';
2204  }
2205 
2206  // Presend form
2207  $modelmail = 'shipping_send';
2208  $defaulttopic = 'SendReceptionRef';
2209  $diroutput = $conf->reception->dir_output;
2210  $trackid = 'rec'.$object->id;
2211 
2212  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2213 }
2214 
2215 
2216 llxFooter();
2217 
2218 $db->close();
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage table commandefournisseurdispatch.
Class to manage predefined suppliers products.
Class to manage line orders.
Class to manage customers orders.
Class to manage a WYSIWYG editor.
Class to manage warehouses.
Class to manage standard extra fields.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage building of HTML components.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
Class to manage notifications.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage proposals.
Class to manage receptions.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:48
$parameters
Actions.
Definition: card.php:83
if(isModEnabled('facture') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $sql
Social contributions to pay.
Definition: index.php:746
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
Definition: files.lib.php:1334
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0)
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
print_date_range($date_start, $date_end, $format='', $outputlangs='')
Format output for start and end date.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
$formconfirm
if ($action == 'delbookkeepingyear') {
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
reception_prepare_head(Reception $object)
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.