dolibarr 20.0.5
dispatch.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005 Eric Seigne <eric.seigne@ryxeo.com>
5 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2010-2021 Juanjo Menent <jmenent@2byte.es>
7 * Copyright (C) 2014 Cedric Gross <c.gross@kreiz-it.fr>
8 * Copyright (C) 2016 Florian Henry <florian.henry@atm-consulting.fr>
9 * Copyright (C) 2017-2022 Ferran Marcet <fmarcet@2byte.es>
10 * Copyright (C) 2018-2022 Frédéric France <frederic.france@netlogic.fr>
11 * Copyright (C) 2019-2020 Christophe Battarel <christophe@altairis.fr>
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <https://www.gnu.org/licenses/>.
25 */
26
33// Load Dolibarr environment
34require '../main.inc.php';
35require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php';
36require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
37require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
38require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
39require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
40require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
41require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
42require_once DOL_DOCUMENT_ROOT.'/core/lib/sendings.lib.php';
43if (isModEnabled('project')) {
44 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
45}
46
47// Load translation files required by the page
48$langs->loadLangs(array("sendings", "companies", "bills", 'deliveries', 'orders', 'stocks', 'other', 'propal', 'receptions'));
49
50if (isModEnabled('productbatch')) {
51 $langs->load('productbatch');
52}
53
54// Security check
55$id = GETPOSTINT("id");
56$ref = GETPOST('ref');
57$lineid = GETPOSTINT('lineid');
58$action = GETPOST('action', 'aZ09');
59$fk_default_warehouse = GETPOSTINT('fk_default_warehouse');
60$cancel = GETPOST('cancel', 'alpha');
61$confirm = GETPOST('confirm', 'alpha');
62
63$error = 0;
64$errors = array();
65
66if ($user->socid) {
67 $socid = $user->socid;
68}
69
70$hookmanager->initHooks(array('expeditiondispatch'));
71
72// Recuperation de l'id de projet
73$projectid = 0;
74if (GETPOSTISSET("projectid")) {
75 $projectid = GETPOSTINT("projectid");
76}
77
78$object = new Expedition($db);
79$objectorder = new Commande($db);
80
81
82if ($id > 0 || !empty($ref)) {
83 $result = $object->fetch($id, $ref);
84 if ($result <= 0) {
85 setEventMessages($object->error, $object->errors, 'errors');
86 }
87 $result = $object->fetch_thirdparty();
88 if ($result < 0) {
89 setEventMessages($object->error, $object->errors, 'errors');
90 }
91 if (!empty($object->origin)) {
92 $origin = $object->origin;
93 $typeobject = $object->origin;
94
95 $object->fetch_origin();
96 }
97}
98
99// $id is id of a purchase order.
100$result = restrictedArea($user, 'expedition', $object, '');
101
102if (!isModEnabled('stock')) {
103 accessforbidden('Module stock disabled');
104}
105
106$usercancreate = $user->hasRight('expedition', 'creer');
107$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php
108
109
110/*
111 * Actions
112 */
113
114$parameters = array();
115$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
116if ($reshook < 0) {
117 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
118}
119
120// Update a dispatched line
121if ($action == 'updatelines' && $usercancreate) {
122 $db->begin();
123 $error = 0;
124
125 $expeditiondispatch = new ExpeditionLigne($db);
126 $expeditionlinebatch = new ExpeditionLineBatch($db);
127
128 $pos = 0;
129
130 foreach ($_POST as $key => $value) {
131 // without batch module enabled
132 $reg = array();
133 if (preg_match('/^product_.*([0-9]+)_([0-9]+)$/i', $key, $reg)) {
134 $pos++;
135 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
136 $modebatch = "barcode";
137 } elseif (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { // With batchmode enabled
138 $modebatch = "batch";
139 }
140
141 $numline = $pos;
142 if ($modebatch == "barcode") {
143 $prod = "product_".$reg[1].'_'.$reg[2];
144 } else {
145 $prod = 'product_batch_'.$reg[1].'_'.$reg[2];
146 }
147 $qty = "qty_".$reg[1].'_'.$reg[2];
148 $ent = "entrepot_".$reg[1].'_'.$reg[2];
149 $fk_commandedet = "fk_commandedet_".$reg[1].'_'.$reg[2];
150 $idline = GETPOST("idline_".$reg[1].'_'.$reg[2]);
151 $warehouse_id = GETPOSTINT($ent);
152 $prod_id = GETPOSTINT($prod);
153 //$pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount
154 $lot = '';
155 $dDLUO = '';
156 $dDLC = '';
157 if ($modebatch == "batch") { //TODO: Make impossible to input non existing batch code
158 $lot = GETPOST('lot_number_'.$reg[1].'_'.$reg[2]);
159 $dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo_'.$reg[1].'_'.$reg[2].'month'), GETPOSTINT('dluo_'.$reg[1].'_'.$reg[2].'day'), GETPOSTINT('dluo_'.$reg[1].'_'.$reg[2].'year'));
160 $dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc_'.$reg[1].'_'.$reg[2].'month'), GETPOSTINT('dlc_'.$reg[1].'_'.$reg[2].'day'), GETPOSTINT('dlc_'.$reg[1].'_'.$reg[2].'year'));
161 }
162
163 $newqty = GETPOSTFLOAT($qty, 'MS');
164 //var_dump("modebatch=".$modebatch." newqty=".$newqty." ent=".$ent." idline=".$idline);
165
166 // We ask to move a qty
167 if (($modebatch == "batch" && $newqty >= 0) || ($modebatch == "barcode" && $newqty != 0)) {
168 if ($newqty > 0) { // If we want a qty, we make test on input data
169 if (!($warehouse_id > 0)) {
170 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.');
171 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline);
172 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
173 $error++;
174 }
175 if (!$error && $modebatch == "batch") {
176 $sql = "SELECT pb.rowid ";
177 $sql .= " FROM ".MAIN_DB_PREFIX."product_batch as pb";
178 $sql .= " JOIN ".MAIN_DB_PREFIX."product_stock as ps";
179 $sql .= " ON ps.rowid = pb.fk_product_stock";
180 $sql .= " WHERE pb.batch = '".$db->escape($lot)."'";
181 $sql .= " AND ps.fk_product = ".((int) $prod_id) ;
182 $sql .= " AND ps.fk_entrepot = ".((int) $warehouse_id) ;
183
184 $resql = $db->query($sql);
185 if ($resql) {
186 $num = $db->num_rows($resql);
187 if ($num > 1) {
188 dol_syslog('No dispatch for line '.$key.' as too many combination warehouse, product, batch code was found ('.$num.').');
189 setEventMessages($langs->trans('ErrorTooManyCombinationBatchcode', $numline, $num), null, 'errors');
190 $error++;
191 } elseif ($num < 1) {
192 $tmpwarehouse = new Entrepot($db);
193 $tmpwarehouse->fetch($warehouse_id);
194 $tmpprod = new Product($db);
195 $tmpprod->fetch($prod_id);
196 dol_syslog('No dispatch for line '.$key.' as no combination warehouse, product, batch code was found.');
197 setEventMessages($langs->trans('ErrorNoCombinationBatchcode', $numline, $tmpwarehouse->ref, $tmpprod->ref, $lot), null, 'errors');
198 $error++;
199 }
200 $db->free($resql);
201 }
202 }
203 }
204 //var_dump($key.' '.$newqty.' '.$idline.' '.$error);
205
206 if (!$error) {
207 $qtystart = 0;
208
209 if ($idline > 0) {
210 $result = $expeditiondispatch->fetch($idline); // get line from llx_expeditiondet
211 if ($result < 0) {
212 setEventMessages($expeditiondispatch->error, $expeditiondispatch->errors, 'errors');
213 $error++;
214 } else {
215 $qtystart = $expeditiondispatch->qty;
216 $expeditiondispatch->qty = $newqty;
217 $expeditiondispatch->entrepot_id = GETPOSTINT($ent);
218
219 if ($newqty > 0) {
220 $result = $expeditiondispatch->update($user);
221 } else {
222 $result = $expeditiondispatch->delete($user);
223 }
224 if ($result < 0) {
225 setEventMessages($expeditiondispatch->error, $expeditiondispatch->errors, 'errors');
226 $error++;
227 }
228
229 if (!$error && $modebatch == "batch") {
230 if ($newqty > 0) {
231 $suffixkeyfordate = preg_replace('/^product_batch/', '', $key);
232 $sellby = dol_mktime(0, 0, 0, GETPOST('dlc'.$suffixkeyfordate.'month'), GETPOST('dlc'.$suffixkeyfordate.'day'), GETPOST('dlc'.$suffixkeyfordate.'year'), '');
233 $eatby = dol_mktime(0, 0, 0, GETPOST('dluo'.$suffixkeyfordate.'month'), GETPOST('dluo'.$suffixkeyfordate.'day'), GETPOST('dluo'.$suffixkeyfordate.'year'));
234
235 $sqlsearchdet = "SELECT rowid FROM ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element;
236 $sqlsearchdet .= " WHERE fk_expeditiondet = ".((int) $idline);
237 $sqlsearchdet .= " AND batch = '".$db->escape($lot)."'";
238 $resqlsearchdet = $db->query($sqlsearchdet);
239
240 if ($resqlsearchdet) {
241 $objsearchdet = $db->fetch_object($resqlsearchdet);
242 } else {
243 dol_print_error($db);
244 }
245
246 if ($objsearchdet) {
247 $sql = "UPDATE ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element." SET";
248 $sql .= " eatby = ".($eatby ? "'".$db->idate($eatby)."'" : "null");
249 $sql .= " , sellby = ".($sellby ? "'".$db->idate($sellby)."'" : "null");
250 $sql .= " , qty = ".((float) $newqty);
251 $sql .= " , fk_warehouse = ".((int) $warehouse_id);
252 $sql .= " WHERE rowid = ".((int) $objsearchdet->rowid);
253 } else {
254 $sql = "INSERT INTO ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element." (";
255 $sql .= "fk_expeditiondet, eatby, sellby, batch, qty, fk_origin_stock, fk_warehouse)";
256 $sql .= " VALUES (".((int) $idline).", ".($eatby ? "'".$db->idate($eatby)."'" : "null").", ".($sellby ? "'".$db->idate($sellby)."'" : "null").", ";
257 $sql .= " '".$db->escape($lot)."', ".((float) $newqty).", 0, ".((int) $warehouse_id).")";
258 }
259 } else {
260 $sql = " DELETE FROM ".MAIN_DB_PREFIX.$expeditionlinebatch->table_element;
261 $sql .= " WHERE fk_expeditiondet = ".((int) $idline);
262 $sql .= " AND batch = '".$db->escape($lot)."'";
263 }
264
265 $resql = $db->query($sql);
266 if (!$resql) {
267 dol_print_error($db);
268 $error++;
269 }
270 }
271 }
272 } else {
273 $expeditiondispatch->fk_expedition = $object->id;
274 $expeditiondispatch->entrepot_id = GETPOSTINT($ent);
275 $expeditiondispatch->fk_elementdet = GETPOSTINT($fk_commandedet);
276 $expeditiondispatch->qty = $newqty;
277
278 if ($newqty > 0) {
279 $idline = $expeditiondispatch->insert($user);
280 if ($idline < 0) {
281 setEventMessages($expeditiondispatch->error, $expeditiondispatch->errors, 'errors');
282 $error++;
283 }
284
285 if ($modebatch == "batch" && !$error) {
286 $expeditionlinebatch->sellby = $dDLUO;
287 $expeditionlinebatch->eatby = $dDLC;
288 $expeditionlinebatch->batch = $lot;
289 $expeditionlinebatch->qty = $newqty;
290 $expeditionlinebatch->fk_origin_stock = 0;
291 $expeditionlinebatch->fk_warehouse = GETPOSTINT($ent);
292
293 $result = $expeditionlinebatch->create($idline);
294 if ($result < 0) {
295 setEventMessages($expeditionlinebatch->error, $expeditionlinebatch->errors, 'errors');
296 $error++;
297 }
298 }
299 }
300 }
301
302 // If module stock is enabled and the stock decrease is done on edition of this page
303 /*
304 if (!$error && GETPOST($ent, 'int') > 0 && isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT_DISPATCH_ORDER)) {
305 $mouv = new MouvementStock($db);
306 $product = GETPOST($prod, 'int');
307 $entrepot = GETPOST($ent, 'int');
308 $qtymouv = price2num(GETPOST($qty, 'alpha'), 'MS') - $qtystart;
309 $price = price2num(GETPOST($pu), 'MU');
310 $comment = GETPOST('comment');
311 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
312 $now = dol_now();
313 $eatby = '';
314 $sellby = '';
315 $batch = '';
316 if ($modebatch == "batch") {
317 $eatby = $dDLUO;
318 $sellby = $dDLC;
319 $batch = $lot ;
320 }
321 if ($product > 0 && $qtymouv != 0) {
322 // $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on)
323 $mouv->origin = $objectorder;
324 $mouv->setOrigin($objectorder->element, $objectorder->id);
325
326 // Method change if qty < 0
327 if (!empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN) && $qtymouv < 0) {
328 $result = $mouv->reception($user, $product, $entrepot, $qtymouv*(-1), $price, $comment, $eatby, $sellby, $batch, '', 0, $inventorycode);
329 } else {
330 $result = $mouv->livraison($user, $product, $entrepot, $qtymouv, $price, $comment, $now, $eatby, $sellby, $batch, 0, $inventorycode);
331 }
332
333 if ($result < 0) {
334 setEventMessages($mouv->error, $mouv->errors, 'errors');
335 $error++;
336 }
337 }
338 }
339 */
340 }
341 }
342 }
343 }
344
345 if ($error > 0) {
346 $db->rollback();
347 setEventMessages($error, $errors, 'errors');
348 } else {
349 $db->commit();
350 setEventMessages($langs->trans("ShipmentUpdated"), null);
351
352 header("Location: ".DOL_URL_ROOT.'/expedition/dispatch.php?id='.$object->id);
353 exit;
354 }
355} elseif ($action == 'setdate_livraison' && $usercancreate) {
356 $datedelivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
357
358 $object->fetch($id);
359 $result = $object->setDeliveryDate($user, $datedelivery);
360 if ($result < 0) {
361 setEventMessages($object->error, $object->errors, 'errors');
362 }
363}
364
365
366/*
367 * View
368 */
369
370$now = dol_now();
371
372$form = new Form($db);
373$formproduct = new FormProduct($db);
374$warehouse_static = new Entrepot($db);
375
376$title = $object->ref." - ".$langs->trans('ShipmentDistribution');
377$help_url = 'EN:Module_Shipments|FR:Module_Expéditions|ES:M&oacute;dulo_Expediciones|DE:Modul_Lieferungen';
378$morejs = array('/expedition/js/lib_dispatch.js.php');
379
380llxHeader('', $title, $help_url, '', 0, 0, $morejs);
381
382if ($object->id > 0 || !empty($object->ref)) {
383 $lines = $object->lines; // This is an array of detail of line, on line per source order line found intolines[]->fk_elementdet, then each line may have sub data
384 //var_dump($lines[0]->fk_elementdet); exit;
385
386 $num_prod = count($lines);
387
388 if (!empty($object->origin) && $object->origin_id > 0) {
389 $object->origin = 'commande';
390 $typeobject = $object->origin;
391 $origin = $object->origin;
392
393 $object->fetch_origin(); // Load property $object->origin_object, $object->commande, $object->propal, ...
394 }
395 $soc = new Societe($db);
396 $soc->fetch($object->socid);
397
398 $author = new User($db);
399 $author->fetch($object->user_author_id);
400
401 $head = shipping_prepare_head($object);
402
403 print dol_get_fiche_head($head, 'dispatch', $langs->trans("Shipment"), -1, $object->picto);
404
405
406 $formconfirm = '';
407
408 // Confirmation to delete line
409 if ($action == 'ask_deleteline') {
410 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
411 }
412
413 // Call Hook formConfirm
414 $parameters = array('lineid' => $lineid);
415 // Note that $action and $object may be modified by hook
416 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
417 if (empty($reshook)) {
418 $formconfirm .= $hookmanager->resPrint;
419 } elseif ($reshook > 0) {
420 $formconfirm = $hookmanager->resPrint;
421 }
422
423 // Print form confirm
424 print $formconfirm;
425
426 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
427 $objectsrc = new Commande($db);
428 $objectsrc->fetch($object->origin_object->id);
429 }
430 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
431 $objectsrc = new Propal($db);
432 $objectsrc->fetch($object->origin_object->id);
433 }
434
435 // Shipment card
436 $linkback = '<a href="'.DOL_URL_ROOT.'/expedition/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
437 $morehtmlref = '<div class="refidno">';
438
439 // Ref customer shipment
440 $morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('expedition', 'creer'), 'string', '', 0, 1);
441 $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);
442
443 // Thirdparty
444 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
445 // Project
446 if (isModEnabled('project')) {
447 $langs->load("projects");
448 $morehtmlref .= '<br>';
449 if (0) { // Do not change on reception
450 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
451 if ($action != 'classify' && $permissiontoadd) {
452 $morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
453 }
454 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
455 } else {
456 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
457 $proj = new Project($db);
458 $proj->fetch($objectsrc->fk_project);
459 $morehtmlref .= $proj->getNomUrl(1);
460 if ($proj->title) {
461 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
462 }
463 }
464 }
465 }
466 $morehtmlref .= '</div>';
467
468 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
469
470
471 print '<div class="fichecenter">';
472 print '<div class="underbanner clearboth"></div>';
473
474 print '<table class="border tableforfield centpercent">';
475
476 // Linked documents
477 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
478 print '<tr><td>';
479 print $langs->trans("RefOrder").'</td>';
480 print '<td colspan="3">';
481 print $objectsrc->getNomUrl(1, 'commande');
482 print "</td>\n";
483 print '</tr>';
484 }
485 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
486 print '<tr><td>';
487 print $langs->trans("RefProposal").'</td>';
488 print '<td colspan="3">';
489 print $objectsrc->getNomUrl(1, 'expedition');
490 print "</td>\n";
491 print '</tr>';
492 }
493
494 // Date creation
495 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
496 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
497 print '</tr>';
498
499 // Delivery date planned
500 print '<tr><td height="10">';
501 print '<table class="nobordernopadding" width="100%"><tr><td>';
502 print $langs->trans('DateDeliveryPlanned');
503 print '</td>';
504 if ($action != 'editdate_livraison') {
505 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>';
506 }
507 print '</tr></table>';
508 print '</td><td colspan="2">';
509 if ($action == 'editdate_livraison') {
510 print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
511 print '<input type="hidden" name="token" value="'.newToken().'">';
512 print '<input type="hidden" name="action" value="setdate_livraison">';
513 print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
514 print '<input type="submit" class="button button-edit smallpaddingimp" value="'.$langs->trans('Modify').'">';
515 print '</form>';
516 } else {
517 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
518 }
519 print '</td>';
520 print '</tr></table>';
521
522 print '<br><center>';
523 if (isModEnabled('barcode') || isModEnabled('productbatch')) {
524 print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=updatebyscaning&token='.currentToken().'" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto('', 'barcode', 'class="paddingrightonly"').$langs->trans("UpdateByScaning").'</a>';
525 }
526 print '<a href="#" id="resetalltoexpected" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'autofill', 'class="pictofixedwidth"').$langs->trans("RestoreWithCurrentQtySaved").'</a></td>';
527 // Link to clear qty
528 print '<a href="#" id="autoreset" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'eraser', 'class="pictofixedwidth"').$langs->trans("ClearQtys").'</a></td>';
529 print '<center>';
530
531 print '<br>';
532 $disabled = 0; // This is used to disable or not the bulk selection of target warehouse. No reason to have it disabled so forced to 0.
533
534 if ($object->statut == Expedition::STATUS_DRAFT) {
535 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
536 $formproduct = new FormProduct($db);
537 $formproduct->loadWarehouses();
538 $entrepot = new Entrepot($db);
539 $listwarehouses = $entrepot->list_array(1);
540
541
542 print '<form method="post" action="'.$_SERVER["PHP_SELF"].'">';
543
544 print '<input type="hidden" name="token" value="'.newToken().'">';
545 print '<input type="hidden" name="action" value="updatelines">';
546 print '<input type="hidden" name="id" value="'.$object->id.'">';
547
548 print '<div class="div-table-responsive-no-min">';
549 print '<table class="noborder centpercent">';
550
551 // Get list of lines of the shipment $products_dispatched, with qty dispatched for each product id
552 $products_dispatched = array();
553 $sql = "SELECT ed.fk_elementdet as rowid, sum(ed.qty) as qty";
554 $sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
555 $sql .= " WHERE ed.fk_expedition = ".((int) $object->id);
556 $sql .= " GROUP BY ed.fk_elementdet";
557
558 $resql = $db->query($sql);
559 if ($resql) {
560 $num = $db->num_rows($resql);
561 $i = 0;
562
563 if ($num) {
564 while ($i < $num) {
565 $objd = $db->fetch_object($resql);
566 $products_dispatched[$objd->rowid] = price2num($objd->qty, 'MS');
567 $i++;
568 }
569 }
570 $db->free($resql);
571 }
572
573 //$sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,";
574 $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, '' AS sref, l.qty as qty,";
575 $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse, p.barcode";
576 // Enable hooks to alter the SQL query (SELECT)
577 $parameters = array();
578 $reshook = $hookmanager->executeHooks(
579 'printFieldListSelect',
580 $parameters,
581 $object,
582 $action
583 );
584 if ($reshook < 0) {
585 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
586 }
587 $sql .= $hookmanager->resPrint;
588
589 $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as l";
590 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid";
591 $sql .= " WHERE l.fk_commande = ".((int) $objectsrc->id);
592 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
593 $sql .= " AND l.product_type = 0";
594 }
595 // Enable hooks to alter the SQL query (WHERE)
596 $parameters = array();
597 $reshook = $hookmanager->executeHooks(
598 'printFieldListWhere',
599 $parameters,
600 $object,
601 $action
602 );
603 if ($reshook < 0) {
604 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
605 }
606 $sql .= $hookmanager->resPrint;
607
608 //$sql .= " GROUP BY p.ref, p.label, p.tobatch, p.fk_default_warehouse, l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref"; // Calculation of amount dispatched is done per fk_product so we must group by fk_product
609 $sql .= " ORDER BY l.rang, p.ref, p.label";
610
611 $resql = $db->query($sql);
612 if ($resql) {
613 $num = $db->num_rows($resql);
614 $i = 0;
615 $numline = 1;
616
617 if ($num) {
618 print '<tr class="liste_titre">';
619
620 print '<td>'.$langs->trans("Description").'</td>';
621 if (isModEnabled('productbatch')) {
622 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>';
623 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
624 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>';
625 }
626 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
627 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>';
628 }
629 } else {
630 print '<td></td>';
631 print '<td></td>';
632 print '<td></td>';
633 }
634 print '<td class="right">'.$langs->trans("QtyOrdered").'</td>';
635 if ($object->status == Expedition::STATUS_DRAFT) {
636 print '<td class="right">'.$langs->trans("QtyToShip"); // Qty to dispatch (sum for all lines of batch detail if there is)
637 } else {
638 print '<td class="right">'.$langs->trans("QtyDispatchedShort").'</td>';
639 }
640 print '<td class="right">'.$langs->trans("Details");
641 print '<td width="32"></td>';
642
643 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
644 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
645 print '<td class="right">'.$langs->trans("Price").'</td>';
646 print '<td class="right">'.$langs->trans("ReductionShort").' (%)</td>';
647 print '<td class="right">'.$langs->trans("UpdatePrice").'</td>';
648 }
649 }
650
651 print '<td align="right">'.$langs->trans("Warehouse");
652
653 // Select warehouse to force it everywhere
654 if (count($listwarehouses) > 1) {
655 print '<br><span class="opacitymedium">'.$langs->trans("ForceTo").'</span> '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 1, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1);
656 } elseif (count($listwarehouses) == 1) {
657 print '<br><span class="opacitymedium">'.$langs->trans("ForceTo").'</span> '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1);
658 }
659
660 print '</td>';
661
662 // Enable hooks to append additional columns
663 $parameters = array();
664 $reshook = $hookmanager->executeHooks(
665 'printFieldListTitle',
666 $parameters,
667 $object,
668 $action
669 );
670 if ($reshook < 0) {
671 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
672 }
673 print $hookmanager->resPrint;
674
675 print "</tr>\n";
676 }
677
678 $nbfreeproduct = 0; // Nb of lins of free products/services
679 $nbproduct = 0; // Nb of predefined product lines to dispatch (already done or not) if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is off (default)
680 // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on.
681
682 $conf->cache['product'] = array();
683
684 // Loop on each line of origin order
685 while ($i < $num) {
686 $objp = $db->fetch_object($resql);
687
688 // On n'affiche pas les produits libres
689 if (!$objp->fk_product > 0) {
690 $nbfreeproduct++;
691 } else {
692 $alreadydispatched = isset($products_dispatched[$objp->rowid]) ? $products_dispatched[$objp->rowid] : 0;
693 $remaintodispatch = price2num($objp->qty, 5); // Calculation of dispatched
694 if ($remaintodispatch < 0 && !getDolGlobalString('SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN')) {
695 $remaintodispatch = 0;
696 }
697
698 if ($remaintodispatch || !getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
699 $nbproduct++;
700
701 // To show detail cref and description value, we must make calculation by cref
702 // print ($objp->cref?' ('.$objp->cref.')':'');
703 // if ($objp->description) print '<br>'.nl2br($objp->description);
704 $suffix = '_0_'.$i;
705
706 print "\n";
707 print '<!-- Line to dispatch '.$suffix.' -->'."\n";
708 // hidden fields for js function
709 print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$objp->qty.'">';
710 print '<input id="qty_dispatched'.$suffix.'" type="hidden" data-dispatched="'.((float) $alreadydispatched).'" value="'.(float) $alreadydispatched.'">';
711 print '<tr class="oddeven">';
712
713 if (empty($conf->cache['product'][$objp->fk_product])) {
714 $tmpproduct = new Product($db);
715 $tmpproduct->fetch($objp->fk_product);
716 $conf->cache['product'][$objp->fk_product] = $tmpproduct;
717 } else {
718 $tmpproduct = $conf->cache['product'][$objp->fk_product];
719 }
720
721 $linktoprod = $tmpproduct->getNomUrl(1);
722 $linktoprod .= ' - '.$objp->label."\n";
723
724 if (isModEnabled('productbatch')) {
725 if ($objp->tobatch) {
726 // Product
727 print '<td id="product_'.$i.'" data-idproduct="'.$objp->fk_product.'" data-barcode="'.$objp->barcode.'">';
728 print $linktoprod;
729 print "</td>";
730 print '<td class="dispatch_batch_number"></td>';
731 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
732 print '<td class="dispatch_dlc"></td>';
733 }
734 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
735 print '<td class="dispatch_dluo"></td>';
736 }
737 } else {
738 // Product
739 print '<td id="product_'.$i.'" data-idproduct="'.$objp->fk_product.'" data-barcode="'.$objp->barcode.'">';
740 print $linktoprod;
741 print "</td>";
742 print '<td class="dispatch_batch_number">';
743 print '<span class="opacitymedium small">'.$langs->trans("ProductDoesNotUseBatchSerial").'</span>';
744 print '</td>';
745 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
746 print '<td class="dispatch_dlc"></td>';
747 }
748 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
749 print '<td class="dispatch_dluo"></td>';
750 }
751 }
752 } else {
753 print '<td colspan="4">';
754 print $linktoprod;
755 print "</td>";
756 }
757
758 // Define unit price for PMP calculation
759 $up_ht_disc = $objp->subprice;
760 if (!empty($objp->remise_percent) && !getDolGlobalString('STOCK_EXCLUDE_DISCOUNT_FOR_PMP')) {
761 $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
762 }
763
764 // Qty ordered
765 print '<td class="right">'.$objp->qty.'</td>';
766
767 // Already dispatched
768 print '<td class="right">'.$alreadydispatched.'</td>';
769
770 print '<td class="right">';
771 print '</td>'; // Qty to dispatch
772 print '<td>';
773 print '</td>'; // Dispatch column
774 print '<td></td>'; // Warehouse column
775
776 $sql = "SELECT ed.rowid";
777 $sql .= ", cd.fk_product";
778 $sql .= ", ".$db->ifsql('eb.rowid IS NULL', 'ed.qty', 'eb.qty')." as qty";
779 $sql .= ", ed.fk_entrepot";
780 $sql .= ", eb.batch, eb.eatby, eb.sellby";
781 $sql .= " FROM ".$db->prefix()."expeditiondet as ed";
782 $sql .= " LEFT JOIN ".$db->prefix()."expeditiondet_batch as eb on ed.rowid = eb.fk_expeditiondet";
783 $sql .= " INNER JOIN ".$db->prefix()."commandedet as cd on ed.fk_elementdet = cd.rowid";
784 $sql .= " WHERE ed.fk_elementdet = ".(int) $objp->rowid;
785 $sql .= " AND ed.fk_expedition = ".(int) $object->id;
786 $sql .= " ORDER BY ed.rowid, ed.fk_elementdet";
787
788 $resultsql = $db->query($sql);
789 $j = 0;
790 if ($resultsql) {
791 $numd = $db->num_rows($resultsql);
792
793 while ($j < $numd) {
794 $suffix = "_".$j."_".$i;
795 $objd = $db->fetch_object($resultsql);
796
797 if (isModEnabled('productbatch') && (!empty($objd->batch) || (is_null($objd->batch) && $tmpproduct->status_batch > 0))) {
798 $type = 'batch';
799
800 // Enable hooks to append additional columns
801 $parameters = array(
802 // allows hook to distinguish between the rows with information and the rows with dispatch form input
803 'is_information_row' => true,
804 'j' => $j,
805 'suffix' => $suffix,
806 'objd' => $objd,
807 );
808 $reshook = $hookmanager->executeHooks(
809 'printFieldListValue',
810 $parameters,
811 $object,
812 $action
813 );
814 if ($reshook < 0) {
815 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
816 }
817 print $hookmanager->resPrint;
818
819 print '</tr>';
820
821 print '<!-- line for batch '.$numline.' -->';
822 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
823 print '<td>';
824 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
825 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
826 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
827
828 print '<!-- This is a U.P. (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
829 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
830
831 print '</td>';
832
833 print '<td>';
834 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.(GETPOSTISSET('lot_number'.$suffix) ? GETPOST('lot_number'.$suffix) : $objd->batch).'">';
835 //print '<input type="hidden" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.$objd->batch.'">';
836 print '</td>';
837 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
838 print '<td class="nowraponall">';
839 $dlcdatesuffix = !empty($objd->sellby) ? dol_stringtotime($objd->sellby) : dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year'));
840 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
841 print '</td>';
842 }
843 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
844 print '<td class="nowraponall">';
845 $dluodatesuffix = !empty($objd->eatby) ? dol_stringtotime($objd->eatby) : dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year'));
846 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
847 print '</td>';
848 }
849 print '<td colspan="2">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
850 } else {
851 $type = 'dispatch';
852 $colspan = 6;
853 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
854 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
855
856 // Enable hooks to append additional columns
857 $parameters = array(
858 // allows hook to distinguish between the rows with information and the rows with dispatch form input
859 'is_information_row' => true,
860 'j' => $j,
861 'suffix' => $suffix,
862 'objd' => $objd,
863 );
864 $reshook = $hookmanager->executeHooks(
865 'printFieldListValue',
866 $parameters,
867 $object,
868 $action
869 );
870 if ($reshook < 0) {
871 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
872 }
873 print $hookmanager->resPrint;
874
875 print '</tr>';
876
877 print '<!-- line no batch '.$numline.' -->';
878 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
879 print '<td colspan="'.$colspan.'">';
880 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
881 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
882 print '<input name="product'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
883 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
884 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
885 print '</td>';
886 }
887 // Qty to dispatch
888 print '<td class="right nowraponall">';
889 print '<a href="" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
890 $suggestedvalue = (GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : $objd->qty);
891 //var_dump($suggestedvalue);exit;
892 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-type="'.$type.'" data-index="'.$i.'" class="width50 right qtydispatchinput" value="'.$suggestedvalue.'" data-expected="'.$objd->qty.'">';
893 print '</td>';
894 print '<td>';
895 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
896 $type = 'batch';
897 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j + 1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
898 } else {
899 $type = 'dispatch';
900 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j + 1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
901 }
902
903 print '</td>';
904
905 // Warehouse
906 print '<td class="right">';
907 if (count($listwarehouses) > 1) {
908 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix);
909 } elseif (count($listwarehouses) == 1) {
910 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix);
911 } else {
912 $langs->load("errors");
913 print $langs->trans("ErrorNoWarehouseDefined");
914 }
915 print "</td>\n";
916
917 // Enable hooks to append additional columns
918 $parameters = array(
919 'is_information_row' => false, // this is a dispatch form row
920 'i' => $i,
921 'suffix' => $suffix,
922 'objp' => $objp,
923 );
924 $reshook = $hookmanager->executeHooks(
925 'printFieldListValue',
926 $parameters,
927 $object,
928 $action
929 );
930 if ($reshook < 0) {
931 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
932 }
933 print $hookmanager->resPrint;
934
935 print "</tr>\n";
936 $j++;
937
938 $numline++;
939 }
940 $suffix = "_".$j."_".$i;
941 } else {
942 $errorMsg = 'Shipment dispatch SQL error : '.$db->lasterror();
943 setEventMessage($errorMsg, 'errors');
944 dol_syslog($errorMsg, LOG_ERR);
945 }
946
947 if ($j == 0) {
948 if (isModEnabled('productbatch') && !empty($objp->tobatch)) {
949 $type = 'batch';
950
951 // Enable hooks to append additional columns
952 $parameters = array(
953 // allows hook to distinguish between the rows with information and the rows with dispatch form input
954 'is_information_row' => true,
955 'j' => $j,
956 'suffix' => $suffix,
957 'objp' => $objp,
958 );
959 $reshook = $hookmanager->executeHooks(
960 'printFieldListValue',
961 $parameters,
962 $object,
963 $action
964 );
965 if ($reshook < 0) {
966 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
967 }
968 print $hookmanager->resPrint;
969
970 print '</tr>';
971
972 print '<!-- line for batch '.$numline.' (not dispatched line yet for this order line) -->';
973 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
974 print '<td>';
975 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
976 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
977 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
978
979 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
980 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
981 print '</td>';
982
983 print '<td>';
984 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.GETPOST('lot_number'.$suffix).'">';
985 print '</td>';
986 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
987 print '<td class="nowraponall">';
988 $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year'));
989 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
990 print '</td>';
991 }
992 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
993 print '<td class="nowraponall">';
994 $dluodatesuffix = dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year'));
995 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
996 print '</td>';
997 }
998 print '<td colspan="2">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
999 } else {
1000 $type = 'dispatch';
1001 $colspan = 6;
1002 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
1003 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
1004
1005 // Enable hooks to append additional columns
1006 $parameters = array(
1007 // allows hook to distinguish between the rows with information and the rows with dispatch form input
1008 'is_information_row' => true,
1009 'j' => $j,
1010 'suffix' => $suffix,
1011 'objp' => $objp,
1012 );
1013 $reshook = $hookmanager->executeHooks(
1014 'printFieldListValue',
1015 $parameters,
1016 $object,
1017 $action
1018 );
1019 if ($reshook < 0) {
1020 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1021 }
1022 print $hookmanager->resPrint;
1023
1024 print '</tr>';
1025
1026 print '<!-- line no batch '.$numline.' (not dispatched line yet for this order line) -->';
1027 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
1028 print '<td colspan="'.$colspan.'">';
1029 print '<input id="fk_commandedet'.$suffix.'" name="fk_commandedet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
1030 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
1031 print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
1032
1033 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
1034 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
1035 print '</td>';
1036 }
1037 // Qty to dispatch
1038 print '<td class="right">';
1039 print '<a href="" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
1040 $amounttosuggest = (GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : (!getDolGlobalString('SUPPLIER_ORDER_DISPATCH_FORCE_QTY_INPUT_TO_ZERO') ? $remaintodispatch : 0));
1041 if (count($products_dispatched)) {
1042 // There is already existing lines into llx_expeditiondet, this means a plan for the shipment has already been started.
1043 // In such a case, we do not suggest new values, we suggest the value known.
1044 $amounttosuggest = (GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : (isset($products_dispatched[$objp->rowid]) ? $products_dispatched[$objp->rowid] : ''));
1045 }
1046 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-index="'.$i.'" data-type="text" class="width50 right qtydispatchinput" value="'.$amounttosuggest.'" data-expected="'.$amounttosuggest.'">';
1047 print '</td>';
1048 print '<td>';
1049 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
1050 $type = 'batch';
1051 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1052 } else {
1053 $type = 'dispatch';
1054 print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1055 }
1056
1057 print '</td>';
1058
1059 // Warehouse
1060 print '<td class="right">';
1061 if (count($listwarehouses) > 1) {
1062 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : ($objp->fk_default_warehouse ? $objp->fk_default_warehouse : ''), "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix);
1063 } elseif (count($listwarehouses) == 1) {
1064 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : ($objp->fk_default_warehouse ? $objp->fk_default_warehouse : ''), "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix);
1065 } else {
1066 $langs->load("errors");
1067 print $langs->trans("ErrorNoWarehouseDefined");
1068 }
1069 print "</td>\n";
1070
1071 // Enable hooks to append additional columns
1072 $parameters = array(
1073 'is_information_row' => false, // this is a dispatch form row
1074 'i' => $i,
1075 'suffix' => $suffix,
1076 'objp' => $objp,
1077 );
1078 $reshook = $hookmanager->executeHooks(
1079 'printFieldListValue',
1080 $parameters,
1081 $object,
1082 $action
1083 );
1084 if ($reshook < 0) {
1085 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1086 }
1087 print $hookmanager->resPrint;
1088 print "</tr>\n";
1089 }
1090 }
1091 }
1092 $i++;
1093 }
1094 $db->free($resql);
1095 } else {
1096 dol_print_error($db);
1097 }
1098
1099 print "</table>\n";
1100 print '</div>';
1101
1102 if ($nbproduct) {
1103 //$checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll'));
1104
1105 print '<div class="center">';
1106 $parameters = array();
1107 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1108 // modified by hook
1109 if (empty($reshook)) {
1110 /*if (empty($conf->reception->enabled)) {
1111 print $langs->trans("Comment").' : ';
1112 print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="';
1113 print GETPOSTISSET("comment") ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref);
1114 // print ' / '.$object->ref_supplier; // Not yet available
1115 print '" class="flat"><br>';
1116
1117 print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel;
1118 }
1119
1120 $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception");
1121
1122 print '<br>';
1123 */
1124
1125 print '<input type="submit" id="submitform" class="button" name="dispatch" value="'.$langs->trans("Save").'"';
1126 $disabled = 0;
1127 if (!$usercancreate) {
1128 $disabled = 1;
1129 }
1130 if (count($listwarehouses) <= 0) {
1131 $disabled = 1;
1132 }
1133 if ($disabled) {
1134 print ' disabled';
1135 }
1136
1137 print '>';
1138 }
1139 print '</div>';
1140 }
1141
1142 // Message if nothing to dispatch
1143 if (!$nbproduct) {
1144 print "<br>\n";
1145 if (!getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
1146 print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all
1147 } else {
1148 print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched.
1149 }
1150 }
1151
1152 print '</form>';
1153 }
1154
1155 print dol_get_fiche_end();
1156
1157 // Popup for mass barcode scanning
1158 if ($action == 'updatebyscaning') {
1159 if ($permissiontoadd) {
1160 // Output the javascript to manage the scanner tool.
1161 print '<script>';
1162
1163 print '
1164 var duplicatedbatchcode = [];
1165 var errortab1 = [];
1166 var errortab2 = [];
1167 var errortab3 = [];
1168 var errortab4 = [];
1169
1170 function barcodescannerjs(){
1171 console.log("We catch inputs in scanner box");
1172 jQuery("#scantoolmessage").text();
1173
1174 var selectaddorreplace = $("select[name=selectaddorreplace]").val();
1175 var barcodemode = $("input[name=barcodemode]:checked").val();
1176 var barcodeproductqty = $("input[name=barcodeproductqty]").val();
1177 var warehousetouse = $("select[name=warehousenew]").val();
1178 var textarea = $("textarea[name=barcodelist]").val();
1179 var textarray = textarea.split(/[\s,;]+/);
1180 var tabproduct = [];
1181 duplicatedbatchcode = [];
1182 errortab1 = [];
1183 errortab2 = [];
1184 errortab3 = [];
1185 errortab4 = [];
1186
1187 textarray = textarray.filter(function(value){
1188 return value != "";
1189 });
1190 if(textarray.some((element) => element != "")){
1191 $(".qtydispatchinput").each(function(){
1192 id = $(this).attr(\'id\');
1193 idarray = id.split(\'_\');
1194 idproduct = idarray[2];
1195 id = idarray[1] + \'_\' + idarray[2];
1196 console.log("Analyze the line "+id+" in inventory, barcodemode="+barcodemode);
1197 warehouse = $("#entrepot_"+id).val();
1198 console.log(warehouse);
1199 productbarcode = $("#product_"+idproduct).attr(\'data-barcode\');
1200 console.log(productbarcode);
1201 productbatchcode = $("#lot_number_"+id).val();
1202 if(productbatchcode == undefined){
1203 productbatchcode = "";
1204 }
1205 console.log(productbatchcode);
1206
1207 if (barcodemode != "barcodeforproduct") {
1208 tabproduct.forEach(product=>{
1209 console.log("product.Batch="+product.Batch+" productbatchcode="+productbatchcode);
1210 if(product.Batch != "" && product.Batch == productbatchcode){
1211 console.log("duplicate batch code found for batch code "+productbatchcode);
1212 duplicatedbatchcode.push(productbatchcode);
1213 }
1214 })
1215 }
1216 productinput = $("#qty_"+id).val();
1217 if(productinput == ""){
1218 productinput = 0
1219 }
1220 tabproduct.push({\'Id\':id,\'Warehouse\':warehouse,\'Barcode\':productbarcode,\'Batch\':productbatchcode,\'Qty\':productinput,\'fetched\':false});
1221 });
1222 console.log("Loop on each record entered in the textarea");
1223
1224 textarray.forEach(function(element,index){
1225 console.log("Process record element="+element+" id="+id);
1226 var verify_batch = false;
1227 var verify_barcode = false;
1228 switch(barcodemode){
1229 case "barcodeforautodetect":
1230 verify_barcode = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"barcode",true);
1231 verify_batch = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"lotserial",true);
1232 break;
1233 case "barcodeforproduct":
1234 verify_barcode = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"barcode");
1235 break;
1236 case "barcodeforlotserial":
1237 verify_batch = barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,"lotserial");
1238 break;
1239 default:
1240 alert(\''.dol_escape_js($langs->trans("ErrorWrongBarcodemode")).' "\'+barcodemode+\'"\');
1241 throw \''.dol_escape_js($langs->trans('ErrorWrongBarcodemode')).' "\'+barcodemode+\'"\';
1242 }
1243
1244 if (verify_batch == false && verify_barcode == false) { /* If the 2 flags are false, not found error */
1245 errortab2.push(element);
1246 } else if (verify_batch == true && verify_barcode == true) { /* If the 2 flags are true, error: we don t know which one to take */
1247 errortab3.push(element);
1248 } else if (verify_batch == true) {
1249 console.log("element="+element);
1250 console.log(duplicatedbatchcode);
1251 if (duplicatedbatchcode.includes(element)) {
1252 errortab1.push(element);
1253 }
1254 }
1255 });
1256
1257 if (Object.keys(errortab1).length < 1 && Object.keys(errortab2).length < 1 && Object.keys(errortab3).length < 1) {
1258 tabproduct.forEach(product => {
1259 if(product.Qty!=0){
1260 if(product.hasOwnProperty("reelqty")){
1261 idprod = $("td[data-idproduct=\'"+product.fk_product+"\']").attr("id");
1262 idproduct = idprod.split("_")[1];
1263 console.log("We create a new line for product_"+idproduct);
1264 if(product.Barcode != null){
1265 modedispatch = "dispatch";
1266 } else {
1267 modedispatch = "batch";
1268 }
1269 addDispatchLine(idproduct,modedispatch);
1270 console.log($("tr[name^=\'"+modedispatch+"_\'][name$=\'_"+idproduct+"\']"));
1271 nbrTrs = $("tr[name^=\'"+modedispatch+"_\'][name$=\'_"+idproduct+"\']").length;
1272
1273 $("#qty_"+(nbrTrs-1)+"_"+idproduct).val(product.Qty);
1274 $("#entrepot_"+(nbrTrs-1)+"_"+idproduct).val(product.Warehouse);
1275
1276 if(modedispatch == "batch"){
1277 $("#lot_number_"+(nbrTrs-1)+"_"+idproduct).val(product.Batch);
1278 }
1279
1280 } else {
1281 console.log("We change #qty_"+product.Id +" to match input in scanner box");
1282 $("#qty_"+product.Id).val(product.Qty);
1283 }
1284 }
1285 });
1286 jQuery("#scantoolmessage").text("'.dol_escape_js($langs->transnoentities("QtyWasAddedToTheScannedBarcode")).'\n");
1287 /* document.forms["formrecord"].submit(); */
1288 } else {
1289 let stringerror = "";
1290 if (Object.keys(errortab1).length > 0) {
1291 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorSameBatchNumber')).': ";
1292 errortab1.forEach(element => {
1293 stringerror += (element + ", ")
1294 });
1295 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1296 }
1297 if (Object.keys(errortab2).length > 0) {
1298 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorCantFindCodeInInventory')).': ";
1299 errortab2.forEach(element => {
1300 stringerror += (element + ", ")
1301 });
1302 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1303 }
1304 if (Object.keys(errortab3).length > 0) {
1305 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorCodeScannedIsBothProductAndSerial')).': ";
1306 errortab3.forEach(element => {
1307 stringerror += (element + ", ")
1308 });
1309 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1310 }
1311 if (Object.keys(errortab4).length > 0) {
1312 stringerror += "<br>'.dol_escape_js($langs->transnoentities('ErrorBarcodeNotFoundForProductWarehouse')).': ";
1313 errortab4.forEach(element => {
1314 stringerror += (element + ", ")
1315 });
1316 stringerror = stringerror.slice(0, -2); /* Remove last ", " */
1317 }
1318
1319 jQuery("#scantoolmessage").html(\''.dol_escape_js($langs->transnoentities("ErrorOnElementsInventory")).'\' + stringerror);
1320 //alert("'.dol_escape_js($langs->trans("ErrorOnElementsInventory")).' :\n" + stringerror);
1321 }
1322 }
1323
1324 }
1325
1326 /* This methode is called by parent barcodescannerjs() */
1327 function barcodeserialforproduct(tabproduct,index,element,barcodeproductqty,warehousetouse,selectaddorreplace,mode,autodetect=false){
1328 BarcodeIsInProduct=0;
1329 newproductrow=0
1330 result=false;
1331 tabproduct.forEach(product => {
1332 $.ajax({ url: \''.DOL_URL_ROOT.'/expedition/ajax/searchfrombarcode.php\',
1333 data: { "token":"'.newToken().'", "action":"existbarcode","fk_entrepot": warehousetouse, "barcode":element, "mode":mode},
1334 type: \'POST\',
1335 async: false,
1336 success: function(response) {
1337 if (response.status == "success"){
1338 console.log(response.message);
1339 if(!newproductrow){
1340 newproductrow = response.object;
1341 }
1342 }else{
1343 if (mode!="lotserial" && autodetect==false && !errortab4.includes(element)){
1344 errortab4.push(element);
1345 console.error(response.message);
1346 }
1347 }
1348 },
1349 error : function(output) {
1350 console.error("Error on barcodeserialforproduct function");
1351 },
1352 });
1353 console.log("Product "+(index+=1)+": "+element);
1354 if(mode == "barcode"){
1355 testonproduct = product.Barcode
1356 }else if (mode == "lotserial"){
1357 testonproduct = product.Batch
1358 }
1359 testonwarehouse = product.Warehouse;
1360 if(testonproduct == element && testonwarehouse == warehousetouse){
1361 if(selectaddorreplace == "add"){
1362 productqty = parseInt(product.Qty,10);
1363 product.Qty = productqty + parseInt(barcodeproductqty,10);
1364 }else if(selectaddorreplace == "replace"){
1365 if(product.fetched == false){
1366 product.Qty = barcodeproductqty
1367 product.fetched=true
1368 }else{
1369 productqty = parseInt(product.Qty,10);
1370 product.Qty = productqty + parseInt(barcodeproductqty,10);
1371 }
1372 }
1373 BarcodeIsInProduct+=1;
1374 }
1375 })
1376 if(BarcodeIsInProduct==0 && newproductrow!=0){
1377 tabproduct.push({\'Id\':tabproduct.length-1,\'Warehouse\':newproductrow.fk_warehouse,\'Barcode\':mode=="barcode"?element:null,\'Batch\':mode=="lotserial"?element:null,\'Qty\':barcodeproductqty,\'fetched\':true,\'reelqty\':newproductrow.reelqty,\'fk_product\':newproductrow.fk_product,\'mode\':mode});
1378 result = true;
1379 }
1380 if(BarcodeIsInProduct > 0){
1381 result = true;
1382 }
1383 return result;
1384 }
1385 ';
1386 print '</script>';
1387 }
1388 include DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
1389 $formother = new FormOther($db);
1390 print $formother->getHTMLScannerForm("barcodescannerjs", 'all', 1);
1391 }
1392
1393 // traitement entrepot par défaut
1394 print '<script type="text/javascript">
1395 $(document).ready(function () {
1396 $("select[name=fk_default_warehouse]").change(function() {
1397 console.log("warehouse is modified");
1398 var fk_default_warehouse = $("option:selected", this).val();
1399 $("select[name^=entrepot_]").val(fk_default_warehouse).change();
1400 });
1401
1402 $("#autoreset").click(function() {
1403 console.log("we click on autoreset");
1404 $(".autoresettr").each(function(){
1405 id = $(this).attr("name");
1406 idtab = id.split("_");
1407 console.log("we process line "+id+" "+idtab);
1408 if ($(this).data("remove") == "clear") { /* data-remove=clear means that line qty must be cleared but line must not be removed */
1409 console.log("We clear the object to expected value")
1410 $("#qty_"+idtab[1]+"_"+idtab[2]).val("");
1411 /*
1412 qtyexpected = $("#qty_"+idtab[1]+"_"+idtab[2]).data("expected")
1413 console.log(qtyexpected);
1414 $("#qty_"+idtab[1]+"_"+idtab[2]).val(qtyexpected);
1415 qtydispatched = $("#qty_dispatched_0_"+idtab[2]).data("dispatched")
1416 $("#qty_dispatched_0_"+idtab[2]).val(qtydispatched);
1417 */
1418 } else { /* data-remove=remove means that line must be removed */
1419 console.log("We remove the object")
1420 $(this).remove();
1421 $("tr[name^=\'"+idtab[0]+"_\'][name$=\'_"+idtab[2]+"\']:last .splitbutton").show();
1422 }
1423 });
1424 return false;
1425 });
1426
1427 $("#resetalltoexpected").click(function(){
1428 $(".qtydispatchinput").each(function(){
1429 console.log("We reset to expected "+$(this).attr("id")+" qty to dispatch");
1430 $(this).val($(this).data("expected"));
1431 });
1432 return false;
1433 });
1434
1435 $(".resetline").on("click", function(event) {
1436 event.preventDefault();
1437 id = $(this).attr("id");
1438 id = id.split("reset_");
1439 console.log("Reset trigger for id = qty_"+id[1]);
1440 $("#qty_"+id[1]).val("");
1441 });
1442 });
1443 </script>';
1444}
1445
1446// End of page
1447llxFooter();
1448$db->close();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage customers orders.
Class to manage comment.
Class to manage warehouses.
Class to manage shipments.
const STATUS_DRAFT
Draft status.
Class to manage lines of shipment.
CRUD class for batch number management within shipment.
Class to manage generation of HTML components Only common components must be here.
Class permettant la generation de composants html autre Only common components are here.
Class with static methods for building HTML components related to products Only components common to ...
Class to manage products or services.
Class to manage projects.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
Class to manage Dolibarr users.
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition date.lib.php:427
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...
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 '.
currentToken()
Return the value of token currently saved into session with name 'token'.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0)
Set event message in dol_events session object.
dol_now($mode='auto')
Return date for now.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
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).
newToken()
Return the value of token currently saved into session with name 'newtoken'.
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
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.
treeview li table
No Email.
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
shipping_prepare_head($object)
Prepare array with list of tabs.
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall TAKEPOS_SHOW_SUBPRICE right right right takeposterminal SELECT e rowid
Definition invoice.php:2010