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/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) { 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/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/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/fourn/class/fournisseur.commande.class.php b/htdocs/fourn/class/fournisseur.commande.class.php index 22acc6258cc..51946f6f278 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 ? "'".$this->db->escape($fk_reception)."'" : "null"); $sql .= ")"; dol_syslog(get_class($this)."::dispatchProduct", LOG_DEBUG); diff --git a/htdocs/fourn/commande/card.php b/htdocs/fourn/commande/card.php index a3f9e8e234e..a9049301bdb 100644 --- a/htdocs/fourn/commande/card.php +++ b/htdocs/fourn/commande/card.php @@ -134,7 +134,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 7083897e25a..25fb890698a 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 6bd2d39ce21..f1b70fa0ceb 100644 --- a/htdocs/fourn/js/lib_dispatch.js.php +++ b/htdocs/fourn/js/lib_dispatch.js.php @@ -65,8 +65,7 @@ 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' var $row0 = $("tr[name='"+type+'_0_'+index+"']"); @@ -80,20 +79,18 @@ function addDispatchLine(index, type, mode) 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 (qty <= 1) { window.alert("Remain quantity to dispatch is too low to be split"); @@ -107,7 +104,7 @@ function addDispatchLine(index, type, mode) } //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 @@ -121,27 +118,42 @@ 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(oldlineqty); //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 () { + 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') { @@ -150,13 +162,19 @@ function addDispatchLine(index, type, mode) } $("#qty_"+nbrTrs+"_"+index).val(newlineqty); // 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"); } } @@ -170,26 +188,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/install/inc.php b/htdocs/install/inc.php index c0bded73cd2..1133f10182e 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"; @@ -134,19 +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:"); - 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:"); + if (count($unknown_options) > 0) { + echo "Unknown option: ".array_values($unknown_options)[0]."\n"; + usage($argv[0], "Usage:"); exit(1); } 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/langs/en_US/receptions.lang b/htdocs/langs/en_US/receptions.lang index 7324f14f2e0..cd4c860e82f 100644 --- a/htdocs/langs/en_US/receptions.lang +++ b/htdocs/langs/en_US/receptions.lang @@ -51,4 +51,7 @@ 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 +DispatchCard=Dispatch card \ No newline at end of file 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/class/product.class.php b/htdocs/product/class/product.class.php index c2de9c24770..f0b7bcaf6a2 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)); @@ -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)); 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/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(); 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).")";