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