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