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