dolibarr  7.0.0-beta
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  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 3 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program. If not, see <http://www.gnu.org/licenses/>.
27  */
28 
35 require '../main.inc.php';
36 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
37 require_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php';
38 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
39 require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
40 require_once DOL_DOCUMENT_ROOT.'/core/lib/sendings.lib.php';
41 require_once DOL_DOCUMENT_ROOT.'/core/modules/expedition/modules_expedition.php';
42 require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
43 require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
44 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
45 require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
46 if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
47 if (! empty($conf->propal->enabled)) require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
48 if (! empty($conf->commande->enabled)) require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
49 if (! empty($conf->productbatch->enabled)) require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
50 if (! empty($conf->projet->enabled)) {
51  require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
52  require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
53 }
54 
55 $langs->loadLangs(array("sendings","companies","bills",'deliveries','orders','stocks','other','propal'));
56 
57 if (!empty($conf->incoterm->enabled)) $langs->load('incoterm');
58 if (! empty($conf->productbatch->enabled)) $langs->load('productbatch');
59 
60 $origin = GETPOST('origin','alpha')?GETPOST('origin','alpha'):'expedition'; // Example: commande, propal
61 $origin_id = GETPOST('id','int')?GETPOST('id','int'):'';
62 $id = $origin_id;
63 if (empty($origin_id)) $origin_id = GETPOST('origin_id','int'); // Id of order or propal
64 if (empty($origin_id)) $origin_id = GETPOST('object_id','int'); // Id of order or propal
65 $ref=GETPOST('ref','alpha');
66 $line_id = GETPOST('lineid','int')?GETPOST('lineid','int'):'';
67 
68 // Security check
69 $socid='';
70 if ($user->societe_id) $socid=$user->societe_id;
71 
72 if ($origin == 'expedition') $result=restrictedArea($user, $origin, $id);
73 else {
74  $result=restrictedArea($user, 'expedition');
75  if (empty($user->rights->{$origin}->lire) && empty($user->rights->{$origin}->read)) accessforbidden();
76 }
77 
78 $action = GETPOST('action','alpha');
79 $confirm = GETPOST('confirm','alpha');
80 $cancel = GETPOST('cancel','alpha');
81 
82 //PDF
83 $hidedetails = (GETPOST('hidedetails','int') ? GETPOST('hidedetails','int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
84 $hidedesc = (GETPOST('hidedesc','int') ? GETPOST('hidedesc','int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
85 $hideref = (GETPOST('hideref','int') ? GETPOST('hideref','int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
86 
87 $object = new Expedition($db);
88 $extrafields = new ExtraFields($db);
89 $extrafieldsline = new ExtraFields($db);
90 
91 // fetch optionals attributes and labels
92 $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
93 
94 // fetch optionals attributes lines and labels
95 $extralabelslines=$extrafieldsline->fetch_name_optionals_label($object->table_element_line);
96 
97 
98 // Load object. Make an object->fetch
99 include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once
100 
101 // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
102 $hookmanager->initHooks(array('expeditioncard','globalcard'));
103 
104 $permissiondellink=$user->rights->expedition->livraison->creer; // Used by the include of actions_dellink.inc.php
105 //var_dump($object->lines[0]->detail_batch);
106 
107 
108 /*
109  * Actions
110  */
111 
112 $parameters=array();
113 $reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks
114 if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
115 
116 if (empty($reshook))
117 {
118  if ($cancel)
119  {
120  $action = '';
121  $object->fetch($id); // show shipment also after canceling modification
122  }
123 
124  include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
125 
126  // Reopen
127  if ($action == 'reopen' && $user->rights->expedition->creer)
128  {
129  $object->fetch($id);
130  $result = $object->reOpen();
131  }
132 
133  // Set incoterm
134  if ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
135  {
136  $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
137  }
138 
139  if ($action == 'setref_customer')
140  {
141  $result = $object->fetch($id);
142  if ($result < 0) {
143  setEventMessages($object->error, $object->errors, 'errors');
144  }
145 
146  $result = $object->setValueFrom('ref_customer', GETPOST('ref_customer','alpha'), '', null, 'text', '', $user, 'SHIPMENT_MODIFY');
147  if ($result < 0) {
148  setEventMessages($object->error, $object->errors, 'errors');
149  $action = 'editref_customer';
150  } else {
151  header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
152  exit;
153  }
154  }
155 
156  if ($action == 'update_extras')
157  {
158  // Fill array 'array_options' with data from update form
159  $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
160  $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute'));
161  if ($ret < 0) $error++;
162 
163  if (! $error)
164  {
165  // Actions on extra fields (by external module or standard code)
166  // TODO le hook fait double emploi avec le trigger !!
167  $hookmanager->initHooks(array('expeditiondao'));
168  $parameters = array('id' => $object->id);
169  $reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
170  if (empty($reshook)) {
171  $result = $object->insertExtraFields();
172  if ($result < 0)
173  {
174  setEventMessages($object->error, $object->errors, 'errors');
175  $error++;
176  }
177  } else if ($reshook < 0)
178  $error++;
179  }
180 
181  if ($error)
182  $action = 'edit_extras';
183  }
184 
185  // Create shipment
186  if ($action == 'add' && $user->rights->expedition->creer)
187  {
188  $error=0;
189  $predef='';
190 
191  $db->begin();
192 
193  $object->note = GETPOST('note','alpha');
194  $object->origin = $origin;
195  $object->origin_id = $origin_id;
196  $object->fk_project = GETPOST('projectid','int');
197  $object->weight = GETPOST('weight','int')==''?"NULL":GETPOST('weight','int');
198  $object->sizeH = GETPOST('sizeH','int')==''?"NULL":GETPOST('sizeH','int');
199  $object->sizeW = GETPOST('sizeW','int')==''?"NULL":GETPOST('sizeW','int');
200  $object->sizeS = GETPOST('sizeS','int')==''?"NULL":GETPOST('sizeS','int');
201  $object->size_units = GETPOST('size_units','int');
202  $object->weight_units = GETPOST('weight_units','int');
203 
204  $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'));
205 
206  // On va boucler sur chaque ligne du document d'origine pour completer objet expedition
207  // avec info diverses + qte a livrer
208  $classname = ucfirst($object->origin);
209  $objectsrc = new $classname($db);
210  $objectsrc->fetch($object->origin_id);
211 
212  $object->socid = $objectsrc->socid;
213  $object->ref_customer = GETPOST('ref_customer','alpha');
214  $object->model_pdf = GETPOST('model');
215  $object->date_delivery = $date_delivery; // Date delivery planed
216  $object->fk_delivery_address = $objectsrc->fk_delivery_address;
217  $object->shipping_method_id = GETPOST('shipping_method_id','int');
218  $object->tracking_number = GETPOST('tracking_number','alpha');
219  $object->ref_int = GETPOST('ref_int','alpha');
220  $object->note_private = GETPOST('note_private','none');
221  $object->note_public = GETPOST('note_public','none');
222  $object->fk_incoterms = GETPOST('incoterm_id', 'int');
223  $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
224 
225  $batch_line = array();
226  $stockLine = array();
227  $array_options=array();
228 
229  $num=count($objectsrc->lines);
230  $totalqty=0;
231 
232  for ($i = 0; $i < $num; $i++)
233  {
234  $idl="idl".$i;
235 
236  $sub_qty=array();
237  $subtotalqty=0;
238 
239  $j=0;
240  $batch="batchl".$i."_0";
241  $stockLocation="ent1".$i."_0";
242  $qty = "qtyl".$i;
243 
244  if ($objectsrc->lines[$i]->product_tobatch) // If product need a batch number
245  {
246  if (isset($_POST[$batch]))
247  {
248  //shipment line with batch-enable product
249  $qty .= '_'.$j;
250  while (isset($_POST[$batch]))
251  {
252  // save line of detail into sub_qty
253  $sub_qty[$j]['q']=GETPOST($qty,'int'); // the qty we want to move for this stock record
254  $sub_qty[$j]['id_batch']=GETPOST($batch,'int'); // the id into llx_product_batch of stock record to move
255  $subtotalqty+=$sub_qty[$j]['q'];
256 
257  //var_dump($qty);var_dump($batch);var_dump($sub_qty[$j]['q']);var_dump($sub_qty[$j]['id_batch']);
258 
259  $j++;
260  $batch="batchl".$i."_".$j;
261  $qty = "qtyl".$i.'_'.$j;
262  }
263 
264  $batch_line[$i]['detail']=$sub_qty; // array of details
265  $batch_line[$i]['qty']=$subtotalqty;
266  $batch_line[$i]['ix_l']=GETPOST($idl,'int');
267 
268  $totalqty+=$subtotalqty;
269  }
270  else
271  {
272  // No detail were provided for lots
273  if (! empty($_POST[$qty]))
274  {
275  // We try to set an amount
276  // Case we dont use the list of available qty for each warehouse/lot
277  // GUI does not allow this yet
278  setEventMessage('StockIsRequiredToChooseWhichLotToUse', 'errors');
279  }
280  }
281  }
282  else if (isset($_POST[$stockLocation]))
283  {
284  //shipment line from multiple stock locations
285  $qty .= '_'.$j;
286  while (isset($_POST[$stockLocation]))
287  {
288  // save sub line of warehouse
289  $stockLine[$i][$j]['qty']=GETPOST($qty,'int');
290  $stockLine[$i][$j]['warehouse_id']=GETPOST($stockLocation,'int');
291  $stockLine[$i][$j]['ix_l']=GETPOST($idl,'int');
292 
293  $totalqty+=GETPOST($qty,'int');
294 
295  $j++;
296  $stockLocation="ent1".$i."_".$j;
297  $qty = "qtyl".$i.'_'.$j;
298  }
299  }
300  else
301  {
302  //var_dump(GETPOST($qty,'int')); var_dump($_POST); var_dump($batch);exit;
303  //shipment line for product with no batch management and no multiple stock location
304  if (GETPOST($qty,'int') > 0) $totalqty+=GETPOST($qty,'int');
305  }
306 
307  // Extrafields
308  $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
309  $array_options[$i] = $extrafieldsline->getOptionalsFromPost($extralabelsline, $i);
310  // Unset extrafield
311  if (is_array($extralabelsline)) {
312  // Get extra fields
313  foreach ($extralabelsline as $key => $value) {
314  unset($_POST["options_" . $key]);
315  }
316  }
317 
318  }
319 
320  //var_dump($batch_line[2]);
321 
322  if ($totalqty > 0) // There is at least one thing to ship
323  {
324  //var_dump($_POST);exit;
325  for ($i = 0; $i < $num; $i++)
326  {
327  $qty = "qtyl".$i;
328  if (! isset($batch_line[$i]))
329  {
330  // not batch mode
331  if (isset($stockLine[$i]))
332  {
333  //shipment from multiple stock locations
334  $nbstockline = count($stockLine[$i]);
335  for($j = 0; $j < $nbstockline; $j++)
336  {
337  if ($stockLine[$i][$j]['qty']>0)
338  {
339  $ret=$object->addline($stockLine[$i][$j]['warehouse_id'], $stockLine[$i][$j]['ix_l'], $stockLine[$i][$j]['qty'], $array_options[$i]);
340  if ($ret < 0)
341  {
342  setEventMessages($object->error, $object->errors, 'errors');
343  $error++;
344  }
345  }
346  }
347  }
348  else
349  {
350  if (GETPOST($qty,'int') > 0 || (GETPOST($qty,'int') == 0 && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS))
351  {
352  $ent = "entl".$i;
353  $idl = "idl".$i;
354  $entrepot_id = is_numeric(GETPOST($ent,'int'))?GETPOST($ent,'int'):GETPOST('entrepot_id','int');
355  if ($entrepot_id < 0) $entrepot_id='';
356  if (! ($objectsrc->lines[$i]->fk_product > 0)) $entrepot_id = 0;
357 
358  $ret=$object->addline($entrepot_id, GETPOST($idl,'int'), GETPOST($qty,'int'), $array_options[$i]);
359  if ($ret < 0)
360  {
361  setEventMessages($object->error, $object->errors, 'errors');
362  $error++;
363  }
364  }
365  }
366  }
367  else
368  {
369  // batch mode
370  if ($batch_line[$i]['qty']>0)
371  {
372  $ret=$object->addline_batch($batch_line[$i],$array_options[$i]);
373  if ($ret < 0)
374  {
375  setEventMessages($object->error, $object->errors, 'errors');
376  $error++;
377  }
378  }
379  }
380  }
381  // Fill array 'array_options' with data from add form
382  $ret = $extrafields->setOptionalsFromPost($extralabels, $object);
383  if ($ret < 0) $error++;
384 
385  if (! $error)
386  {
387  $ret=$object->create($user); // This create shipment (like Odoo picking) and line of shipments. Stock movement will when validating shipment.
388  if ($ret <= 0)
389  {
390  setEventMessages($object->error, $object->errors, 'errors');
391  $error++;
392  }
393  }
394  }
395  else
396  {
397  setEventMessages($langs->trans("ErrorFieldRequired",$langs->transnoentitiesnoconv("QtyToShip").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
398  $error++;
399  }
400 
401  if (! $error)
402  {
403  $db->commit();
404  header("Location: card.php?id=".$object->id);
405  exit;
406  }
407  else
408  {
409  $db->rollback();
410  $_GET["commande_id"]=GETPOST('commande_id','int');
411  $action='create';
412  }
413  }
414 
415  /*
416  * Build a receiving receipt
417  */
418  else if ($action == 'create_delivery' && $conf->livraison_bon->enabled && $user->rights->expedition->livraison->creer)
419  {
420  $result = $object->create_delivery($user);
421  if ($result > 0)
422  {
423  header("Location: ".DOL_URL_ROOT.'/livraison/card.php?action=create_delivery&id='.$result);
424  exit;
425  }
426  else
427  {
428  setEventMessages($object->error, $object->errors, 'errors');
429  }
430  }
431 
432  else if ($action == 'confirm_valid' && $confirm == 'yes' &&
433  ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
434  || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate)))
435  )
436  {
437  $object->fetch_thirdparty();
438 
439  $result = $object->valid($user);
440 
441  if ($result < 0)
442  {
443  $langs->load("errors");
444  setEventMessages($langs->trans($object->error), null, 'errors');
445  }
446  else
447  {
448  // Define output language
449  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
450  {
451  $outputlangs = $langs;
452  $newlang = '';
453  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
454  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
455  if (! empty($newlang)) {
456  $outputlangs = new Translate("", $conf);
457  $outputlangs->setDefaultLang($newlang);
458  }
459  $model=$object->modelpdf;
460  $ret = $object->fetch($id); // Reload to get new records
461 
462  $result=$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
463  if ($result < 0) dol_print_error($db,$result);
464  }
465  }
466  }
467 
468  else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->expedition->supprimer)
469  {
470  $result = $object->delete();
471  if ($result > 0)
472  {
473  header("Location: ".DOL_URL_ROOT.'/expedition/index.php');
474  exit;
475  }
476  else
477  {
478  setEventMessages($object->error, $object->errors, 'errors');
479  }
480  }
481  // TODO add alternative status
482  /*else if ($action == 'reopen' && (! empty($user->rights->expedition->creer) || ! empty($user->rights->expedition->shipping_advance->validate)))
483  {
484  $result = $object->setStatut(0);
485  if ($result < 0)
486  {
487  setEventMessages($object->error, $object->errors, 'errors');
488  }
489  }*/
490 
491  else if ($action == 'setdate_livraison' && $user->rights->expedition->creer)
492  {
493  //print "x ".$_POST['liv_month'].", ".$_POST['liv_day'].", ".$_POST['liv_year'];
494  $datedelivery=dol_mktime(GETPOST('liv_hour','int'), GETPOST('liv_min','int'), 0, GETPOST('liv_month','int'), GETPOST('liv_day','int'), GETPOST('liv_year','int'));
495 
496  $object->fetch($id);
497  $result=$object->set_date_livraison($user,$datedelivery);
498  if ($result < 0)
499  {
500  setEventMessages($object->error, $object->errors, 'errors');
501  }
502  }
503 
504  // Action update
505  else if ($action == 'settracking_number' || $action == 'settracking_url'
506  || $action == 'settrueWeight'
507  || $action == 'settrueWidth'
508  || $action == 'settrueHeight'
509  || $action == 'settrueDepth'
510  || $action == 'setshipping_method_id')
511  {
512  $error=0;
513 
514  if ($action == 'settracking_number') $object->tracking_number = trim(GETPOST('tracking_number','alpha'));
515  if ($action == 'settracking_url') $object->tracking_url = trim(GETPOST('tracking_url','int'));
516  if ($action == 'settrueWeight') {
517  $object->trueWeight = trim(GETPOST('trueWeight','int'));
518  $object->weight_units = GETPOST('weight_units','int');
519  }
520  if ($action == 'settrueWidth') $object->trueWidth = trim(GETPOST('trueWidth','int'));
521  if ($action == 'settrueHeight'){
522  $object->trueHeight = trim(GETPOST('trueHeight','int'));
523  $object->size_units = GETPOST('size_units','int');
524  }
525  if ($action == 'settrueDepth') $object->trueDepth = trim(GETPOST('trueDepth','int'));
526  if ($action == 'setshipping_method_id') $object->shipping_method_id = trim(GETPOST('shipping_method_id','int'));
527 
528  if (! $error)
529  {
530  if ($object->update($user) >= 0)
531  {
532  header("Location: card.php?id=".$object->id);
533  exit;
534  }
535  setEventMessages($object->error, $object->errors, 'errors');
536  }
537 
538  $action="";
539  }
540 
541  // Build document
542  else if ($action == 'builddoc') // En get ou en post
543  {
544  // Save last template used to generate document
545  if (GETPOST('model')) $object->setDocModel($user, GETPOST('model','alpha'));
546 
547  // Define output language
548  $outputlangs = $langs;
549  $newlang='';
550  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09');
551  if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang=$shipment->thirdparty->default_lang;
552  if (! empty($newlang))
553  {
554  $outputlangs = new Translate("",$conf);
555  $outputlangs->setDefaultLang($newlang);
556  }
557  $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
558  if ($result <= 0)
559  {
560  setEventMessages($object->error, $object->errors, 'errors');
561  $action='';
562  }
563  }
564 
565  // Delete file in doc form
566  elseif ($action == 'remove_file')
567  {
568  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
569 
570  $upload_dir = $conf->expedition->dir_output . "/sending";
571  $file = $upload_dir . '/' . GETPOST('file');
572  $ret=dol_delete_file($file,0,0,0,$object);
573  if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
574  else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
575  }
576 
577  elseif ($action == 'classifybilled')
578  {
579  $object->fetch($id);
580  $result = $object->set_billed();
581  if($result >= 0) {
582  header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
583  exit();
584  }
585  }
586 
587  elseif ($action == 'classifyclosed')
588  {
589  $object->fetch($id);
590  $result = $object->setClosed();
591  if($result >= 0) {
592  header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
593  exit();
594  }
595  }
596 
597  /*
598  * delete a line
599  */
600  elseif ($action == 'deleteline' && ! empty($line_id))
601  {
602  $object->fetch($id);
603  $lines = $object->lines;
604  $line = new ExpeditionLigne($db);
605 
606  $num_prod = count($lines);
607  for ($i = 0 ; $i < $num_prod ; $i++)
608  {
609  if ($lines[$i]->id == $line_id)
610  {
611  if (count($lines[$i]->details_entrepot) > 1)
612  {
613  // delete multi warehouse lines
614  foreach ($lines[$i]->details_entrepot as $details_entrepot) {
615  $line->id = $details_entrepot->line_id;
616  if (! $error && $line->delete($user) < 0)
617  {
618  $error++;
619  }
620  }
621  }
622  else
623  {
624  // delete single warehouse line
625  $line->id = $line_id;
626  if (! $error && $line->delete($user) < 0)
627  {
628  $error++;
629  }
630  }
631  }
632  unset($_POST["lineid"]);
633  }
634 
635  if(! $error) {
636  header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
637  exit();
638  }
639  else
640  {
641  setEventMessages($line->error, $line->errors, 'errors');
642  }
643  }
644 
645  /*
646  * Update a line
647  */
648  else if ($action == 'updateline' && $user->rights->expedition->creer && GETPOST('save'))
649  {
650  // Clean parameters
651  $qty=0;
652  $entrepot_id = 0;
653  $batch_id = 0;
654 
655  $lines = $object->lines;
656  $num_prod = count($lines);
657  for ($i = 0 ; $i < $num_prod ; $i++)
658  {
659  if ($lines[$i]->id == $line_id) // we have found line to update
660  {
661  $line = new ExpeditionLigne($db);
662  // Extrafields Lines
663  $extrafieldsline = new ExtraFields($db);
664  $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
665  $line->array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline);
666  // Unset extrafield POST Data
667  if (is_array($extralabelsline)) {
668  foreach ($extralabelsline as $key => $value) {
669  unset($_POST["options_" . $key]);
670  }
671  }
672  $line->fk_product = $lines[$i]->fk_product;
673  if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
674  {
675  // line with lot
676  foreach ($lines[$i]->detail_batch as $detail_batch)
677  {
678  $lotStock = new Productbatch($db);
679  $batch="batchl".$detail_batch->fk_expeditiondet."_".$detail_batch->fk_origin_stock;
680  $qty = "qtyl".$detail_batch->fk_expeditiondet.'_'.$detail_batch->id;
681  $batch_id = GETPOST($batch,'int');
682  $batch_qty = GETPOST($qty, 'int');
683  if (! empty($batch_id) && ($batch_id != $detail_batch->fk_origin_stock || $batch_qty != $detail_batch->dluo_qty))
684  {
685  if ($lotStock->fetch($batch_id) > 0 && $line->fetch($detail_batch->fk_expeditiondet) > 0) // $line is ExpeditionLine
686  {
687  if ($lines[$i]->entrepot_id != 0)
688  {
689  // allow update line entrepot_id if not multi warehouse shipping
690  $line->entrepot_id = $lotStock->warehouseid;
691  }
692 
693  // detail_batch can be an object with keys, or an array of ExpeditionLineBatch
694  if (empty($line->detail_batch)) $line->detail_batch=new stdClass();
695 
696  $line->detail_batch->fk_origin_stock = $batch_id;
697  $line->detail_batch->batch = $lotStock->batch;
698  $line->detail_batch->id = $detail_batch->id;
699  $line->detail_batch->entrepot_id = $lotStock->warehouseid;
700  $line->detail_batch->dluo_qty = $batch_qty;
701  if ($line->update($user) < 0) {
702  setEventMessages($line->error, $line->errors, 'errors');
703  $error++;
704  }
705  }
706  else
707  {
708  setEventMessages($lotStock->error, $lotStock->errors, 'errors');
709  $error++;
710  }
711  }
712  unset($_POST[$batch]);
713  unset($_POST[$qty]);
714  }
715  // add new batch
716  $lotStock = new Productbatch($db);
717  $batch="batchl".$line_id."_0";
718  $qty = "qtyl".$line_id."_0";
719  $batch_id = GETPOST($batch,'int');
720  $batch_qty = GETPOST($qty, 'int');
721  $lineIdToAddLot = 0;
722  if ($batch_qty > 0 && ! empty($batch_id))
723  {
724  if ($lotStock->fetch($batch_id) > 0)
725  {
726  // check if lotStock warehouse id is same as line warehouse id
727  if ($lines[$i]->entrepot_id > 0)
728  {
729  // single warehouse shipment line
730  if ($lines[i]->entrepot_id == $lotStock->warehouseid)
731  {
732  $lineIdToAddLot = $line_id;
733  }
734  }
735  else if (count($lines[$i]->details_entrepot) > 1)
736  {
737  // multi warehouse shipment lines
738  foreach ($lines[$i]->details_entrepot as $detail_entrepot)
739  {
740  if ($detail_entrepot->entrepot_id == $lotStock->warehouseid)
741  {
742  $lineIdToAddLot = $detail_entrepot->line_id;
743  }
744  }
745  }
746  if ($lineIdToAddLot)
747  {
748  // add lot to existing line
749  if ($line->fetch($lineIdToAddLot) > 0)
750  {
751  $line->detail_batch->fk_origin_stock = $batch_id;
752  $line->detail_batch->batch = $lotStock->batch;
753  $line->detail_batch->entrepot_id = $lotStock->warehouseid;
754  $line->detail_batch->dluo_qty = $batch_qty;
755  if ($line->update($user) < 0) {
756  setEventMessages($line->error, $line->errors, 'errors');
757  $error++;
758  }
759  }
760  else
761  {
762  setEventMessages($line->error, $line->errors, 'errors');
763  $error++;
764  }
765  }
766  else
767  {
768  // create new line with new lot
769  $line->origin_line_id = $lines[$i]->origin_line_id;
770  $line->entrepot_id = $lotStock->warehouseid;
771  $line->detail_batch[0] = new ExpeditionLineBatch($db);
772  $line->detail_batch[0]->fk_origin_stock = $batch_id;
773  $line->detail_batch[0]->batch = $lotStock->batch;
774  $line->detail_batch[0]->entrepot_id = $lotStock->warehouseid;
775  $line->detail_batch[0]->dluo_qty = $batch_qty;
776  if ($object->create_line_batch($line, $line->array_options) < 0)
777  {
778  setEventMessages($object->error, $object->errors, 'errors');
779  $error++;
780  }
781  }
782  }
783  else
784  {
785  setEventMessages($lotStock->error, $lotStock->errors, 'errors');
786  $error++;
787  }
788  }
789  }
790  else
791  {
792  if ($lines[$i]->fk_product > 0)
793  {
794  // line without lot
795  if ($lines[$i]->entrepot_id > 0)
796  {
797  // single warehouse shipment line
798  $stockLocation="entl".$line_id;
799  $qty = "qtyl".$line_id;
800  $line->id = $line_id;
801  $line->entrepot_id = GETPOST($stockLocation,'int');
802  $line->qty = GETPOST($qty, 'int');
803  if ($line->update($user) < 0) {
804  setEventMessages($line->error, $line->errors, 'errors');
805  $error++;
806  }
807  unset($_POST[$stockLocation]);
808  unset($_POST[$qty]);
809  }
810  else if (count($lines[$i]->details_entrepot) > 1)
811  {
812  // multi warehouse shipment lines
813  foreach ($lines[$i]->details_entrepot as $detail_entrepot)
814  {
815  if (! $error) {
816  $stockLocation="entl".$detail_entrepot->line_id;
817  $qty = "qtyl".$detail_entrepot->line_id;
818  $warehouse = GETPOST($stockLocation,'int');
819  if (!empty ($warehouse))
820  {
821  $line->id = $detail_entrepot->line_id;
822  $line->entrepot_id = $warehouse;
823  $line->qty = GETPOST($qty, 'int');
824  if ($line->update($user) < 0) {
825  setEventMessages($line->error, $line->errors, 'errors');
826  $error++;
827  }
828  }
829  unset($_POST[$stockLocation]);
830  unset($_POST[$qty]);
831  }
832  }
833  }
834  }
835  else // Product no predefined
836  {
837  $qty = "qtyl".$line_id;
838  $line->id = $line_id;
839  $line->qty = GETPOST($qty, 'int');
840  $line->entrepot_id = 0;
841  if ($line->update($user) < 0) {
842  setEventMessages($line->error, $line->errors, 'errors');
843  $error++;
844  }
845  unset($_POST[$qty]);
846  }
847  }
848  }
849  }
850 
851  unset($_POST["lineid"]);
852 
853  if (! $error) {
854  if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
855  // Define output language
856  $outputlangs = $langs;
857  $newlang = '';
858  if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09'))
859  $newlang = GETPOST('lang_id','aZ09');
860  if ($conf->global->MAIN_MULTILANGS && empty($newlang))
861  $newlang = $object->thirdparty->default_lang;
862  if (! empty($newlang)) {
863  $outputlangs = new Translate("", $conf);
864  $outputlangs->setDefaultLang($newlang);
865  }
866 
867  $ret = $object->fetch($object->id); // Reload to get new records
868  $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
869  }
870  }
871  else
872  {
873  header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
874  exit();
875  }
876  }
877 
878  else if ($action == 'updateline' && $user->rights->expedition->creer && GETPOST('cancel','alpha') == $langs->trans('Cancel')) {
879  header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
880  exit();
881  }
882 
883  include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
884 
885  // Actions to send emails
886  if (empty($id)) $id=$facid;
887  $trigger_name='SHIPPING_SENTBYMAIL';
888  $paramname='id';
889  $mode='emailfromshipment';
890  $trackid='shi'.$object->id;
891  include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
892 
893 }
894 
895 
896 /*
897  * View
898  */
899 
900 llxHeader('',$langs->trans('Shipment'),'Expedition');
901 
902 $form = new Form($db);
903 $formfile = new FormFile($db);
904 $formproduct = new FormProduct($db);
905 if (! empty($conf->projet->enabled)) { $formproject = new FormProjets($db); }
906 
907 $product_static = new Product($db);
908 $shipment_static = new Expedition($db);
909 $warehousestatic = new Entrepot($db);
910 
911 if ($action == 'create2')
912 {
913  print load_fiche_titre($langs->trans("CreateShipment")).'<br>';
914  print $langs->trans("ShipmentCreationIsDoneFromOrder");
915  $action=''; $id=''; $ref='';
916 }
917 
918 // Mode creation.
919 if ($action == 'create')
920 {
921  $expe = new Expedition($db);
922 
923  print load_fiche_titre($langs->trans("CreateShipment"));
924  if (! $origin)
925  {
926  setEventMessages($langs->trans("ErrorBadParameters"), null, 'errors');
927  }
928 
929  if ($origin)
930  {
931  $classname = ucfirst($origin);
932 
933  $object = new $classname($db);
934  if ($object->fetch($origin_id)) // This include the fetch_lines
935  {
936  $soc = new Societe($db);
937  $soc->fetch($object->socid);
938 
939  $author = new User($db);
940  $author->fetch($object->user_author_id);
941 
942  if (! empty($conf->stock->enabled)) $entrepot = new Entrepot($db);
943 
944  print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
945  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
946  print '<input type="hidden" name="action" value="add">';
947  print '<input type="hidden" name="origin" value="'.$origin.'">';
948  print '<input type="hidden" name="origin_id" value="'.$object->id.'">';
949  print '<input type="hidden" name="ref_int" value="'.$object->ref_int.'">';
950  if (GETPOST('entrepot_id','int'))
951  {
952  print '<input type="hidden" name="entrepot_id" value="'.GETPOST('entrepot_id','int').'">';
953  }
954 
955  dol_fiche_head('');
956 
957  print '<table class="border centpercent">';
958 
959  // Ref
960  print '<tr><td class="titlefieldcreate fieldrequired">';
961  if ($origin == 'commande' && ! empty($conf->commande->enabled))
962  {
963  print $langs->trans("RefOrder").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/commande/card.php?id='.$object->id.'">'.img_object($langs->trans("ShowOrder"),'order').' '.$object->ref;
964  }
965  if ($origin == 'propal' && ! empty($conf->propal->enabled))
966  {
967  print $langs->trans("RefProposal").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/comm/card.php?id='.$object->id.'">'.img_object($langs->trans("ShowProposal"),'propal').' '.$object->ref;
968  }
969  print '</a></td>';
970  print "</tr>\n";
971 
972  // Ref client
973  print '<tr><td>';
974  if ($origin == 'commande') print $langs->trans('RefCustomerOrder');
975  else if ($origin == 'propal') print $langs->trans('RefCustomerOrder');
976  else print $langs->trans('RefCustomer');
977  print '</td><td colspan="3">';
978  print '<input type="text" name="ref_customer" value="'.$object->ref_client.'" />';
979  print '</td>';
980  print '</tr>';
981 
982  // Tiers
983  print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Company').'</td>';
984  print '<td colspan="3">'.$soc->getNomUrl(1).'</td>';
985  print '</tr>';
986 
987  // Project
988  if (! empty($conf->projet->enabled))
989  {
990  $projectid = GETPOST('projectid','int')?GETPOST('projectid','int'):0;
991  if ($origin == 'project') $projectid = ($originid ? $originid : 0);
992 
993  $langs->load("projects");
994  print '<tr>';
995  print '<td>' . $langs->trans("Project") . '</td><td colspan="2">';
996  $numprojet = $formproject->select_projects($soc->id, $projectid, 'projectid', 0);
997  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).'">' . $langs->trans("AddProject") . '</a>';
998  print '</td>';
999  print '</tr>';
1000  }
1001 
1002  // Date delivery planned
1003  print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
1004  print '<td colspan="3">';
1005  //print dol_print_date($object->date_livraison,"day"); // date_livraison come from order and will be stored into date_delivery planed.
1006  $date_delivery = ($date_delivery?$date_delivery:$object->date_livraison); // $date_delivery comes from GETPOST
1007  print $form->select_date($date_delivery?$date_delivery:-1,'date_delivery',1,1,1);
1008  print "</td>\n";
1009  print '</tr>';
1010 
1011  // Note Public
1012  print '<tr><td>'.$langs->trans("NotePublic").'</td>';
1013  print '<td colspan="3">';
1014  $doleditor = new DolEditor('note_public', $object->note_public, '', 60, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
1015  print $doleditor->Create(1);
1016  print "</td></tr>";
1017 
1018  // Note Private
1019  if ($object->note_private && ! $user->societe_id)
1020  {
1021  print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
1022  print '<td colspan="3">';
1023  $doleditor = new DolEditor('note_private', $object->note_private, '', 60, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
1024  print $doleditor->Create(1);
1025  print "</td></tr>";
1026  }
1027 
1028  // Weight
1029  print '<tr><td>';
1030  print $langs->trans("Weight");
1031  print '</td><td colspan="3"><input name="weight" size="4" value="'.GETPOST('weight','int').'"> ';
1032  $text=$formproduct->select_measuring_units("weight_units","weight",GETPOST('weight_units','int'));
1033  $htmltext=$langs->trans("KeepEmptyForAutoCalculation");
1034  print $form->textwithpicto($text, $htmltext);
1035  print '</td></tr>';
1036  // Dim
1037  print '<tr><td>';
1038  print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
1039  print ' </td><td colspan="3"><input name="sizeW" size="4" value="'.GETPOST('sizeW','int').'">';
1040  print ' x <input name="sizeH" size="4" value="'.GETPOST('sizeH','int').'">';
1041  print ' x <input name="sizeS" size="4" value="'.GETPOST('sizeS','int').'">';
1042  print ' ';
1043  $text=$formproduct->select_measuring_units("size_units","size");
1044  $htmltext=$langs->trans("KeepEmptyForAutoCalculation");
1045  print $form->textwithpicto($text, $htmltext);
1046  print '</td></tr>';
1047 
1048  // Delivery method
1049  print "<tr><td>".$langs->trans("DeliveryMethod")."</td>";
1050  print '<td colspan="3">';
1051  $expe->fetch_delivery_methods();
1052  print $form->selectarray("shipping_method_id", $expe->meths, GETPOST('shipping_method_id','int'),1,0,0,"",1);
1053  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1054  print "</td></tr>\n";
1055 
1056  // Tracking number
1057  print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
1058  print '<td colspan="3">';
1059  print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number','alpha').'">';
1060  print "</td></tr>\n";
1061 
1062  // Other attributes
1063  $parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'socid'=>$socid);
1064  $reshook=$hookmanager->executeHooks('formObjectOptions',$parameters,$expe,$action); // Note that $action and $object may have been modified by hook
1065  print $hookmanager->resPrint;
1066 
1067  if (empty($reshook) && ! empty($extrafields->attribute_label)) {
1068  // copy from order
1069  $orderExtrafields = new Extrafields($db);
1070  $orderExtrafieldLabels = $orderExtrafields->fetch_name_optionals_label($object->table_element);
1071  if ($object->fetch_optionals($object->id, $orderExtrafieldLabels) > 0) {
1072  $expe->array_options = array_merge($expe->array_options, $object->array_options);
1073  }
1074  print $object->showOptionals($extrafields, 'edit');
1075  }
1076 
1077 
1078  // Incoterms
1079  if (!empty($conf->incoterm->enabled))
1080  {
1081  print '<tr>';
1082  print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->libelle_incoterms, 1).'</label></td>';
1083  print '<td colspan="3" class="maxwidthonsmartphone">';
1084  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''));
1085  print '</td></tr>';
1086  }
1087 
1088  // Document model
1089  include_once DOL_DOCUMENT_ROOT . '/core/modules/expedition/modules_expedition.php';
1090  $liste = ModelePdfExpedition::liste_modeles($db);
1091  if (count($liste) > 1)
1092  {
1093  print "<tr><td>".$langs->trans("DefaultModel")."</td>";
1094  print '<td colspan="3">';
1095  print $form->selectarray('model', $liste, $conf->global->EXPEDITION_ADDON_PDF);
1096  print "</td></tr>\n";
1097  }
1098 
1099  print "</table>";
1100 
1101  dol_fiche_end();
1102 
1103 
1104  // Shipment lines
1105 
1106  $numAsked = count($object->lines);
1107 
1108  print '<script type="text/javascript" language="javascript">
1109  jQuery(document).ready(function() {
1110  jQuery("#autofill").click(function() {';
1111  $i=0;
1112  while($i < $numAsked)
1113  {
1114  print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
1115  $i++;
1116  }
1117  print '});
1118  jQuery("#autoreset").click(function() {';
1119  $i=0;
1120  while($i < $numAsked)
1121  {
1122  print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
1123  $i++;
1124  }
1125  print '});
1126  });
1127  </script>';
1128 
1129 
1130  print '<br>';
1131 
1132 
1133  print '<table class="noborder" width="100%">';
1134 
1135 
1136  // Load shipments already done for same order
1137  $object->loadExpeditions();
1138 
1139  if ($numAsked)
1140  {
1141  print '<tr class="liste_titre">';
1142  print '<td>'.$langs->trans("Description").'</td>';
1143  print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
1144  print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
1145  print '<td align="center">'.$langs->trans("QtyToShip");
1146  if (empty($conf->productbatch->enabled))
1147  {
1148  print ' <br>(<a href="#" id="autofill">'.$langs->trans("Fill").'</a>';
1149  print ' / <a href="#" id="autoreset">'.$langs->trans("Reset").'</a>)';
1150  }
1151  print '</td>';
1152  if (! empty($conf->stock->enabled))
1153  {
1154  if (empty($conf->productbatch->enabled))
1155  {
1156  print '<td align="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
1157  }
1158  else
1159  {
1160  print '<td align="left">'.$langs->trans("Warehouse").' / '.$langs->trans("Batch").' ('.$langs->trans("Stock").')</td>';
1161  }
1162  }
1163  print "</tr>\n";
1164  }
1165 
1166  $var=true;
1167  $indiceAsked = 0;
1168  while ($indiceAsked < $numAsked)
1169  {
1170  $product = new Product($db);
1171 
1172  $line = $object->lines[$indiceAsked];
1173 
1174 
1175  // Show product and description
1176  $type=$line->product_type?$line->product_type:$line->fk_product_type;
1177  // Try to enhance type detection using date_start and date_end for free lines where type
1178  // was not saved.
1179  if (! empty($line->date_start)) $type=1;
1180  if (! empty($line->date_end)) $type=1;
1181 
1182  print '<!-- line '.$line->rowid.' for product -->'."\n";
1183  print '<tr class="oddeven">'."\n";
1184 
1185  // Product label
1186  if ($line->fk_product > 0) // If predefined product
1187  {
1188  $product->fetch($line->fk_product);
1189  $product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
1190  //var_dump($product->stock_warehouse[1]);
1191 
1192  print '<td>';
1193  print '<a name="'.$line->rowid.'"></a>'; // ancre pour retourner sur la ligne
1194 
1195  // Show product and description
1196  $product_static->type=$line->fk_product_type;
1197  $product_static->id=$line->fk_product;
1198  $product_static->ref=$line->ref;
1199  $product_static->status_batch=$line->product_tobatch;
1200  $text=$product_static->getNomUrl(1);
1201  $text.= ' - '.(! empty($line->label)?$line->label:$line->product_label);
1202  $description=($conf->global->PRODUIT_DESC_IN_FORM?'':dol_htmlentitiesbr($line->desc));
1203  print $form->textwithtooltip($text,$description,3,'','',$i);
1204 
1205  // Show range
1206  print_date_range($db->jdate($line->date_start),$db->jdate($line->date_end));
1207 
1208  // Add description in form
1209  if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
1210  {
1211  print ($line->desc && $line->desc!=$line->product_label)?'<br>'.dol_htmlentitiesbr($line->desc):'';
1212  }
1213 
1214  print '</td>';
1215  }
1216  else
1217  {
1218  print "<td>";
1219  if ($type==1) $text = img_object($langs->trans('Service'),'service');
1220  else $text = img_object($langs->trans('Product'),'product');
1221 
1222  if (! empty($line->label)) {
1223  $text.= ' <strong>'.$line->label.'</strong>';
1224  print $form->textwithtooltip($text,$line->desc,3,'','',$i);
1225  } else {
1226  print $text.' '.nl2br($line->desc);
1227  }
1228 
1229  // Show range
1230  print_date_range($db->jdate($line->date_start),$db->jdate($line->date_end));
1231  print "</td>\n";
1232  }
1233 
1234  // Qty
1235  print '<td align="center">'.$line->qty;
1236  print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
1237  print '</td>';
1238  $qtyProdCom=$line->qty;
1239 
1240  // Qty already shipped
1241  print '<td align="center">';
1242  $quantityDelivered = $object->expeditions[$line->id];
1243  print $quantityDelivered;
1244  print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
1245  print '</td>';
1246 
1247  // Qty to ship
1248  $quantityAsked = $line->qty;
1249  if ($line->product_type == 1 && empty($conf->global->STOCK_SUPPORTS_SERVICES))
1250  {
1251  $quantityToBeDelivered = 0;
1252  }
1253  else
1254  {
1255  $quantityToBeDelivered = $quantityAsked - $quantityDelivered;
1256  }
1257  $warehouse_id = GETPOST('entrepot_id','int');
1258 
1259  $warehouseObject = null;
1260  if ($warehouse_id > 0 || ! ($line->fk_product > 0) || empty($conf->stock->enabled)) // If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
1261  {
1262  print '<!-- Case warehouse already known or product not a predefined product -->';
1263  //ship from preselected location
1264  $stock = + $product->stock_warehouse[$warehouse_id]->real; // Convert to number
1265  $deliverableQty=min($quantityToBeDelivered, $stock);
1266  if ($deliverableQty < 0) $deliverableQty = 0;
1267  if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
1268  {
1269  // Quantity to send
1270  print '<td align="center">';
1271  if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1272  {
1273  if (GETPOST('qtyl'.$indiceAsked, 'int')) $defaultqty=GETPOST('qtyl'.$indiceAsked, 'int');
1274  print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1275  print '<input name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1276  }
1277  else print $langs->trans("NA");
1278  print '</td>';
1279 
1280  // Stock
1281  if (! empty($conf->stock->enabled))
1282  {
1283  print '<td align="left">';
1284  if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES)) // Type of product need stock change ?
1285  {
1286  // Show warehouse combo list
1287  $ent = "entl".$indiceAsked;
1288  $idl = "idl".$indiceAsked;
1289  $tmpentrepot_id = is_numeric(GETPOST($ent,'int'))?GETPOST($ent,'int'):$warehouse_id;
1290  if ($line->fk_product > 0)
1291  {
1292  print '<!-- Show warehouse selection -->';
1293  print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 1, 0, $line->fk_product, '', 1);
1294  if ($tmpentrepot_id > 0 && $tmpentrepot_id == $warehouse_id)
1295  {
1296  //print $stock.' '.$quantityToBeDelivered;
1297  if ($stock < $quantityToBeDelivered)
1298  {
1299  print ' '.img_warning($langs->trans("StockTooLow")); // Stock too low for this $warehouse_id but you can change warehouse
1300  }
1301  }
1302  }
1303  }
1304  else
1305  {
1306  print $langs->trans("Service");
1307  }
1308  print '</td>';
1309  }
1310 
1311  print "</tr>\n";
1312 
1313  // Show subproducts of product
1314  if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
1315  {
1316  $product->get_sousproduits_arbo();
1317  $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
1318  if(count($prods_arbo) > 0)
1319  {
1320  foreach($prods_arbo as $key => $value)
1321  {
1322  //print $value[0];
1323  $img='';
1324  if ($value['stock'] < $value['stock_alert'])
1325  {
1326  $img=img_warning($langs->trans("StockTooLow"));
1327  }
1328  print "<tr class=\"oddeven\"><td>&nbsp; &nbsp; &nbsp; ->
1329  <a href=\"".DOL_URL_ROOT."/product/card.php?id=".$value['id']."\">".$value['fullpath']."
1330  </a> (".$value['nb'].")</td><td align=\"center\"> ".$value['nb_total']."</td><td>&nbsp</td><td>&nbsp</td>
1331  <td align=\"center\">".$value['stock']." ".$img."</td></tr>";
1332  }
1333  }
1334  }
1335  }
1336  else
1337  {
1338  // Product need lot
1339  print '<td></td><td></td></tr>'; // end line and start a new one for lot/serial
1340 
1341  $staticwarehouse=new Entrepot($db);
1342  if ($warehouse_id > 0) $staticwarehouse->fetch($warehouse_id);
1343 
1344  $subj=0;
1345  // Define nb of lines suggested for this order line
1346  $nbofsuggested=0;
1347  if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
1348  {
1349  foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)
1350  {
1351  $nbofsuggested++;
1352  }
1353  }
1354  print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1355  if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch))
1356  {
1357  foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch)
1358  {
1359  //var_dump($dbatch);
1360  $batchStock = + $dbatch->qty; // To get a numeric
1361  $deliverableQty = min($quantityToBeDelivered,$batchStock);
1362  print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'>';
1363  print '<td colspan="3" ></td><td align="center">';
1364  print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$deliverableQty.'">';
1365  print '</td>';
1366 
1367  print '<!-- Show details of lot -->';
1368  print '<td align="left">';
1369 
1370  print $staticwarehouse->getNomUrl(0).' / ';
1371 
1372  print '<input name="batchl'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$dbatch->id.'">';
1373 
1374  $detail='';
1375  $detail.= $langs->trans("Batch").': '.$dbatch->batch;
1376  $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby,"day");
1377  $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby,"day");
1378  $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->dluo_qty;
1379  $detail.= '<br>';
1380  print $detail;
1381 
1382  $quantityToBeDelivered -= $deliverableQty;
1383  if ($quantityToBeDelivered < 0)
1384  {
1385  $quantityToBeDelivered = 0;
1386  }
1387  $subj++;
1388  print '</td></tr>';
1389  }
1390  }
1391  else
1392  {
1393  print '<!-- Case there is no details of lot at all -->';
1394  print '<tr class="oddeven"><td colspan="3"></td><td align="center">';
1395  print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0" disabled="disabled"> ';
1396  print '</td>';
1397 
1398  print '<td align="left">';
1399  print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $staticwarehouse->libelle);
1400  print '</td></tr>';
1401  }
1402  }
1403  }
1404  else
1405  {
1406  // ship from multiple locations
1407  if (empty($conf->productbatch->enabled) || ! $product->hasbatch())
1408  {
1409  print '<!-- Case warehouse not already known and product does not need lot -->';
1410  print '<td></td><td></td></tr>'."\n"; // end line and start a new one for each warehouse
1411 
1412  print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1413  $subj=0;
1414  // Define nb of lines suggested for this order line
1415  $nbofsuggested=0;
1416  foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1417  {
1418  if ($stock_warehouse->real > 0)
1419  {
1420  $nbofsuggested++;
1421  }
1422  }
1423  $tmpwarehouseObject=new Entrepot($db);
1424  foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse) // $stock_warehouse is product_stock
1425  {
1426  $tmpwarehouseObject->fetch($warehouse_id);
1427  if ($stock_warehouse->real > 0)
1428  {
1429  $stock = + $stock_warehouse->real; // Convert it to number
1430  $deliverableQty = min($quantityToBeDelivered,$stock);
1431  $deliverableQty = max(0, $deliverableQty);
1432  // Quantity to send
1433  print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'>';
1434  print '<td colspan="3" ></td><td align="center"><!-- qty to ship (no lot management for product line indiceAsked='.$indiceAsked.') -->';
1435  if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1436  {
1437  print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
1438  print '<input name="ent1'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$warehouse_id.'">';
1439  }
1440  else print $langs->trans("NA");
1441  print '</td>';
1442 
1443  // Stock
1444  if (! empty($conf->stock->enabled))
1445  {
1446  print '<td align="left">';
1447  if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1448  {
1449  print $tmpwarehouseObject->getNomUrl(0).' ';
1450 
1451  print '<!-- Show details of stock -->';
1452  print '('.$stock.')';
1453 
1454  }
1455  else
1456  {
1457  print $langs->trans("Service");
1458  }
1459  print '</td>';
1460  }
1461  $quantityToBeDelivered -= $deliverableQty;
1462  if ($quantityToBeDelivered < 0)
1463  {
1464  $quantityToBeDelivered = 0;
1465  }
1466  $subj++;
1467  print "</tr>\n";
1468  }
1469  }
1470  // Show subproducts of product (not recommanded)
1471  if (! empty($conf->global->PRODUIT_SOUSPRODUITS) && $line->fk_product > 0)
1472  {
1473  $product->get_sousproduits_arbo();
1474  $prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
1475  if (count($prods_arbo) > 0)
1476  {
1477  foreach($prods_arbo as $key => $value)
1478  {
1479  //print $value[0];
1480  $img='';
1481  if ($value['stock'] < $value['stock_alert'])
1482  {
1483  $img=img_warning($langs->trans("StockTooLow"));
1484  }
1485  print '<tr class"oddeven"><td>';
1486  print "&nbsp; &nbsp; &nbsp; ->
1487  <a href=\"".DOL_URL_ROOT."/product/card.php?id=".$value['id']."\">".$value['fullpath']."
1488  </a> (".$value['nb'].")</td><td align=\"center\"> ".$value['nb_total']."</td><td>&nbsp</td><td>&nbsp</td>
1489  <td align=\"center\">".$value['stock']." ".$img."</td>";
1490  print "</tr>";
1491  }
1492  }
1493  }
1494  }
1495  else
1496  {
1497  print '<!-- Case warehouse not already known and product need lot -->';
1498  print '<td></td><td></td></tr>'; // end line and start a new one for lot/serial
1499 
1500  $subj=0;
1501  print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
1502 
1503  $tmpwarehouseObject=new Entrepot($db);
1504  $productlotObject=new Productlot($db);
1505  // Define nb of lines suggested for this order line
1506  $nbofsuggested=0;
1507  foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1508  {
1509  if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
1510  foreach ($stock_warehouse->detail_batch as $dbatch)
1511  {
1512  $nbofsuggested++;
1513  }
1514  }
1515  }
1516  foreach ($product->stock_warehouse as $warehouse_id=>$stock_warehouse)
1517  {
1518  $tmpwarehouseObject->fetch($warehouse_id);
1519  if (($stock_warehouse->real > 0) && (count($stock_warehouse->detail_batch))) {
1520  foreach ($stock_warehouse->detail_batch as $dbatch)
1521  {
1522  //var_dump($dbatch);
1523  $batchStock = + $dbatch->qty; // To get a numeric
1524  $deliverableQty = min($quantityToBeDelivered,$batchStock);
1525  if ($deliverableQty < 0) $deliverableQty = 0;
1526  print '<!-- subj='.$subj.'/'.$nbofsuggested.' --><tr '.((($subj + 1) == $nbofsuggested)?$bc[$var]:'').'><td colspan="3"></td><td align="center">';
1527  print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$deliverableQty.'">';
1528  print '</td>';
1529 
1530  print '<td align="left">';
1531 
1532  print $tmpwarehouseObject->getNomUrl(0).' / ';
1533 
1534  print '<!-- Show details of lot -->';
1535  print '<input name="batchl'.$indiceAsked.'_'.$subj.'" type="hidden" value="'.$dbatch->id.'">';
1536 
1537  //print $line->fk_product.' - '.$dbatch->batch;
1538  print $langs->trans("Batch").': ';
1539  $result = $productlotObject->fetch(0, $line->fk_product, $dbatch->batch);
1540  if ($result > 0) print $productlotObject->getNomUrl(1);
1541  else print 'TableLotIncompleteRunRepair';
1542  print ' ('.$dbatch->qty.')';
1543  $quantityToBeDelivered -= $deliverableQty;
1544  if ($quantityToBeDelivered < 0)
1545  {
1546  $quantityToBeDelivered = 0;
1547  }
1548  //dol_syslog('deliverableQty = '.$deliverableQty.' batchStock = '.$batchStock);
1549  $subj++;
1550  print '</td></tr>';
1551  }
1552  }
1553  }
1554 
1555  }
1556  if ($subj == 0) // Line not shown yet, we show it
1557  {
1558  print '<!-- line not shown yet, we show it -->';
1559  print '<tr class="oddeven"><td colspan="3" ></td><td align="center">';
1560  if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1561  {
1562  $disabled='';
1563  if (! empty($conf->productbatch->enabled) && $product->hasbatch())
1564  {
1565  $disabled='disabled="disabled"';
1566  }
1567  print '<input name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0"'.($disabled?' '.$disabled:'').'> ';
1568  }
1569  else
1570  {
1571  print $langs->trans("NA");
1572  }
1573  print '</td>';
1574 
1575  print '<td align="left">';
1576  if ($line->product_type == Product::TYPE_PRODUCT || ! empty($conf->global->STOCK_SUPPORTS_SERVICES))
1577  {
1578  $warehouse_selected_id = GETPOST('entrepot_id','int');
1579  if ($warehouse_selected_id > 0)
1580  {
1581  $warehouseObject=new Entrepot($db);
1582  $warehouseObject->fetch($warehouse_selected_id);
1583  print img_warning().' '.$langs->trans("NoProductToShipFoundIntoStock", $warehouseObject->libelle);
1584  }
1585  else
1586  {
1587  if ($line->fk_product) print img_warning().' '.$langs->trans("StockTooLow");
1588  else print '';
1589  }
1590  }
1591  else
1592  {
1593  print $langs->trans("Service");
1594  }
1595  print '</td>';
1596  print '</tr>';
1597  }
1598  }
1599 
1600 
1601  //Display lines extrafields
1602  if (is_array($extralabelslines) && count($extralabelslines)>0)
1603  {
1604  $colspan=5;
1605  $orderLineExtrafields = new Extrafields($db);
1606  $orderLineExtrafieldLabels = $orderLineExtrafields->fetch_name_optionals_label($object->table_element_line);
1607  $srcLine = new OrderLine($db);
1608  $srcLine->fetch_optionals($line->id,$orderLineExtrafieldLabels); // fetch extrafields also available in orderline
1609  $line = new ExpeditionLigne($db);
1610  $line->fetch_optionals($object->id,$extralabelslines);
1611  $line->array_options = array_merge($line->array_options, $srcLine->array_options);
1612  print '<tr class="oddeven">';
1613  print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
1614  print '</tr>';
1615  }
1616 
1617  $indiceAsked++;
1618  }
1619 
1620  print "</table>";
1621 
1622  print '<br>';
1623 
1624  print '<div class="center">';
1625  print '<input type="submit" class="button" name="add" value="'.dol_escape_htmltag($langs->trans("Create")).'">';
1626  print '&nbsp; ';
1627  print '<input type="'.($backtopage?"submit":"button").'" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'"'.($backtopage?'':' onclick="javascript:history.go(-1)"').'>'; // Cancel for create does not post form if we don't know the backtopage
1628  print '</div>';
1629 
1630  print '</form>';
1631 
1632  print '<br>';
1633  }
1634  else
1635  {
1636  dol_print_error($db);
1637  }
1638  }
1639 }
1640 else if ($id || $ref)
1641 /* *************************************************************************** */
1642 /* */
1643 /* Edit and view mode */
1644 /* */
1645 /* *************************************************************************** */
1646 {
1647  $lines = $object->lines;
1648 
1649  $num_prod = count($lines);
1650 
1651  if ($object->id > 0)
1652  {
1653  if (!empty($object->origin) && $object->origin_id > 0)
1654  {
1655  $typeobject = $object->origin;
1656  $origin = $object->origin;
1657  $origin_id = $object->origin_id;
1658  $object->fetch_origin(); // Load property $object->commande, $object->propal, ...
1659  }
1660 
1661  $soc = new Societe($db);
1662  $soc->fetch($object->socid);
1663 
1664  $res = $object->fetch_optionals($object->id, $extralabels);
1665 
1666  $head=shipping_prepare_head($object);
1667  dol_fiche_head($head, 'shipping', $langs->trans("Shipment"), -1, 'sending');
1668 
1669  $formconfirm='';
1670 
1671  // Confirm deleteion
1672  if ($action == 'delete')
1673  {
1674  $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('DeleteSending'),$langs->trans("ConfirmDeleteSending",$object->ref),'confirm_delete','',0,1);
1675  }
1676 
1677  // Confirmation validation
1678  if ($action == 'valid')
1679  {
1680  $objectref = substr($object->ref, 1, 4);
1681  if ($objectref == 'PROV')
1682  {
1683  $numref = $object->getNextNumRef($soc);
1684  }
1685  else
1686  {
1687  $numref = $object->ref;
1688  }
1689 
1690  $text = $langs->trans("ConfirmValidateSending",$numref);
1691 
1692  if (! empty($conf->notification->enabled))
1693  {
1694  require_once DOL_DOCUMENT_ROOT .'/core/class/notify.class.php';
1695  $notify=new Notify($db);
1696  $text.='<br>';
1697  $text.=$notify->confirmMessage('SHIPPING_VALIDATE',$object->socid, $object);
1698  }
1699 
1700  $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('ValidateSending'),$text,'confirm_valid','',0,1);
1701 
1702  }
1703  // Confirm cancelation
1704  if ($action == 'annuler')
1705  {
1706  $formconfirm=$form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id,$langs->trans('CancelSending'),$langs->trans("ConfirmCancelSending",$object->ref),'confirm_cancel','',0,1);
1707 
1708  }
1709 
1710  if (! $formconfirm) {
1711  $parameters = array();
1712  $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1713  if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
1714  elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
1715  }
1716 
1717  // Print form confirm
1718  print $formconfirm;
1719 
1720 
1721  // Calculate totalWeight and totalVolume for all products
1722  // by adding weight and volume of each product line.
1723  $tmparray=$object->getTotalWeightVolume();
1724  $totalWeight=$tmparray['weight'];
1725  $totalVolume=$tmparray['volume'];
1726 
1727 
1728  if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled))
1729  {
1730  $objectsrc=new Commande($db);
1731  $objectsrc->fetch($object->$typeobject->id);
1732  }
1733  if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled))
1734  {
1735  $objectsrc=new Propal($db);
1736  $objectsrc->fetch($object->$typeobject->id);
1737  }
1738 
1739  // Shipment card
1740  $linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">'.$langs->trans("BackToList").'</a>';
1741  $morehtmlref='<div class="refidno">';
1742  // Ref customer shipment
1743  $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', 0, 1);
1744  $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->rights->expedition->creer, 'string', '', null, null, '', 1);
1745  // Thirdparty
1746  $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
1747  // Project
1748  if (! empty($conf->projet->enabled)) {
1749  $langs->load("projects");
1750  $morehtmlref .= '<br>' . $langs->trans('Project') . ' ';
1751  if (0) { // Do not change on shipment
1752  if ($action != 'classify') {
1753  $morehtmlref .= '<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
1754  }
1755  if ($action == 'classify') {
1756  // $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
1757  $morehtmlref .= '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
1758  $morehtmlref .= '<input type="hidden" name="action" value="classin">';
1759  $morehtmlref .= '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '">';
1760  $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
1761  $morehtmlref .= '<input type="submit" class="button" value="' . $langs->trans("Modify") . '">';
1762  $morehtmlref .= '</form>';
1763  } else {
1764  $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
1765  }
1766  } else {
1767  // We don't have project on shipment, so we will use the project or source object instead
1768  // TODO Add project on shipment
1769  $morehtmlref .= ' : ';
1770  if (! empty($objectsrc->fk_project)) {
1771  $proj = new Project($db);
1772  $proj->fetch($objectsrc->fk_project);
1773  $morehtmlref .= '<a href="' . DOL_URL_ROOT . '/projet/card.php?id=' . $objectsrc->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
1774  $morehtmlref .= $proj->ref;
1775  $morehtmlref .= '</a>';
1776  } else {
1777  $morehtmlref .= '';
1778  }
1779  }
1780  }
1781  $morehtmlref.='</div>';
1782 
1783 
1784  dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
1785 
1786 
1787  print '<div class="fichecenter">';
1788  print '<div class="fichehalfleft">';
1789  print '<div class="underbanner clearboth"></div>';
1790 
1791  print '<table class="border" width="100%">';
1792 
1793  // Linked documents
1794  if ($typeobject == 'commande' && $object->$typeobject->id && ! empty($conf->commande->enabled))
1795  {
1796  print '<tr><td>';
1797  print $langs->trans("RefOrder").'</td>';
1798  print '<td colspan="3">';
1799  print $objectsrc->getNomUrl(1,'commande');
1800  print "</td>\n";
1801  print '</tr>';
1802  }
1803  if ($typeobject == 'propal' && $object->$typeobject->id && ! empty($conf->propal->enabled))
1804  {
1805  print '<tr><td>';
1806  print $langs->trans("RefProposal").'</td>';
1807  print '<td colspan="3">';
1808  print $objectsrc->getNomUrl(1,'expedition');
1809  print "</td>\n";
1810  print '</tr>';
1811  }
1812 
1813  // Date creation
1814  print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
1815  print '<td colspan="3">'.dol_print_date($object->date_creation,"dayhour")."</td>\n";
1816  print '</tr>';
1817 
1818  // Delivery date planned
1819  print '<tr><td height="10">';
1820  print '<table class="nobordernopadding" width="100%"><tr><td>';
1821  print $langs->trans('DateDeliveryPlanned');
1822  print '</td>';
1823 
1824  if ($action != 'editdate_livraison') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&amp;id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'),1).'</a></td>';
1825  print '</tr></table>';
1826  print '</td><td colspan="2">';
1827  if ($action == 'editdate_livraison')
1828  {
1829  print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1830  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1831  print '<input type="hidden" name="action" value="setdate_livraison">';
1832  print $form->select_date($object->date_delivery?$object->date_delivery:-1,'liv_',1,1,'',"setdate_livraison",1,0,1);
1833  print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
1834  print '</form>';
1835  }
1836  else
1837  {
1838  print $object->date_delivery ? dol_print_date($object->date_delivery,'dayhour') : '&nbsp;';
1839  }
1840  print '</td>';
1841  print '</tr>';
1842 
1843  // Weight
1844  print '<tr><td>';
1845  print $form->editfieldkey("Weight",'trueWeight',$object->trueWeight,$object,$user->rights->expedition->creer);
1846  print '</td><td colspan="3">';
1847 
1848  if ($action=='edittrueWeight')
1849  {
1850  print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1851  print '<input name="action" value="settrueWeight" type="hidden">';
1852  print '<input name="id" value="'.$object->id.'" type="hidden">';
1853  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1854  print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
1855  print $formproduct->select_measuring_units("weight_units","weight",$object->weight_units);
1856  print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1857  print ' <input class="button" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1858  print '</form>';
1859 
1860  }
1861  else
1862  {
1863  print $object->trueWeight;
1864  print ($object->trueWeight && $object->weight_units!='')?' '.measuring_units_string($object->weight_units,"weight"):'';
1865  }
1866 
1867  // Calculated
1868  if ($totalWeight > 0)
1869  {
1870  if (!empty($object->trueWeight)) print ' ('.$langs->trans("SumOfProductWeights").': ';
1871  //print $totalWeight.' '.measuring_units_string(0,"weight");
1872  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');
1873  //if (empty($object->trueWeight)) print ' ('.$langs->trans("Calculated").')';
1874  if (!empty($object->trueWeight)) print ')';
1875  }
1876  print '</td></tr>';
1877 
1878  // Width
1879  print '<tr><td>'.$form->editfieldkey("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1880  print $form->editfieldval("Width",'trueWidth',$object->trueWidth,$object,$user->rights->expedition->creer);
1881  print ($object->trueWidth && $object->width_units!='')?' '.measuring_units_string($object->width_units,"size"):'';
1882  print '</td></tr>';
1883 
1884  // Height
1885  print '<tr><td>'.$form->editfieldkey("Height",'trueHeight',$object->trueHeight,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1886  if($action=='edittrueHeight')
1887  {
1888  print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1889  print '<input name="action" value="settrueHeight" type="hidden">';
1890  print '<input name="id" value="'.$object->id.'" type="hidden">';
1891  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1892  print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
1893  print $formproduct->select_measuring_units("size_units","size",$object->size_units);
1894  print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
1895  print ' <input class="button" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
1896  print '</form>';
1897 
1898  }
1899  else
1900  {
1901  print $object->trueHeight;
1902  print ($object->trueHeight && $object->height_units!='')?' '.measuring_units_string($object->height_units,"size"):'';
1903  }
1904 
1905  print '</td></tr>';
1906 
1907  // Depth
1908  print '<tr><td>'.$form->editfieldkey("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1909  print $form->editfieldval("Depth",'trueDepth',$object->trueDepth,$object,$user->rights->expedition->creer);
1910  print ($object->trueDepth && $object->depth_units!='')?' '.measuring_units_string($object->depth_units,"size"):'';
1911  print '</td></tr>';
1912 
1913  // Volume
1914  print '<tr><td>';
1915  print $langs->trans("Volume");
1916  print '</td>';
1917  print '<td colspan="3">';
1918  $calculatedVolume=0;
1919  $volumeUnit=0;
1920  if ($object->trueWidth && $object->trueHeight && $object->trueDepth)
1921  {
1922  $calculatedVolume=($object->trueWidth * $object->trueHeight * $object->trueDepth);
1923  $volumeUnit=$object->size_units * 3;
1924  }
1925  // If sending volume not defined we use sum of products
1926  if ($calculatedVolume > 0)
1927  {
1928  if ($volumeUnit < 50)
1929  {
1930  //print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
1931  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');
1932  }
1933  else print $calculatedVolume.' '.measuring_units_string($volumeUnit,"volume");
1934  }
1935  if ($totalVolume > 0)
1936  {
1937  if ($calculatedVolume) print ' ('.$langs->trans("SumOfProductVolumes").': ';
1938  //print $totalVolume.' '.measuring_units_string(0,"volume");
1939  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');
1940  //if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
1941  if ($calculatedVolume) print ')';
1942  }
1943  print "</td>\n";
1944  print '</tr>';
1945 
1946  // Other attributes
1947  $cols = 2;
1948  include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
1949 
1950  print '</table>';
1951 
1952  print '</div>';
1953  print '<div class="fichehalfright">';
1954  print '<div class="ficheaddleft">';
1955  print '<div class="underbanner clearboth"></div>';
1956 
1957  print '<table class="border centpercent">';
1958 
1959  // Sending method
1960  print '<tr><td height="10">';
1961  print '<table class="nobordernopadding" width="100%"><tr><td>';
1962  print $langs->trans('SendingMethod');
1963  print '</td>';
1964 
1965  if ($action != 'editshipping_method_id') print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshipping_method_id&amp;id='.$object->id.'">'.img_edit($langs->trans('SetSendingMethod'),1).'</a></td>';
1966  print '</tr></table>';
1967  print '</td><td colspan="2">';
1968  if ($action == 'editshipping_method_id')
1969  {
1970  print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
1971  print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
1972  print '<input type="hidden" name="action" value="setshipping_method_id">';
1973  $object->fetch_delivery_methods();
1974  print $form->selectarray("shipping_method_id",$object->meths,$object->shipping_method_id,1,0,0,"",1);
1975  if ($user->admin) print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"),1);
1976  print '<input type="submit" class="button" value="'.$langs->trans('Modify').'">';
1977  print '</form>';
1978  }
1979  else
1980  {
1981  if ($object->shipping_method_id > 0)
1982  {
1983  // Get code using getLabelFromKey
1984  $code=$langs->getLabelFromKey($db,$object->shipping_method_id,'c_shipment_mode','rowid','code');
1985  print $langs->trans("SendingMethod".strtoupper($code));
1986  }
1987  }
1988  print '</td>';
1989  print '</tr>';
1990 
1991  // Tracking Number
1992  print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber",'tracking_number',$object->tracking_number,$object,$user->rights->expedition->creer).'</td><td colspan="3">';
1993  print $form->editfieldval("TrackingNumber",'tracking_number',$object->tracking_url,$object,$user->rights->expedition->creer,'string',$object->tracking_number);
1994  print '</td></tr>';
1995 
1996  // Incoterms
1997  if (!empty($conf->incoterm->enabled))
1998  {
1999  print '<tr><td>';
2000  print '<table width="100%" class="nobordernopadding"><tr><td>';
2001  print $langs->trans('IncotermLabel');
2002  print '<td><td align="right">';
2003  if ($user->rights->expedition->creer) print '<a href="'.DOL_URL_ROOT.'/expedition/card.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
2004  else print '&nbsp;';
2005  print '</td></tr></table>';
2006  print '</td>';
2007  print '<td colspan="3">';
2008  if ($action != 'editincoterm')
2009  {
2010  print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
2011  }
2012  else
2013  {
2014  print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
2015  }
2016  print '</td></tr>';
2017  }
2018 
2019  print "</table>";
2020 
2021  print '</div>';
2022  print '</div>';
2023  print '</div>';
2024 
2025  print '<div class="clearboth"></div>';
2026 
2027 
2028  // Lines of products
2029 
2030  if ($action == 'editline')
2031  {
2032  print ' <form name="updateline" id="updateline" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;lineid=' . $line_id . '" method="POST">
2033  <input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">
2034  <input type="hidden" name="action" value="updateline">
2035  <input type="hidden" name="mode" value="">
2036  <input type="hidden" name="id" value="' . $object->id . '">
2037  ';
2038  }
2039  print '<br>';
2040 
2041  print '<div class="div-table-responsive-no-min">';
2042  print '<table class="noborder" width="100%">';
2043  print '<tr class="liste_titre">';
2044  // #
2045  if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
2046  {
2047  print '<td width="5" align="center">&nbsp;</td>';
2048  }
2049  // Product/Service
2050  print '<td>'.$langs->trans("Products").'</td>';
2051  // Qty
2052  print '<td align="center">'.$langs->trans("QtyOrdered").'</td>';
2053  if ($origin && $origin_id > 0)
2054  {
2055  print '<td align="center">'.$langs->trans("QtyInOtherShipments").'</td>';
2056  }
2057  if ($action == 'editline')
2058  {
2059  $editColspan = 3;
2060  if (empty($conf->stock->enabled)) $editColspan--;
2061  if (empty($conf->productbatch->enabled)) $editColspan--;
2062  print '<td align="center" colspan="'. $editColspan . '">';
2063  if ($object->statut <= 1)
2064  {
2065  print $langs->trans("QtyToShip").' - ';
2066  }
2067  else
2068  {
2069  print $langs->trans("QtyShipped").' - ';
2070  }
2071  if (! empty($conf->stock->enabled))
2072  {
2073  print $langs->trans("WarehouseSource").' - ';
2074  }
2075  if (! empty($conf->productbatch->enabled))
2076  {
2077  print $langs->trans("Batch");
2078  }
2079  print '</td>';
2080  }
2081  else
2082  {
2083  if ($object->statut <= 1)
2084  {
2085  print '<td align="center">'.$langs->trans("QtyToShip").'</td>';
2086  }
2087  else
2088  {
2089  print '<td align="center">'.$langs->trans("QtyShipped").'</td>';
2090  }
2091  if (! empty($conf->stock->enabled))
2092  {
2093  print '<td align="left">'.$langs->trans("WarehouseSource").'</td>';
2094  }
2095 
2096  if (! empty($conf->productbatch->enabled))
2097  {
2098  print '<td align="left">'.$langs->trans("Batch").'</td>';
2099  }
2100  }
2101  print '<td align="center">'.$langs->trans("CalculatedWeight").'</td>';
2102  print '<td align="center">'.$langs->trans("CalculatedVolume").'</td>';
2103  //print '<td align="center">'.$langs->trans("Size").'</td>';
2104  if ($object->statut == 0)
2105  {
2106  print '<td class="linecoledit"></td>';
2107  print '<td class="linecoldelete" width="10"></td>';
2108  }
2109  print "</tr>\n";
2110 
2111  $var=false;
2112 
2113  if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
2114  {
2115  $object->fetch_thirdparty();
2116  $outputlangs = $langs;
2117  $newlang='';
2118  if (empty($newlang) && GETPOST('lang_id','aZ09')) $newlang=GETPOST('lang_id','aZ09');
2119  if (empty($newlang)) $newlang=$object->thirdparty->default_lang;
2120  if (! empty($newlang))
2121  {
2122  $outputlangs = new Translate("",$conf);
2123  $outputlangs->setDefaultLang($newlang);
2124  }
2125  }
2126 
2127  // Get list of products already sent for same source object into $alreadysent
2128  $alreadysent = array();
2129  if ($origin && $origin_id > 0)
2130  {
2131  $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";
2132  $sql.= ", ed.rowid as shipmentline_id, ed.qty as qty_shipped, ed.fk_expedition as expedition_id, ed.fk_origin_line, ed.fk_entrepot";
2133  $sql.= ", e.rowid as shipment_id, e.ref as shipment_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_expedition";
2134  //if ($conf->livraison_bon->enabled) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
2135  $sql.= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
2136  $sql.= ', p.description as product_desc';
2137  $sql.= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
2138  $sql.= ", ".MAIN_DB_PREFIX."expedition as e";
2139  $sql.= ", ".MAIN_DB_PREFIX.$origin."det as obj";
2140  //if ($conf->livraison_bon->enabled) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."livraison as l ON l.fk_expedition = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."livraisondet as ld ON ld.fk_livraison = l.rowid AND obj.rowid = ld.fk_origin_line";
2141  $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
2142  $sql.= " WHERE e.entity IN (".getEntity('expedition').")";
2143  $sql.= " AND obj.fk_".$origin." = ".$origin_id;
2144  $sql.= " AND obj.rowid = ed.fk_origin_line";
2145  $sql.= " AND ed.fk_expedition = e.rowid";
2146  //if ($filter) $sql.= $filter;
2147  $sql.= " ORDER BY obj.fk_product";
2148 
2149  dol_syslog("get list of shipment lines", LOG_DEBUG);
2150  $resql = $db->query($sql);
2151  if ($resql)
2152  {
2153  $num = $db->num_rows($resql);
2154  $i = 0;
2155 
2156  while($i < $num)
2157  {
2158  $obj = $db->fetch_object($resql);
2159  if ($obj)
2160  {
2161  // $obj->rowid is rowid in $origin."det" table
2162  $alreadysent[$obj->rowid][$obj->shipmentline_id]=array('shipment_ref'=>$obj->shipment_ref, 'shipment_id'=>$obj->shipment_id, 'warehouse'=>$obj->fk_entrepot, 'qty_shipped'=>$obj->qty_shipped, 'date_valid'=>$obj->date_valid, 'date_delivery'=>$obj->date_delivery);
2163  }
2164  $i++;
2165  }
2166  }
2167  //var_dump($alreadysent);
2168  }
2169 
2170  // Loop on each product to send/sent
2171  for ($i = 0 ; $i < $num_prod ; $i++)
2172  {
2173  print '<!-- origin line id = '.$lines[$i]->origin_line_id.' -->'; // id of order line
2174  print '<tr class="oddeven">';
2175 
2176  // #
2177  if (! empty($conf->global->MAIN_VIEW_LINE_NUMBER))
2178  {
2179  print '<td align="center">'.($i+1).'</td>';
2180  }
2181 
2182  // Predefined product or service
2183  if ($lines[$i]->fk_product > 0)
2184  {
2185  // Define output language
2186  if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE))
2187  {
2188  $prod = new Product($db);
2189  $prod->fetch($lines[$i]->fk_product);
2190  $label = ( ! empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label;
2191  }
2192  else
2193  $label = (! empty($lines[$i]->label)?$lines[$i]->label:$lines[$i]->product_label);
2194 
2195  print '<td>';
2196 
2197  // Show product and description
2198  $product_static->type=$lines[$i]->fk_product_type;
2199  $product_static->id=$lines[$i]->fk_product;
2200  $product_static->ref=$lines[$i]->ref;
2201  $product_static->status_batch=$lines[$i]->product_tobatch;
2202  $text=$product_static->getNomUrl(1);
2203  $text.= ' - '.$label;
2204  $description=(! empty($conf->global->PRODUIT_DESC_IN_FORM)?'':dol_htmlentitiesbr($lines[$i]->description));
2205  print $form->textwithtooltip($text,$description,3,'','',$i);
2206  print_date_range($lines[$i]->date_start,$lines[$i]->date_end);
2207  if (! empty($conf->global->PRODUIT_DESC_IN_FORM))
2208  {
2209  print (! empty($lines[$i]->description) && $lines[$i]->description!=$lines[$i]->product)?'<br>'.dol_htmlentitiesbr($lines[$i]->description):'';
2210  }
2211  print "</td>\n";
2212  }
2213  else
2214  {
2215  print "<td>";
2216  if ($lines[$i]->product_type == Product::TYPE_SERVICE) $text = img_object($langs->trans('Service'),'service');
2217  else $text = img_object($langs->trans('Product'),'product');
2218 
2219  if (! empty($lines[$i]->label)) {
2220  $text.= ' <strong>'.$lines[$i]->label.'</strong>';
2221  print $form->textwithtooltip($text,$lines[$i]->description,3,'','',$i);
2222  } else {
2223  print $text.' '.nl2br($lines[$i]->description);
2224  }
2225 
2226  print_date_range($lines[$i]->date_start,$lines[$i]->date_end);
2227  print "</td>\n";
2228  }
2229 
2230  // Qty ordered
2231  print '<td align="center">'.$lines[$i]->qty_asked.'</td>';
2232 
2233  // Qty in other shipments (with shipment and warehouse used)
2234  if ($origin && $origin_id > 0)
2235  {
2236  print '<td align="center" class="nowrap">';
2237  foreach ($alreadysent as $key => $val)
2238  {
2239  if ($lines[$i]->fk_origin_line == $key)
2240  {
2241  $j = 0;
2242  foreach($val as $shipmentline_id=> $shipmentline_var)
2243  {
2244  if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) continue; // We want to show only "other shipments"
2245 
2246  $j++;
2247  if ($j > 1) print '<br>';
2248  $shipment_static->fetch($shipmentline_var['shipment_id']);
2249  print $shipment_static->getNomUrl(1);
2250  print ' - '.$shipmentline_var['qty_shipped'];
2251  $htmltext=$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid'])?$langs->trans("Draft"):dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
2252  if (! empty($conf->stock->enabled) && $shipmentline_var['warehouse'] > 0)
2253  {
2254  $warehousestatic->fetch($shipmentline_var['warehouse']);
2255  $htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1);
2256  }
2257  print ' '.$form->textwithpicto('', $htmltext, 1);
2258  }
2259  }
2260  }
2261  }
2262  print '</td>';
2263 
2264  if ($action == 'editline' && $lines[$i]->id == $line_id)
2265  {
2266  // edit mode
2267  print '<td colspan="'.$editColspan.'" align="center"><table class="nobordernopadding">';
2268  if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0)
2269  {
2270  print '<!-- case edit 1 -->';
2271  $line = new ExpeditionLigne($db);
2272  foreach ($lines[$i]->detail_batch as $detail_batch)
2273  {
2274  print '<tr>';
2275  // Qty to ship or shipped
2276  print '<td>' . '<input name="qtyl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->id.'" id="qtyl'.$line_id.'_'.$detail_batch->id.'" type="text" size="4" value="'.$detail_batch->dluo_qty.'">' . '</td>';
2277  // Batch number managment
2278  if ($lines[$i]->entrepot_id == 0)
2279  {
2280  // only show lot numbers from src warehouse when shipping from multiple warehouses
2281  $line->fetch($detail_batch->fk_expeditiondet);
2282  }
2283  print '<td>' . $formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl'.$detail_batch->fk_expeditiondet.'_'.$detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $line->entrepot_id). '</td>';
2284  print '</tr>';
2285  }
2286  // add a 0 qty lot row to be able to add a lot
2287  print '<tr>';
2288  // Qty to ship or shipped
2289  print '<td>' . '<input name="qtyl'.$line_id.'_0" id="qtyl'.$line_id.'_0" type="text" size="4" value="0">' . '</td>';
2290  // Batch number managment
2291  print '<td>' . $formproduct->selectLotStock('', 'batchl'.$line_id.'_0', '', 1, 0, $lines[$i]->fk_product). '</td>';
2292  print '</tr>';
2293  }
2294  else if (! empty($conf->stock->enabled))
2295  {
2296  if ($lines[$i]->fk_product > 0)
2297  {
2298  if ($lines[$i]->entrepot_id > 0)
2299  {
2300  print '<!-- case edit 2 -->';
2301  print '<tr>';
2302  // Qty to ship or shipped
2303  print '<td>' . '<input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty_shipped.'">' . '</td>';
2304  // Warehouse source
2305  print '<td>' . $formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1). '</td>';
2306  // Batch number managment
2307  print '<td> - ' . $langs->trans("NA") . '</td>';
2308  print '</tr>';
2309  }
2310  else if (count($lines[$i]->details_entrepot) > 1)
2311  {
2312  print '<!-- case edit 3 -->';
2313  foreach ($lines[$i]->details_entrepot as $detail_entrepot)
2314  {
2315  print '<tr>';
2316  // Qty to ship or shipped
2317  print '<td>' . '<input name="qtyl'.$detail_entrepot->line_id.'" id="qtyl'.$detail_entrepot->line_id.'" type="text" size="4" value="'.$detail_entrepot->qty_shipped.'">' . '</td>';
2318  // Warehouse source
2319  print '<td>' . $formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl'.$detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1) . '</td>';
2320  // Batch number managment
2321  print '<td> - ' . $langs->trans("NA") . '</td>';
2322  print '</tr>';
2323  }
2324  }
2325  else
2326  {
2327  print '<!-- case edit 4 -->';
2328  print '<tr><td colspan="3">'.$langs->trans("NotEnoughStock").'</td></tr>';
2329  }
2330  }
2331  else
2332  {
2333  print '<!-- case edit 5 -->';
2334  print '<tr>';
2335  // Qty to ship or shipped
2336  print '<td>' . '<input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty_shipped.'">' . '</td>';
2337  // Warehouse source
2338  print '<td>' . '</td>';
2339  // Batch number managment
2340  print '<td>' . '</td>';
2341  print '</tr>';
2342  }
2343  }
2344  print '</table></td>';
2345  }
2346  else
2347  {
2348  // Qty to ship or shipped
2349  print '<td align="center">'.$lines[$i]->qty_shipped.'</td>';
2350 
2351  // Warehouse source
2352  if (! empty($conf->stock->enabled))
2353  {
2354  print '<td align="left">';
2355  if ($lines[$i]->entrepot_id > 0)
2356  {
2357  $entrepot = new Entrepot($db);
2358  $entrepot->fetch($lines[$i]->entrepot_id);
2359  print $entrepot->getNomUrl(1);
2360  }
2361  else if (count($lines[$i]->details_entrepot) > 1)
2362  {
2363  $detail = '';
2364  foreach ($lines[$i]->details_entrepot as $detail_entrepot)
2365  {
2366  if ($detail_entrepot->entrepot_id > 0)
2367  {
2368  $entrepot = new Entrepot($db);
2369  $entrepot->fetch($detail_entrepot->entrepot_id);
2370  $detail.= $langs->trans("DetailWarehouseFormat",$entrepot->libelle,$detail_entrepot->qty_shipped).'<br/>';
2371  }
2372  }
2373  print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"),$detail);
2374  }
2375  print '</td>';
2376  }
2377 
2378  // Batch number managment
2379  if (! empty($conf->productbatch->enabled))
2380  {
2381  if (isset($lines[$i]->detail_batch))
2382  {
2383  print '<!-- Detail of lot -->';
2384  print '<td>';
2385  if ($lines[$i]->product_tobatch)
2386  {
2387  $detail = '';
2388  foreach ($lines[$i]->detail_batch as $dbatch)
2389  {
2390  $detail.= $langs->trans("Batch").': '.$dbatch->batch;
2391  $detail.= ' - '.$langs->trans("SellByDate").': '.dol_print_date($dbatch->sellby,"day");
2392  $detail.= ' - '.$langs->trans("EatByDate").': '.dol_print_date($dbatch->eatby,"day");
2393  $detail.= ' - '.$langs->trans("Qty").': '.$dbatch->dluo_qty;
2394  $detail.= '<br>';
2395  }
2396  print $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"),$detail);
2397  }
2398  else
2399  {
2400  print $langs->trans("NA");
2401  }
2402  print '</td>';
2403  } else {
2404  print '<td></td>';
2405  }
2406  }
2407  }
2408 
2409  // Weight
2410  print '<td align="center">';
2411  if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->weight*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->weight_units,"weight");
2412  else print '&nbsp;';
2413  print '</td>';
2414 
2415  // Volume
2416  print '<td align="center">';
2417  if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) print $lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume");
2418  else print '&nbsp;';
2419  print '</td>';
2420 
2421  // Size
2422  //print '<td align="center">'.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuring_units_string($lines[$i]->volume_units,"volume").'</td>';
2423 
2424  if ($action == 'editline' && $lines[$i]->id == $line_id)
2425  {
2426  print '<td align="center" colspan="2" valign="middle">';
2427  print '<input type="submit" class="button" id="savelinebutton" name="save" value="' . $langs->trans("Save") . '"><br>';
2428  print '<input type="submit" class="button" id="cancellinebutton" name="cancel" value="' . $langs->trans("Cancel") . '"><br>';
2429  }
2430  else if ($object->statut == 0)
2431  {
2432  // edit-delete buttons
2433  print '<td class="linecoledit" align="center">';
2434  print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=editline&amp;lineid=' . $lines[$i]->id . '">' . img_edit() . '</a>';
2435  print '</td>';
2436  print '<td class="linecoldelete" width="10">';
2437  print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=deleteline&amp;lineid=' . $lines[$i]->id . '">' . img_delete() . '</a>';
2438  print '</td>';
2439 
2440  // Display lines extrafields
2441  if (! empty($rowExtrafieldsStart))
2442  {
2443  print $rowExtrafieldsStart;
2444  print $rowExtrafieldsView;
2445  print $rowEnd;
2446  }
2447  }
2448  print "</tr>";
2449 
2450  // Display lines extrafields
2451  if (is_array($extralabelslines) && count($extralabelslines)>0) {
2452  $colspan= empty($conf->productbatch->enabled) ? 5 : 6;
2453  $line = new ExpeditionLigne($db);
2454  $line->fetch_optionals($lines[$i]->id,$extralabelslines);
2455  print '<tr class="oddeven">';
2456  if ($action == 'editline' && $lines[$i]->id == $line_id)
2457  {
2458  print $line->showOptionals($extrafieldsline, 'edit', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
2459  }
2460  else
2461  {
2462  print $line->showOptionals($extrafieldsline, 'view', array('style'=>$bc[$var], 'colspan'=>$colspan),$indiceAsked);
2463  }
2464  print '</tr>';
2465  }
2466  }
2467 
2468  // TODO Show also lines ordered but not delivered
2469 
2470  print "</table>\n";
2471  print '</div>';
2472  }
2473 
2474 
2475  dol_fiche_end();
2476 
2477 
2478  $object->fetchObjectLinked($object->id,$object->element);
2479 
2480 
2481  /*
2482  * Boutons actions
2483  */
2484 
2485  if (($user->societe_id == 0) && ($action!='presend'))
2486  {
2487  print '<div class="tabsAction">';
2488 
2489  $parameters = array();
2490  $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
2491  // modified by hook
2492  if (empty($reshook))
2493  {
2494 
2495  if ($object->statut == 0 && $num_prod > 0)
2496  {
2497  if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->creer))
2498  || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->expedition->shipping_advance->validate)))
2499  {
2500  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=valid">'.$langs->trans("Validate").'</a>';
2501  }
2502  else
2503  {
2504  print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
2505  }
2506  }
2507 
2508  // TODO add alternative status
2509  // 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
2510  if ($object->statut == 2 && $object->billed && $user->rights->expedition->creer)
2511  {
2512  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=reopen">'.$langs->trans("ReOpen").'</a>';
2513  }
2514 
2515  // Send
2516  if ($object->statut > 0)
2517  {
2518  if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->expedition->shipping_advance->send)
2519  {
2520  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
2521  }
2522  else print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
2523  }
2524 
2525  // Create bill
2526  if (! empty($conf->facture->enabled) && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED))
2527  {
2528  if ($user->rights->facture->creer)
2529  {
2530  // TODO show button only if (! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
2531  // If we do that, we must also make this option official.
2532  print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
2533  }
2534  }
2535 
2536  // This is just to generate a delivery receipt
2537  //var_dump($object->linkedObjectsIds['delivery']);
2538  if ($conf->livraison_bon->enabled && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED) && $user->rights->expedition->livraison->creer && count($object->linkedObjectsIds['delivery']) == 0)
2539  {
2540  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=create_delivery">'.$langs->trans("CreateDeliveryOrder").'</a>';
2541  }
2542  // Close
2543  if ($object->statut == Expedition::STATUS_VALIDATED)
2544  {
2545  if ($user->rights->expedition->creer && $object->statut > 0 && ! $object->billed)
2546  {
2547  $label="Close"; $paramaction='classifyclosed'; // = Transferred/Received
2548  // Label here should be "Close" or "ClassifyBilled" if we decided to make bill on shipments instead of orders
2549  if (! empty($conf->facture->enabled) && ! empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
2550  {
2551  $label="ClassifyBilled";
2552  $paramaction='classifybilled';
2553  }
2554  print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action='.$paramaction.'">'.$langs->trans($label).'</a>';
2555  }
2556  }
2557 
2558  if ($user->rights->expedition->supprimer)
2559  {
2560  print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&amp;action=delete">'.$langs->trans("Delete").'</a>';
2561  }
2562 
2563  }
2564 
2565  print '</div>';
2566  }
2567 
2568 
2569  /*
2570  * Documents generated
2571  */
2572 
2573  if ($action != 'presend' && $action != 'editline')
2574  {
2575  print '<div class="fichecenter"><div class="fichehalfleft">';
2576 
2577  $objectref = dol_sanitizeFileName($object->ref);
2578  $filedir = $conf->expedition->dir_output . "/sending/" .$objectref;
2579 
2580  $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
2581 
2582  $genallowed=$user->rights->expedition->lire;
2583  $delallowed=$user->rights->expedition->creer;
2584 
2585  print $formfile->showdocuments('expedition',$objectref,$filedir,$urlsource,$genallowed,$delallowed,$object->modelpdf,1,0,0,28,0,'','','',$soc->default_lang);
2586 
2587 
2588  // Show links to link elements
2589  //$linktoelem = $form->showLinkToObjectBlock($object, null, array('order'));
2590  $somethingshown = $form->showLinkedObjectBlock($object, '');
2591 
2592 
2593  print '</div><div class="fichehalfright"><div class="ficheaddleft">';
2594 
2595  // List of actions on element
2596  include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
2597  $formactions=new FormActions($db);
2598  $somethingshown = $formactions->showactions($object,'shipping',$socid,1);
2599 
2600  print '</div></div></div>';
2601  }
2602 
2603 
2604  /*
2605  * Action presend
2606  */
2607 
2608  //Select mail models is same action as presend
2609  if (GETPOST('modelselected')) {
2610  $action = 'presend';
2611  }
2612 
2613  // Presend form
2614  $modelmail='shipping_send';
2615  $defaulttopic='SendShippingRef';
2616  $diroutput = $conf->expedition->dir_output. '/sending';
2617  $trackid = 'shi'.$object->id;
2618 
2619  include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
2620 }
2621 
2622 
2623 llxFooter();
2624 
2625 $db->close();
shipping_prepare_head($object)
Prepare array with list of tabs.
llxFooter()
Empty footer.
Definition: wrapper.php:58
Class to manage notifications.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='')
Show picto whatever it's its name (generic function)
Class with list of lots and properties.
Classe de gestion des lignes de bons d'expedition.
setEventMessages($mesg, $mesgs, $style='mesgs')
Set event messages in dol_events session object.
Class to manage building of HTML components.
CRUD class for batch number management within shipment.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm=false, $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_fiche_head($links=array(), $active='0', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='')
Show tab header of a card.
</td >< tdclass="liste_titre"align="right"></td ></tr >< trclass="liste_titre">< inputtype="checkbox"onClick="toggle(this)"/> Ref p ref Label p label Duration p duration warehouseinternal SELECT description FROM product_lang WHERE qty< br > qty qty qty StockTooLow img yes disabled img no img no< trclass="oddeven">< td >< inputtype="checkbox"class="check"name="'.$i.'"'.$disabled.'></td >< td >< inputtype="checkbox"class="check"name="choose'.$i.'"></td >< tdclass="nowrap"></td >< td >< inputtype="hidden"name="desc'.$i.'"value="'.dol_escape_htmltag($objp-> description
Only used if Module[ID]Desc translation string is not found.
Definition: replenish.php:554
dol_sanitizeFileName($str, $newstr='_', $unaccent=1)
Clean a string to use it as a file name.
if(GETPOST('cancel','alpha')) if(!GETPOST('confirmmassaction','alpha')&&$massaction!= 'presend'&&$massaction!= 'confirm_presend')
Draft customers invoices.
Definition: list.php:147
Class to manage products or services.
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.
Class to manage Dolibarr users.
Definition: user.class.php:39
const TYPE_SERVICE
Service.
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
const TYPE_PRODUCT
Regular product.
if(empty($reshook)) $form
View.
Definition: perms.php:103
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
GETPOST($paramname, $check='none', $method=0, $filter=NULL, $options=NULL, $noreplace=0)
Return value of a param into GET or POST supervariable.
Class to manage order lines.
Class with static methods for building HTML components related to products Only components common to ...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0)
Show a message to say access is forbidden and stop program Calling this function terminate execution ...
Class to manage standard extra fields.
Class to manage generation of HTML components Only common components must be here.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1')
Show information for admin users or standard users.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
Class to manage third parties objects (customers, suppliers, prospects...)
img_warning($titlealt= 'default', $moreatt= '')
Show warning logo.
Class to manage projects.
Class to manage building of HTML components.
Class to manage shipments.
dol_fiche_end($notab=0)
Show tab footer of a card.
Class to manage customers orders.
load_fiche_titre($titre, $morehtmlright='', $picto='title_generic.png', $pictoisfullpath=0, $id=0, $morecssontable='', $morehtmlcenter='')
Load a title with picto.
llxHeader()
Empty header.
Definition: wrapper.php:46
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Class to manage translations.
img_delete($titlealt= 'default', $other= 'class="pictodelete"')
Show delete logo.
Class to offer components to list and upload files.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Manage record for batch number management.
print
Draft customers invoices.
Definition: index.php:91
setEventMessage($mesgs, $style='mesgs')
Set event message in dol_events session object.
if(preg_match('/set_(.*)/', $action, $reg)) if(preg_match('/del_(.*)/', $action, $reg)) if($action== 'set') else if($action== 'specimen') else if($action== 'setmodel') else if($action== 'del') else if($action== 'setdoc' $formactions)
View.
measuring_units_string($unit, $measuring_style='')
Return translation label of a unit key.
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->societe->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if(!empty($conf->fournisseur->enabled)&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1013
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...
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null)
Remove a file or several files with a mask.
Definition: files.lib.php:1103
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput='no')
Output a dimension with best unit.
Class to manage a WYSIWYG editor.
static liste_modeles($db, $maxfilenamelength=0)
Return list of active generation modules.
print_date_range($date_start, $date_end, $format= '', $outputlangs='')
Format output for start and end date.
img_edit($titlealt= 'default', $float=0, $other= 'class="pictoedit"')
Show logo editer/modifier fiche.
restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null)
Check permissions of a user to show a page and an object.
Class to manage proposals.
$parameters
Actions.
Definition: card.php:112
Class to manage warehouses.