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