dolibarr 24.0.2
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-2026 Frédéric France <frederic.france@free.fr>
11 * Copyright (C) 2019-2020 Christophe Battarel <christophe@altairis.fr>
12 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
34// Load Dolibarr environment
35require '../main.inc.php';
36require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php';
37require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
38require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php';
39require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
40require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
41require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
42require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php';
43require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
44require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
45
54// Load translation files required by the page
55$langs->loadLangs(array("bills", "orders", "sendings", "companies", "products", "stocks", "receptions"));
56
57if (isModEnabled('productbatch')) {
58 $langs->load('productbatch');
59}
60
61// Security check
62$id = GETPOSTINT("id");
63$ref = GETPOST('ref');
64$lineid = GETPOSTINT('lineid');
65$action = GETPOST('action', 'aZ09');
66$fk_default_warehouse = GETPOSTINT('fk_default_warehouse');
67$cancel = GETPOST('cancel', 'alpha');
68$confirm = GETPOST('confirm', 'alpha');
69
70$error = 0;
71$errors = array();
72
73if ($user->socid) {
74 $socid = $user->socid;
75}
76
77$hookmanager->initHooks(array('ordersupplierdispatch'));
78
79// Recuperation de l'id de projet
80$projectid = 0;
81if (GETPOSTISSET("projectid")) {
82 $projectid = GETPOSTINT("projectid");
83}
84
85$object = new Reception($db);
86$objectsrc = null;
87
88if ($id > 0 || !empty($ref)) {
89 $result = $object->fetch($id, $ref);
90 if ($result < 0) {
91 setEventMessages($object->error, $object->errors, 'errors');
92 }
93 $result = $object->fetch_thirdparty();
94 if ($result < 0) {
95 setEventMessages($object->error, $object->errors, 'errors');
96 }
97 $origin = null;
98 if (!empty($object->origin)) {
99 $origin = $object->origin;
100 $typeobject = $object->origin;
101
102 $object->fetch_origin();
103 }
104 if ($origin == 'order_supplier' && $object->origin_object->id && (isModEnabled("fournisseur") && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') || isModEnabled("supplier_order"))) {
105 $origin_id = $object->origin_object->id;
106 $objectsrc = new CommandeFournisseur($db);
107 $objectsrc->fetch($origin_id);
108 }
109}
110
111if (empty($conf->reception->enabled)) {
112 $permissiontoreceive = $user->hasRight('fournisseur', 'commande', 'receptionner');
113 $permissiontocontrol = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande', 'receptionner')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande_advance', 'check')));
114} else {
115 $permissiontoreceive = $user->hasRight('reception', 'creer');
116 $permissiontocontrol = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate')));
117}
118
119// $id is id of a reception
120$result = restrictedArea($user, 'reception', $object->id);
121
122if (!isModEnabled('stock')) {
123 accessforbidden('Module stock disabled');
124}
125
126$usercancreate = $user->hasRight('reception', 'creer');
127$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php
128
129
130/*
131 * Actions
132 */
133
134$parameters = array();
135$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
136if ($reshook < 0) {
137 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
138}
139
140// Update a dispatched line
141if ($action == 'updatelines' && $permissiontoreceive) {
142 $db->begin();
143 $error = 0;
144
145 $supplierorderdispatch = new CommandeFournisseurDispatch($db);
146 $pos = 0;
147
148 foreach ($_POST as $key => $value) {
149 // without batch module enabled
150 $reg = array();
151 if (preg_match('/^product_.*([0-9]+)_([0-9]+)$/i', $key, $reg)) {
152 $pos++;
153 $modebatch = '';
154 if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
155 $modebatch = "barcode";
156 } elseif (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { // With batchmode enabled
157 $modebatch = "batch";
158 }
159
160 $numline = $pos;
161 if ($modebatch == "barcode") {
162 $prod = "product_".$reg[1].'_'.$reg[2];
163 } else {
164 $prod = 'product_batch_'.$reg[1].'_'.$reg[2];
165 }
166 $qty = "qty_".$reg[1].'_'.$reg[2];
167 $ent = "entrepot_".$reg[1].'_'.$reg[2];
168 $pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount
169 $fk_commandefourndet = "fk_commandefourndet_".$reg[1].'_'.$reg[2];
170 $idline = GETPOSTINT("idline_".$reg[1].'_'.$reg[2]);
171 $lot = '';
172 $dDLUO = '';
173 $dDLC = '';
174 if ($modebatch == "batch") {
175 $lot = GETPOST('lot_number_'.$reg[1].'_'.$reg[2]);
176 $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'));
177 $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'));
178 }
179
180 $saveprice = '__invalidsavepricekey__';
181 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
182 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
183 $dto = GETPOSTINT("dto_".$reg[1].'_'.$reg[2]);
184 if (!empty($dto)) {
185 $unit_price = (float) price2num(GETPOSTFLOAT("pu_".$reg[1]) * (100 - $dto) / 100, 'MU');
186 }
187 $saveprice = "saveprice_".$reg[1].'_'.$reg[2];
188 }
189 }
190
191 // We ask to move a qty
192 if (($modebatch == "batch" && GETPOST($qty) > 0) || ($modebatch == "barcode" && GETPOST($qty) != 0)) {
193 if (!(GETPOSTINT($ent) > 0)) {
194 dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.');
195 $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline);
196 setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors');
197 $error++;
198 }
199
200 if (!$error) {
201 if ($idline > 0) {
202 $result = $supplierorderdispatch->fetch($idline);
203 if ($result > 0 && (int) $supplierorderdispatch->fk_reception !== (int) $object->id) {
204 // The line must be a line of the reception of the page
205 $supplierorderdispatch->error = $langs->trans('ErrorRecordNotFound');
206 $result = -1;
207 }
208 if ($result < 0) {
209 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
210 $error++;
211 } else {
212 $qtystart = $supplierorderdispatch->qty;
213 $supplierorderdispatch->qty = (float) price2num(GETPOST($qty));
214 $supplierorderdispatch->fk_entrepot = GETPOSTINT($ent);
215 if ($modebatch == "batch") {
216 $supplierorderdispatch->eatby = $dDLUO;
217 $supplierorderdispatch->sellby = $dDLC;
218 }
219
220 $result = $supplierorderdispatch->update($user);
221 if ($result < 0) {
222 setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors');
223 $error++;
224 }
225
226 // If module stock is enabled and the stock decrease is done on edition of this page
227 /*
228 if (!$error && GETPOST($ent, 'int') > 0 && isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) {
229 $mouv = new MouvementStock($db);
230 $product = GETPOST($prod, 'int');
231 $entrepot = GETPOST($ent, 'int');
232 $qtymouv = GETPOST($qty) - $qtystart;
233 $price = GETPOST($pu);
234 $comment = GETPOST('comment');
235 $inventorycode = dol_print_date(dol_now(), 'dayhourlog');
236 $now = dol_now();
237 $eatby = '';
238 $sellby = '';
239 $batch = '';
240 if ($modebatch == "batch") {
241 $eatby = $dDLUO;
242 $sellby = $dDLC;
243 $batch = $supplierorderdispatch->batch;
244 }
245 if ($product > 0) {
246 // $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on)
247 $mouv->origin = $objectsrc;
248 $mouv->setOrigin($objectsrc->element, $objectsrc->id);
249
250 // Method change if qty < 0
251 if (getDolGlobalString('SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN') && $qtymouv < 0) {
252 $result = $mouv->livraison($user, $product, $entrepot, $qtymouv*(-1), $price, $comment, $now, $eatby, $sellby, $batch, 0, $inventorycode);
253 } else {
254 $result = $mouv->reception($user, $product, $entrepot, $qtymouv, $price, $comment, $eatby, $sellby, $batch, '', 0, $inventorycode);
255 }
256
257 if ($result < 0) {
258 setEventMessages($mouv->error, $mouv->errors, 'errors');
259 $error++;
260 }
261 }
262 }
263 */
264 }
265 } else {
266 $result = $objectsrc->dispatchProduct($user, GETPOSTINT($prod), GETPOSTFLOAT($qty), GETPOSTINT($ent), GETPOSTFLOAT($pu), GETPOST('comment'), $dDLUO, $dDLC, $lot, GETPOSTINT($fk_commandefourndet), 0, $object->id);
267 if ($result < 0) {
268 setEventMessages($objectsrc->error, $objectsrc->errors, 'errors');
269 $error++;
270 }
271 }
272
273 if (!$error && getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
274 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
275 $dto = price2num(GETPOST("dto_".$reg[1].'_'.$reg[2]), '');
276 if (empty($dto)) {
277 $dto = 0;
278 }
279
280 //update supplier price
281 if (GETPOSTISSET($saveprice)) {
282 // TODO Use class
283 $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price";
284 $sql .= " SET unitprice='".price2num(GETPOST($pu), 'MU')."'";
285 $sql .= ", price=".price2num(GETPOST($pu), 'MU')."*quantity";
286 $sql .= ", remise_percent = ".((float) $dto);
287 $sql .= " WHERE fk_soc=".((int) $object->socid);
288 $sql .= " AND fk_product=".(GETPOSTINT($prod));
289
290 $resql = $db->query($sql);
291 }
292 }
293 }
294 }
295 }
296 }
297 }
298 if ($error > 0) {
299 $db->rollback();
300 setEventMessages($langs->trans("Error"), $errors, 'errors');
301 } else {
302 $db->commit();
303 setEventMessages($langs->trans("ReceptionUpdated"), null);
304
305 header("Location: ".DOL_URL_ROOT.'/reception/dispatch.php?id='.$object->id);
306 exit;
307 }
308}
309
310
311/*
312 * View
313 */
314
315$now = dol_now();
316
317$form = new Form($db);
318$formproduct = new FormProduct($db);
319$warehouse_static = new Entrepot($db);
320$supplierorderdispatch = new CommandeFournisseurDispatch($db);
321
322$title = $object->ref." - ".$langs->trans('ReceptionDistribution');
323$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores';
324$morejs = array('/fourn/js/lib_dispatch.js.php');
325$numline = 0;
326
327llxHeader('', $title, $help_url, '', 0, 0, $morejs, '', '', 'mod-reception page-card_dispatch');
328
329if ($id > 0 || !empty($ref)) {
330 $typeobject = '';
331 if (!empty($object->origin) && $object->origin_id > 0) {
332 $typeobject = $object->origin;
333 $origin = $object->origin;
334 $origin_id = $object->origin_id;
335 $object->fetch_origin(); // Load property $object->origin_object, $object->commande, $object->propal, ...
336 }
337 $soc = new Societe($db);
338 $soc->fetch($object->socid);
339
340 $author = new User($db);
341 $author->fetch($object->user_author_id);
342
343 $head = reception_prepare_head($object);
344
345 $title = $langs->trans("SupplierOrder");
346 print dol_get_fiche_head($head, 'dispatch', $langs->trans("Reception"), -1, 'dollyrevert');
347
348
349 $formconfirm = '';
350
351 // Confirmation to delete line
352 if ($action == 'ask_deleteline') {
353 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1);
354 }
355
356 // Call Hook formConfirm
357 $parameters = array('lineid' => $lineid);
358 // Note that $action and $object may be modified by hook
359 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action);
360 if (empty($reshook)) {
361 $formconfirm .= $hookmanager->resPrint;
362 } elseif ($reshook > 0) {
363 $formconfirm = $hookmanager->resPrint;
364 }
365
366 // Print form confirm
367 print $formconfirm;
368
369 // Reception card
370 $linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
371 $morehtmlref = '<div class="refidno">';
372 // Ref customer reception
373
374 $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', 0, 1);
375 $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', null, null, '', 1);
376
377 // Thirdparty
378 $morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
379 // Project
380 if (isModEnabled('project')) {
381 $langs->load("projects");
382 $morehtmlref .= '<br>';
383 if (0) { // @phpstan-ignore-line Do not change on reception
384 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
385 if ($action != 'classify' && $permissiontoadd) {
386 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
387 }
388 $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $object->socid : -1), (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
389 } else {
390 if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
391 $proj = new Project($db);
392 $proj->fetch($objectsrc->fk_project);
393 $morehtmlref .= $proj->getNomUrl(1);
394 if ($proj->title) {
395 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
396 }
397 }
398 }
399 }
400 $morehtmlref .= '</div>';
401
402 dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
403
404
405 print '<div class="fichecenter">';
406 print '<div class="underbanner clearboth"></div>';
407
408 print '<table class="border tableforfield" width="100%">';
409
410 // Linked documents
411 if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
412 print '<tr><td>';
413 print $langs->trans("RefOrder").'</td>';
414 print '<td colspan="3">';
415 print $objectsrc->getNomUrl(1, 'commande');
416 print "</td>\n";
417 print '</tr>';
418 }
419 if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
420 print '<tr><td>';
421 print $langs->trans("RefProposal").'</td>';
422 print '<td colspan="3">';
423 print $objectsrc->getNomUrl(1, 'reception');
424 print "</td>\n";
425 print '</tr>';
426 }
427 if (($typeobject == 'supplier_order' || $typeobject == 'order_supplier') && $object->origin_object->id && isModEnabled("propal")) {
428 print '<tr><td>';
429 print $langs->trans("SupplierOrder").'</td>';
430 print '<td colspan="3">';
431 print $objectsrc->getNomUrl(1, 'reception');
432 print "</td>\n";
433 print '</tr>';
434 }
435
436 // Date creation
437 print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
438 print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
439 print '</tr>';
440
441 // Delivery date planned
442 print '<tr><td height="10">';
443 print '<table class="nobordernopadding" width="100%"><tr><td>';
444 print $langs->trans('DateDeliveryPlanned');
445 print '</td>';
446 print '</tr></table>';
447 print '</td><td colspan="2">';
448 print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : '&nbsp;';
449 print '</td>';
450 print '</tr>';
451 print '</table>';
452
453 print '<br><br><center>';
454 print '<a href="#" id="resetalltoexpected" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'autofill', 'class="pictofixedwidth"').$langs->trans("RestoreWithCurrentQtySaved").'</a></td>';
455 // Link to clear qty
456 print '<a href="#" id="autoreset" class="marginrightonly paddingright marginleftonly paddingleft">'.img_picto("", 'eraser', 'class="pictofixedwidth"').$langs->trans("ClearQtys").'</a></td>';
457 print '<center>';
458
459 print '<br>';
460 $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.
461
462 $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)
463
464 if ($object->statut == Reception::STATUS_DRAFT || ($object->statut == Reception::STATUS_VALIDATED && !getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION'))) {
465 require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
466 $formproduct = new FormProduct($db);
467 $formproduct->loadWarehouses();
468 $entrepot = new Entrepot($db);
469 $listwarehouses = $entrepot->list_array(1);
470
471 print '<form method="post" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'">';
472
473 print '<input type="hidden" name="token" value="'.newToken().'">';
474 print '<input type="hidden" name="action" value="updatelines">';
475 print '<input type="hidden" name="id" value="'.$object->id.'">';
476
477 print '<div class="div-table-responsive-no-min">';
478 print '<table class="noborder centpercent">';
479
480 // Get list of lines from the original Order into $products_dispatched with qty dispatched for each product id
481 $products_dispatched = array();
482 $sql = "SELECT l.rowid, cfd.fk_product, sum(cfd.qty) as qty";
483 $sql .= " FROM ".MAIN_DB_PREFIX."receptiondet_batch as cfd";
484 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."receptiondet_batch as l on l.rowid = cfd.fk_elementdet";
485 $sql .= " WHERE cfd.fk_reception = ".((int) $object->id);
486 $sql .= " GROUP BY l.rowid, cfd.fk_product";
487
488 $resql = $db->query($sql);
489 if ($resql) {
490 $num = $db->num_rows($resql);
491 $i = 0;
492
493 if ($num) {
494 while ($i < $num) {
495 $objd = $db->fetch_object($resql);
496 $products_dispatched[$objd->rowid] = price2num($objd->qty, 'MS');
497 $i++;
498 }
499 }
500 $db->free($resql);
501 }
502
503
504 //$sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,";
505 $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, l.qty as qty,";
506 $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse";
507 // Enable hooks to alter the SQL query (SELECT)
508 $parameters = array();
509 $reshook = $hookmanager->executeHooks(
510 'printFieldListSelect',
511 $parameters,
512 $object,
513 $action
514 );
515 if ($reshook < 0) {
516 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
517 }
518 $sql .= $hookmanager->resPrint;
519 $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as l";
520 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid";
521 $sql .= " WHERE l.fk_commande = ".((int) $objectsrc->id);
522 if (!getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
523 $sql .= " AND l.product_type = 0";
524 }
525 // Enable hooks to alter the SQL query (WHERE)
526 $parameters = array();
527 $reshook = $hookmanager->executeHooks(
528 'printFieldListWhere',
529 $parameters,
530 $object,
531 $action
532 );
533 if ($reshook < 0) {
534 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
535 }
536 $sql .= $hookmanager->resPrint;
537
538 //$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
539 $sql .= " ORDER BY l.rang, p.ref, p.label";
540
541 $resql = $db->query($sql);
542 if ($resql) {
543 $num = $db->num_rows($resql);
544 $i = 0;
545
546 if ($num) {
547 print '<tr class="liste_titre">';
548
549 print '<td>'.$langs->trans("Description").'</td>';
550 if (isModEnabled('productbatch')) {
551 print '<td class="dispatch_batch_number_title">'.$langs->trans("batch_number").'</td>';
552 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
553 print '<td class="dispatch_dlc_title">'.$langs->trans("SellByDate").'</td>';
554 }
555 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
556 print '<td class="dispatch_dluo_title">'.$langs->trans("EatByDate").'</td>';
557 }
558 } else {
559 print '<td></td>';
560 print '<td></td>';
561 print '<td></td>';
562 }
563 print '<td class="right">'.$langs->trans("SupplierRef").'</td>';
564 print '<td class="right">'.$langs->trans("QtyOrdered").'</td>';
565 if ($object->status == Reception::STATUS_DRAFT) {
566 print '<td class="right">'.$langs->trans("QtyToReceive"); // Qty to dispatch (sum for all lines of batch detail if there is)
567 } else {
568 print '<td class="right">'.$langs->trans("QtyDispatchedShort").'</td>';
569 }
570 print '<td class="right">'.$langs->trans("Details");
571 print '<td width="32"></td>';
572
573 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
574 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
575 print '<td class="right">'.$langs->trans("Price").'</td>';
576 print '<td class="right">'.$langs->trans("ReductionShort").' (%)</td>';
577 print '<td class="right">'.$langs->trans("UpdatePrice").'</td>';
578 }
579 }
580
581 print '<td align="right">'.$langs->trans("Warehouse");
582
583 // Select warehouse to force it everywhere
584 if (count($listwarehouses) > 1) {
585 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);
586 } elseif (count($listwarehouses) == 1) {
587 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);
588 }
589
590 print '</td>';
591
592 // Enable hooks to append additional columns
593 $parameters = array();
594 $reshook = $hookmanager->executeHooks(
595 'printFieldListTitle',
596 $parameters,
597 $object,
598 $action
599 );
600 if ($reshook < 0) {
601 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
602 }
603 print $hookmanager->resPrint;
604
605 print "</tr>\n";
606 }
607
608 $nbfreeproduct = 0; // Nb of lines of free products/services
609 // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on.
610
611 $conf->cache['product'] = array();
612
613 // Loop on each source order line (may be more or less than current number of lines in llx_commande_fournisseurdet)
614 while ($i < $num) {
615 $objp = $db->fetch_object($resql);
616
617 // Hide the free products
618 if (!$objp->fk_product > 0) {
619 $nbfreeproduct++;
620 } else {
621 $alreadydispatched = isset($products_dispatched[$objp->rowid]) ? $products_dispatched[$objp->rowid] : 0;
622 $remaintodispatch = price2num($objp->qty, 5); // Calculation of dispatched
623 if ($remaintodispatch < 0 && !getDolGlobalString('SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN')) {
624 $remaintodispatch = 0;
625 }
626
627 if ($remaintodispatch || !getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
628 $nbproduct++;
629
630 // To show detail cref and description value, we must make calculation by cref
631 // print ($objp->cref?' ('.$objp->cref.')':'');
632 // if ($objp->description) print '<br>'.nl2br($objp->description);
633 $suffix = '_0_'.$i;
634
635 print "\n";
636 print '<!-- Line to dispatch '.$suffix.' -->'."\n";
637 // hidden fields for js function
638 print '<input id="qty_ordered'.$suffix.'" type="hidden" value="'.$objp->qty.'">';
639 print '<input id="qty_dispatched'.$suffix.'" type="hidden" data-dispatched="'.((float) $alreadydispatched).'" value="'.(float) $alreadydispatched.'">';
640 print '<tr class="oddeven">';
641
642 if (empty($conf->cache['product'][$objp->fk_product])) {
643 $tmpproduct = new Product($db);
644 $tmpproduct->fetch($objp->fk_product);
645 $conf->cache['product'][$objp->fk_product] = $tmpproduct;
646 } else {
647 $tmpproduct = $conf->cache['product'][$objp->fk_product];
648 }
649
650 $linktoprod = $tmpproduct->getNomUrl(1);
651 $linktoprod .= ' - '.$objp->label."\n";
652
653 if (isModEnabled('productbatch')) {
654 if ($objp->tobatch) {
655 // Product
656 print '<td class="tdoverflowmax200">';
657 print $linktoprod;
658 print "</td>";
659 print '<td class="dispatch_batch_number"></td>';
660 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
661 print '<td class="dispatch_dlc"></td>';
662 }
663 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
664 print '<td class="dispatch_dluo"></td>';
665 }
666 } else {
667 // Product
668 print '<td class="tdoverflowmax200">';
669 print $linktoprod;
670 print "</td>";
671 print '<td class="dispatch_batch_number">';
672 print '<span class="opacitymedium small">'.$form->textwithpicto($langs->transnoentitiesnoconv("NA"), $langs->transnoentitiesnoconv("ProductDoesNotUseBatchSerial")).'</small>';
673 print '</td>';
674 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
675 print '<td class="dispatch_dlc"></td>';
676 }
677 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
678 print '<td class="dispatch_dluo"></td>';
679 }
680 }
681 } else {
682 print '<td colspan="4">';
683 print $linktoprod;
684 print "</td>";
685 }
686
687 // Define unit price for PMP calculation
688 $up_ht_disc = $objp->subprice;
689 if (!empty($objp->remise_percent) && !getDolGlobalString('STOCK_EXCLUDE_DISCOUNT_FOR_PMP')) {
690 $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU');
691 }
692
693 // Supplier ref
694 print '<td class="right">'.$objp->sref.'</td>';
695
696 // Qty ordered
697 print '<td class="right">'.$objp->qty.'</td>';
698
699 // Already dispatched
700 print '<td class="right">'.$alreadydispatched.'</td>';
701
702 print '<td class="right">';
703 print '</td>'; // Qty to dispatch
704 print '<td>';
705 print '</td>'; // Dispatch column
706 print '<td></td>'; // Warehouse column
707
708 $sql = "SELECT cfd.rowid, cfd.qty, cfd.fk_entrepot, cfd.batch, cfd.eatby, cfd.sellby, cfd.fk_product";
709 $sql .= " FROM ".MAIN_DB_PREFIX."receptiondet_batch as cfd";
710 $sql .= " WHERE cfd.fk_reception = ".((int) $object->id);
711 $sql .= " AND cfd.fk_element = ".((int) $objectsrc->id);
712 $sql .= " AND cfd.fk_elementdet = ".(int) $objp->rowid;
713
714 //print $sql;
715 $resultsql = $db->query($sql);
716 $j = 0;
717 if ($resultsql) {
718 $numd = $db->num_rows($resultsql);
719
720 while ($j < $numd) {
721 $suffix = "_".$j."_".$i;
722 $objd = $db->fetch_object($resultsql);
723
724 if (isModEnabled('productbatch') && (!empty($objd->batch) || (is_null($objd->batch) && $tmpproduct->status_batch > 0))) {
725 $type = 'batch';
726
727 // Enable hooks to append additional columns
728 $parameters = array(
729 // allows hook to distinguish between the rows with information and the rows with dispatch form input
730 'is_information_row' => true,
731 'j' => $j,
732 'suffix' => $suffix,
733 'objd' => $objd,
734 );
735 $reshook = $hookmanager->executeHooks(
736 'printFieldListValue',
737 $parameters,
738 $object,
739 $action
740 );
741 if ($reshook < 0) {
742 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
743 }
744 print $hookmanager->resPrint;
745
746 print '</tr>';
747
748 print '<!-- line for batch '.$numline.' -->';
749 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
750 print '<td>';
751 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
752 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
753 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
754
755 print '<!-- This is a U.P. (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
756 if (getDolGlobalString('SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT')) { // Not tested !
757 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
758 } else {
759 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
760 }
761
762 print '</td>';
763
764 print '<td>';
765 print '<input disabled="" type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.(GETPOSTISSET('lot_number'.$suffix) ? GETPOST('lot_number'.$suffix) : $objd->batch).'">';
766 print '</td>';
767 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
768 print '<td class="nowraponall">';
769 $dlcdatesuffix = !empty($objd->sellby) ? dol_stringtotime($objd->sellby) : dol_mktime(0, 0, 0, GETPOSTINT('dlc'.$suffix.'month'), GETPOSTINT('dlc'.$suffix.'day'), GETPOSTINT('dlc'.$suffix.'year'));
770 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
771 print '</td>';
772 }
773 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
774 print '<td class="nowraponall">';
775 $dluodatesuffix = !empty($objd->eatby) ? dol_stringtotime($objd->eatby) : dol_mktime(0, 0, 0, GETPOSTINT('dluo'.$suffix.'month'), GETPOSTINT('dluo'.$suffix.'day'), GETPOSTINT('dluo'.$suffix.'year'));
776 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
777 print '</td>';
778 }
779 print '<td colspan="3">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
780 } else {
781 $type = 'dispatch';
782 $colspan = 7;
783 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
784 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
785
786 // Enable hooks to append additional columns
787 $parameters = array(
788 // allows hook to distinguish between the rows with information and the rows with dispatch form input
789 'is_information_row' => true,
790 'j' => $j,
791 'suffix' => $suffix,
792 'objd' => $objd,
793 );
794 $reshook = $hookmanager->executeHooks(
795 'printFieldListValue',
796 $parameters,
797 $object,
798 $action
799 );
800 if ($reshook < 0) {
801 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
802 }
803 print $hookmanager->resPrint;
804
805 print '</tr>';
806
807 print '<!-- line no batch '.$numline.' -->';
808 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
809 print '<td colspan="'.$colspan.'">';
810 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
811 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="'.$objd->rowid.'">';
812 print '<input name="product'.$suffix.'" type="hidden" value="'.$objd->fk_product.'">';
813
814 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
815 if (getDolGlobalString('SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT')) { // Not tested !
816 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
817 } else {
818 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
819 }
820
821 print '</td>';
822 }
823 // Qty to dispatch
824 print '<td class="right nowraponall">';
825 print '<a href="#" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
826 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-type="'.$type.'" data-index="'.$i.'" class="width50 right qtydispatchinput" value="'.(GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : $objd->qty).'" data-expected="'.$objd->qty.'">';
827 print '</td>';
828 print '<td>';
829 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
830 $type = 'batch';
831 print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" '.($numd != $j + 1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
832 } else {
833 $type = 'dispatch';
834 print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" '.($numd != $j + 1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"');
835 }
836
837 print '</td>';
838
839 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
840 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
841 // Price
842 print '<td class="right">';
843 print '<input id="pu'.$suffix.'" name="pu'.$suffix.'" type="text" size="8" value="'.price((GETPOST('pu'.$suffix) != '' ? price2num(GETPOST('pu'.$suffix)) : $up_ht_disc)).'">';
844 print '</td>';
845
846 // Discount
847 print '<td class="right">';
848 print '<input id="dto'.$suffix.'" name="dto'.$suffix.'" type="text" size="8" value="'.(GETPOST('dto'.$suffix) != '' ? GETPOST('dto'.$suffix) : '').'">';
849 print '</td>';
850
851 // Save price
852 print '<td class="center">';
853 print '<input class="flat checkformerge" type="checkbox" name="saveprice'.$suffix.'" value="'.(GETPOST('saveprice'.$suffix) != '' ? GETPOST('saveprice'.$suffix) : '').'">';
854 print '</td>';
855 }
856 }
857
858 // Warehouse
859 print '<td class="right">';
860 if (count($listwarehouses) > 1) {
861 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, array(), 'csswarehouse'.$suffix);
862 } elseif (count($listwarehouses) == 1) {
863 print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ? GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, array(), 'csswarehouse'.$suffix);
864 } else {
865 $langs->load("errors");
866 print $langs->trans("ErrorNoWarehouseDefined");
867 }
868 print "</td>\n";
869
870 // Enable hooks to append additional columns
871 $parameters = array(
872 'is_information_row' => false, // this is a dispatch form row
873 'i' => $i,
874 'suffix' => $suffix,
875 'objp' => $objp,
876 );
877 $reshook = $hookmanager->executeHooks(
878 'printFieldListValue',
879 $parameters,
880 $object,
881 $action
882 );
883 if ($reshook < 0) {
884 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
885 }
886 print $hookmanager->resPrint;
887
888 print "</tr>\n";
889 $j++;
890
891 $numline++;
892 }
893 $suffix = "_".$j."_".$i;
894 }
895
896 if ($j == 0) {
897 if (isModEnabled('productbatch') && !empty($objp->tobatch)) {
898 $type = 'batch';
899
900 // Enable hooks to append additional columns
901 $parameters = array(
902 // allows hook to distinguish between the rows with information and the rows with dispatch form input
903 'is_information_row' => true,
904 'j' => $j,
905 'suffix' => $suffix,
906 'objp' => $objp,
907 );
908 $reshook = $hookmanager->executeHooks(
909 'printFieldListValue',
910 $parameters,
911 $object,
912 $action
913 );
914 if ($reshook < 0) {
915 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
916 }
917 print $hookmanager->resPrint;
918
919 print '</tr>';
920
921 print '<!-- line for batch '.$numline.' (not dispatched line yet for this order line) -->';
922 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'">';
923 print '<td>';
924 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
925 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
926 print '<input name="product_batch'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
927
928 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
929 if (getDolGlobalString('SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT')) { // Not tested !
930 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" type="text" value="'.price2num($up_ht_disc, 'MU').'">';
931 } else {
932 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
933 }
934
935 print '</td>';
936
937 print '<td>';
938 print '<input type="text" class="inputlotnumber quatrevingtquinzepercent" id="lot_number'.$suffix.'" name="lot_number'.$suffix.'" value="'.GETPOST('lot_number'.$suffix).'">';
939 print '</td>';
940 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
941 print '<td class="nowraponall">';
942 $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOSTINT('dlc'.$suffix.'month'), GETPOSTINT('dlc'.$suffix.'day'), GETPOSTINT('dlc'.$suffix.'year'));
943 print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, 0, 0, 1, '');
944 print '</td>';
945 }
946 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
947 print '<td class="nowraponall">';
948 $dluodatesuffix = dol_mktime(0, 0, 0, GETPOSTINT('dluo'.$suffix.'month'), GETPOSTINT('dluo'.$suffix.'day'), GETPOSTINT('dluo'.$suffix.'year'));
949 print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, 0, 0, 1, '');
950 print '</td>';
951 }
952 print '<td colspan="3">&nbsp;</td>'; // Supplier ref + Qty ordered + qty already dispatched
953 } else {
954 $type = 'dispatch';
955 $colspan = 7;
956 $colspan = (getDolGlobalString('PRODUCT_DISABLE_SELLBY')) ? --$colspan : $colspan;
957 $colspan = (getDolGlobalString('PRODUCT_DISABLE_EATBY')) ? --$colspan : $colspan;
958
959 // Enable hooks to append additional columns
960 $parameters = array(
961 // allows hook to distinguish between the rows with information and the rows with dispatch form input
962 'is_information_row' => true,
963 'j' => $j,
964 'suffix' => $suffix,
965 'objp' => $objp,
966 );
967 $reshook = $hookmanager->executeHooks(
968 'printFieldListValue',
969 $parameters,
970 $object,
971 $action
972 );
973 if ($reshook < 0) {
974 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
975 }
976 print $hookmanager->resPrint;
977
978 print '</tr>';
979
980 print '<!-- line no batch '.$numline.' (not dispatched line yet for this order line) -->';
981 print '<tr class="oddeven autoresettr" name="'.$type.$suffix.'" data-remove="clear">';
982 print '<td colspan="'.$colspan.'">';
983 print '<input id="fk_commandefourndet'.$suffix.'" name="fk_commandefourndet'.$suffix.'" type="hidden" value="'.$objp->rowid.'">';
984 print '<input id="idline'.$suffix.'" name="idline'.$suffix.'" type="hidden" value="-1">';
985 print '<input name="product'.$suffix.'" type="hidden" value="'.$objp->fk_product.'">';
986
987 print '<!-- This is a up (may include discount or not depending on STOCK_EXCLUDE_DISCOUNT_FOR_PMP. will be used for PMP calculation) -->';
988 if (getDolGlobalString('SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT')) { // Not tested !
989 print $langs->trans("BuyingPrice").': <input class="maxwidth75" name="pu'.$suffix.'" data-type="text" value="'.price2num($up_ht_disc, 'MU').'">';
990 } else {
991 print '<input class="maxwidth75" name="pu'.$suffix.'" type="hidden" value="'.price2num($up_ht_disc, 'MU').'">';
992 }
993
994 print '</td>';
995 }
996 // Qty to dispatch
997 print '<td class="right">';
998 print '<a href="#" id="reset'.$suffix.'" class="resetline">'.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').'</a>';
999 print '<input id="qty'.$suffix.'" onchange="onChangeDispatchLineQty($(this))" name="qty'.$suffix.'" data-index="'.$i.'" data-type="text" class="width50 right qtydispatchinput" value="'.(GETPOSTISSET('qty'.$suffix) ? GETPOSTINT('qty'.$suffix) : (!getDolGlobalString('SUPPLIER_ORDER_DISPATCH_FORCE_QTY_INPUT_TO_ZERO') ? $remaintodispatch : 0)).'" data-expected="'.$remaintodispatch.'">';
1000 print '</td>';
1001 print '<td>';
1002 if (isModEnabled('productbatch') && $objp->tobatch > 0) {
1003 $type = 'batch';
1004 print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1005 } else {
1006 $type = 'dispatch';
1007 print img_picto($langs->trans('AddStockLocationLine'), 'split', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"');
1008 }
1009
1010 print '</td>';
1011
1012 if (getDolGlobalString('SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT')) {
1013 if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) {
1014 // Price
1015 print '<td class="right">';
1016 print '<input id="pu'.$suffix.'" name="pu'.$suffix.'" type="text" size="8" value="'.price((GETPOST('pu'.$suffix) != '' ? price2num(GETPOST('pu'.$suffix)) : $up_ht_disc)).'">';
1017 print '</td>';
1018
1019 // Discount
1020 print '<td class="right">';
1021 print '<input id="dto'.$suffix.'" name="dto'.$suffix.'" type="text" size="8" value="'.(GETPOST('dto'.$suffix) != '' ? GETPOST('dto'.$suffix) : '').'">';
1022 print '</td>';
1023
1024 // Save price
1025 print '<td class="center">';
1026 print '<input class="flat checkformerge" type="checkbox" name="saveprice'.$suffix.'" value="'.(GETPOST('saveprice'.$suffix) != '' ? GETPOST('saveprice'.$suffix) : '').'">';
1027 print '</td>';
1028 }
1029 }
1030
1031 // Warehouse
1032 print '<td class="right">';
1033 if (count($listwarehouses) > 1) {
1034 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, array(), 'csswarehouse'.$suffix);
1035 } elseif (count($listwarehouses) == 1) {
1036 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, array(), 'csswarehouse'.$suffix);
1037 } else {
1038 $langs->load("errors");
1039 print $langs->trans("ErrorNoWarehouseDefined");
1040 }
1041 print "</td>\n";
1042
1043 // Enable hooks to append additional columns
1044 $parameters = array(
1045 'is_information_row' => false, // this is a dispatch form row
1046 'i' => $i,
1047 'suffix' => $suffix,
1048 'objp' => $objp,
1049 );
1050 $reshook = $hookmanager->executeHooks(
1051 'printFieldListValue',
1052 $parameters,
1053 $object,
1054 $action
1055 );
1056 if ($reshook < 0) {
1057 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
1058 }
1059 print $hookmanager->resPrint;
1060 print "</tr>\n";
1061 }
1062 }
1063 }
1064 $i++;
1065 }
1066 $db->free($resql);
1067 } else {
1068 dol_print_error($db);
1069 }
1070
1071 print "</table>\n";
1072 print '</div>';
1073
1074 if ($nbproduct) {
1075 print '<div class="center">';
1076 $parameters = array();
1077 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
1078 // modified by hook
1079 if (empty($reshook)) {
1080 /*$checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll'));
1081
1082 if (empty($conf->reception->enabled)) {
1083 print $langs->trans("Comment").' : ';
1084 print '<input type="text" class="minwidth400" maxlength="128" name="comment" value="';
1085 print GETPOSTISSET("comment") ? GETPOST("comment") : $langs->trans("DispatchSupplierOrder", $object->ref);
1086 // print ' / '.$object->ref_supplier; // Not yet available
1087 print '" class="flat"><br>';
1088
1089 print '<input type="checkbox" checked="checked" name="closeopenorder"> '.$checkboxlabel;
1090 }
1091
1092 $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception");
1093
1094 print '<br>';
1095 */
1096
1097 print '<input type="submit" id="submitform" class="button" name="dispatch" value="'.$langs->trans("Save").'"';
1098 $disabled = 0;
1099 if (!$permissiontoreceive) {
1100 $disabled = 1;
1101 }
1102 if (count($listwarehouses) <= 0) {
1103 $disabled = 1;
1104 }
1105 if ($disabled) {
1106 print ' disabled';
1107 }
1108
1109 print '>';
1110 }
1111 print '</div>';
1112 }
1113
1114 // Message if nothing to dispatch
1115 if (!$nbproduct) {
1116 print "<br>\n";
1117 if (!getDolGlobalString('SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED')) {
1118 print '<div class="opacitymedium">'.$langs->trans("NoPredefinedProductToDispatch").'</div>'; // No predefined line at all
1119 } else {
1120 print '<div class="opacitymedium">'.$langs->trans("NoMorePredefinedProductToDispatch").'</div>'; // No predefined line that remain to be dispatched.
1121 }
1122 }
1123
1124 print '</form>';
1125 }
1126
1127 print dol_get_fiche_end();
1128
1129 // Handling of the default warehouse
1130 print '<script type="text/javascript">
1131 $(document).ready(function () {
1132 $("select[name=fk_default_warehouse]").change(function() {
1133 var fk_default_warehouse = $("option:selected", this).val();
1134 $("select[name^=entrepot_]").val(fk_default_warehouse).change();
1135 });
1136
1137 $("#autoreset").click(function() {
1138 $(".autoresettr").each(function(){
1139 id = $(this).attr("name");
1140 idtab = id.split("_");
1141 if ($(this).data("remove") == "clear"){
1142 console.log("We clear the object to expected value")
1143 $("#qty_"+idtab[1]+"_"+idtab[2]).val("");
1144 /*
1145 qtyexpected = $("#qty_"+idtab[1]+"_"+idtab[2]).data("expected")
1146 console.log(qtyexpected);
1147 $("#qty_"+idtab[1]+"_"+idtab[2]).val(qtyexpected);
1148 qtydispatched = $("#qty_dispatched_0_"+idtab[2]).data("dispatched")
1149 $("#qty_dispatched_0_"+idtab[2]).val(qtydispatched);
1150 */
1151 } else {
1152 console.log("We remove the object")
1153 $(this).remove();
1154 $("tr[name^=\'"+idtab[0]+"_\'][name$=\'_"+idtab[2]+"\']:last .splitbutton").show();
1155 }
1156 });
1157 return false;
1158 });
1159
1160 $("#resetalltoexpected").click(function(){
1161 $(".qtydispatchinput").each(function(){
1162 console.log("We reset to expected "+$(this).attr("id")+" qty to dispatch");
1163 $(this).val($(this).data("expected"));
1164 });
1165 return false;
1166 });
1167
1168 $(".resetline").click(function(e){
1169 e.preventDefault();
1170 id = $(this).attr("id");
1171 id = id.split("reset_");
1172 console.log("Reset trigger for id = qty_"+id[1]);
1173 $("#qty_"+id[1]).val("");
1174 return false;
1175 });
1176 });
1177 </script>';
1178}
1179
1180// End of page
1181llxFooter();
1182$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
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:73
Class to manage table ReceptionLineBatch.
Class to manage predefined suppliers products.
Class to manage comment.
Class to manage warehouses.
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 products or services.
Class to manage projects.
Class to manage receptions.
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:451
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
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...
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTFLOAT($paramname, $rounding='', $option=2)
Return the value of a $_GET or $_POST supervariable, converted into float.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
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.
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
treeview li table
No Email.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php
reception_prepare_head(Reception $object)
Prepare array with list of tabs.
$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, $nodie=0, $mode='')
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.