From 3760f0696147fc0430c870483b81f55afc25e77b Mon Sep 17 00:00:00 2001 From: hystepik Date: Thu, 6 Apr 2023 15:50:34 +0200 Subject: [PATCH 01/11] add remove of lines for reception --- htdocs/fourn/commande/card.php | 2 +- htdocs/fourn/commande/dispatch.php | 35 +++++++++++++++++++++-------- htdocs/fourn/js/lib_dispatch.js.php | 15 +++++++++++++ 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index f79c9fe49b4..f99809d4091 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -133,7 +133,7 @@ if ($id > 0 || !empty($ref)) { // Security check $isdraft = (isset($object->statut) && ($object->statut == $object::STATUS_DRAFT) ? 1 : 0); -$result = restrictedArea($user, 'fournisseur', $id, 'commande_fournisseur', 'commande', 'fk_soc', 'rowid', $isdraft); +$result = restrictedArea($user, 'fournisseur', $object, 'commande_fournisseur', 'commande', 'fk_soc', 'rowid', $isdraft); // Common permissions $usercanread = ($user->rights->fournisseur->commande->lire || $user->rights->supplier_order->lire); diff --git a/htdocs/fourn/commande/dispatch.php b/htdocs/fourn/commande/dispatch.php index 50508f171df..fc07217846f 100644 --- a/htdocs/fourn/commande/dispatch.php +++ b/htdocs/fourn/commande/dispatch.php @@ -94,7 +94,7 @@ if (empty($conf->reception->enabled)) { } // $id is id of a purchase order. -$result = restrictedArea($user, 'fournisseur', $id, 'commande_fournisseur', 'commande'); +$result = restrictedArea($user, 'fournisseur', $object, 'commande_fournisseur', 'commande'); if (!isModEnabled('stock')) { accessforbidden(); @@ -978,7 +978,8 @@ if ($id > 0 || !empty($ref)) { // Qty to dispatch print ''; - print ''; + print ''.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').''; + print ''; print ''; print ''; @@ -1115,14 +1116,30 @@ if ($id > 0 || !empty($ref)) { $("select[name^=entrepot_]").val(fk_default_warehouse).change(); }); - jQuery("#autoreset").click(function() {'; - $i = 0; - while ($i < $nbproduct) { - print ' jQuery("#qty_0_'.$i.'").val("");'; - $i++; - } - print ' + $("#autoreset").click(function() { + $(".qtydispatchinput").each(function(){ + id = $(this).attr("id"); + idtab = id.split("_"); + if(idtab[1] == 0){ + console.log(idtab); + $(this).val(""); + $("#qty_dispatched_0_"+idtab[2]).val("0"); + } else { + obj = $(this).parent().parent(); + nameobj = obj.attr("name"); + nametab = nameobj.split("_"); + obj.remove(); + $("tr[name^=\'"+nametab[0]+"_\'][name$=\'_"+nametab[2]+"\']:last .splitbutton").show(); + } + }); }); + + $(".resetline").click(function(){ + id = $(this).attr("id"); + id = id.split("reset_"); + console.log("Reset trigger for id = qty_"+id[1]); + $("#qty_"+id[1]).val(""); + }); }); '; diff --git a/htdocs/fourn/js/lib_dispatch.js.php b/htdocs/fourn/js/lib_dispatch.js.php index ff822543ddb..7d711d3a19a 100644 --- a/htdocs/fourn/js/lib_dispatch.js.php +++ b/htdocs/fourn/js/lib_dispatch.js.php @@ -133,6 +133,21 @@ function addDispatchLine(index, type, mode) $("tr[name^='"+type+"_'][name$='_"+index+"'] .splitbutton").hide(); $("tr[name^='"+type+"_'][name$='_"+index+"']:last .splitbutton").show(); + $("#reset_"+(nbrTrs)+"_"+index).click(function(){ + id = $(this).attr("id"); + id = id.split("reset_"); + idrow = id[1]; + idlast = $("tr[name^='"+type+"_'][name$='_"+index+"']:last .qtydispatchinput").attr("id"); + if (idlast == $("#qty_"+idrow).attr("id")) { + console.log("Remove trigger for tr name = "+type+"_"+idrow); + $('tr[name="'+type+'_'+idrow+'"').remove(); + $("tr[name^='"+type+"_'][name$='_"+index+"']:last .splitbutton").show(); + } else { + console.log("Reset trigger for id = #qty_"+idrow); + $("#qty_"+idrow).val(""); + } + });; + if (mode === 'lessone') { qty = 1; // keep 1 in old line From ca815ff9c6e03be4869e06f6b1306f44b535fb23 Mon Sep 17 00:00:00 2001 From: hystepik Date: Thu, 27 Apr 2023 14:56:27 +0200 Subject: [PATCH 02/11] working dispatchcard reception --- htdocs/core/lib/reception.lib.php | 7 + .../class/fournisseur.commande.class.php | 7 +- htdocs/fourn/js/lib_dispatch.js.php | 123 +- htdocs/langs/en_US/receptions.lang | 4 +- htdocs/reception/dispatch.php | 1135 +++++++++++++++++ 5 files changed, 1213 insertions(+), 63 deletions(-) create mode 100644 htdocs/reception/dispatch.php diff --git a/htdocs/core/lib/reception.lib.php b/htdocs/core/lib/reception.lib.php index e697908e8cb..16e036991f9 100644 --- a/htdocs/core/lib/reception.lib.php +++ b/htdocs/core/lib/reception.lib.php @@ -46,6 +46,13 @@ function reception_prepare_head(Reception $object) $head[$h][2] = 'reception'; $h++; + if ($object->statut == Reception::STATUS_DRAFT) { + $head[$h][0] = DOL_URL_ROOT."/reception/dispatch.php?id=".$object->id; + $head[$h][1] = $langs->trans("DispatchCard"); + $head[$h][2] = 'dispatch'; + $h++; + } + if (empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) { $objectsrc = $object; if ($object->origin == 'supplier_order' && $object->origin_id > 0) { diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index e3f8e3c5f81..738b7eb3dc2 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2110,9 +2110,10 @@ class CommandeFournisseur extends CommonOrder * @param string $batch Lot number * @param int $fk_commandefourndet Id of supplier order line * @param int $notrigger 1 = notrigger + * @param int $fk_reception Id of reception to link * @return int <0 if KO, >0 if OK */ - public function dispatchProduct($user, $product, $qty, $entrepot, $price = 0, $comment = '', $eatby = '', $sellby = '', $batch = '', $fk_commandefourndet = 0, $notrigger = 0) + public function dispatchProduct($user, $product, $qty, $entrepot, $price = 0, $comment = '', $eatby = '', $sellby = '', $batch = '', $fk_commandefourndet = 0, $notrigger = 0, $fk_reception = 0) { global $conf, $langs; @@ -2142,9 +2143,9 @@ class CommandeFournisseur extends CommonOrder $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseur_dispatch"; - $sql .= " (fk_commande, fk_product, qty, fk_entrepot, fk_user, datec, fk_commandefourndet, status, comment, eatby, sellby, batch) VALUES"; + $sql .= " (fk_commande, fk_product, qty, fk_entrepot, fk_user, datec, fk_commandefourndet, status, comment, eatby, sellby, batch, fk_reception) VALUES"; $sql .= " ('".$this->id."','".$product."','".$qty."',".($entrepot > 0 ? "'".$entrepot."'" : "null").",'".$user->id."','".$this->db->idate($now)."','".$fk_commandefourndet."', ".$dispatchstatus.", '".$this->db->escape($comment)."', "; - $sql .= ($eatby ? "'".$this->db->idate($eatby)."'" : "null").", ".($sellby ? "'".$this->db->idate($sellby)."'" : "null").", ".($batch ? "'".$this->db->escape($batch)."'" : "null"); + $sql .= ($eatby ? "'".$this->db->idate($eatby)."'" : "null").", ".($sellby ? "'".$this->db->idate($sellby)."'" : "null").", ".($batch ? "'".$this->db->escape($batch)."'" : "null").", ".($fk_reception > 0 ? "'".$fk_reception."'" : "null"); $sql .= ")"; dol_syslog(get_class($this)."::dispatchProduct", LOG_DEBUG); diff --git a/htdocs/fourn/js/lib_dispatch.js.php b/htdocs/fourn/js/lib_dispatch.js.php index 7d711d3a19a..44a4df1161e 100644 --- a/htdocs/fourn/js/lib_dispatch.js.php +++ b/htdocs/fourn/js/lib_dispatch.js.php @@ -65,39 +65,36 @@ if (empty($dolibarr_nocache)) { * @param type string type of dispatch (batch = batch dispatch, dispatch = non batch dispatch) * @param mode string 'qtymissing' will create new line with qty missing, 'lessone' will keep 1 in old line and the rest in new one */ -function addDispatchLine(index, type, mode) -{ +function addDispatchLine(index, type, mode) { mode = mode || 'qtymissing' - console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode); - var $row0 = $("tr[name='"+type+'_0_'+index+"']"); + console.log("fourn/js/lib_dispatch.js.php Split line type=" + type + " index=" + index + " mode=" + mode); + var $row0 = $("tr[name='" + type + '_0_' + index + "']"); var $dpopt = $row0.find('.hasDatepicker').first().datepicker('option', 'all'); // get current datepicker options to apply the same to the cloned datepickers var $row = $row0.clone(true); // clone first batch line to jQuery object - var nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length; // position of line for batch - var qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()); // Qty ordered is same for all rows - var qty = parseFloat($("#qty_"+(nbrTrs - 1)+"_"+index).val()); - var qtyDispatched; + var nbrTrs = $("tr[name^='" + type + "_'][name$='_" + index + "']").length; // position of line for batch + var qtyOrdered = parseFloat($("#qty_ordered_0_" + index).val()); // Qty ordered is same for all rows + var qty = parseFloat($("#qty_" + (nbrTrs - 1) + "_" + index).val()); + var qtyDispatched; - if (mode === 'lessone') - { - qtyDispatched = parseFloat($("#qty_dispatched_0_"+index).val()) + 1; + if (mode === 'lessone') { + qtyDispatched = parseFloat($("#qty_dispatched_0_" + index).val()) + 1; } - else - { - qtyDispatched = parseFloat($("#qty_dispatched_0_"+index).val()) + qty; + else { + qtyDispatched = parseFloat($("#qty_dispatched_0_" + index).val()) + qty; // If user did not reduced the qty to dispatch on old line, we keep only 1 on old line and the rest on new line if (qtyDispatched == qtyOrdered && qtyDispatched > 1) { - qtyDispatched = parseFloat($("#qty_dispatched_0_"+index).val()) + 1; + qtyDispatched = parseFloat($("#qty_dispatched_0_" + index).val()) + 1; mode = 'lessone'; } } - console.log("qtyDispatched="+qtyDispatched+" qtyOrdered="+qtyOrdered); + console.log("qtyDispatched=" + qtyDispatched + " qtyOrdered=" + qtyOrdered); if (qtyDispatched >= qtyOrdered || qtyOrdered <= 1) { window.alert("Remain quantity to dispatch is too low to be split"); } else if (qtyDispatched < qtyOrdered) { //replace tr suffix nbr - $row.html($row.html().replace(/_0_/g,"_"+nbrTrs+"_")); + $row.html($row.html().replace(/_0_/g, "_" + nbrTrs + "_")); // jquery's deep clone is incompatible with date pickers (the clone shares data with the original) // so we destroy and rebuild the new date pickers @@ -111,57 +108,63 @@ function addDispatchLine(index, type, mode) }, 0); //create new select2 to avoid duplicate id of cloned one - $row.find("select[name='"+'entrepot_'+nbrTrs+'_'+index+"']").select2(); + $row.find("select[name='" + 'entrepot_' + nbrTrs + '_' + index + "']").select2(); // TODO find solution to copy selected option to new select // TODO find solution to keep new tr's after page refresh //clear value $row.find("input[name^='qty']").val(''); //change name of new row - $row.attr('name',type+'_'+nbrTrs+'_'+index); + $row.attr('name', type + '_' + nbrTrs + '_' + index); //insert new row before last row - $("tr[name^='"+type+"_'][name$='_"+index+"']:last").after($row); + $("tr[name^='" + type + "_'][name$='_" + index + "']:last").after($row); //remove cloned select2 with duplicate id. - $("#s2id_entrepot_"+nbrTrs+'_'+index).detach(); // old way to find duplicated select2 component - $(".csswarehouse_"+nbrTrs+"_"+index+":first-child").parent("span.selection").parent(".select2").detach(); + $("#s2id_entrepot_" + nbrTrs + '_' + index).detach(); // old way to find duplicated select2 component + $(".csswarehouse_" + nbrTrs + "_" + index + ":first-child").parent("span.selection").parent(".select2").detach(); /* Suffix of lines are: _ trs.length _ index */ - $("#qty_"+nbrTrs+"_"+index).focus(); - $("#qty_dispatched_0_"+index).val(qtyDispatched); + $("#qty_" + nbrTrs + "_" + index).focus(); + $("#qty_dispatched_0_" + index).val(qtyDispatched); //hide all buttons then show only the last one - $("tr[name^='"+type+"_'][name$='_"+index+"'] .splitbutton").hide(); - $("tr[name^='"+type+"_'][name$='_"+index+"']:last .splitbutton").show(); + $("tr[name^='" + type + "_'][name$='_" + index + "'] .splitbutton").hide(); + $("tr[name^='" + type + "_'][name$='_" + index + "']:last .splitbutton").show(); - $("#reset_"+(nbrTrs)+"_"+index).click(function(){ + $("#reset_" + (nbrTrs) + "_" + index).click(function () { id = $(this).attr("id"); id = id.split("reset_"); idrow = id[1]; - idlast = $("tr[name^='"+type+"_'][name$='_"+index+"']:last .qtydispatchinput").attr("id"); - if (idlast == $("#qty_"+idrow).attr("id")) { - console.log("Remove trigger for tr name = "+type+"_"+idrow); - $('tr[name="'+type+'_'+idrow+'"').remove(); - $("tr[name^='"+type+"_'][name$='_"+index+"']:last .splitbutton").show(); + idlast = $("tr[name^='" + type + "_'][name$='_" + index + "']:last .qtydispatchinput").attr("id"); + if (idlast == $("#qty_" + idrow).attr("id")) { + console.log("Remove trigger for tr name = " + type + "_" + idrow); + $('tr[name="' + type + '_' + idrow + '"').remove(); + $("tr[name^='" + type + "_'][name$='_" + index + "']:last .splitbutton").show(); } else { - console.log("Reset trigger for id = #qty_"+idrow); - $("#qty_"+idrow).val(""); + console.log("Reset trigger for id = #qty_" + idrow); + $("#qty_" + idrow).val(""); } - });; + }); - if (mode === 'lessone') - { - qty = 1; // keep 1 in old line - $("#qty_"+(nbrTrs-1)+"_"+index).val(qty); - } - $("#qty_"+nbrTrs+"_"+index).val(qtyOrdered - qtyDispatched); + if (mode === 'lessone') + { + qty = 1; // keep 1 in old line + $("#qty_"+(nbrTrs-1)+"_"+index).val(qty); + } + $("#qty_" + nbrTrs + "_" + index).val(qtyOrdered - qtyDispatched); // Store arbitrary data for dispatch qty input field change event - $("#qty_"+(nbrTrs-1)+"_"+index).data('qty', qty); - $("#qty_"+(nbrTrs-1)+"_"+index).data('type', type); - $("#qty_"+(nbrTrs-1)+"_"+index).data('index', index); + $("#qty_" + (nbrTrs - 1) + "_" + index).data('qty', qty); + $("#qty_" + (nbrTrs - 1) + "_" + index).data('type', type); + $("#qty_" + (nbrTrs - 1) + "_" + index).data('index', index); // Update dispatched qty when value dispatch qty input field changed - $("#qty_"+(nbrTrs-1)+"_"+index).change(this.onChangeDispatchLineQty); + //$("#qty_" + (nbrTrs - 1) + "_" + index).change(this.onChangeDispatchLineQty); //set focus on lot of new line (if it exists) - $("#lot_number_"+(nbrTrs)+"_"+index).focus(); + $("#lot_number_" + (nbrTrs) + "_" + index).focus(); + //Clean bad values + $("tr[name^='" + type + "_'][name$='_" + index + "']:last").data("remove", "remove"); + $("#lot_number_" + (nbrTrs) + "_" + index).val("") + $("#idline_" + (nbrTrs) + "_" + index).val("-1") + $("#qty_" + (nbrTrs) + "_" + index).data('expected', "0"); + $("#lot_number_" + (nbrTrs) + "_" + index).removeAttr("disabled"); } } @@ -175,26 +178,28 @@ function addDispatchLine(index, type, mode) * element requires arbitrary data qty (value before change), type (type of dispatch) and index (index of product line) */ -function onChangeDispatchLineQty() { - var index = $(this).data('index'), - type = $(this).data('type'), - qty = parseFloat($(this).data('qty')), +function onChangeDispatchLineQty(element) { + var type = $(element).data('type'), + qty = parseFloat($(element).data('expected')), changedQty, nbrTrs, dispatchingQty, qtyOrdered, qtyDispatched; + id = $(element).attr("id"); + id = id.split("_"); + index = id[2]; if (index >= 0 && type && qty >= 0) { - nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length; - qtyChanged = parseFloat($(this).val()) - qty; // qty changed - qtyDispatching = parseFloat($("#qty_"+(nbrTrs-1)+"_"+index).val()); // qty currently being dispatched - qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()); // qty ordered - qtyDispatched = parseFloat($("#qty_dispatched_0_"+index).val()); // qty already dispatched + nbrTrs = $("tr[name^='" + type + "_'][name$='_" + index + "']").length; + qtyChanged = parseFloat($(element).val()) - qty; // qty changed + qtyDispatching = parseFloat($(element).val()); // qty currently being dispatched + qtyOrdered = parseFloat($("#qty_ordered_0_" + index).val()); // qty ordered + qtyDispatched = parseFloat($("#qty_dispatched_0_" + index).val()); // qty already dispatched - console.log("onChangeDispatchLineQty qtyChanged: " + qtyChanged + " qtyDispatching: " + qtyDispatching + " qtyOrdered: " + qtyOrdered + " qtyDispatched: "+ qtyDispatched); + console.log("onChangeDispatchLineQty qtyChanged: " + qtyChanged + " qtyDispatching: " + qtyDispatching + " qtyOrdered: " + qtyOrdered + " qtyDispatched: " + qtyDispatched); if ((qtyChanged) <= (qtyOrdered - (qtyDispatched + qtyDispatching))) { - $("#qty_dispatched_0_"+index).val(qtyDispatched + qtyChanged); + $("#qty_dispatched_0_" + index).val(qtyDispatched + qtyChanged); } else { - $(this).val($(this).data('qty')); + $(element).val($(element).data('expected')); } - $(this).data('qty', $(this).val()); + $(element).data('expected', $(element).val()); } } diff --git a/htdocs/langs/en_US/receptions.lang b/htdocs/langs/en_US/receptions.lang index 7324f14f2e0..43f1512ecef 100644 --- a/htdocs/langs/en_US/receptions.lang +++ b/htdocs/langs/en_US/receptions.lang @@ -51,4 +51,6 @@ NoMorePredefinedProductToDispatch=No more predefined products to dispatch ReceptionExist=A reception exists ReceptionBackToDraftInDolibarr=Reception %s back to draft ReceptionClassifyClosedInDolibarr=Reception %s classified Closed -ReceptionUnClassifyCloseddInDolibarr=Reception %s re-open \ No newline at end of file +ReceptionUnClassifyCloseddInDolibarr=Reception %s re-open +ResetQtyToDispatch=Reset all quantities to dispatch +ReceptionUpdated=Reception sucessfully updated \ No newline at end of file diff --git a/htdocs/reception/dispatch.php b/htdocs/reception/dispatch.php new file mode 100644 index 00000000000..a9c6c91d675 --- /dev/null +++ b/htdocs/reception/dispatch.php @@ -0,0 +1,1135 @@ + + * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2005 Eric Seigne + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2010-2021 Juanjo Menent + * Copyright (C) 2014 Cedric Gross + * Copyright (C) 2016 Florian Henry + * Copyright (C) 2017-2022 Ferran Marcet + * Copyright (C) 2018-2022 Frédéric France + * Copyright (C) 2019-2020 Christophe Battarel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/fourn/commande/dispatch.php + * \ingroup commande + * \brief Page to dispatch receiving + */ + +// Load Dolibarr environment +require '../main.inc.php'; +require_once DOL_DOCUMENT_ROOT.'/core/modules/supplier_order/modules_commandefournisseur.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/fourn.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php'; +require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; +require_once DOL_DOCUMENT_ROOT.'/product/stock/class/mouvementstock.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php'; + + +if (isModEnabled('project')) { + require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; +} + +// Load translation files required by the page +$langs->loadLangs(array("bills", "orders", "sendings", "companies", "deliveries", "products", "stocks", "receptions")); + +if (isModEnabled('productbatch')) { + $langs->load('productbatch'); +} + + // Security check +$id = GETPOST("id", 'int'); +$ref = GETPOST('ref'); +$lineid = GETPOST('lineid', 'int'); +$action = GETPOST('action', 'aZ09'); +$fk_default_warehouse = GETPOST('fk_default_warehouse', 'int'); +$cancel = GETPOST('cancel', 'alpha'); +$confirm = GETPOST('confirm', 'alpha'); + +if ($user->socid) { + $socid = $user->socid; +} + +$hookmanager->initHooks(array('ordersupplierdispatch')); + +// Recuperation de l'id de projet +$projectid = 0; +if (GETPOSTISSET("projectid")) { + $projectid = GETPOST("projectid", 'int'); +} + +$object = new Reception($db); + +if ($id > 0 || !empty($ref)) { + $result = $object->fetch($id, $ref); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } + $result = $object->fetch_thirdparty(); + if ($result < 0) { + setEventMessages($object->error, $object->errors, 'errors'); + } + if (!empty($object->origin)) { + $origin = $object->origin; + + $object->fetch_origin(); + $typeobject = $object->origin; + } + if ($origin == 'order_supplier' && $object->$typeobject->id && (isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD) || isModEnabled("supplier_order"))) { + $origin_id = $object->$typeobject->id; + $objectsrc = new CommandeFournisseur($db); + $objectsrc->fetch($object->$typeobject->id); + } +} + +if (empty($conf->reception->enabled)) { + $permissiontoreceive = $user->rights->fournisseur->commande->receptionner; + $permissiontocontrol = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->fournisseur->commande->receptionner)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->fournisseur->commande_advance->check))); +} else { + $permissiontoreceive = $user->rights->reception->creer; + $permissiontocontrol = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->creer)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->reception->reception_advance->validate))); +} + +// $id is id of a purchase order. +$result = restrictedArea($user, 'fournisseur', $object, 'reception'); + +if (!isModEnabled('stock')) { + accessforbidden(); +} + +$usercancreate = $user->rights->reception->creer; +$permissiontoadd = $usercancreate; // Used by the include of actions_addupdatedelete.inc.php + + +/* + * Actions + */ + +$parameters = array(); +$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); +} + +// Update a dispatched line +if ($action == 'updatelines' && $permissiontoreceive) { + $db->begin(); + $error = 0; + + $supplierorderdispatch = new CommandeFournisseurDispatch($db); + $pos = 0; + + foreach ($_POST as $key => $value) { + // without batch module enabled + $reg = array(); + if (preg_match('/^product_.*([0-9]+)_([0-9]+)$/i', $key, $reg)) { + $pos++; + if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) { + $modebatch = "barcode"; + } elseif (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) { // With batchmode enabled + $modebatch = "batch"; + } + + $numline = $pos; + if ($modebatch == "barcode") { + $prod = "product_".$reg[1].'_'.$reg[2]; + } else { + $prod = 'product_batch_'.$reg[1].'_'.$reg[2]; + } + $qty = "qty_".$reg[1].'_'.$reg[2]; + $ent = "entrepot_".$reg[1].'_'.$reg[2]; + $pu = "pu_".$reg[1].'_'.$reg[2]; // This is unit price including discount + $fk_commandefourndet = "fk_commandefourndet_".$reg[1].'_'.$reg[2]; + $idline = GETPOST("idline_".$reg[1].'_'.$reg[2]); + $lot = ''; + $dDLUO = ''; + $dDLC = ''; + if ($modebatch == "batch") { + $lot = GETPOST('lot_number_'.$reg[1].'_'.$reg[2]); + $dDLUO = dol_mktime(12, 0, 0, GETPOST('dluo_'.$reg[1].'_'.$reg[2].'month', 'int'), GETPOST('dluo_'.$reg[1].'_'.$reg[2].'day', 'int'), GETPOST('dluo_'.$reg[1].'_'.$reg[2].'year', 'int')); + $dDLC = dol_mktime(12, 0, 0, GETPOST('dlc_'.$reg[1].'_'.$reg[2].'month', 'int'), GETPOST('dlc_'.$reg[1].'_'.$reg[2].'day', 'int'), GETPOST('dlc_'.$reg[1].'_'.$reg[2].'year', 'int')); + } + + if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { + if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) { + $dto = GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'); + if (!empty($dto)) { + $unit_price = price2num(GETPOST("pu_".$reg[1]) * (100 - $dto) / 100, 'MU'); + } + $saveprice = "saveprice_".$reg[1].'_'.$reg[2]; + } + } + + // We ask to move a qty + if (($modebatch == "batch" && GETPOST($qty) > 0) || ($modebatch == "barcode" && GETPOST($qty) != 0)) { + if (!(GETPOST($ent, 'int') > 0)) { + dol_syslog('No dispatch for line '.$key.' as no warehouse was chosen.'); + $text = $langs->transnoentities('Warehouse').', '.$langs->transnoentities('Line').' '.($numline); + setEventMessages($langs->trans('ErrorFieldRequired', $text), null, 'errors'); + $error++; + } + + if (!$error) { + if ($idline > 0) { + $result = $supplierorderdispatch->fetch($idline); + if ($result < 0) { + setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); + $error++; + } else { + $qtystart = $supplierorderdispatch->qty; + $supplierorderdispatch->qty = GETPOST($qty); + $supplierorderdispatch->fk_entrepot = GETPOST($ent, 'int'); + if ($modebatch == "batch") { + $supplierorderdispatch->eatby = $dDLUO; + $supplierorderdispatch->sellby = $dDLC; + } + + $result = $supplierorderdispatch->update($user); + if ($result < 0) { + setEventMessages($supplierorderdispatch->error, $supplierorderdispatch->errors, 'errors'); + $error++; + } + + // If module stock is enabled and the stock increase is done on purchase order dispatching + if (!$error && GETPOST($ent, 'int') > 0 && isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER)) { + $mouv = new MouvementStock($db); + $product = GETPOST($prod, 'int'); + $entrepot = GETPOST($ent, 'int'); + $qtymouv = GETPOST($qty) - $qtystart; + $price = GETPOST($pu); + $comment = GETPOST('comment'); + $inventorycode = dol_print_date(dol_now(), 'dayhourlog'); + $now = dol_now(); + $eatby = ''; + $sellby = ''; + $batch = ''; + if ($modebatch == "batch") { + $eatby = $dDLUO; + $sellby = $dDLC; + $batch = $supplierorderdispatch->batch; + } + if ($product > 0) { + // $price should take into account discount (except if option STOCK_EXCLUDE_DISCOUNT_FOR_PMP is on) + $mouv->origin = $objectsrc; + $mouv->setOrigin($objectsrc->element, $objectsrc->id); + + // Method change if qty < 0 + if (!empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN) && $qtymouv < 0) { + $result = $mouv->livraison($user, $product, $entrepot, $qtymouv*(-1), $price, $comment, $now, $eatby, $sellby, $batch, 0, $inventorycode); + } else { + $result = $mouv->reception($user, $product, $entrepot, $qtymouv, $price, $comment, $eatby, $sellby, $batch, '', 0, $inventorycode); + } + + if ($result < 0) { + setEventMessages($mouv->error, $mouv->errors, 'errors'); + $error++; + } + } + } + } + } else { + $result = $objectsrc->dispatchProduct($user, GETPOST($prod, 'int'), GETPOST($qty), GETPOST($ent, 'int'), GETPOST($pu), GETPOST('comment'), $dDLUO, $dDLC, $lot, GETPOST($fk_commandefourndet, 'int'), 0, $object->id); + if ($result < 0) { + setEventMessages($objectsrc->error, $objectsrc->errors, 'errors'); + $error++; + } + } + + if (!$error && !empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { + if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) { + $dto = price2num(GETPOST("dto_".$reg[1].'_'.$reg[2], 'int'), ''); + if (empty($dto)) { + $dto = 0; + } + + //update supplier price + if (GETPOSTISSET($saveprice)) { + // TODO Use class + $sql = "UPDATE ".MAIN_DB_PREFIX."product_fournisseur_price"; + $sql .= " SET unitprice='".price2num(GETPOST($pu), 'MU')."'"; + $sql .= ", price=".price2num(GETPOST($pu), 'MU')."*quantity"; + $sql .= ", remise_percent = ".((float) $dto); + $sql .= " WHERE fk_soc=".((int) $object->socid); + $sql .= " AND fk_product=".((int) GETPOST($prod, 'int')); + + $resql = $db->query($sql); + } + } + } + } + } + } + } + if ($error > 0) { + $db->rollback(); + setEventMessages($error, $errors, 'errors'); + } else { + $db->commit(); + setEventMessages($langs->trans("ReceptionUpdated"), null); + } +} + + +/* + * View + */ + +$now = dol_now(); + +$form = new Form($db); +$formproduct = new FormProduct($db); +$warehouse_static = new Entrepot($db); +$supplierorderdispatch = new CommandeFournisseurDispatch($db); + +$title = $object->ref." - ".$langs->trans('OrderDispatch'); +$help_url = 'EN:Module_Suppliers_Orders|FR:CommandeFournisseur|ES:Módulo_Pedidos_a_proveedores'; +$morejs = array('/fourn/js/lib_dispatch.js.php'); + +llxHeader('', $title, $help_url, '', 0, 0, $morejs); + +if ($id > 0 || !empty($ref)) { + if (!empty($object->origin) && $object->origin_id > 0) { + $object->origin = 'CommandeFournisseur'; + $typeobject = $object->origin; + $origin = $object->origin; + $origin_id = $object->origin_id; + $object->fetch_origin(); // Load property $object->commande, $object->propal, ... + } + $soc = new Societe($db); + $soc->fetch($object->socid); + + $author = new User($db); + $author->fetch($object->user_author_id); + + $head = reception_prepare_head($object); + + $title = $langs->trans("SupplierOrder"); + print dol_get_fiche_head($head, 'dispatch', $langs->trans("Reception"), -1, 'dollyrevert'); + + + $formconfirm = ''; + + // Confirmation to delete line + if ($action == 'ask_deleteline') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$lineid, $langs->trans('DeleteLine'), $langs->trans('ConfirmDeleteLine'), 'confirm_deleteline', '', 0, 1); + } + + // Call Hook formConfirm + $parameters = array('lineid' => $lineid); + // Note that $action and $object may be modified by hook + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); + if (empty($reshook)) { + $formconfirm .= $hookmanager->resPrint; + } elseif ($reshook > 0) { + $formconfirm = $hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + // Reception card + $linkback = ''.$langs->trans("BackToList").''; + $morehtmlref = '
'; + // Ref customer reception + + $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', 0, 1); + $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->rights->reception->creer, 'string', '', null, null, '', 1); + + // Thirdparty + $morehtmlref .= '
'.$object->thirdparty->getNomUrl(1); + // Project + if (!empty($conf->project->enabled)) { + $langs->load("projects"); + $morehtmlref .= '
'; + if (0) { // Do not change on reception + $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"'); + if ($action != 'classify' && $permissiontoadd) { + $morehtmlref .= ''.img_edit($langs->transnoentitiesnoconv('SetProject')).' '; + } + $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, (empty($conf->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS) ? $object->socid : -1), $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300'); + } else { + if (!empty($objectsrc) && !empty($objectsrc->fk_project)) { + $proj = new Project($db); + $proj->fetch($objectsrc->fk_project); + $morehtmlref .= $proj->getNomUrl(1); + if ($proj->title) { + $morehtmlref .= ' - '.dol_escape_htmltag($proj->title).''; + } + } + } + } + $morehtmlref .= '
'; + + dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref); + + + print '
'; + print '
'; + + print ''; + + // Linked documents + if ($typeobject == 'commande' && $object->$typeobject->id && isModEnabled('commande')) { + print ''; + print '\n"; + print ''; + } + if ($typeobject == 'propal' && $object->$typeobject->id && isModEnabled("propal")) { + print ''; + print '\n"; + print ''; + } + if ($typeobject == 'CommandeFournisseur' && $object->$typeobject->id && isModEnabled("propal")) { + print ''; + print '\n"; + print ''; + } + + // Date creation + print ''; + print '\n"; + print ''; + + // Delivery date planned + print ''; + print ''; + print '
'; + print $langs->trans("RefOrder").''; + print $objectsrc->getNomUrl(1, 'commande'); + print "
'; + print $langs->trans("RefProposal").''; + print $objectsrc->getNomUrl(1, 'reception'); + print "
'; + print $langs->trans("SupplierOrder").''; + print $objectsrc->getNomUrl(1, 'reception'); + print "
'.$langs->trans("DateCreation").''.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."
'; + print ''; + print '
'; + print $langs->trans('DateDeliveryPlanned'); + print '
'; + print '
'; + print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : ' '; + print '
'; + print '
'; + print ''.img_picto("", 'eraser', 'class="pictofixedwidth"').$langs->trans("ResetQtyToDispatch").''; + print ''.img_picto("", 'eraser', 'class="pictofixedwidth"').$langs->trans("Reset").''; + print '
'; + + print '
'; + $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. + + if ($object->statut == Reception::STATUS_DRAFT) { + require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php'; + $formproduct = new FormProduct($db); + $formproduct->loadWarehouses(); + $entrepot = new Entrepot($db); + $listwarehouses = $entrepot->list_array(1); + + + print '
'; + + + print ''; + print ''; + print ''; + + + print '
'; + print ''; + + // Set $products_dispatched with qty dispatched for each product id + $products_dispatched = array(); + $sql = "SELECT l.rowid, cfd.fk_product, sum(cfd.qty) as qty"; + $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseurdet as l on l.rowid = cfd.fk_commandefourndet"; + $sql .= " WHERE cfd.fk_reception = ".((int) $object->id); + $sql .= " GROUP BY l.rowid, cfd.fk_product"; + + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + + if ($num) { + while ($i < $num) { + $objd = $db->fetch_object($resql); + $products_dispatched[$objd->rowid] = price2num($objd->qty, 5); + $i++; + } + } + $db->free($resql); + } + + //$sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, SUM(l.qty) as qty,"; + $sql = "SELECT l.rowid, l.fk_product, l.subprice, l.remise_percent, l.ref AS sref, l.qty as qty,"; + $sql .= " p.ref, p.label, p.tobatch, p.fk_default_warehouse"; + + // Enable hooks to alter the SQL query (SELECT) + $parameters = array(); + $reshook = $hookmanager->executeHooks( + 'printFieldListSelect', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + $sql .= $hookmanager->resPrint; + + $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseurdet as l"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON l.fk_product=p.rowid"; + $sql .= " WHERE l.fk_commande = ".((int) $objectsrc->id); + if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) { + $sql .= " AND l.product_type = 0"; + } + + // Enable hooks to alter the SQL query (WHERE) + $parameters = array(); + $reshook = $hookmanager->executeHooks( + 'printFieldListWhere', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + $sql .= $hookmanager->resPrint; + + //$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 + $sql .= " ORDER BY l.rang, p.ref, p.label"; + + $resql = $db->query($sql); + if ($resql) { + $num = $db->num_rows($resql); + $i = 0; + + if ($num) { + print ''; + + print ''; + if (isModEnabled('productbatch')) { + print ''; + if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { + print ''; + } + if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { + print ''; + } + } else { + print ''; + print ''; + print ''; + } + print ''; + print ''; + print ''; + print ' '; + + if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { + if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) { + print ''; + print ''; + print ''; + } + } + + print ''; + + // Enable hooks to append additional columns + $parameters = array(); + $reshook = $hookmanager->executeHooks( + 'printFieldListTitle', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + + print "\n"; + } + + $nbfreeproduct = 0; // Nb of lins of free products/services + $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) + // or nb of line that remain to dispatch if SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED is on. + + $conf->cache['product'] = array(); + + while ($i < $num) { + $objp = $db->fetch_object($resql); + + // On n'affiche pas les produits libres + if (!$objp->fk_product > 0) { + $nbfreeproduct++; + } else { + $alreadydispatched = isset($products_dispatched[$objp->rowid])?$products_dispatched[$objp->rowid]:0; + $remaintodispatch = price2num($objp->qty, 5); // Calculation of dispatched + if ($remaintodispatch < 0 && empty($conf->global->SUPPLIER_ORDER_ALLOW_NEGATIVE_QTY_FOR_SUPPLIER_ORDER_RETURN)) { + $remaintodispatch = 0; + } + + if ($remaintodispatch || empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) { + $nbproduct++; + + // To show detail cref and description value, we must make calculation by cref + // print ($objp->cref?' ('.$objp->cref.')':''); + // if ($objp->description) print '
'.nl2br($objp->description); + $suffix = '_0_'.$i; + + print "\n"; + print ''."\n"; + // hidden fields for js function + print ''; + print ''; + print ''; + + if (empty($conf->cache['product'][$objp->fk_product])) { + $tmpproduct = new Product($db); + $tmpproduct->fetch($objp->fk_product); + $conf->cache['product'][$objp->fk_product] = $tmpproduct; + } else { + $tmpproduct = $conf->cache['product'][$objp->fk_product]; + } + + $linktoprod = $tmpproduct->getNomUrl(1); + $linktoprod .= ' - '.$objp->label."\n"; + + if (isModEnabled('productbatch')) { + if ($objp->tobatch) { + // Product + print '"; + print ''; + if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { + print ''; + } + if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { + print ''; + } + } else { + // Product + print '"; + print ''; + if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { + print ''; + } + if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { + print ''; + } + } + } else { + print '"; + } + + // Define unit price for PMP calculation + $up_ht_disc = $objp->subprice; + if (!empty($objp->remise_percent) && empty($conf->global->STOCK_EXCLUDE_DISCOUNT_FOR_PMP)) { + $up_ht_disc = price2num($up_ht_disc * (100 - $objp->remise_percent) / 100, 'MU'); + } + + // Supplier ref + print ''; + + // Qty ordered + print ''; + + // Already dispatched + print ''; + + print ''; // Qty to dispatch + print ''; // Dispatch column + print ''; // Warehouse column + + $sql = "SELECT cfd.rowid, cfd.qty, cfd.fk_entrepot, cfd.batch, cfd.eatby, cfd.sellby, cfd.fk_product"; + $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur_dispatch as cfd"; + $sql .= " WHERE cfd.fk_commandefourndet = ".(int) $objp->rowid; + $resultsql = $db->query($sql); + $j = 0; + if ($resultsql) { + $numd = $db->num_rows($resultsql); + + while ($j < $numd) { + $suffix = "_".$j."_".$i; + $objd = $db->fetch_object($resultsql); + if (isModEnabled('productbatch') && !empty($objd->batch)) { + $type = 'batch'; + + // Enable hooks to append additional columns + $parameters = array( + // allows hook to distinguish between the rows with information and the rows with dispatch form input + 'is_information_row' => true, + 'j' => $j, + 'suffix' => $suffix, + 'objd' => $objd, + ); + $reshook = $hookmanager->executeHooks( + 'printFieldListValue', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + + print ''; + + print ''; + print ''; + + print ''; + if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { + print ''; + } + if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { + print ''; + } + print ''; // Supplier ref + Qty ordered + qty already dispatched + } else { + $type = 'dispatch'; + $colspan = 7; + $colspan = (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) ? --$colspan : $colspan; + $colspan = (!empty($conf->global->PRODUCT_DISABLE_EATBY)) ? --$colspan : $colspan; + + // Enable hooks to append additional columns + $parameters = array( + // allows hook to distinguish between the rows with information and the rows with dispatch form input + 'is_information_row' => true, + 'j' => $j, + 'suffix' => $suffix, + 'objd' => $objd, + ); + $reshook = $hookmanager->executeHooks( + 'printFieldListValue', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + + print ''; + + print ''; + print ''; + } + // Qty to dispatch + print ''; + print ''; + + if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { + if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) { + // Price + print ''; + + // Discount + print ''; + + // Save price + print ''; + } + } + + // Warehouse + print '\n"; + + // Enable hooks to append additional columns + $parameters = array( + 'is_information_row' => false, // this is a dispatch form row + 'i' => $i, + 'suffix' => $suffix, + 'objp' => $objp, + ); + $reshook = $hookmanager->executeHooks( + 'printFieldListValue', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + + print "\n"; + $j++; + } + $suffix = "_".$j."_".$i; + } + if ($j == 0) { + if (isModEnabled('productbatch') && !empty($objp->batch)) { + $type = 'batch'; + + // Enable hooks to append additional columns + $parameters = array( + // allows hook to distinguish between the rows with information and the rows with dispatch form input + 'is_information_row' => true, + 'j' => $j, + 'suffix' => $suffix, + 'objp' => $objp, + ); + $reshook = $hookmanager->executeHooks( + 'printFieldListValue', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + + print ''; + + print ''; + print ''; + + print ''; + if (empty($conf->global->PRODUCT_DISABLE_SELLBY)) { + print ''; + } + if (empty($conf->global->PRODUCT_DISABLE_EATBY)) { + print ''; + } + print ''; // Supplier ref + Qty ordered + qty already dispatched + } else { + $type = 'dispatch'; + $colspan = 7; + $colspan = (!empty($conf->global->PRODUCT_DISABLE_SELLBY)) ? --$colspan : $colspan; + $colspan = (!empty($conf->global->PRODUCT_DISABLE_EATBY)) ? --$colspan : $colspan; + + // Enable hooks to append additional columns + $parameters = array( + // allows hook to distinguish between the rows with information and the rows with dispatch form input + 'is_information_row' => true, + 'j' => $j, + 'suffix' => $suffix, + 'objp' => $objp, + ); + $reshook = $hookmanager->executeHooks( + 'printFieldListValue', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + + print ''; + + print ''; + print ''; + } + // Qty to dispatch + print ''; + print ''; + + if (!empty($conf->global->SUPPLIER_ORDER_CAN_UPDATE_BUYINGPRICE_DURING_RECEIPT)) { + if (!isModEnabled("multicurrency") && empty($conf->dynamicprices->enabled)) { + // Price + print ''; + + // Discount + print ''; + + // Save price + print ''; + } + } + + // Warehouse + print '\n"; + + // Enable hooks to append additional columns + $parameters = array( + 'is_information_row' => false, // this is a dispatch form row + 'i' => $i, + 'suffix' => $suffix, + 'objp' => $objp, + ); + $reshook = $hookmanager->executeHooks( + 'printFieldListValue', + $parameters, + $object, + $action + ); + if ($reshook < 0) { + setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + } + print $hookmanager->resPrint; + print "\n"; + } + } + } + $i++; + } + $db->free($resql); + } else { + dol_print_error($db); + } + + print "
'.$langs->trans("Description").''.$langs->trans("batch_number").''.$langs->trans("SellByDate").''.$langs->trans("EatByDate").''.$langs->trans("SupplierRef").''.$langs->trans("QtyOrdered").''.$langs->trans("QtyDispatchedShort").''.$langs->trans("QtyToDispatchShort"); + print ''.$langs->trans("Price").''.$langs->trans("ReductionShort").' (%)'.$langs->trans("UpdatePrice").''.$langs->trans("Warehouse"); + + // Select warehouse to force it everywhere + if (count($listwarehouses) > 1) { + print '
'.$langs->trans("ForceTo").' '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 1, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); + } elseif (count($listwarehouses) == 1) { + print '
'.$langs->trans("ForceTo").' '.$form->selectarray('fk_default_warehouse', $listwarehouses, $fk_default_warehouse, 0, 0, 0, '', 0, 0, $disabled, '', 'minwidth100 maxwidth300', 1); + } + + print '
'; + print $linktoprod; + print "'; + print $linktoprod; + print "'; + print $langs->trans("ProductDoesNotUseBatchSerial"); + print ''; + print $linktoprod; + print "'.$objp->sref.''.$objp->qty.''.$alreadydispatched.''; + print ''; + print '
'; + print ''; + print ''; + print ''; + + print ''; + if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested ! + print $langs->trans("BuyingPrice").': '; + } else { + print ''; + } + + print ''; + print ''; + print ''; + $dlcdatesuffix = !empty($objd->sellby) ? dol_stringtotime($objd->sellby) : dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year')); + print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, '', '', 1, ''); + print ''; + $dluodatesuffix = !empty($objd->eatby) ? dol_stringtotime($objd->eatby) : dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year')); + print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, '', '', 1, ''); + print ' 
'; + print ''; + print ''; + print ''; + + print ''; + if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested ! + print $langs->trans("BuyingPrice").': '; + } else { + print ''; + } + + print ''; + print ''.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').''; + print ''; + print ''; + if (isModEnabled('productbatch') && $objp->tobatch > 0) { + $type = 'batch'; + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j+1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"'); + } else { + $type = 'dispatch'; + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" '.($numd != $j+1 ? 'style="display:none"' : '').' onClick="addDispatchLine('.$i.', \''.$type.'\')"'); + } + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if (count($listwarehouses) > 1) { + print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix); + } elseif (count($listwarehouses) == 1) { + print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : $objd->fk_entrepot, "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix); + } else { + $langs->load("errors"); + print $langs->trans("ErrorNoWarehouseDefined"); + } + print "
'; + print ''; + print ''; + print ''; + + print ''; + if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested ! + print $langs->trans("BuyingPrice").': '; + } else { + print ''; + } + + print ''; + print ''; + print ''; + $dlcdatesuffix = dol_mktime(0, 0, 0, GETPOST('dlc'.$suffix.'month'), GETPOST('dlc'.$suffix.'day'), GETPOST('dlc'.$suffix.'year')); + print $form->selectDate($dlcdatesuffix, 'dlc'.$suffix, '', '', 1, ''); + print ''; + $dluodatesuffix = dol_mktime(0, 0, 0, GETPOST('dluo'.$suffix.'month'), GETPOST('dluo'.$suffix.'day'), GETPOST('dluo'.$suffix.'year')); + print $form->selectDate($dluodatesuffix, 'dluo'.$suffix, '', '', 1, ''); + print ' 
'; + print ''; + print ''; + print ''; + + print ''; + if (!empty($conf->global->SUPPLIER_ORDER_EDIT_BUYINGPRICE_DURING_RECEIPT)) { // Not tested ! + print $langs->trans("BuyingPrice").': '; + } else { + print ''; + } + + print ''; + print ''.img_picto($langs->trans("Reset"), 'eraser', 'class="pictofixedwidth opacitymedium"').''; + print ''; + print ''; + if (isModEnabled('productbatch') && $objp->tobatch > 0) { + $type = 'batch'; + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); + } else { + $type = 'dispatch'; + print img_picto($langs->trans('AddStockLocationLine'), 'split.png', 'class="splitbutton" onClick="addDispatchLine('.$i.', \''.$type.'\')"'); + } + + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + if (count($listwarehouses) > 1) { + print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : ($objp->fk_default_warehouse ? $objp->fk_default_warehouse : ''), "entrepot".$suffix, '', 1, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix); + } elseif (count($listwarehouses) == 1) { + print $formproduct->selectWarehouses(GETPOST("entrepot".$suffix) ?GETPOST("entrepot".$suffix) : ($objp->fk_default_warehouse ? $objp->fk_default_warehouse : ''), "entrepot".$suffix, '', 0, 0, $objp->fk_product, '', 1, 0, null, 'csswarehouse'.$suffix); + } else { + $langs->load("errors"); + print $langs->trans("ErrorNoWarehouseDefined"); + } + print "
\n"; + print '
'; + + if ($nbproduct) { + $checkboxlabel = $langs->trans("CloseReceivedSupplierOrdersAutomatically", $langs->transnoentitiesnoconv('StatusOrderReceivedAll')); + + print '
'; + $parameters = array(); + $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been + // modified by hook + if (empty($reshook)) { + if (empty($conf->reception->enabled)) { + print $langs->trans("Comment").' : '; + print 'trans("DispatchSupplierOrder", $object->ref); + // print ' / '.$object->ref_supplier; // Not yet available + print '" class="flat">
'; + + print ' '.$checkboxlabel; + } + + $dispatchBt = empty($conf->reception->enabled) ? $langs->trans("Receive") : $langs->trans("CreateReception"); + + print '
'; + print ''; + } + print '
'; + } + + // Message if nothing to dispatch + if (!$nbproduct) { + print "
\n"; + if (empty($conf->global->SUPPLIER_ORDER_DISABLE_STOCK_DISPATCH_WHEN_TOTAL_REACHED)) { + print '
'.$langs->trans("NoPredefinedProductToDispatch").'
'; // No predefined line at all + } else { + print '
'.$langs->trans("NoMorePredefinedProductToDispatch").'
'; // No predefined line that remain to be dispatched. + } + } + + print '
'; + } + + print dol_get_fiche_end(); + + // traitement entrepot par défaut + print ''; +} + +// End of page +llxFooter(); +$db->close(); From e979a8c97c8ec41df92f986fc31ad0d01dfc4eff Mon Sep 17 00:00:00 2001 From: hystepik Date: Thu, 27 Apr 2023 15:35:00 +0200 Subject: [PATCH 03/11] add trans --- htdocs/langs/en_US/receptions.lang | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/langs/en_US/receptions.lang b/htdocs/langs/en_US/receptions.lang index 43f1512ecef..cd4c860e82f 100644 --- a/htdocs/langs/en_US/receptions.lang +++ b/htdocs/langs/en_US/receptions.lang @@ -53,4 +53,5 @@ ReceptionBackToDraftInDolibarr=Reception %s back to draft ReceptionClassifyClosedInDolibarr=Reception %s classified Closed ReceptionUnClassifyCloseddInDolibarr=Reception %s re-open ResetQtyToDispatch=Reset all quantities to dispatch -ReceptionUpdated=Reception sucessfully updated \ No newline at end of file +ReceptionUpdated=Reception sucessfully updated +DispatchCard=Dispatch card \ No newline at end of file From d7f715cc36626dce2b3ebdce49744b6b97edfd4d Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux Date: Thu, 27 Apr 2023 13:35:34 +0200 Subject: [PATCH 04/11] Fix: install/inc: remove optional argument check htdocs/install/step2.php has two optional argv parameters: action and selectlang. It doesn't have any version indicator, and thus doesn't have any constraint on the number of parameters, so remove it from inc.php. The constraint can still be re-included in the other files including inc.php, as well as the other script-specific options. --- htdocs/install/inc.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index c0bded73cd2..dcd2462b14f 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -143,13 +143,6 @@ if (php_sapi_name() === "cli") { exit(1); } - // Currently, scripts using inc.php will require addtional arguments, - // see help above for more details. - if ($rest_index > $argc - 2) { - usage($argv[0], "Missing mandatory arguments, usage:"); - exit(1); - } - // Tricky argument list hack, should be removed someday. // Reset argv to remove the argument that were parsed. This is needed // currently because some install code, like in upgrade.php, are using From f19a36856ba8ef791a078b5585e740023e6d67a4 Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux Date: Thu, 27 Apr 2023 13:35:34 +0200 Subject: [PATCH 05/11] install/inc: add some usage documentation Change the way the existing script syntax is documented and add the syntax and options for the step2.php script. --- htdocs/install/inc.php | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index dcd2462b14f..ed1f3f93ad2 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -93,9 +93,20 @@ $long_options = array( function usage($program, $header) { echo $header."\n"; - echo " php ".$program." [options] previous_version new_version [script options]\n"; + echo " php ".$program." [options] [script options]\n"; echo "\n"; - echo "Script options when using upgrade.php:\n"; + echo "Script syntax when using step2.php:\n"; + echo " php ".$program." [options] [action] [selectlang]\n"; + echo "\n"; + echo " action:\n"; + echo " Specify the action to execute for the file among the following ones.\n"; + echo " - set: Create tables, keys, functions and data for the instance.\n"; + echo "\n"; + echo " selectlang:\n"; + echo " Setup the default lang to use, default to 'auto'.\n"; + echo "\n"; + echo "Script syntax when using upgrade.php:\n"; + echo " php ".$program." [options] previous_version new_version [script options]\n"; echo "\n"; echo " dirmodule:\n"; echo " Specify dirmodule to provide a path for an external module\n"; @@ -105,10 +116,11 @@ function usage($program, $header) echo " Allow to run migration even if database version does\n"; echo " not match start version of migration.\n"; echo "\n"; - echo "Script options when using upgrade2.php:\n"; + echo "Script syntax when using upgrade2.php:\n"; + echo " php ".$program." [options] previous_version new_version [module list]\n"; echo "\n"; - echo " MODULE_NAME1_TO_ENABLE,MODULE_NAME2_TO_ENABLE:\n"; - echo " Specify a list of module-name to enable, joined by comma.\n"; + echo " MAIN_MODULE_NAME1,MAIN_MODULE_NAME2:\n"; + echo " Specify a list of module-name to enable, in upper case, with MAIN_MODULE_ prefix, joined by comma.\n"; echo "\n"; echo "Options:\n"; echo " -c, --config :\n"; From ef8f8d990ac741ef60298d19d1ccad5005525368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 27 Apr 2023 20:07:36 +0200 Subject: [PATCH 06/11] Fix unknown variable in product.class.php --- htdocs/product/class/product.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index c2de9c24770..c901808aaa4 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -572,7 +572,7 @@ class Product extends CommonObject */ public function check() { - if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + if (getDolGlobalInt('MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS')) { $this->ref = trim($this->ref); } else { $this->ref = dol_sanitizeFileName(stripslashes($this->ref)); From ec964040e6cf92997e139ce0af24b893bf2e1755 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Thu, 27 Apr 2023 20:12:39 +0200 Subject: [PATCH 07/11] Update product.class.php --- htdocs/product/class/product.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index c901808aaa4..f0b7bcaf6a2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -608,7 +608,7 @@ class Product extends CommonObject $error = 0; // Clean parameters - if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + if (getDolGlobalInt('MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS')) { $this->ref = trim($this->ref); } else { $this->ref = dol_sanitizeFileName(dol_string_nospecial(trim($this->ref))); @@ -702,7 +702,7 @@ class Product extends CommonObject if (empty($this->ref) || $this->ref == 'auto') { // Load object modCodeProduct - $module = (!empty($conf->global->PRODUCT_CODEPRODUCT_ADDON) ? $conf->global->PRODUCT_CODEPRODUCT_ADDON : 'mod_codeproduct_leopard'); + $module = getDolGlobalString('PRODUCT_CODEPRODUCT_ADDON', 'mod_codeproduct_leopard'); if ($module != 'mod_codeproduct_leopard') { // Do not load module file for leopard if (substr($module, 0, 16) == 'mod_codeproduct_' && substr($module, -3) == 'php') { $module = substr($module, 0, dol_strlen($module) - 4); @@ -1008,7 +1008,7 @@ class Product extends CommonObject } // Clean parameters - if (!empty($conf->global->MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS)) { + if (getDolGlobalInt('MAIN_SECURITY_ALLOW_UNSECURED_REF_LABELS')) { $this->ref = trim($this->ref); } else { $this->ref = dol_string_nospecial(trim($this->ref)); From 926aa6fec76e89a7ddac79da2051435914075242 Mon Sep 17 00:00:00 2001 From: VMR Global Solutions Date: Fri, 28 Apr 2023 09:31:33 +0200 Subject: [PATCH 08/11] API add / fix filter on extrafields in index() Add / change in api_xxx.class.php files the ability to filter on extrafields when missing in the public functions index() by changing the SQL query with the pattern " FROM ".MAIN_DB_PREFIX"xxxx AS t LEFT JOIN ".MAIN_DB_PREFIX."xxxx_extrafields AS ef ON (ef.fk_object = t.rowid) --- htdocs/adherents/class/api_members.class.php | 2 +- htdocs/adherents/class/api_memberstypes.class.php | 2 +- htdocs/bom/class/api_boms.class.php | 2 +- htdocs/categories/class/api_categories.class.php | 2 +- htdocs/comm/action/class/api_agendaevents.class.php | 2 +- htdocs/comm/propal/class/api_proposals.class.php | 3 ++- htdocs/commande/class/api_orders.class.php | 2 +- htdocs/compta/bank/class/api_bankaccounts.class.php | 2 +- htdocs/compta/facture/class/api_invoices.class.php | 2 +- htdocs/contrat/class/api_contracts.class.php | 2 +- htdocs/don/class/api_donations.class.php | 2 +- htdocs/expedition/class/api_shipments.class.php | 2 +- htdocs/expensereport/class/api_expensereports.class.php | 2 +- htdocs/fichinter/class/api_interventions.class.php | 2 +- htdocs/fourn/class/api_supplier_invoices.class.php | 2 +- htdocs/fourn/class/api_supplier_orders.class.php | 2 +- .../class/api_knowledgemanagement.class.php | 2 +- htdocs/modulebuilder/template/class/api_mymodule.class.php | 2 +- htdocs/mrp/class/api_mos.class.php | 2 +- htdocs/partnership/class/api_partnership.class.php | 2 +- htdocs/product/class/api_products.class.php | 3 ++- htdocs/product/stock/class/api_stockmovements.class.php | 3 ++- htdocs/product/stock/class/api_warehouses.class.php | 2 +- htdocs/projet/class/api_tasks.class.php | 2 +- htdocs/reception/class/api_receptions.class.php | 4 ++-- htdocs/recruitment/class/api_recruitment.class.php | 4 ++-- .../supplier_proposal/class/api_supplier_proposals.class.php | 2 +- htdocs/ticket/class/api_tickets.class.php | 2 +- htdocs/user/class/api_users.class.php | 4 ++-- 29 files changed, 35 insertions(+), 32 deletions(-) diff --git a/htdocs/adherents/class/api_members.class.php b/htdocs/adherents/class/api_members.class.php index db7b05b0832..f126403f597 100644 --- a/htdocs/adherents/class/api_members.class.php +++ b/htdocs/adherents/class/api_members.class.php @@ -222,7 +222,7 @@ class Members extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."adherent as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."adherent AS t LEFT JOIN ".MAIN_DB_PREFIX."adherent_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call if ($category > 0) { $sql .= ", ".MAIN_DB_PREFIX."categorie_member as c"; } diff --git a/htdocs/adherents/class/api_memberstypes.class.php b/htdocs/adherents/class/api_memberstypes.class.php index 109531de9d8..aa1ccf12f90 100644 --- a/htdocs/adherents/class/api_memberstypes.class.php +++ b/htdocs/adherents/class/api_memberstypes.class.php @@ -97,7 +97,7 @@ class MembersTypes extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."adherent_type AS t LEFT JOIN ".MAIN_DB_PREFIX."adherent_type_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields $sql .= ' WHERE t.entity IN ('.getEntity('member_type').')'; // Add sql filters diff --git a/htdocs/bom/class/api_boms.class.php b/htdocs/bom/class/api_boms.class.php index 439d1c23031..67b0baac323 100644 --- a/htdocs/bom/class/api_boms.class.php +++ b/htdocs/bom/class/api_boms.class.php @@ -121,7 +121,7 @@ class Boms extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index f5cda44ffb9..5b82bcd6d2c 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -141,7 +141,7 @@ class Categories extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."categorie as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."categorie AS t LEFT JOIN ".MAIN_DB_PREFIX."categories_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields $sql .= ' WHERE t.entity IN ('.getEntity('category').')'; if (!empty($type)) { $sql .= ' AND t.type='.array_search($type, Categories::$TYPES); diff --git a/htdocs/comm/action/class/api_agendaevents.class.php b/htdocs/comm/action/class/api_agendaevents.class.php index 0067df7e5cf..4f7a944070b 100644 --- a/htdocs/comm/action/class/api_agendaevents.class.php +++ b/htdocs/comm/action/class/api_agendaevents.class.php @@ -134,7 +134,7 @@ class AgendaEvents extends DolibarrApi $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } } - $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm AS t LEFT JOIN ".MAIN_DB_PREFIX."actioncomm_extrafields AS ef ON (ef.fk_object = t.id)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if (isModEnabled("societe")) { if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/comm/propal/class/api_proposals.class.php b/htdocs/comm/propal/class/api_proposals.class.php index c193edf8cfb..fdb44741e48 100644 --- a/htdocs/comm/propal/class/api_proposals.class.php +++ b/htdocs/comm/propal/class/api_proposals.class.php @@ -181,7 +181,8 @@ class Proposals extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."propal as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."propal AS t LEFT JOIN ".MAIN_DB_PREFIX."propal_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index 9138a757989..bb51b8c2111 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -184,7 +184,7 @@ class Orders extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."commande as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture AS t LEFT JOIN ".MAIN_DB_PREFIX."facture_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/compta/bank/class/api_bankaccounts.class.php b/htdocs/compta/bank/class/api_bankaccounts.class.php index b0cdd95d85a..35896ef272d 100644 --- a/htdocs/compta/bank/class/api_bankaccounts.class.php +++ b/htdocs/compta/bank/class/api_bankaccounts.class.php @@ -70,7 +70,7 @@ class BankAccounts extends DolibarrApi throw new RestException(401); } - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."bank_account as t"; + $sql = "SELECT t.rowid FROM ".MAIN_DB_PREFIX."bank_account AS t LEFT JOIN ".MAIN_DB_PREFIX."bank_account_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($category > 0) { $sql .= ", ".MAIN_DB_PREFIX."categorie_account as c"; } diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index e8605916d5a..96ecf3381b2 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -199,7 +199,7 @@ class Invoices extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."facture as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture AS t LEFT JOIN ".MAIN_DB_PREFIX."facture_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/contrat/class/api_contracts.class.php b/htdocs/contrat/class/api_contracts.class.php index 68ace23a26a..fbcd3c0804d 100644 --- a/htdocs/contrat/class/api_contracts.class.php +++ b/htdocs/contrat/class/api_contracts.class.php @@ -125,7 +125,7 @@ class Contracts extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."contrat as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."contrat AS t LEFT JOIN ".MAIN_DB_PREFIX."contrat_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/don/class/api_donations.class.php b/htdocs/don/class/api_donations.class.php index 804271414df..426e2a8ced9 100644 --- a/htdocs/don/class/api_donations.class.php +++ b/htdocs/don/class/api_donations.class.php @@ -116,7 +116,7 @@ class Donations extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids)) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."don as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."don AS t LEFT JOIN ".MAIN_DB_PREFIX."don_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields $sql .= ' WHERE t.entity IN ('.getEntity('don').')'; if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids)) { diff --git a/htdocs/expedition/class/api_shipments.class.php b/htdocs/expedition/class/api_shipments.class.php index d2f9da404e4..a6d0b14f924 100644 --- a/htdocs/expedition/class/api_shipments.class.php +++ b/htdocs/expedition/class/api_shipments.class.php @@ -122,7 +122,7 @@ class Shipments extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."expedition as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."expedition AS t LEFT JOIN ".MAIN_DB_PREFIX."expedition_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/expensereport/class/api_expensereports.class.php b/htdocs/expensereport/class/api_expensereports.class.php index c3bfeb2264d..9fe196ad9f2 100644 --- a/htdocs/expensereport/class/api_expensereports.class.php +++ b/htdocs/expensereport/class/api_expensereports.class.php @@ -109,7 +109,7 @@ class ExpenseReports extends DolibarrApi //$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe; $sql = "SELECT t.rowid"; - $sql .= " FROM ".MAIN_DB_PREFIX."expensereport as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."expensereport AS t LEFT JOIN ".MAIN_DB_PREFIX."expensereport_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields $sql .= ' WHERE t.entity IN ('.getEntity('expensereport').')'; if ($user_ids) { $sql .= " AND t.fk_user_author IN (".$this->db->sanitize($user_ids).")"; diff --git a/htdocs/fichinter/class/api_interventions.class.php b/htdocs/fichinter/class/api_interventions.class.php index 6609ce03786..79f8991dc09 100644 --- a/htdocs/fichinter/class/api_interventions.class.php +++ b/htdocs/fichinter/class/api_interventions.class.php @@ -133,7 +133,7 @@ class Interventions extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."fichinter as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."fichinter AS t LEFT JOIN ".MAIN_DB_PREFIX."fichinter_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/fourn/class/api_supplier_invoices.class.php b/htdocs/fourn/class/api_supplier_invoices.class.php index 02bed2c5e0a..72a7558cc09 100644 --- a/htdocs/fourn/class/api_supplier_invoices.class.php +++ b/htdocs/fourn/class/api_supplier_invoices.class.php @@ -122,7 +122,7 @@ class SupplierInvoices extends DolibarrApi if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; } - $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture_fourn AS t LEFT JOIN ".MAIN_DB_PREFIX."facture_fourn_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields // We need this table joined to the select in order to filter by sale if (!DolibarrApiAccess::$user->rights->societe->client->voir || $search_sale > 0) { diff --git a/htdocs/fourn/class/api_supplier_orders.class.php b/htdocs/fourn/class/api_supplier_orders.class.php index bd37c81e57e..e56e20dd7fb 100644 --- a/htdocs/fourn/class/api_supplier_orders.class.php +++ b/htdocs/fourn/class/api_supplier_orders.class.php @@ -120,7 +120,7 @@ class SupplierOrders extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."commande_fournisseur AS t LEFT JOIN ".MAIN_DB_PREFIX."commande_fournisseur_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php index 42b3ce9acd2..ee61b4e566b 100644 --- a/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php +++ b/htdocs/knowledgemanagement/class/api_knowledgemanagement.class.php @@ -162,7 +162,7 @@ class KnowledgeManagement extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/modulebuilder/template/class/api_mymodule.class.php b/htdocs/modulebuilder/template/class/api_mymodule.class.php index a48b2f5010b..bf6910ca52f 100644 --- a/htdocs/modulebuilder/template/class/api_mymodule.class.php +++ b/htdocs/modulebuilder/template/class/api_mymodule.class.php @@ -129,7 +129,7 @@ class MyModuleApi extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/mrp/class/api_mos.class.php b/htdocs/mrp/class/api_mos.class.php index 594cd0e1ac4..a6ce28fdc44 100644 --- a/htdocs/mrp/class/api_mos.class.php +++ b/htdocs/mrp/class/api_mos.class.php @@ -119,7 +119,7 @@ class Mos extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/partnership/class/api_partnership.class.php b/htdocs/partnership/class/api_partnership.class.php index 13bc447c51d..288b4966ebe 100644 --- a/htdocs/partnership/class/api_partnership.class.php +++ b/htdocs/partnership/class/api_partnership.class.php @@ -127,7 +127,7 @@ class PartnershipApi extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index 2e1d926f5f7..f144011fde3 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -873,7 +873,8 @@ class Products extends DolibarrApi } $sql = "SELECT t.rowid, t.ref, t.ref_ext"; - $sql .= " FROM ".$this->db->prefix()."product as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."product AS t LEFT JOIN ".MAIN_DB_PREFIX."product_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields + if ($category > 0) { $sql .= ", ".$this->db->prefix()."categorie_product as c"; } diff --git a/htdocs/product/stock/class/api_stockmovements.class.php b/htdocs/product/stock/class/api_stockmovements.class.php index 5250913a5f6..27b4d2409e9 100644 --- a/htdocs/product/stock/class/api_stockmovements.class.php +++ b/htdocs/product/stock/class/api_stockmovements.class.php @@ -104,7 +104,8 @@ class StockMovements extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".$this->db->prefix()."stock_mouvement as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement AS t LEFT JOIN ".MAIN_DB_PREFIX."stock_mouvement_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields + //$sql.= ' WHERE t.entity IN ('.getEntity('stock').')'; $sql .= ' WHERE 1 = 1'; // Add sql filters diff --git a/htdocs/product/stock/class/api_warehouses.class.php b/htdocs/product/stock/class/api_warehouses.class.php index a0646598d96..55012aa681c 100644 --- a/htdocs/product/stock/class/api_warehouses.class.php +++ b/htdocs/product/stock/class/api_warehouses.class.php @@ -104,7 +104,7 @@ class Warehouses extends DolibarrApi } $sql = "SELECT t.rowid"; - $sql .= " FROM ".$this->db->prefix()."entrepot as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."entrepot AS t LEFT JOIN ".MAIN_DB_PREFIX."entrepot_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($category > 0) { $sql .= ", ".$this->db->prefix()."categorie_societe as c"; } diff --git a/htdocs/projet/class/api_tasks.class.php b/htdocs/projet/class/api_tasks.class.php index 7c68b8bdeab..4f1cc85ce8c 100644 --- a/htdocs/projet/class/api_tasks.class.php +++ b/htdocs/projet/class/api_tasks.class.php @@ -127,7 +127,7 @@ class Tasks extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."projet_task as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."projet_task AS t LEFT JOIN ".MAIN_DB_PREFIX."projet_task_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/reception/class/api_receptions.class.php b/htdocs/reception/class/api_receptions.class.php index b24a8dbef11..87ac6a354ac 100644 --- a/htdocs/reception/class/api_receptions.class.php +++ b/htdocs/reception/class/api_receptions.class.php @@ -121,7 +121,7 @@ class Receptions extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."reception as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."reception AS t LEFT JOIN ".MAIN_DB_PREFIX."reception_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale @@ -709,7 +709,7 @@ class Receptions extends DolibarrApi private function _validate($data) { $reception = array(); - foreach (Receptions::$FIELDS as $field) { + foreach (Shipments::$FIELDS as $field) { if (!isset($data[$field])) { throw new RestException(400, "$field field missing"); } diff --git a/htdocs/recruitment/class/api_recruitment.class.php b/htdocs/recruitment/class/api_recruitment.class.php index b665bda1279..bcce3d9b92c 100644 --- a/htdocs/recruitment/class/api_recruitment.class.php +++ b/htdocs/recruitment/class/api_recruitment.class.php @@ -165,7 +165,7 @@ class Recruitment extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale @@ -272,7 +272,7 @@ class Recruitment extends DolibarrApi if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; + $sql .= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." AS t LEFT JOIN ".MAIN_DB_PREFIX.$tmpobject->table_element."_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php index 2a18ce0bfd2..6e162258d17 100644 --- a/htdocs/supplier_proposal/class/api_supplier_proposals.class.php +++ b/htdocs/supplier_proposal/class/api_supplier_proposals.class.php @@ -117,7 +117,7 @@ class Supplierproposals extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."supplier_proposal AS t LEFT JOIN ".MAIN_DB_PREFIX."supplier_proposal_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/ticket/class/api_tickets.class.php b/htdocs/ticket/class/api_tickets.class.php index 8b53680ac95..918dd6eb5a1 100644 --- a/htdocs/ticket/class/api_tickets.class.php +++ b/htdocs/ticket/class/api_tickets.class.php @@ -223,7 +223,7 @@ class Tickets extends DolibarrApi if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) } - $sql .= " FROM ".MAIN_DB_PREFIX."ticket as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."ticket AS t LEFT JOIN ".MAIN_DB_PREFIX."ticket_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index f1941b8c079..23c8d77478d 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -82,7 +82,7 @@ class Users extends DolibarrApi //$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe; $sql = "SELECT t.rowid"; - $sql .= " FROM ".$this->db->prefix()."user as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."user AS t LEFT JOIN ".MAIN_DB_PREFIX."user_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields if ($category > 0) { $sql .= ", ".$this->db->prefix()."categorie_user as c"; } @@ -535,7 +535,7 @@ class Users extends DolibarrApi //$socid = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $societe; $sql = "SELECT t.rowid"; - $sql .= " FROM ".$this->db->prefix()."usergroup as t"; + $sql .= " FROM ".MAIN_DB_PREFIX."usergroup AS t LEFT JOIN ".MAIN_DB_PREFIX."usergroup_extrafields AS ef ON (ef.fk_object = t.rowid)"; // Modification VMR Global Solutions to include extrafields as search parameters in the API GET call, so we will be able to filter on extrafields $sql .= ' WHERE t.entity IN ('.getEntity('user').')'; if ($group_ids) { $sql .= " AND t.rowid IN (".$this->db->sanitize($group_ids).")"; From cec58e5631fe1c4ada879ac27c5c8f0662c63938 Mon Sep 17 00:00:00 2001 From: Francis Appels Date: Fri, 28 Apr 2023 10:42:39 +0200 Subject: [PATCH 09/11] Add missing error message on modify order error. --- htdocs/commande/card.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index 17ade08b776..c6ebb04eb03 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -1402,6 +1402,8 @@ if (empty($reshook)) { $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); } + } else { + setEventMessages($object->error, $object->errors, 'errors'); } } } elseif ($action == 'confirm_shipped' && $confirm == 'yes' && $usercanclose) { From 397e6dce38cef58c12f1344f416a1541156d2d80 Mon Sep 17 00:00:00 2001 From: hystepik Date: Fri, 28 Apr 2023 12:18:14 +0200 Subject: [PATCH 10/11] Fix CI --- htdocs/fourn/class/fournisseur.commande.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index e8d76e56450..51946f6f278 100644 --- a/htdocs/fourn/class/fournisseur.commande.class.php +++ b/htdocs/fourn/class/fournisseur.commande.class.php @@ -2145,7 +2145,7 @@ class CommandeFournisseur extends CommonOrder $sql = "INSERT INTO ".MAIN_DB_PREFIX."commande_fournisseur_dispatch"; $sql .= " (fk_commande, fk_product, qty, fk_entrepot, fk_user, datec, fk_commandefourndet, status, comment, eatby, sellby, batch, fk_reception) VALUES"; $sql .= " ('".$this->id."','".$product."','".$qty."',".($entrepot > 0 ? "'".$entrepot."'" : "null").",'".$user->id."','".$this->db->idate($now)."','".$fk_commandefourndet."', ".$dispatchstatus.", '".$this->db->escape($comment)."', "; - $sql .= ($eatby ? "'".$this->db->idate($eatby)."'" : "null").", ".($sellby ? "'".$this->db->idate($sellby)."'" : "null").", ".($batch ? "'".$this->db->escape($batch)."'" : "null").", ".($fk_reception > 0 ? "'".$fk_reception."'" : "null"); + $sql .= ($eatby ? "'".$this->db->idate($eatby)."'" : "null").", ".($sellby ? "'".$this->db->idate($sellby)."'" : "null").", ".($batch ? "'".$this->db->escape($batch)."'" : "null").", ".($fk_reception > 0 ? "'".$this->db->escape($fk_reception)."'" : "null"); $sql .= ")"; dol_syslog(get_class($this)."::dispatchProduct", LOG_DEBUG); From 9b2ffafd9314be9635c192e6d09960e373fb9390 Mon Sep 17 00:00:00 2001 From: Alexandre Janniaux Date: Thu, 27 Apr 2023 14:09:55 +0200 Subject: [PATCH 11/11] Fix install/inc: detect unknown options Previous commit 3c883c4b319c1742fa8d4403200081b0119a4f3a added support for parsing option -- in particular -c/--config -- and added some way of detecting invalid arguments. But the detection was incorrect. getopt will stop looking for arguments when it detects a non-argument (dash-prefixed) which is not an option parameter, but checking that options were all consumed should be done right after by comparing the options up to this last non-argument and those that were detected. This only displays the first unrecognized option, mimicking the behaviour of most software. --- htdocs/install/inc.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index ed1f3f93ad2..1133f10182e 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -146,12 +146,26 @@ if (php_sapi_name() === "cli") { exit(0); } + // Parse the arguments to find the options. + $args_options = array_filter(array_slice($argv, 0, $rest_index), function ($arg) { + return strlen($arg) >= 2 && $arg[0] == '-'; + }); + $parsed_options = array_map(function ($arg) { + if (strlen($arg) > 1) + return "--" . $arg; + return "-" . $arg; + }, array_keys($opts)); + + // Find options (dash-prefixed) that were not parsed. + $unknown_options = array_diff($args_options, $parsed_options); + // In the following test, only dash-prefixed arguments will trigger an // error, given that scripts options can allow a variable number of // additional non-prefixed argument and we mostly want to check for // typo right now. - if ($rest_index < $argc && $argv[$rest_index][0] == "-") { - usage($argv[0], "Unknown option ".$argv[$rest_index]. ", usage:"); + if (count($unknown_options) > 0) { + echo "Unknown option: ".array_values($unknown_options)[0]."\n"; + usage($argv[0], "Usage:"); exit(1); }