dolibarr  x.y.z
card.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4  * Copyright (C) 2005 Simon TOSSER <simon@kornog-computing.com>
5  * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
6  * Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
7  * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
8  * Copyright (C) 2013 Marcos García <marcosgdf@gmail.com>
9  * Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
10  * Copyright (C) 2014-2017 Francis Appels <francis.appels@yahoo.com>
11  * Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
12  * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
13  * Copyright (C) 2016 Yasser Carreón <yacasia@gmail.com>
14  * Copyright (C) 2018 Quentin Vial-Gouteyron <quentin.vial-gouteyron@atm-consulting.fr>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program. If not, see <https://www.gnu.org/licenses/>.
28  */
29 
36 // Load Dolibarr environment
37 require '../main.inc.php';
38 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
40 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
42 require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
43 require_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
44 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
45 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
46 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
47 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
48 if (isModEnabled("product") || isModEnabled("service")) {
49  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
50 }
51 if (isModEnabled("propal")) {
52  require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
53 }
54 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
55 require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
56 if (isModEnabled('productbatch')) {
57  require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
58 }
59 if (!empty($conf->project->enabled)) {
60  require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
61  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
62 }
63 
64 $langs->loadLangs(array("receptions", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal', 'sendings'));
65 
66 if (isModEnabled('incoterm')) {
67  $langs->load('incoterm');
68 }
69 if (isModEnabled('productbatch')) {
70  $langs->load('productbatch');
71 }
72 
73 $origin = GETPOST('origin', 'alpha') ?GETPOST('origin', 'alpha') : 'reception'; // Example: commande, propal
74 $origin_id = GETPOST('id', 'int') ? GETPOST('id', 'int') : '';
75 $id = $origin_id;
76 if (empty($origin_id)) {
77  $origin_id = GETPOST('origin_id', 'int'); // Id of order or propal
78 }
79 if (empty($origin_id)) {
80  $origin_id = GETPOST('object_id', 'int'); // Id of order or propal
81 }
82 if (empty($origin_id)) {
83  $origin_id = GETPOST('originid', 'int'); // Id of order or propal
84 }
85 $ref = GETPOST('ref', 'alpha');
86 $line_id = GETPOST('lineid', 'int') ?GETPOST('lineid', 'int') : '';
87 $facid = GETPOST('facid', 'int');
88 
89 $action = GETPOST('action', 'alpha');
90 //Select mail models is same action as presend
91 if (GETPOST('modelselected')) {
92  $action = 'presend';
93 }
94 $confirm = GETPOST('confirm', 'alpha');
95 $cancel = GETPOST('cancel', 'alpha');
96 
97 //PDF
98 $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
99 $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
100 $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
101 
102 $object = new Reception($db);
103 $objectorder = new CommandeFournisseur($db);
104 $extrafields = new ExtraFields($db);
105 
106 // fetch optionals attributes and labels
107 $extrafields->fetch_name_optionals_label($object->table_element);
108 $extrafields->fetch_name_optionals_label($object->table_element_line);
109 $extrafields->fetch_name_optionals_label($objectorder->table_element_line);
110 
111 // Load object. Make an object->fetch
112 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
113 
114 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
115 $hookmanager->initHooks(array('receptioncard', 'globalcard'));
116 
117 $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'));
118 
119 if ($id > 0 || !empty($ref)) {
120  $object->fetch($id, $ref);
121  $object->fetch_thirdparty();
122 
123  if (!empty($object->origin)) {
124  $origin = $object->origin;
125 
126  $object->fetch_origin();
127  $typeobject = $object->origin;
128  }
129 
130  // Linked documents
131  if ($origin == 'order_supplier' && $object->$typeobject->id && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order"))) {
132  $origin_id = $object->$typeobject->id;
133  $objectsrc = new CommandeFournisseur($db);
134  $objectsrc->fetch($object->$typeobject->id);
135  }
136 }
137 
138 // Security check
139 $socid = '';
140 if ($user->socid) {
141  $socid = $user->socid;
142 }
143 
144 if (isModEnabled("reception") || $origin == 'reception' || empty($origin)) {
145  $result = restrictedArea($user, 'reception', $id);
146 } else {
147  // We do not use the reception module, so we test permission on the supplier orders
148  if ($origin == 'supplierorder' || $origin == 'order_supplier') {
149  $result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande');
150  } elseif (empty($user->rights->{$origin}->lire) && empty($user->rights->{$origin}->read)) {
151  accessforbidden();
152  }
153 }
154 
155 if (isModEnabled("reception")) {
156  $permissiontoread = $user->rights->reception->lire;
157  $permissiontoadd = $user->rights->reception->creer;
158  $permissiondellink = $user->rights->reception->creer; // Used by the include of actions_dellink.inc.php
159  $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)));
160  $permissiontodelete = $user->rights->reception->supprimer;
161 } else {
162  $permissiontoread = $user->rights->fournisseur->commande->receptionner;
163  $permissiontoadd = $user->rights->fournisseur->commande->receptionner;
164  $permissiondellink = $user->rights->fournisseur->commande->receptionner; // Used by the include of actions_dellink.inc.php
165  $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)));
166  $permissiontodelete = $user->rights->fournisseur->commande->receptionner;
167 }
168 
169 
170 /*
171  * Actions
172  */
173 
174 $parameters = array();
175 $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
176 if ($reshook < 0) {
177  setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
178 }
179 
180 if (empty($reshook)) {
181  if ($cancel) {
182  $action = '';
183  }
184 
185  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
186 
187  // Reopen
188  if ($action == 'reopen' && $permissiontoadd) {
189  $result = $object->reOpen();
190  }
191 
192  // Confirm back to draft status
193  if ($action == 'modif' && $permissiontoadd) {
194  $result = $object->setDraft($user);
195  if ($result >= 0) {
196  // Define output language
197  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
198  $outputlangs = $langs;
199  $newlang = '';
200  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
201  $newlang = GETPOST('lang_id', 'aZ09');
202  }
203  if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
204  $newlang = $object->thirdparty->default_lang;
205  }
206  if (!empty($newlang)) {
207  $outputlangs = new Translate("", $conf);
208  $outputlangs->setDefaultLang($newlang);
209  }
210  $model = $object->model_pdf;
211  $ret = $object->fetch($id); // Reload to get new records
212  $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
213  }
214  } else {
215  setEventMessages($object->error, $object->errors, 'errors');
216  }
217  }
218 
219  // Set incoterm
220  if ($action == 'set_incoterms' && isModEnabled('incoterm') && $permissiontoadd) {
221  $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
222  }
223 
224  if ($action == 'setref_supplier' && $permissiontoadd) {
225  if ($result < 0) {
226  setEventMessages($object->error, $object->errors, 'errors');
227  }
228 
229  $result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'RECEPTION_MODIFY');
230  if ($result < 0) {
231  setEventMessages($object->error, $object->errors, 'errors');
232  $action = 'editref_supplier';
233  } else {
234  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
235  exit;
236  }
237  }
238 
239  if ($action == 'update_extras' && $permissiontoadd) {
240  $object->oldcopy = dol_clone($object);
241 
242  // Fill array 'array_options' with data from update form
243  $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
244  if ($ret < 0) {
245  $error++;
246  }
247 
248  if (!$error) {
249  // Actions on extra fields
250  $result = $object->insertExtraFields('RECEPTION_MODIFY');
251  if ($result < 0) {
252  setEventMessages($object->error, $object->errors, 'errors');
253  $error++;
254  }
255  }
256 
257  if ($error) {
258  $action = 'edit_extras';
259  }
260  }
261 
262  // Create reception
263  if ($action == 'add' && $permissiontoadd) {
264  $error = 0;
265  $predef = '';
266 
267  $db->begin();
268 
269  $object->note = GETPOST('note', 'alpha');
270  $object->origin = $origin;
271  $object->origin_id = $origin_id;
272  $object->fk_project = GETPOST('projectid', 'int');
273  $object->weight = GETPOST('weight', 'int') == '' ? null : GETPOST('weight', 'int');
274  $object->trueHeight = GETPOST('trueHeight', 'int') == '' ? null : GETPOST('trueHeight', 'int');
275  $object->trueWidth = GETPOST('trueWidth', 'int') == '' ? null : GETPOST('trueWidth', 'int');
276  $object->trueDepth = GETPOST('trueDepth', 'int') == '' ? null : GETPOST('trueDepth', 'int');
277  $object->size_units = GETPOST('size_units', 'int');
278  $object->weight_units = GETPOST('weight_units', 'int');
279 
280  // On va boucler sur chaque ligne du document d'origine pour completer objet reception
281  // avec info diverses + qte a livrer
282 
283  if ($object->origin == "supplierorder") {
284  $classname = 'CommandeFournisseur';
285  } else {
286  $classname = ucfirst($object->origin);
287  }
288  $objectsrc = new $classname($db);
289  $objectsrc->fetch($object->origin_id);
290 
291  $object->socid = $objectsrc->socid;
292  $object->ref_supplier = GETPOST('ref_supplier', 'alpha');
293  $object->model_pdf = GETPOST('model');
294  $object->date_delivery = $date_delivery; // Date delivery planed
295  $object->fk_delivery_address = $objectsrc->fk_delivery_address;
296  $object->shipping_method_id = GETPOST('shipping_method_id', 'int');
297  $object->tracking_number = GETPOST('tracking_number', 'alpha');
298  $object->note_private = GETPOST('note_private', 'restricthtml');
299  $object->note_public = GETPOST('note_public', 'restricthtml');
300  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
301  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
302 
303  $batch_line = array();
304  $stockLine = array();
305  $array_options = array();
306 
307  $totalqty = 0;
308 
309  $num = 0;
310  foreach ($_POST as $key => $value) {
311  // without batch module enabled
312 
313  if (strpos($key, 'qtyasked') !== false) {
314  $num++;
315  }
316  }
317 
318  for ($i = 1; $i <= $num; $i++) {
319  $idl = "idl".$i;
320 
321  $sub_qty = array();
322  $subtotalqty = 0;
323 
324  $j = 0;
325  $batch = "batchl".$i."_0";
326  $stockLocation = "ent1".$i."_0";
327  $qty = "qtyl".$i;
328 
329  //reception line for product with no batch management and no multiple stock location
330  if (GETPOST($qty, 'alpha') > 0) {
331  $totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
332  }
333 
334  // Extrafields
335  $array_options[$i] = $extrafields->getOptionalsFromPost($object->table_element_line, $i);
336  }
337 
338 
339  if ($totalqty > 0) { // There is at least one thing to ship
340  for ($i = 1; $i <= $num; $i++) {
341  $lineToTest = '';
342  $lineId = GETPOST($idl, 'int');
343  foreach ($objectsrc->lines as $linesrc) {
344  if ($linesrc->id == $lineId) {
345  $lineToTest = $linesrc;
346  break;
347  }
348  }
349  if (empty($lineToTest)) {
350  continue;
351  }
352  $qty = "qtyl".$i;
353  $comment = "comment".$i;
354  // EATBY <-> DLUO see productbatch.class.php
355  // SELLBY <-> DLC
356  $eatby = "dluo".$i;
357  $sellby = "dlc".$i;
358  $batch = "batch".$i;
359  $cost_price = "cost_price".$i;
360 
361  //if (GETPOST($qty, 'int') > 0 || (GETPOST($qty, 'int') == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS')) || (GETPOST($qty, 'int') < 0 && getDolGlobalString('RECEPTION_ALLOW_NEGATIVE_QTY'))) {
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 (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
440  $newlang = GETPOST('lang_id', 'aZ09');
441  }
442  if (getDolGlobalInt('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 (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
535  $newlang = GETPOST('lang_id', 'aZ09');
536  }
537  if (getDolGlobalInt('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 (isModEnabled('productbatch')) {
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 (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang) && GETPOST('lang_id', 'aZ09')) {
670  $newlang = GETPOST('lang_id', 'aZ09');
671  }
672  if (getDolGlobalInt('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 (isModEnabled('stock')) {
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' && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order"))) {
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' && isModEnabled("propal")) {
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 (isModEnabled('incoterm')) {
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 (isModEnabled('stock')) {
1042  print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1043  }
1044  if (isModEnabled('productbatch')) {
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 = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : 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 (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
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 (isModEnabled('stock')) { // 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 (isModEnabled('stock')) {
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 (isModEnabled('productbatch')) {
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  $colspan = 5;
1246  if (isModEnabled('productbatch')) {
1247  $colspan += 2;
1248  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1249  $colspan += 1;
1250  }
1251  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1252  $colspan += 1;
1253  }
1254  }
1255  $recLine = new CommandeFournisseurDispatch($db);
1256 
1257  $srcLine = new CommandeFournisseurLigne($db);
1258  $srcLine->id = $line->id;
1259  $srcLine->fetch_optionals(); // fetch extrafields also available in orderline
1260 
1261  if (empty($recLine->array_options) && !empty($dispatchLines[$indiceAsked]['array_options'])) {
1262  $recLine->array_options = $dispatchLines[$indiceAsked]['array_options'];
1263  }
1264  $recLine->array_options = array_merge($recLine->array_options, $srcLine->array_options);
1265 
1266  print $recLine->showOptionals($extrafields, 'edit', array('style'=>'class="oddeven"', 'colspan'=>$colspan), $indiceAsked, '', 1);
1267  }
1268 
1269  $indiceAsked++;
1270  }
1271 
1272  print "</table>";
1273 
1274  print '<br>';
1275 
1276  print $form->buttonsSaveCancel("Create");
1277 
1278  print '</form>';
1279 
1280  print '<br>';
1281  } else {
1282  dol_print_error($db);
1283  }
1284  }
1285 } elseif ($id || $ref) {
1286  /* *************************************************************************** */
1287  /* */
1288  /* Edit and view mode */
1289  /* */
1290  /* *************************************************************************** */
1291  $lines = $object->lines;
1292 
1293  $num_prod = count($lines);
1294  $indiceAsked = 0;
1295  if ($object->id > 0) {
1296  if (!empty($object->origin) && $object->origin_id > 0) {
1297  $object->origin = 'CommandeFournisseur';
1298  $typeobject = $object->origin;
1299  $origin = $object->origin;
1300  $origin_id = $object->origin_id;
1301  $object->fetch_origin(); // Load property $object->commande, $object->propal, ...
1302  }
1303 
1304  $soc = new Societe($db);
1305  $soc->fetch($object->socid);
1306 
1307  $res = $object->fetch_optionals();
1308 
1309  $head = reception_prepare_head($object);
1310  print dol_get_fiche_head($head, 'reception', $langs->trans("Reception"), -1, 'dollyrevert');
1311 
1312  $formconfirm = '';
1313 
1314  // Confirm deleteion
1315  if ($action == 'delete') {
1316  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeleteReception'), $langs->trans("ConfirmDeleteReception", $object->ref), 'confirm_delete', '', 0, 1);
1317  }
1318 
1319  // Confirmation validation
1320  if ($action == 'valid') {
1321  $objectref = substr($object->ref, 1, 4);
1322  if ($objectref == 'PROV') {
1323  $numref = $object->getNextNumRef($soc);
1324  } else {
1325  $numref = $object->ref;
1326  }
1327 
1328  $text = $langs->trans("ConfirmValidateReception", $numref);
1329 
1330  if (isModEnabled('notification')) {
1331  require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
1332  $notify = new Notify($db);
1333  $text .= '<br>';
1334  $text .= $notify->confirmMessage('RECEPTION_VALIDATE', $object->socid, $object);
1335  }
1336 
1337  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateReception'), $text, 'confirm_valid', '', 0, 1);
1338  }
1339 
1340  // Confirm cancelation
1341  if ($action == 'annuler') {
1342  $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelReception'), $langs->trans("ConfirmCancelReception", $object->ref), 'confirm_cancel', '', 0, 1);
1343  }
1344 
1345  if (!$formconfirm) {
1346  $parameters = array('formConfirm' => $formconfirm);
1347  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1348  if (empty($reshook)) {
1349  $formconfirm .= $hookmanager->resPrint;
1350  } elseif ($reshook > 0) {
1351  $formconfirm = $hookmanager->resPrint;
1352  }
1353  }
1354 
1355  // Print form confirm
1356  print $formconfirm;
1357 
1358 
1359  // Calculate totalWeight and totalVolume for all products
1360  // by adding weight and volume of each product line.
1361  $tmparray = $object->getTotalWeightVolume();
1362  $totalWeight = $tmparray['weight'];
1363  $totalVolume = $tmparray['volume'];
1364 
1365 
1366  if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
1367  $objectsrc = new Commande($db);
1368  $objectsrc->fetch($object->$typeobject->id);
1369  }
1370  if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
1371  $objectsrc = new Propal($db);
1372  $objectsrc->fetch($object->$typeobject->id);
1373  }
1374  if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order"))) {
1375  $objectsrc = new CommandeFournisseur($db);
1376  $objectsrc->fetch($object->$typeobject->id);
1377  }
1378  // Reception card
1379  $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
1380  $morehtmlref = '<div class="refidno">';
1381  // Ref customer reception
1382 
1383  $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', 0, 1);
1384  $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', null, null, '', 1);
1385 
1386  // Thirdparty
1387  $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
1388  // Project
1389  if (!empty($conf->project->enabled)) {
1390  $langs->load("projects");
1391  $morehtmlref .= '<br>';
1392  if (0) { // Do not change on reception
1393  $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
1394  if ($action != 'classify' && $permissiontoadd) {
1395  $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
1396  }
1397  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, ($action == 'classify' ? 1 : 0), 0, 1, '');
1398  } else {
1399  if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
1400  $proj = new Project($db);
1401  $proj->fetch($objectsrc->fk_project);
1402  $morehtmlref .= $proj->getNomUrl(1);
1403  if ($proj->title) {
1404  $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
1405  }
1406  }
1407  }
1408  }
1409  $morehtmlref .= '</div>';
1410 
1411  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1412 
1413 
1414  print '<div class="fichecenter">';
1415  print '<div class="fichehalfleft">';
1416  print '<div class="underbanner clearboth"></div>';
1417 
1418  print '<table class="border centpercent tableforfield">';
1419 
1420  // Linked documents
1421  if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) {
1422  print '<tr><td>';
1423  print $langs->trans("RefOrder").'</td>';
1424  print '<td colspan="3">';
1425  print $objectsrc->getNomUrl(1, 'commande');
1426  print "</td>\n";
1427  print '</tr>';
1428  }
1429  if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) {
1430  print '<tr><td>';
1431  print $langs->trans("RefProposal").'</td>';
1432  print '<td colspan="3">';
1433  print $objectsrc->getNomUrl(1, 'reception');
1434  print "</td>\n";
1435  print '</tr>';
1436  }
1437  if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("propal")) {
1438  print '<tr><td>';
1439  print $langs->trans("SupplierOrder").'</td>';
1440  print '<td colspan="3">';
1441  print $objectsrc->getNomUrl(1, 'reception');
1442  print "</td>\n";
1443  print '</tr>';
1444  }
1445 
1446  // Date creation
1447  print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1448  print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
1449  print '</tr>';
1450 
1451  // Delivery date planned
1452  print '<tr><td height="10">';
1453  print '<table class="nobordernopadding" width="100%"><tr><td>';
1454  print $langs->trans('DateDeliveryPlanned');
1455  print '</td>';
1456 
1457  if ($action != 'editdate_livraison') {
1458  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>';
1459  }
1460  print '</tr></table>';
1461  print '</td><td colspan="2">';
1462  if ($action == 'editdate_livraison') {
1463  print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1464  print '<input type="hidden" name="token" value="'.newToken().'">';
1465  print '<input type="hidden" name="action" value="setdate_livraison">';
1466  print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, '', "setdate_livraison", 1, 0);
1467  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1468  print '</form>';
1469  } else {
1470  print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
1471  }
1472  print '</td>';
1473  print '</tr>';
1474 
1475  // Weight
1476  print '<tr><td>';
1477  print $form->editfieldkey("Weight", 'trueWeight', $object->trueWeight, $object, $user->rights->reception->creer);
1478  print '</td><td colspan="3">';
1479 
1480  if ($action == 'edittrueWeight') {
1481  print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1482  print '<input name="action" value="settrueWeight" type="hidden">';
1483  print '<input name="id" value="'.$object->id.'" type="hidden">';
1484  print '<input type="hidden" name="token" value="'.newToken().'">';
1485  print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1486  print $formproduct->selectMeasuringUnits("weight_units", "weight", $object->weight_units, 0, 2);
1487  print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1488  print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1489  print '</form>';
1490  } else {
1491  print $object->trueWeight;
1492  print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : '';
1493  }
1494 
1495  // Calculated
1496  if ($totalWeight > 0) {
1497  if (!empty($object->trueWeight)) {
1498  print ' ('.$langs->trans("SumOfProductWeights").': ';
1499  }
1500  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');
1501  if (!empty($object->trueWeight)) {
1502  print ')';
1503  }
1504  }
1505  print '</td></tr>';
1506 
1507  // Width
1508  print '<tr><td>'.$form->editfieldkey("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1509  print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->rights->reception->creer);
1510  print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : '';
1511  print '</td></tr>';
1512 
1513  // Height
1514  print '<tr><td>'.$form->editfieldkey("Height", 'trueHeight', $object->trueHeight, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1515  if ($action == 'edittrueHeight') {
1516  print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1517  print '<input name="action" value="settrueHeight" type="hidden">';
1518  print '<input name="id" value="'.$object->id.'" type="hidden">';
1519  print '<input type="hidden" name="token" value="'.newToken().'">';
1520  print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1521  print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
1522  print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1523  print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1524  print '</form>';
1525  } else {
1526  print $object->trueHeight;
1527  print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : '';
1528  }
1529 
1530  print '</td></tr>';
1531 
1532  // Depth
1533  print '<tr><td>'.$form->editfieldkey("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1534  print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->rights->reception->creer);
1535  print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : '';
1536  print '</td></tr>';
1537 
1538  // Volume
1539  print '<tr><td>';
1540  print $langs->trans("Volume");
1541  print '</td>';
1542  print '<td colspan="3">';
1543  $calculatedVolume = 0;
1544  $volumeUnit = 0;
1545  if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
1546  $calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
1547  $volumeUnit = $object->size_units * 3;
1548  }
1549  // If reception volume not defined we use sum of products
1550  if ($calculatedVolume > 0) {
1551  if ($volumeUnit < 50) {
1552  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');
1553  } else {
1554  print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit);
1555  }
1556  }
1557  if ($totalVolume > 0) {
1558  if ($calculatedVolume) {
1559  print ' ('.$langs->trans("SumOfProductVolumes").': ';
1560  }
1561  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');
1562  //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1563  if ($calculatedVolume) {
1564  print ')';
1565  }
1566  }
1567  print "</td>\n";
1568  print '</tr>';
1569 
1570  // Other attributes
1571  $cols = 2;
1572 
1573  include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1574 
1575  print '</table>';
1576 
1577  print '</div>';
1578  print '<div class="fichehalfright">';
1579  print '<div class="underbanner clearboth"></div>';
1580 
1581  print '<table class="border centpercent tableforfield">';
1582 
1583  // Reception method
1584  print '<tr><td height="10">';
1585  print '<table class="nobordernopadding centpercent"><tr><td>';
1586  print $langs->trans('ReceptionMethod');
1587  print '</td>';
1588 
1589  if ($action != 'editshipping_method_id') {
1590  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>';
1591  }
1592  print '</tr></table>';
1593  print '</td><td colspan="2">';
1594  if ($action == 'editshipping_method_id') {
1595  print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1596  print '<input type="hidden" name="token" value="'.newToken().'">';
1597  print '<input type="hidden" name="action" value="setshipping_method_id">';
1598  $object->fetch_delivery_methods();
1599  print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1);
1600  if ($user->admin) {
1601  print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
1602  }
1603  print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
1604  print '</form>';
1605  } else {
1606  if ($object->shipping_method_id > 0) {
1607  // Get code using getLabelFromKey
1608  $code = $langs->getLabelFromKey($db, $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
1609  print $langs->trans("SendingMethod".strtoupper($code));
1610  }
1611  }
1612  print '</td>';
1613  print '</tr>';
1614 
1615  // Tracking Number
1616  print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->rights->reception->creer).'</td><td colspan="3">';
1617  print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->rights->reception->creer, 'safehtmlstring', $object->tracking_number);
1618  print '</td></tr>';
1619 
1620  // Incoterms
1621  if (isModEnabled('incoterm')) {
1622  print '<tr><td>';
1623  print '<table width="100%" class="nobordernopadding"><tr><td>';
1624  print $langs->trans('IncotermLabel');
1625  print '<td><td class="right">';
1626  if ($user->rights->reception->creer) {
1627  print '<a class="editfielda" href="'.DOL_URL_ROOT.'/reception/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
1628  } else {
1629  print '&nbsp;';
1630  }
1631  print '</td></tr></table>';
1632  print '</td>';
1633  print '<td colspan="3">';
1634  if ($action != 'editincoterm') {
1635  print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
1636  } else {
1637  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
1638  }
1639  print '</td></tr>';
1640  }
1641 
1642  print "</table>";
1643 
1644  print '</div>';
1645  print '</div>';
1646 
1647  print '<div class="clearboth"></div>';
1648 
1649 
1650  // Lines of products
1651  if ($action == 'editline') {
1652  print '<form name="updateline" id="updateline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;lineid='.$line_id.'" method="POST">
1653  <input type="hidden" name="token" value="' . newToken().'">
1654  <input type="hidden" name="action" value="updateline">
1655  <input type="hidden" name="mode" value="">
1656  <input type="hidden" name="id" value="' . $object->id.'">';
1657  }
1658  print '<br>';
1659 
1660  print '<div class="div-table-responsive-no-min">';
1661  print '<table id="tablelines" class="noborder centpercent">';
1662  print '<thead>';
1663  print '<tr class="liste_titre">';
1664  // #
1665  if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
1666  print '<td width="5" class="center">&nbsp;</td>';
1667  }
1668  // Product/Service
1669  print '<td>'.$langs->trans("Products").'</td>';
1670  // Comment
1671  print '<td>'.$langs->trans("Comment").'</td>';
1672  // Qty
1673  print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
1674  if ($origin && $origin_id > 0) {
1675  print '<td class="center">'.$langs->trans("QtyInOtherReceptions").'</td>';
1676  }
1677  if ($action == 'editline') {
1678  $editColspan = 3;
1679  if (!isModEnabled('stock')) {
1680  $editColspan--;
1681  }
1682  if (empty($conf->productbatch->enabled)) {
1683  $editColspan--;
1684  }
1685  print '<td class="center" colspan="'.$editColspan.'">';
1686  if ($object->statut <= 1) {
1687  print $langs->trans("QtyToReceive").' - ';
1688  } else {
1689  print $langs->trans("QtyReceived").' - ';
1690  }
1691  if (isModEnabled('stock')) {
1692  print $langs->trans("WarehouseSource").' - ';
1693  }
1694  if (isModEnabled('productbatch')) {
1695  print $langs->trans("Batch");
1696  }
1697  print '</td>';
1698  } else {
1699  $statusreceived = $object::STATUS_CLOSED;
1700  if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) {
1701  $statusreceived = $object::STATUS_VALIDATED;
1702  }
1703  if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) {
1704  $statusreceived = $object::STATUS_CLOSED;
1705  }
1706  if ($object->statut < $statusreceived) {
1707  print '<td class="center">'.$langs->trans("QtyToReceive").'</td>';
1708  } else {
1709  print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
1710  }
1711  if (isModEnabled('stock')) {
1712  print '<td class="left">'.$langs->trans("WarehouseSource").'</td>';
1713  }
1714 
1715  if (isModEnabled('productbatch')) {
1716  print '<td class="left">'.$langs->trans("Batch").'</td>';
1717  }
1718  }
1719  print '<td class="center">'.$langs->trans("CalculatedWeight").'</td>';
1720  print '<td class="center">'.$langs->trans("CalculatedVolume").'</td>';
1721  //print '<td class="center">'.$langs->trans("Size").'</td>';
1722  if ($object->statut == 0) {
1723  print '<td class="linecoledit"></td>';
1724  print '<td class="linecoldelete" width="10"></td>';
1725  }
1726  print "</tr>\n";
1727  print '</thead>';
1728 
1729  $var = false;
1730 
1731  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1732  $object->fetch_thirdparty();
1733  $outputlangs = $langs;
1734  $newlang = '';
1735  if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
1736  $newlang = GETPOST('lang_id', 'aZ09');
1737  }
1738  if (empty($newlang)) {
1739  $newlang = $object->thirdparty->default_lang;
1740  }
1741  if (!empty($newlang)) {
1742  $outputlangs = new Translate("", $conf);
1743  $outputlangs->setDefaultLang($newlang);
1744  }
1745  }
1746 
1747  // Get list of products already sent for same source object into $alreadysent
1748  $alreadysent = array();
1749 
1750  $origin = 'commande_fournisseur';
1751 
1752  if ($origin && $origin_id > 0) {
1753  $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";
1754  $sql .= ", ed.rowid as receptionline_id, ed.qty, ed.fk_reception as reception_id, ed.fk_entrepot";
1755  $sql .= ", e.rowid as reception_id, e.ref as reception_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_reception";
1756  //if ($conf->delivery_note->enabled) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
1757  $sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
1758  $sql .= ', p.description as product_desc';
1759  $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as ed";
1760  $sql .= ", ".MAIN_DB_PREFIX."reception as e";
1761  $sql .= ", ".MAIN_DB_PREFIX.$origin."det as obj";
1762  //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";
1763  $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
1764  $sql .= " WHERE e.entity IN (".getEntity('reception').")";
1765  $sql .= " AND obj.fk_commande = ".((int) $origin_id);
1766  $sql .= " AND obj.rowid = ed.fk_commandefourndet";
1767  $sql .= " AND ed.fk_reception = e.rowid";
1768  $sql .= " AND ed.fk_reception !=".((int) $object->id);
1769  //if ($filter) $sql.= $filter;
1770  $sql .= " ORDER BY obj.fk_product";
1771 
1772  dol_syslog("get list of reception lines", LOG_DEBUG);
1773  $resql = $db->query($sql);
1774  if ($resql) {
1775  $num = $db->num_rows($resql);
1776  $i = 0;
1777 
1778  while ($i < $num) {
1779  $obj = $db->fetch_object($resql);
1780  if ($obj) {
1781  // $obj->rowid is rowid in $origin."det" table
1782  $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);
1783  }
1784  $i++;
1785  }
1786  }
1787  //var_dump($alreadysent);
1788  }
1789 
1790  $arrayofpurchaselinealreadyoutput = array();
1791 
1792  // Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output)
1793  print '<tbody>';
1794  for ($i = 0; $i < $num_prod; $i++) {
1795  print '<!-- origin line id = '.(!empty($lines[$i]->origin_line_id) ? $lines[$i]->origin_line_id : 0).' -->'; // id of order line
1796  print '<tr class="oddeven" id="row-'.$lines[$i]->id.'" data-id="'.$lines[$i]->id.'" data-element="'.$lines[$i]->element.'">';
1797 
1798  // #
1799  if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
1800  print '<td class="center">'.($i + 1).'</td>';
1801  }
1802 
1803  // Predefined product or service
1804  if ($lines[$i]->fk_product > 0) {
1805  // Define output language
1806  if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
1807  $prod = new Product($db);
1808  $prod->fetch($lines[$i]->fk_product);
1809  $label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product->label;
1810  } else {
1811  $label = (!empty($lines[$i]->product->label) ? $lines[$i]->product->label : $lines[$i]->product->product_label);
1812  }
1813 
1814  print '<td class="linecoldescription">';
1815  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1816  $text = $lines[$i]->product->getNomUrl(1);
1817  $text .= ' - '.$label;
1818  $description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->product->description));
1819  print $form->textwithtooltip($text, $description, 3, '', '', $i);
1820  print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : 0, !empty($lines[$i]->date_end) ? $lines[$i]->date_end : 0);
1821  if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
1822  print (!empty($lines[$i]->product->description) && $lines[$i]->description != $lines[$i]->product->description) ? '<br>'.dol_htmlentitiesbr($lines[$i]->description) : '';
1823  }
1824  }
1825  print "</td>\n";
1826  } else {
1827  print '<td class="linecoldescription">';
1828  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1829  if ($lines[$i]->product_type == Product::TYPE_SERVICE) {
1830  $text = img_object($langs->trans('Service'), 'service');
1831  } else {
1832  $text = img_object($langs->trans('Product'), 'product');
1833  }
1834 
1835  if (!empty($lines[$i]->label)) {
1836  $text .= ' <strong>'.$lines[$i]->label.'</strong>';
1837  print $form->textwithtooltip($text, $lines[$i]->description, 3, '', '', $i);
1838  } else {
1839  print $text.' '.nl2br($lines[$i]->description);
1840  }
1841 
1842  print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
1843  }
1844  print "</td>\n";
1845  }
1846 
1847  if ($action == 'editline' && $lines[$i]->id == $line_id) {
1848  print '<td><input name="comment'.$line_id.'" id="comment'.$line_id.'" value="'.dol_escape_htmltag($lines[$i]->comment).'"></td>';
1849  } else {
1850  print '<td style="white-space: pre-wrap; max-width: 200px;">'.dol_escape_htmltag($lines[$i]->comment).'</td>';
1851  }
1852 
1853 
1854  // Qty ordered
1855  print '<td class="center linecolqty">';
1856  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1857  print $lines[$i]->qty_asked;
1858  }
1859  print '</td>';
1860 
1861  // Qty in other receptions (with reception and warehouse used)
1862  if ($origin && $origin_id > 0) {
1863  print '<td class="center nowrap linecolqtyinotherreceptions">';
1864  if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
1865  foreach ($alreadysent as $key => $val) {
1866  if ($lines[$i]->fk_commandefourndet == $key) {
1867  $j = 0;
1868  foreach ($val as $receptionline_id => $receptionline_var) {
1869  if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) {
1870  continue; // We want to show only "other receptions"
1871  }
1872 
1873  $j++;
1874  if ($j > 1) {
1875  print '<br>';
1876  }
1877  $reception_static->fetch($receptionline_var['reception_id']);
1878  print $reception_static->getNomUrl(1);
1879  print ' - '.$receptionline_var['qty'];
1880 
1881  $htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour'));
1882  if (isModEnabled('stock') && $receptionline_var['warehouse'] > 0) {
1883  $warehousestatic->fetch($receptionline_var['warehouse']);
1884  $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
1885  }
1886  print ' '.$form->textwithpicto('', $htmltext, 1);
1887  }
1888  }
1889  }
1890  }
1891  }
1892  print '</td>';
1893 
1894  if ($action == 'editline' && $lines[$i]->id == $line_id) {
1895  // edit mode
1896  print '<td colspan="'.$editColspan.'" class="center"><table class="nobordernopadding">';
1897  if (isModEnabled('stock')) {
1898  if ($lines[$i]->fk_product > 0) {
1899  print '<!-- case edit 1 -->';
1900  print '<tr>';
1901  // Qty to receive or received
1902  print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
1903  // Warehouse source
1904  print '<td>'.$formproduct->selectWarehouses($lines[$i]->fk_entrepot, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).'</td>';
1905  // Batch number managment
1906  if ($conf->productbatch->enabled && !empty($lines[$i]->product->status_batch)) {
1907  print '<td class="nowraponall"><input name="batch'.$line_id.'" id="batch'.$line_id.'" type="text" value="'.$lines[$i]->batch.'"><br>';
1908  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1909  print $langs->trans('SellByDate').' : ';
1910  print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, '', '', 1, "").'</br>';
1911  }
1912  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1913  print $langs->trans('EatByDate').' : ';
1914  print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, '', '', 1, "");
1915  }
1916  print '</td>';
1917  }
1918  print '</tr>';
1919  } else {
1920  print '<!-- case edit 2 -->';
1921  print '<tr>';
1922  // Qty to receive or received
1923  print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
1924  // Warehouse source
1925  print '<td></td>';
1926  // Batch number managment
1927  print '<td></td>';
1928  print '</tr>';
1929  }
1930  }
1931  print '</table></td>';
1932  } else {
1933  // Qty to receive or received
1934  print '<td class="center linecolqtytoreceive">'.$lines[$i]->qty.'</td>';
1935 
1936  // Warehouse source
1937  if (isModEnabled('stock')) {
1938  if ($lines[$i]->fk_entrepot > 0) {
1939  $entrepot = new Entrepot($db);
1940  $entrepot->fetch($lines[$i]->fk_entrepot);
1941 
1942  print '<td class="left tdoverflowmax150" title="'.dol_escape_htmltag($entrepot->label).'">';
1943  print $entrepot->getNomUrl(1);
1944  print '</td>';
1945  } else {
1946  print '<td></td>';
1947  }
1948  }
1949 
1950  // Batch number managment
1951  if (isModEnabled('productbatch')) {
1952  if (isset($lines[$i]->batch)) {
1953  print '<!-- Detail of lot -->';
1954  print '<td class="linecolbatch nowrap">';
1955  $detail = $langs->trans("NA");
1956  if ($lines[$i]->product->status_batch && $lines[$i]->fk_product > 0) {
1957  require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
1958  $productlot = new Productlot($db);
1959  $reslot = $productlot->fetch(0, $lines[$i]->fk_product, $lines[$i]->batch);
1960  if ($reslot > 0) {
1961  $detail = $productlot->getNomUrl(1);
1962  } else {
1963  // lot is not created and info is only in reception lines
1964  $batchinfo = $langs->trans("Batch").': '.$lines[$i]->batch;
1965  if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) {
1966  $batchinfo .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($lines[$i]->sellby, "day");
1967  }
1968  if (empty($conf->global->PRODUCT_DISABLE_EATBY)) {
1969  $batchinfo .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($lines[$i]->eatby, "day");
1970  }
1971  $detail = $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $batchinfo);
1972  }
1973  }
1974  print $detail . '</td>';
1975  } else {
1976  print '<td></td>';
1977  }
1978  }
1979  }
1980 
1981  // Weight
1982  print '<td class="center linecolweight">';
1983  if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
1984  print $lines[$i]->product->weight * $lines[$i]->qty.' '.measuringUnitString(0, "weight", $lines[$i]->product->weight_units);
1985  } else {
1986  print '&nbsp;';
1987  }
1988  print '</td>';
1989 
1990  // Volume
1991  print '<td class="center linecolvolume">';
1992  if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
1993  print $lines[$i]->product->volume * $lines[$i]->qty.' '.measuringUnitString(0, "volume", $lines[$i]->product->volume_units);
1994  } else {
1995  print '&nbsp;';
1996  }
1997  print '</td>';
1998 
1999 
2000  if ($action == 'editline' && $lines[$i]->id == $line_id) {
2001  print '<td class="center" colspan="2" valign="middle">';
2002  print '<input type="submit" class="button button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'"><br>';
2003  print '<input type="submit" class="button button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'"><br>';
2004  } elseif ($object->statut == Reception::STATUS_DRAFT) {
2005  // edit-delete buttons
2006  print '<td class="linecoledit center">';
2007  print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_edit().'</a>';
2008  print '</td>';
2009  print '<td class="linecoldelete" width="10">';
2010  print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_delete().'</a>';
2011  print '</td>';
2012 
2013  // Display lines extrafields
2014  if (!empty($rowExtrafieldsStart)) {
2015  print $rowExtrafieldsStart;
2016  print $rowExtrafieldsView;
2017  print $rowEnd;
2018  }
2019  }
2020  print "</tr>";
2021 
2022  $arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet;
2023 
2024  // Display lines extrafields
2025  $extralabelslines = $extrafields->attributes[$lines[$i]->table_element];
2026  if (!empty($extralabelslines) && is_array($extralabelslines) && count($extralabelslines) > 0) {
2027  $colspan = empty($conf->productbatch->enabled) ? 8 : 9;
2028  $line = new CommandeFournisseurDispatch($db);
2029  $line->id = $lines[$i]->id;
2030  $line->fetch_optionals();
2031 
2032  if ($action == 'editline' && $lines[$i]->id == $line_id) {
2033  print $line->showOptionals($extrafields, 'edit', array('colspan'=>$colspan), $indiceAsked);
2034  } else {
2035  print $line->showOptionals($extrafields, 'view', array('colspan'=>$colspan), $indiceAsked);
2036  }
2037  }
2038  }
2039  print '</tbody>';
2040 
2041  // TODO Show also lines ordered but not delivered
2042 
2043  print "</table>\n";
2044  print '</div>';
2045  }
2046 
2047 
2048  print dol_get_fiche_end();
2049 
2050 
2051  $object->fetchObjectLinked($object->id, $object->element);
2052 
2053 
2054  /*
2055  * Boutons actions
2056  */
2057 
2058  if (($user->socid == 0) && ($action != 'presend')) {
2059  print '<div class="tabsAction">';
2060 
2061  $parameters = array();
2062  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
2063  if (empty($reshook)) {
2064  if ($object->statut == Reception::STATUS_DRAFT && $num_prod > 0) {
2065  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer))
2066  || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate))) {
2067  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'">'.$langs->trans("Validate").'</a>';
2068  } else {
2069  print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2070  }
2071  }
2072  // Back to draft
2073  if ($object->statut == Reception::STATUS_VALIDATED && $user->rights->reception->creer) {
2074  print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('SetToDraft').'</a></div>';
2075  }
2076 
2077  // TODO add alternative status
2078  // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2079  if ($object->statut == Reception::STATUS_CLOSED && $user->rights->reception->creer) {
2080  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 ?
2081  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ClassifyUnbilled").'</a>';
2082  } else {
2083  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
2084  }
2085  }
2086 
2087  // Send
2088  if (empty($user->socid)) {
2089  if ($object->statut > 0) {
2090  if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->reception->reception_advance->send) {
2091  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
2092  } else {
2093  print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
2094  }
2095  }
2096  }
2097 
2098  // Create bill
2099  if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_invoice")) && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) {
2100  if ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer) {
2101  // TODO show button only if (!empty($conf->global->WORKFLOW_BILL_ON_RECEPTION))
2102  // If we do that, we must also make this option official.
2103  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>';
2104  }
2105  }
2106 
2107 
2108  // Close
2109  if ($object->statut == Reception::STATUS_VALIDATED) {
2110  if ($user->rights->reception->creer && $object->statut > 0 && !$object->billed) {
2111  $label = "Close"; $paramaction = 'classifyclosed'; // = Transferred/Received
2112  // Label here should be "Close" or "ClassifyBilled" if we decided to make bill on receptions instead of orders
2113  if (((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)) || isModEnabled("supplier_order")) && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2114  $label = "ClassifyBilled";
2115  $paramaction = 'classifybilled';
2116  }
2117  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$paramaction.'&token='.newToken().'">'.$langs->trans($label).'</a>';
2118  }
2119  }
2120 
2121  if ($user->rights->reception->supprimer) {
2122  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
2123  }
2124  }
2125 
2126  print '</div>';
2127  }
2128 
2129 
2130  /*
2131  * Documents generated
2132  */
2133 
2134  if ($action != 'presend' && $action != 'editline') {
2135  print '<div class="fichecenter"><div class="fichehalfleft">';
2136 
2137  $objectref = dol_sanitizeFileName($object->ref);
2138  $filedir = $conf->reception->dir_output."/".$objectref;
2139 
2140  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2141 
2142  $genallowed = $user->rights->reception->lire;
2143  $delallowed = $user->rights->reception->creer;
2144 
2145  print $formfile->showdocuments('reception', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
2146 
2147  // Show links to link elements
2148  //$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
2149  $somethingshown = $form->showLinkedObjectBlock($object, '');
2150 
2151  print '</div><div class="fichehalfright">';
2152 
2153  print '</div></div>';
2154  }
2155 
2156  // Presend form
2157  $modelmail = 'shipping_send';
2158  $defaulttopic = 'SendReceptionRef';
2159  $diroutput = $conf->reception->dir_output;
2160  $trackid = 'rec'.$object->id;
2161 
2162  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2163 }
2164 
2165 
2166 llxFooter();
2167 
2168 $db->close();
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:56
llxFooter()
Empty footer.
Definition: wrapper.php:70
Class to manage table commandefournisseurdispatch.
Class to manage predefined suppliers products.
Class to manage line orders.
Class to manage customers orders.
Class to manage a WYSIWYG editor.
Class to manage warehouses.
Class to manage standard extra fields.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage building of HTML components.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
Class to manage notifications.
Class to manage products or services.
const TYPE_PRODUCT
Regular product.
const TYPE_SERVICE
Service.
Class with list of lots and properties.
Class to manage projects.
Class to manage proposals.
Class to manage receptions.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage translations.
Class to manage Dolibarr users.
Definition: user.class.php:45
$parameters
Actions.
Definition: card.php:79
if(isModEnabled('facture') &&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur') &&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') &&!empty($user->rights->don->lire)) if(isModEnabled('tax') &&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture') &&isModEnabled('commande') && $user->hasRight("commande", "lire") &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:745
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:143
print *****$script_file(".$version.") pid cd cd cd description as description
Only used if Module[ID]Desc translation string is not found.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
Definition: files.lib.php:1250
dol_banner_tab($object, $paramid, $morehtml='', $shownav=1, $fieldid='rowid', $fieldref='ref', $morehtmlref='', $moreparam='', $nodbprefix=0, $morehtmlleft='', $morehtmlstatus='', $onlybanner=0, $morehtmlright='')
Show tab footer of a card.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='')
Show tabs of a record.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
dol_get_fiche_end($notab=0)
Return tab footer of a card.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no', $use_short_label=0)
Output a dimension with best unit.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for each properties) With native =...
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
print_date_range($date_start, $date_end, $format='', $outputlangs='')
Format output for start and end date.
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom='UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
isModEnabled($module)
Is Dolibarr module enabled.
img_edit($titlealt='default', $float=0, $other='')
Show logo editer/modifier fiche.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
$formconfirm
if ($action == 'delbookkeepingyear') {
measuringUnitString($unit, $measuring_style='', $scale='', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
reception_prepare_head(Reception $object)
Prepare array with list of tabs.
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.