From 844333688bf503b2d5e22a74e244f4dc5f25ca11 Mon Sep 17 00:00:00 2001 From: Philippe GRAND Date: Thu, 6 Sep 2018 14:33:22 +0200 Subject: [PATCH 01/17] typo --- htdocs/compta/facture/class/facture.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index c6e43206c78..27462f3be59 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -206,7 +206,7 @@ class Facture extends CommonInvoice * If paid partially, $this->close_code can be: * - CLOSECODE_DISCOUNTVAT * - CLOSECODE_BADDEBT - * If paid completelly, this->close_code will be null + * If paid completely, this->close_code will be null */ const STATUS_CLOSED = 2; @@ -2362,7 +2362,7 @@ class Facture extends CommonInvoice } } - // Set new ref and define current statut + // Set new ref and define current status if (! $error) { $this->ref = $num; @@ -4827,7 +4827,7 @@ class FactureLigne extends CommonInvoiceLine if (is_null($this->fk_prev_id) || empty($this->fk_prev_id) || $this->fk_prev_id == "") { return 0; } else { - // If invoice is a not a situation invoice, this->fk_prev_id is used for something else + // If invoice is not a situation invoice, this->fk_prev_id is used for something else $tmpinvoice=new Facture($this->db); $tmpinvoice->fetch($invoiceid); if ($tmpinvoice->type != Facture::TYPE_SITUATION) return 0; From 402bbbe83967a563e500fd5388bfdd6ec80b2fa5 Mon Sep 17 00:00:00 2001 From: De Coninck Laurent Date: Fri, 19 Oct 2018 17:23:53 +0200 Subject: [PATCH 02/17] fix the member e-mail on resign and validation. Since the member module is only using the new configuration and the name of the global variabels changed you have a blocking e-mail error when you try to resign or validate a member. In order to fix that I fallback on the previous variable like that it's still working. [see: #9640] --- htdocs/adherents/card.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index a3df6705df9..c9a8eebf0fe 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -634,6 +634,12 @@ if (empty($reshook)) $msg = $arraydefaultmessage->content; } + if (empty($labeltouse)) { + //fallback on the old configuration. + $subject = $conf->global->ADHERENT_MAIL_VALID_SUBJECT; + $msg = $conf->global->ADHERENT_MAIL_VALID; + } + $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object); complete_substitutions_array($substitutionarray, $outputlangs, $object); $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); @@ -707,6 +713,12 @@ if (empty($reshook)) $msg = $arraydefaultmessage->content; } + if (empty($labeltouse)) { + //fallback on the old configuration. + $subject = $conf->global->ADHERENT_MAIL_RESIL_SUBJECT; + $msg = $conf->global->ADHERENT_MAIL_RESIL; + } + $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object); complete_substitutions_array($substitutionarray, $outputlangs, $object); $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); From 16c35035c1452dd325d13d2f85ce11bd5757c697 Mon Sep 17 00:00:00 2001 From: Marc de Lima Lucio Date: Thu, 25 Oct 2018 12:07:40 +0200 Subject: [PATCH 03/17] FIX: pdf typhon: order reference duplicate --- .../livraison/doc/pdf_typhon.modules.php | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/htdocs/core/modules/livraison/doc/pdf_typhon.modules.php b/htdocs/core/modules/livraison/doc/pdf_typhon.modules.php index 1f8e06eb04d..bbc74f3b6bb 100644 --- a/htdocs/core/modules/livraison/doc/pdf_typhon.modules.php +++ b/htdocs/core/modules/livraison/doc/pdf_typhon.modules.php @@ -754,43 +754,6 @@ class pdf_typhon extends ModelePDFDeliveryOrder $posy+=2; - // Add list of linked orders on shipment - // Currently not supported by pdf_writeLinkedObjects, link for delivery to order is done through shipment) - if ($object->origin == 'expedition' || $object->origin == 'shipping') - { - $Yoff=$posy-5; - - include_once DOL_DOCUMENT_ROOT.'/expedition/class/expedition.class.php'; - $shipment = new Expedition($this->db); - $shipment->fetch($object->origin_id); - - $origin = $shipment->origin; - $origin_id = $shipment->origin_id; - - if ($conf->$origin->enabled) - { - $outputlangs->load('orders'); - - $classname = ucfirst($origin); - $linkedobject = new $classname($this->db); - $result=$linkedobject->fetch($origin_id); - if ($result >= 0) - { - $pdf->SetFont('','', $default_font_size - 2); - $text=$linkedobject->ref; - if ($linkedobject->ref_client) $text.=' ('.$linkedobject->ref_client.')'; - $Yoff = $Yoff+8; - $pdf->SetXY($this->page_largeur - $this->marge_droite - 100,$Yoff); - $pdf->MultiCell(100, 2, $outputlangs->transnoentities("RefOrder") ." : ".$outputlangs->transnoentities($text), 0, 'R'); - $Yoff = $Yoff+3; - $pdf->SetXY($this->page_largeur - $this->marge_droite - 60,$Yoff); - $pdf->MultiCell(60, 2, $outputlangs->transnoentities("OrderDate")." : ".dol_print_date($linkedobject->date,"day",false,$outputlangs,true), 0, 'R'); - } - } - - $posy=$Yoff; - } - // Show list of linked objects $posy = pdf_writeLinkedObjects($pdf, $object, $outputlangs, $posx, $posy, 100, 3, 'R', $default_font_size); From d347cf3a85b04ea11d8a2cfae348948dbac446f6 Mon Sep 17 00:00:00 2001 From: De Coninck Laurent Date: Fri, 26 Oct 2018 16:18:27 +0200 Subject: [PATCH 04/17] set a message --- htdocs/adherents/card.php | 66 ++++++++++++++++--------------- htdocs/core/lib/functions.lib.php | 2 +- 2 files changed, 36 insertions(+), 32 deletions(-) diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index c9a8eebf0fe..2aceb437d23 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -634,25 +634,27 @@ if (empty($reshook)) $msg = $arraydefaultmessage->content; } - if (empty($labeltouse)) { + if (empty($labeltouse) || (int)$labeltouse === -1) { //fallback on the old configuration. - $subject = $conf->global->ADHERENT_MAIL_VALID_SUBJECT; - $msg = $conf->global->ADHERENT_MAIL_VALID; + setEventMessages('WarningMandatorySetupNotComplete', [], 'errors'); + $error++; + }else{ + $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); + $texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnValid()), $substitutionarray, $outputlangs); + + $moreinheader='X-Dolibarr-Info: send_an_email by adherents/card.php'."\r\n"; + + $result=$object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader); + if ($result < 0) + { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + } } - $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object); - complete_substitutions_array($substitutionarray, $outputlangs, $object); - $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); - $texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnValid()), $substitutionarray, $outputlangs); - $moreinheader='X-Dolibarr-Info: send_an_email by adherents/card.php'."\r\n"; - - $result=$object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader); - if ($result < 0) - { - $error++; - setEventMessages($object->error, $object->errors, 'errors'); - } } } else @@ -713,26 +715,28 @@ if (empty($reshook)) $msg = $arraydefaultmessage->content; } - if (empty($labeltouse)) { + if (empty($labeltouse) || (int)$labeltouse === -1) { //fallback on the old configuration. - $subject = $conf->global->ADHERENT_MAIL_RESIL_SUBJECT; - $msg = $conf->global->ADHERENT_MAIL_RESIL; + setEventMessages('WarningMandatorySetupNotComplete', [], 'errors'); + $error++; + }else{ + $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object); + complete_substitutions_array($substitutionarray, $outputlangs, $object); + $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); + $texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnResiliate()), $substitutionarray, $outputlangs); + + $moreinheader='X-Dolibarr-Info: send_an_email by adherents/card.php'."\r\n"; + + $result=$object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader); + if ($result < 0) + { + $error++; + setEventMessages($object->error, $object->errors, 'errors'); + } } + } - $substitutionarray=getCommonSubstitutionArray($outputlangs, 0, null, $object); - complete_substitutions_array($substitutionarray, $outputlangs, $object); - $subjecttosend = make_substitutions($subject, $substitutionarray, $outputlangs); - $texttosend = make_substitutions(dol_concatdesc($msg, $adht->getMailOnResiliate()), $substitutionarray, $outputlangs); - $moreinheader='X-Dolibarr-Info: send_an_email by adherents/card.php'."\r\n"; - - $result=$object->send_an_email($texttosend, $subjecttosend, array(), array(), array(), "", "", 0, -1, '', $moreinheader); - } - if ($result < 0) - { - $error++; - setEventMessages($object->error, $object->errors, 'errors'); - } } else { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 3ec1f226993..6649bf17bbb 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6555,7 +6555,7 @@ function get_htmloutput_errors($mesgstring='', $mesgarray='', $keepembedded=0) * @see dol_htmloutput_errors * @see setEventMessages */ -function dol_htmloutput_mesg($mesgstring='',$mesgarray='', $style='ok', $keepembedded=0) +function dol_htmloutput_mesg($mesgstring = '',$mesgarray = [], $style = 'ok', $keepembedded=0) { if (empty($mesgstring) && (! is_array($mesgarray) || count($mesgarray) == 0)) return; From a30091fd7485c31a9ea3310b6d953d850a141d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20FRANCE?= Date: Sat, 27 Oct 2018 09:51:19 +0200 Subject: [PATCH 05/17] Update commande.class.php --- htdocs/commande/class/commande.class.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index d2f915406f8..cc64226a67a 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -76,6 +76,9 @@ class Commande extends CommonOrder public $facturee; public $billed; // billed or not + /** + * @var int Draft Status of the order + */ public $brouillon; public $cond_reglement_code; @@ -226,7 +229,7 @@ class Commande extends CommonOrder $mybool|=@include_once $dir.$file; } - if (! $mybool) + if ($mybool === false) { dol_print_error('',"Failed to include file ".$file); return ''; @@ -400,6 +403,7 @@ class Commande extends CommonOrder { $this->ref = $num; $this->statut = self::STATUS_VALIDATED; + $this->brouillon = 0; } if (! $error) From fcd687642c89d627523402baf87533638682cce6 Mon Sep 17 00:00:00 2001 From: Librethic <34575536+librethic-code@users.noreply.github.com> Date: Sat, 27 Oct 2018 11:46:12 +0200 Subject: [PATCH 06/17] FIX: keep external module element when adding resource When adding object from external module as a resource we need to keep @modulename as defined into url rather than use `element` property (which do not contain @modulename). --- htdocs/resource/element_resource.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/resource/element_resource.php b/htdocs/resource/element_resource.php index 389d0236759..b9ff15f1461 100644 --- a/htdocs/resource/element_resource.php +++ b/htdocs/resource/element_resource.php @@ -1,5 +1,5 @@ +/* Copyright (C) 2013-2018 Jean-François Ferry * Copyright (C) 2016 Gilles Poirier * * This program is free software: you can redistribute it and/or modify @@ -94,7 +94,7 @@ if ($action == 'add_element_resource' && ! $cancel) else { $objstat = fetchObjectByElement($element_id, $element); - + $objstat->element = $element; // For externals module, we need to keep @xx $res = $objstat->add_element_resource($resource_id, $resource_type, $busy, $mandatory); } if (! $error && $res > 0) From 2fe4763570848f4f36611ea1a6aa837aacbf5842 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Sun, 28 Oct 2018 09:22:55 +0100 Subject: [PATCH 07/17] Fix default accounting accounts on loan creation #9643 --- htdocs/loan/card.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index 79569f62df3..d7e81c9e2dd 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -340,19 +340,19 @@ if ($action == 'create') // Accountancy_account_capital print ''.$langs->trans("LoanAccountancyCapitalCode").''; print ''; - print $formaccounting->select_account($object->accountancy_account_capital, 'accountancy_account_capital', 1, '', 0, 1); + print $formaccounting->select_account(GETPOST('accountancy_account_capital')?GETPOST('accountancy_account_capital'):$conf->global->LOAN_ACCOUNTING_ACCOUNT_CAPITAL, 'accountancy_account_capital', 1, '', 1, 1); print ''; // Accountancy_account_insurance print ''.$langs->trans("LoanAccountancyInsuranceCode").''; print ''; - print $formaccounting->select_account($object->accountancy_account_insurance, 'accountancy_account_insurance', 1, '', 0, 1); + print $formaccounting->select_account(GETPOST('accountancy_account_insurance')?GETPOST('accountancy_account_insurance'):$conf->global->LOAN_ACCOUNTING_ACCOUNT_INSURANCE, 'accountancy_account_insurance', 1, '', 1, 1); print ''; // Accountancy_account_interest print ''.$langs->trans("LoanAccountancyInterestCode").''; print ''; - print $formaccounting->select_account($object->accountancy_account_interest, 'accountancy_account_interest', 1, '', 0, 1); + print $formaccounting->select_account(GETPOST('accountancy_account_interest')?GETPOST('accountancy_account_interest'):$conf->global->LOAN_ACCOUNTING_ACCOUNT_INTEREST, 'accountancy_account_interest', 1, '', 1, 1); print ''; } else // For external software From 46d3bec104695e17dd08430d78438190dc95c4d9 Mon Sep 17 00:00:00 2001 From: Maxime Kohlhaas Date: Sun, 28 Oct 2018 10:25:56 +0100 Subject: [PATCH 08/17] Fix replenish wasn't caring about supplier price min quantity #9561 --- htdocs/langs/en_US/errors.lang | 1 + htdocs/product/stock/replenish.php | 45 +++++++++++++++++------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/htdocs/langs/en_US/errors.lang b/htdocs/langs/en_US/errors.lang index 45c1426556e..25a5344ff62 100644 --- a/htdocs/langs/en_US/errors.lang +++ b/htdocs/langs/en_US/errors.lang @@ -88,6 +88,7 @@ ErrorFileIsInfectedWithAVirus=The antivirus program was not able to validate the ErrorSpecialCharNotAllowedForField=Special characters are not allowed for field "%s" ErrorNumRefModel=A reference exists into database (%s) and is not compatible with this numbering rule. Remove record or renamed reference to activate this module. ErrorQtyTooLowForThisSupplier=Quantity too low for this vendor or no price defined on this product for this supplier +ErrorOrdersNotCreatedQtyTooLow=Some orders haven't been created beacuse of too low quantity ErrorModuleSetupNotComplete=Setup of module looks to be uncomplete. Go on Home - Setup - Modules to complete. ErrorBadMask=Error on mask ErrorBadMaskFailedToLocatePosOfSequence=Error, mask without sequence number diff --git a/htdocs/product/stock/replenish.php b/htdocs/product/stock/replenish.php index 46200a2f6a7..3bc2bcdd85c 100644 --- a/htdocs/product/stock/replenish.php +++ b/htdocs/product/stock/replenish.php @@ -106,12 +106,15 @@ if ($action == 'order' && isset($_POST['valid'])) { $linecount = GETPOST('linecount', 'int'); $box = 0; + $errorQty = 0; unset($_POST['linecount']); if ($linecount > 0) { $db->begin(); $suppliers = array(); + require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php'; + $productsupplier = new ProductFournisseur($db); for ($i = 0; $i < $linecount; $i++) { if (GETPOST('choose' . $i, 'alpha') === 'on' && GETPOST('fourn' . $i, 'int') > 0) @@ -121,13 +124,9 @@ if ($action == 'order' && isset($_POST['valid'])) $supplierpriceid = GETPOST('fourn'.$i, 'int'); //get all the parameters needed to create a line $qty = GETPOST('tobuy'.$i, 'int'); - //$desc = GETPOST('desc'.$i, 'alpha'); - $sql = 'SELECT fk_product, fk_soc, ref_fourn'; - $sql .= ', tva_tx, unitprice, remise_percent FROM '; - $sql .= MAIN_DB_PREFIX . 'product_fournisseur_price'; - $sql .= ' WHERE rowid = ' . $supplierpriceid; - $resql = $db->query($sql); - if ($resql && $db->num_rows($resql) > 0) + $idprod=$productsupplier->get_buyprice($supplierpriceid, $qty); + $res=$productsupplier->fetch($idprod); + if ($res && $idprod > 0) { if ($qty) { @@ -135,33 +134,37 @@ if ($action == 'order' && isset($_POST['valid'])) $obj = $db->fetch_object($resql); $line = new CommandeFournisseurLigne($db); $line->qty = $qty; - $line->fk_product = $obj->fk_product; + $line->fk_product = $idprod; - $product = new Product($db); - $product->fetch($obj->fk_product); + //$product = new Product($db); + //$product->fetch($obj->fk_product); if (! empty($conf->global->MAIN_MULTILANGS)) { - $product->getMultiLangs(); + $productsupplier->getMultiLangs(); } - $line->desc = $product->description; + $line->desc = $productsupplier->description; if (! empty($conf->global->MAIN_MULTILANGS)) { // TODO Get desc in language of thirdparty } - $line->tva_tx = $obj->tva_tx; - $line->subprice = $obj->unitprice; - $line->total_ht = $obj->unitprice * $qty; + $line->tva_tx = $productsupplier->vatrate_supplier; + $line->subprice = $productsupplier->fourn_pu; + $line->total_ht = $productsupplier->fourn_pu * $qty; $tva = $line->tva_tx / 100; $line->total_tva = $line->total_ht * $tva; $line->total_ttc = $line->total_ht + $line->total_tva; - $line->remise_percent = $obj->remise_percent; - $line->ref_fourn = $obj->ref_fourn; - $line->type = $product->type; - $line->fk_unit = $product->fk_unit; - $suppliers[$obj->fk_soc]['lines'][] = $line; + $line->remise_percent = $productsupplier->remise_percent; + $line->ref_fourn = $productsupplier->ref_supplier; + $line->type = $productsupplier->type; + $line->fk_unit = $productsupplier->fk_unit; + $suppliers[$productsupplier->fourn_socid]['lines'][] = $line; } } + elseif ($idprod == -1) + { + $errorQty++; + } else { $error=$db->lasterror(); @@ -242,6 +245,8 @@ if ($action == 'order' && isset($_POST['valid'])) } } + if($errorQty) setEventMessages($langs->trans('ErrorOrdersNotCreatedQtyTooLow'), null, 'warnings'); + if (! $fail && $id) { $db->commit(); From c83e67123d3ca50e3309dbe3c86d9107ee5dae1a Mon Sep 17 00:00:00 2001 From: atm-ph Date: Mon, 29 Oct 2018 11:04:16 +0100 Subject: [PATCH 09/17] Fix pgsql : operator does not exist: timestamp without time zone ~~ unknown --- htdocs/adherents/subscription/list.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 21ba01088e4..575bd3a233a 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -126,7 +126,8 @@ $sql.= " WHERE d.rowid = c.fk_adherent"; $sql.= " AND d.entity IN (".getEntity('adherent').")"; if (isset($date_select) && $date_select != '') { - $sql.= " AND c.dateadh LIKE '".$date_select."%'"; + $sql.= " AND c.dateadh >= '".$date_select."-01-01 00:00:00'"; + $sql.= " AND c.dateadh < '".($date_select+1)."-01-01 00:00:00'"; } if ($search_ref) { From 85b8c9f21920be7c4e2559f02bc8ae0b28b49c31 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Oct 2018 14:35:42 +0100 Subject: [PATCH 10/17] FIX Delete of draft invoice --- htdocs/compta/facture/card.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index be65b2ec5ab..8c80c5caa9c 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -959,7 +959,7 @@ if (empty($reshook)) if($facture_source->type == Facture::TYPE_SITUATION) { - $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id + $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id $line->fk_prev_id = $line->id; // Credit note line need to be linked to the situation invoice it is create from if(!empty($facture_source->tab_previous_situation_invoice)) @@ -1543,8 +1543,8 @@ if (empty($reshook)) $line->origin_id = $line->id; $line->fk_prev_id = $line->id; $line->fetch_optionals($line->id); - $line->situation_percent = $line->get_prev_progress($object->id); // get good progress including credit note - + $line->situation_percent = $line->get_prev_progress($object->id); // get good progress including credit note + // Si fk_remise_except defini on vérifie si la réduction à déjà été appliquée if ($line->fk_remise_except) { @@ -4811,9 +4811,9 @@ else if ($id > 0 || ! empty($ref)) } // Delete - if ($user->rights->facture->supprimer) + $isErasable = $object->is_erasable(); + if ($user->rights->facture->supprimer || $isErasable == 1) // isErasable = 1 means draft (draft can always be deleted with no need of permissions) { - $isErasable = $object->is_erasable(); //var_dump($isErasable); if ($isErasable == -4) { print ''; From 27d82d0e8e723ba26784cbb3da9c2d7227af153e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Oct 2018 14:41:00 +0100 Subject: [PATCH 11/17] FIX Delete of draft invoice --- htdocs/compta/facture/card.php | 4 ++-- htdocs/core/class/commoninvoice.class.php | 5 +++-- htdocs/fourn/facture/card.php | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 8c80c5caa9c..7589801787c 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -190,7 +190,7 @@ if (empty($reshook)) $qualified_for_stock_change = $object->hasProductsOrServices(1); } - if ($object->is_erasable()) + if ($object->is_erasable() > 0) { $result = $object->delete($user, 0, $idwarehouse); if ($result > 0) { @@ -4812,7 +4812,7 @@ else if ($id > 0 || ! empty($ref)) // Delete $isErasable = $object->is_erasable(); - if ($user->rights->facture->supprimer || $isErasable == 1) // isErasable = 1 means draft (draft can always be deleted with no need of permissions) + if ($user->rights->facture->supprimer || $isErasable == 1) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions) { //var_dump($isErasable); if ($isErasable == -4) { diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 9bab103d2e4..3aa8eb4e1ab 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -328,12 +328,13 @@ abstract class CommonInvoice extends CommonObject /** * Return if an invoice can be deleted * Rule is: - * If invoice is draft and has a temporary ref -> yes + * If invoice is draft and has a temporary ref -> yes (1) * If hidden option INVOICE_CAN_NEVER_BE_REMOVED is on -> no (0) * If invoice is dispatched in bookkeeping -> no (-1) * If invoice has a definitive ref, is not last and INVOICE_CAN_ALWAYS_BE_REMOVED off -> no (-2) * If invoice not last in a cycle -> no (-3) * If there is payment -> no (-4) + * Otherwise -> yes (2) * * @return int <=0 if no, >0 if yes */ @@ -381,7 +382,7 @@ abstract class CommonInvoice extends CommonObject // Test if there is at least one payment. If yes, refuse to delete. if (empty($conf->global->INVOICE_CAN_ALWAYS_BE_REMOVED) && $this->getSommePaiement() > 0) return -4; - return 1; + return 2; } /** diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 36785a154dc..75e0f15220d 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -3117,9 +3117,9 @@ else } // Delete - if ($action != 'confirm_edit' && $user->rights->fournisseur->facture->supprimer) + $isErasable=$object->is_erasable(); + if ($action != 'confirm_edit' && ($user->rights->fournisseur->facture->supprimer || $isErasable == 1)) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions) { - $isErasable=$object->is_erasable(); //var_dump($isErasable); if ($isErasable == -4) { print ''; From 824757bca6eba8dcf64522a9fb3f7745c498970a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Oct 2018 14:47:33 +0100 Subject: [PATCH 12/17] Fix perm to delete --- htdocs/compta/facture/card.php | 2 +- htdocs/fourn/facture/card.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 7589801787c..856b430c646 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -4812,7 +4812,7 @@ else if ($id > 0 || ! empty($ref)) // Delete $isErasable = $object->is_erasable(); - if ($user->rights->facture->supprimer || $isErasable == 1) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions) + if ($user->rights->facture->supprimer || ($user->rights->facture->creer && $isErasable == 1)) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions) { //var_dump($isErasable); if ($isErasable == -4) { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 75e0f15220d..78c64ae1062 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -3118,7 +3118,7 @@ else // Delete $isErasable=$object->is_erasable(); - if ($action != 'confirm_edit' && ($user->rights->fournisseur->facture->supprimer || $isErasable == 1)) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions) + if ($action != 'confirm_edit' && ($user->rights->fournisseur->facture->supprimer || ($user->rights->fournisseur->facture->creer && $isErasable == 1))) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions) { //var_dump($isErasable); if ($isErasable == -4) { From d02fccd7e41671e6521c3aba9604202634f92701 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Oct 2018 14:56:00 +0100 Subject: [PATCH 13/17] Fix deletion of draft invoice --- htdocs/compta/facture/card.php | 7 +++++-- htdocs/fourn/facture/card.php | 25 ++++++++++++++++--------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 856b430c646..14a1ead5098 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -177,7 +177,7 @@ if (empty($reshook)) } // Delete invoice - else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->facture->supprimer) { + else if ($action == 'confirm_delete' && $confirm == 'yes') { $result = $object->fetch($id); $object->fetch_thirdparty(); @@ -190,7 +190,10 @@ if (empty($reshook)) $qualified_for_stock_change = $object->hasProductsOrServices(1); } - if ($object->is_erasable() > 0) + $isErasable=$object->is_erasable(); + + if (($user->rights->facture->supprimer && $isErasable > 0) + || ($user->rights->facture->creer && $isErasable == 1)) { $result = $object->delete($user, 0, $idwarehouse); if ($result > 0) { diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 78c64ae1062..2ce28875425 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -218,19 +218,26 @@ if (empty($reshook)) } } - elseif ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->fournisseur->facture->supprimer) + elseif ($action == 'confirm_delete' && $confirm == 'yes') { $object->fetch($id); $object->fetch_thirdparty(); - $result=$object->delete($user); - if ($result > 0) + + $isErasable=$object->is_erasable(); + + if (($user->rights->fournisseur->facture->supprimer && $isErasable > 0) + || ($user->rights->fournisseur->facture->creer && $isErasable == 1)) { - header('Location: list.php?restore_lastsearch_values=1'); - exit; - } - else - { - setEventMessages($object->error, $object->errors, 'errors'); + $result=$object->delete($user); + if ($result > 0) + { + header('Location: list.php?restore_lastsearch_values=1'); + exit; + } + else + { + setEventMessages($object->error, $object->errors, 'errors'); + } } } From 0266db7aa8688698ae41a662274a06dd17891b33 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Oct 2018 18:19:40 +0100 Subject: [PATCH 14/17] FIX deletion on draft is allowed if we are allwoed to create --- htdocs/compta/facture/card.php | 10 +- htdocs/core/lib/security.lib.php | 479 ++++++++++++++++--------------- htdocs/fourn/facture/card.php | 10 +- 3 files changed, 250 insertions(+), 249 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 14a1ead5098..aa1176e0295 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -92,11 +92,6 @@ $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0)); $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0)); -// Security check -$fieldid = (! empty($ref) ? 'facnumber' : 'rowid'); -if ($user->societe_id) $socid = $user->societe_id; -$result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid); - // Nombre de ligne pour choix de produit/service predefinis $NBLINES = 4; @@ -117,6 +112,11 @@ $permissionnote = $user->rights->facture->creer; // Used by the include of actio $permissiondellink=$user->rights->facture->creer; // Used by the include of actions_dellink.inc.php $permissiontoedit = $user->rights->facture->creer; // Used by the include of actions_lineupdonw.inc.php +// Security check +$fieldid = (! empty($ref) ? 'facnumber' : 'rowid'); +if ($user->societe_id) $socid = $user->societe_id; +$result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid, null, (($object->statut == Facture::STATUS_DRAFT) ? 1 : 0)); + /* * Actions diff --git a/htdocs/core/lib/security.lib.php b/htdocs/core/lib/security.lib.php index 9fa5fb8b7c3..d2b768d75d5 100644 --- a/htdocs/core/lib/security.lib.php +++ b/htdocs/core/lib/security.lib.php @@ -39,7 +39,7 @@ function dol_encode($chain, $key='1') if (is_numeric($key) && $key == '1') // rule 1 is offset of 17 for char { $output_tab=array(); - $strlength=dol_strlen($chain); + $strlength=dol_strlen($chain); for ($i=0; $i < $strlength; $i++) { $output_tab[$i] = chr(ord(substr($chain,$i,1))+17); @@ -175,18 +175,19 @@ function dol_verifyHash($chain, $hash, $type='0') * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional) * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional) * @param Canvas $objcanvas Object canvas + * @param int $isdraft 1=The object with id=$objectid is a draft * @return int Always 1, die process if not allowed * @see dol_check_secure_access_document */ -function restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null) +function restrictedArea($user, $features, $objectid=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $objcanvas=null, $isdraft=0) { global $db, $conf; global $hookmanager; - //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename,$feature2,$dbt_socfield,$dbt_select"); - //print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid; - //print ", dbtablename=".$dbtablename.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select; - //print ", perm: ".$features."->".$feature2."=".($user->rights->$features->$feature2->lire)."
"; + //dol_syslog("functions.lib:restrictedArea $feature, $objectid, $dbtablename,$feature2,$dbt_socfield,$dbt_select"); + //print "user_id=".$user->id.", features=".$features.", feature2=".$feature2.", objectid=".$objectid; + //print ", dbtablename=".$dbtablename.", dbt_socfield=".$dbt_keyfield.", dbt_select=".$dbt_select; + //print ", perm: ".$features."->".$feature2."=".($user->rights->$features->$feature2->lire)."
"; // Get more permissions checks from hooks $parameters=array('features'=>$features, 'objectid'=>$objectid, 'idtype'=>$dbt_select); @@ -197,225 +198,225 @@ function restrictedArea($user, $features, $objectid=0, $tableandshare='', $featu if ($dbt_select != 'rowid' && $dbt_select != 'id') $objectid = "'".$objectid."'"; // Features/modules to check - $featuresarray = array($features); - if (preg_match('/&/', $features)) $featuresarray = explode("&", $features); - else if (preg_match('/\|/', $features)) $featuresarray = explode("|", $features); + $featuresarray = array($features); + if (preg_match('/&/', $features)) $featuresarray = explode("&", $features); + else if (preg_match('/\|/', $features)) $featuresarray = explode("|", $features); - // More subfeatures to check - if (! empty($feature2)) $feature2 = explode("|", $feature2); + // More subfeatures to check + if (! empty($feature2)) $feature2 = explode("|", $feature2); - // More parameters - $params = explode('&', $tableandshare); - $dbtablename=(! empty($params[0]) ? $params[0] : ''); - $sharedelement=(! empty($params[1]) ? $params[1] : $dbtablename); + // More parameters + $params = explode('&', $tableandshare); + $dbtablename=(! empty($params[0]) ? $params[0] : ''); + $sharedelement=(! empty($params[1]) ? $params[1] : $dbtablename); $listofmodules=explode(',',$conf->global->MAIN_MODULES_FOR_EXTERNAL); // Check read permission from module - $readok=1; $nbko=0; - foreach ($featuresarray as $feature) // first we check nb of test ko - { - $featureforlistofmodule=$feature; - if ($featureforlistofmodule == 'produit') $featureforlistofmodule='product'; - if (! empty($user->societe_id) && ! empty($conf->global->MAIN_MODULES_FOR_EXTERNAL) && ! in_array($featureforlistofmodule,$listofmodules)) // If limits on modules for external users, module must be into list of modules for external users - { - $readok=0; $nbko++; - continue; - } + $readok=1; $nbko=0; + foreach ($featuresarray as $feature) // first we check nb of test ko + { + $featureforlistofmodule=$feature; + if ($featureforlistofmodule == 'produit') $featureforlistofmodule='product'; + if (! empty($user->societe_id) && ! empty($conf->global->MAIN_MODULES_FOR_EXTERNAL) && ! in_array($featureforlistofmodule,$listofmodules)) // If limits on modules for external users, module must be into list of modules for external users + { + $readok=0; $nbko++; + continue; + } - if ($feature == 'societe') - { - if (! $user->rights->societe->lire && ! $user->rights->fournisseur->lire) { $readok=0; $nbko++; } - } - else if ($feature == 'contact') - { - if (! $user->rights->societe->contact->lire) { $readok=0; $nbko++; } - } - else if ($feature == 'produit|service') - { - if (! $user->rights->produit->lire && ! $user->rights->service->lire) { $readok=0; $nbko++; } - } - else if ($feature == 'prelevement') - { - if (! $user->rights->prelevement->bons->lire) { $readok=0; $nbko++; } - } - else if ($feature == 'cheque') - { - if (! $user->rights->banque->cheque) { $readok=0; $nbko++; } - } - else if ($feature == 'projet') - { - if (! $user->rights->projet->lire && ! $user->rights->projet->all->lire) { $readok=0; $nbko++; } - } - else if (! empty($feature2)) // This should be used for future changes - { - $tmpreadok=1; - foreach($feature2 as $subfeature) - { - if (! empty($subfeature) && empty($user->rights->$feature->$subfeature->lire) && empty($user->rights->$feature->$subfeature->read)) { $tmpreadok=0; } - else if (empty($subfeature) && empty($user->rights->$feature->lire) && empty($user->rights->$feature->read)) { $tmpreadok=0; } - else { $tmpreadok=1; break; } // Break is to bypass second test if the first is ok - } - if (! $tmpreadok) // We found a test on feature that is ko - { - $readok=0; // All tests are ko (we manage here the and, the or will be managed later using $nbko). - $nbko++; - } - } - else if (! empty($feature) && ($feature!='user' && $feature!='usergroup')) // This is for old permissions - { - if (empty($user->rights->$feature->lire) - && empty($user->rights->$feature->read) - && empty($user->rights->$feature->run)) { $readok=0; $nbko++; } - } - } + if ($feature == 'societe') + { + if (! $user->rights->societe->lire && ! $user->rights->fournisseur->lire) { $readok=0; $nbko++; } + } + else if ($feature == 'contact') + { + if (! $user->rights->societe->contact->lire) { $readok=0; $nbko++; } + } + else if ($feature == 'produit|service') + { + if (! $user->rights->produit->lire && ! $user->rights->service->lire) { $readok=0; $nbko++; } + } + else if ($feature == 'prelevement') + { + if (! $user->rights->prelevement->bons->lire) { $readok=0; $nbko++; } + } + else if ($feature == 'cheque') + { + if (! $user->rights->banque->cheque) { $readok=0; $nbko++; } + } + else if ($feature == 'projet') + { + if (! $user->rights->projet->lire && ! $user->rights->projet->all->lire) { $readok=0; $nbko++; } + } + else if (! empty($feature2)) // This should be used for future changes + { + $tmpreadok=1; + foreach($feature2 as $subfeature) + { + if (! empty($subfeature) && empty($user->rights->$feature->$subfeature->lire) && empty($user->rights->$feature->$subfeature->read)) { $tmpreadok=0; } + else if (empty($subfeature) && empty($user->rights->$feature->lire) && empty($user->rights->$feature->read)) { $tmpreadok=0; } + else { $tmpreadok=1; break; } // Break is to bypass second test if the first is ok + } + if (! $tmpreadok) // We found a test on feature that is ko + { + $readok=0; // All tests are ko (we manage here the and, the or will be managed later using $nbko). + $nbko++; + } + } + else if (! empty($feature) && ($feature!='user' && $feature!='usergroup')) // This is for old permissions + { + if (empty($user->rights->$feature->lire) + && empty($user->rights->$feature->read) + && empty($user->rights->$feature->run)) { $readok=0; $nbko++; } + } + } - // If a or and at least one ok - if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $readok=1; + // If a or and at least one ok + if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $readok=1; - if (! $readok) accessforbidden(); - //print "Read access is ok"; + if (! $readok) accessforbidden(); + //print "Read access is ok"; - // Check write permission from module - $createok=1; $nbko=0; - if (GETPOST('action','aZ09') == 'create') - { - foreach ($featuresarray as $feature) - { - if ($feature == 'contact') - { - if (! $user->rights->societe->contact->creer) { $createok=0; $nbko++; } - } - else if ($feature == 'produit|service') - { - if (! $user->rights->produit->creer && ! $user->rights->service->creer) { $createok=0; $nbko++; } - } - else if ($feature == 'prelevement') - { - if (! $user->rights->prelevement->bons->creer) { $createok=0; $nbko++; } - } - else if ($feature == 'commande_fournisseur') - { - if (! $user->rights->fournisseur->commande->creer) { $createok=0; $nbko++; } - } - else if ($feature == 'banque') - { - if (! $user->rights->banque->modifier) { $createok=0; $nbko++; } - } - else if ($feature == 'cheque') - { - if (! $user->rights->banque->cheque) { $createok=0; $nbko++; } - } - else if (! empty($feature2)) // This should be used - { - foreach($feature2 as $subfeature) - { - if (empty($user->rights->$feature->$subfeature->creer) - && empty($user->rights->$feature->$subfeature->write) - && empty($user->rights->$feature->$subfeature->create)) { $createok=0; $nbko++; } - else { $createok=1; break; } // Break to bypass second test if the first is ok - } - } - else if (! empty($feature)) // This is for old permissions ('creer' or 'write') - { - //print '
feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write; - if (empty($user->rights->$feature->creer) - && empty($user->rights->$feature->write) - && empty($user->rights->$feature->create)) { $createok=0; $nbko++; } - } - } + // Check write permission from module (we need to know write permission to create but also to delete drafts record) + $createok=1; $nbko=0; + if (GETPOST('action','aZ09') == 'create' || ((GETPOST("action","aZ09") == 'confirm_delete' && GETPOST("confirm","aZ09") == 'yes') || GETPOST("action","aZ09") == 'delete')) + { + foreach ($featuresarray as $feature) + { + if ($feature == 'contact') + { + if (! $user->rights->societe->contact->creer) { $createok=0; $nbko++; } + } + else if ($feature == 'produit|service') + { + if (! $user->rights->produit->creer && ! $user->rights->service->creer) { $createok=0; $nbko++; } + } + else if ($feature == 'prelevement') + { + if (! $user->rights->prelevement->bons->creer) { $createok=0; $nbko++; } + } + else if ($feature == 'commande_fournisseur') + { + if (! $user->rights->fournisseur->commande->creer) { $createok=0; $nbko++; } + } + else if ($feature == 'banque') + { + if (! $user->rights->banque->modifier) { $createok=0; $nbko++; } + } + else if ($feature == 'cheque') + { + if (! $user->rights->banque->cheque) { $createok=0; $nbko++; } + } + else if (! empty($feature2)) // This should be used + { + foreach($feature2 as $subfeature) + { + if (empty($user->rights->$feature->$subfeature->creer) + && empty($user->rights->$feature->$subfeature->write) + && empty($user->rights->$feature->$subfeature->create)) { $createok=0; $nbko++; } + else { $createok=1; break; } // Break to bypass second test if the first is ok + } + } + else if (! empty($feature)) // This is for old permissions ('creer' or 'write') + { + //print '
feature='.$feature.' creer='.$user->rights->$feature->creer.' write='.$user->rights->$feature->write; + if (empty($user->rights->$feature->creer) + && empty($user->rights->$feature->write) + && empty($user->rights->$feature->create)) { $createok=0; $nbko++; } + } + } - // If a or and at least one ok - if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $createok=1; + // If a or and at least one ok + if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $createok=1; - if (! $createok) accessforbidden(); - //print "Write access is ok"; - } + if (GETPOST('action','aZ09') == 'create' && ! $createok) accessforbidden(); + //print "Write access is ok"; + } - // Check create user permission - $createuserok=1; - if (GETPOST('action','aZ09') == 'confirm_create_user' && GETPOST("confirm",'aZ09') == 'yes') - { - if (! $user->rights->user->user->creer) $createuserok=0; + // Check create user permission + $createuserok=1; + if (GETPOST('action','aZ09') == 'confirm_create_user' && GETPOST("confirm",'aZ09') == 'yes') + { + if (! $user->rights->user->user->creer) $createuserok=0; - if (! $createuserok) accessforbidden(); - //print "Create user access is ok"; - } + if (! $createuserok) accessforbidden(); + //print "Create user access is ok"; + } - // Check delete permission from module - $deleteok=1; $nbko=0; - if ((GETPOST("action","aZ09") == 'confirm_delete' && GETPOST("confirm","aZ09") == 'yes') || GETPOST("action","aZ09") == 'delete') - { - foreach ($featuresarray as $feature) - { - if ($feature == 'contact') - { - if (! $user->rights->societe->contact->supprimer) $deleteok=0; - } - else if ($feature == 'produit|service') - { - if (! $user->rights->produit->supprimer && ! $user->rights->service->supprimer) $deleteok=0; - } - else if ($feature == 'commande_fournisseur') - { - if (! $user->rights->fournisseur->commande->supprimer) $deleteok=0; - } - else if ($feature == 'banque') - { - if (! $user->rights->banque->modifier) $deleteok=0; - } - else if ($feature == 'cheque') - { - if (! $user->rights->banque->cheque) $deleteok=0; - } - else if ($feature == 'ecm') - { - if (! $user->rights->ecm->upload) $deleteok=0; - } - else if ($feature == 'ftp') - { - if (! $user->rights->ftp->write) $deleteok=0; - }else if ($feature == 'salaries') - { - if (! $user->rights->salaries->delete) $deleteok=0; - } - else if ($feature == 'salaries') - { - if (! $user->rights->salaries->delete) $deleteok=0; - } - else if (! empty($feature2)) // This should be used for future changes - { - foreach($feature2 as $subfeature) - { - if (empty($user->rights->$feature->$subfeature->supprimer) && empty($user->rights->$feature->$subfeature->delete)) $deleteok=0; - else { $deleteok=1; break; } // For bypass the second test if the first is ok - } - } - else if (! empty($feature)) // This is for old permissions - { - //print '
feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete; - if (empty($user->rights->$feature->supprimer) - && empty($user->rights->$feature->delete) - && empty($user->rights->$feature->run)) $deleteok=0; - } - } + // Check delete permission from module + $deleteok=1; $nbko=0; + if ((GETPOST("action","aZ09") == 'confirm_delete' && GETPOST("confirm","aZ09") == 'yes') || GETPOST("action","aZ09") == 'delete') + { + foreach ($featuresarray as $feature) + { + if ($feature == 'contact') + { + if (! $user->rights->societe->contact->supprimer) $deleteok=0; + } + else if ($feature == 'produit|service') + { + if (! $user->rights->produit->supprimer && ! $user->rights->service->supprimer) $deleteok=0; + } + else if ($feature == 'commande_fournisseur') + { + if (! $user->rights->fournisseur->commande->supprimer) $deleteok=0; + } + else if ($feature == 'banque') + { + if (! $user->rights->banque->modifier) $deleteok=0; + } + else if ($feature == 'cheque') + { + if (! $user->rights->banque->cheque) $deleteok=0; + } + else if ($feature == 'ecm') + { + if (! $user->rights->ecm->upload) $deleteok=0; + } + else if ($feature == 'ftp') + { + if (! $user->rights->ftp->write) $deleteok=0; + }else if ($feature == 'salaries') + { + if (! $user->rights->salaries->delete) $deleteok=0; + } + else if ($feature == 'salaries') + { + if (! $user->rights->salaries->delete) $deleteok=0; + } + else if (! empty($feature2)) // This should be used for permissions on 2 levels + { + foreach($feature2 as $subfeature) + { + if (empty($user->rights->$feature->$subfeature->supprimer) && empty($user->rights->$feature->$subfeature->delete)) $deleteok=0; + else { $deleteok=1; break; } // For bypass the second test if the first is ok + } + } + else if (! empty($feature)) // This is used for permissions on 1 level + { + //print '
feature='.$feature.' creer='.$user->rights->$feature->supprimer.' write='.$user->rights->$feature->delete; + if (empty($user->rights->$feature->supprimer) + && empty($user->rights->$feature->delete) + && empty($user->rights->$feature->run)) $deleteok=0; + } + } - // If a or and at least one ok - if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $deleteok=1; + // If a or and at least one ok + if (preg_match('/\|/', $features) && $nbko < count($featuresarray)) $deleteok=1; - if (! $deleteok) accessforbidden(); - //print "Delete access is ok"; - } + if (! $deleteok && ! ($isdraft && $createok)) accessforbidden(); + //print "Delete access is ok"; + } - // If we have a particular object to check permissions on, we check this object - // is linked to a company allowed to $user. - if (! empty($objectid) && $objectid > 0) - { - $ok = checkUserAccessToObject($user, $featuresarray, $objectid, $tableandshare, $feature2, $dbt_keyfield, $dbt_select); - return $ok ? 1 : accessforbidden(); - } + // If we have a particular object to check permissions on, we check this object + // is linked to a company allowed to $user. + if (! empty($objectid) && $objectid > 0) + { + $ok = checkUserAccessToObject($user, $featuresarray, $objectid, $tableandshare, $feature2, $dbt_keyfield, $dbt_select); + return $ok ? 1 : accessforbidden(); + } - return 1; + return 1; } /** @@ -577,8 +578,8 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh { if (! empty($conf->projet->enabled) && empty($user->rights->projet->all->lire)) { - $task = new Task($db); - $task->fetch($objectid); + $task = new Task($db); + $task->fetch($objectid); include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php'; $projectstatic=new Project($db); @@ -658,37 +659,37 @@ function checkUserAccessToObject($user, $featuresarray, $objectid=0, $tableandsh */ function accessforbidden($message='',$printheader=1,$printfooter=1,$showonlymessage=0) { - global $conf, $db, $user, $langs; - if (! is_object($langs)) - { - include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php'; - $langs=new Translate('',$conf); - } + global $conf, $db, $user, $langs; + if (! is_object($langs)) + { + include_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php'; + $langs=new Translate('',$conf); + } - $langs->load("errors"); + $langs->load("errors"); - if ($printheader) - { - if (function_exists("llxHeader")) llxHeader(''); - else if (function_exists("llxHeaderVierge")) llxHeaderVierge(''); - } - print '
'; - if (! $message) print $langs->trans("ErrorForbidden"); - else print $message; - print '
'; - print '
'; - if (empty($showonlymessage)) - { - if ($user->login) - { - print $langs->trans("CurrentLogin").': '.$user->login.'
'; - print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users")); - } - else - { - print $langs->trans("ErrorForbidden3"); - } - } - if ($printfooter && function_exists("llxFooter")) llxFooter(); - exit(0); + if ($printheader) + { + if (function_exists("llxHeader")) llxHeader(''); + else if (function_exists("llxHeaderVierge")) llxHeaderVierge(''); + } + print '
'; + if (! $message) print $langs->trans("ErrorForbidden"); + else print $message; + print '
'; + print '
'; + if (empty($showonlymessage)) + { + if ($user->login) + { + print $langs->trans("CurrentLogin").': '.$user->login.'
'; + print $langs->trans("ErrorForbidden2",$langs->trans("Home"),$langs->trans("Users")); + } + else + { + print $langs->trans("ErrorForbidden3"); + } + } + if ($printfooter && function_exists("llxFooter")) llxFooter(); + exit(0); } diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 2ce28875425..29e9f6fe85e 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -72,11 +72,6 @@ $hidedetails = (GETPOST('hidedetails','int') ? GETPOST('hidedetails','int') : (! $hidedesc = (GETPOST('hidedesc','int') ? GETPOST('hidedesc','int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0)); $hideref = (GETPOST('hideref','int') ? GETPOST('hideref','int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0)); -// Security check -$socid=''; -if (! empty($user->societe_id)) $socid=$user->societe_id; -$result = restrictedArea($user, 'fournisseur', $id, 'facture_fourn', 'facture'); - // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context $hookmanager->initHooks(array('invoicesuppliercard','globalcard')); @@ -95,6 +90,11 @@ if ($id > 0 || ! empty($ref)) if ($ret < 0) dol_print_error($db,$object->error); } +// Security check +$socid=''; +if (! empty($user->societe_id)) $socid=$user->societe_id; +$result = restrictedArea($user, 'fournisseur', $id, 'facture_fourn', 'facture', 'fk_soc', 'rowid', null, (($object->statut == FactureFournisseur::STATUS_DRAFT) ? 1 : 0)); + $permissionnote=$user->rights->fournisseur->facture->creer; // Used by the include of actions_setnotes.inc.php $permissiondellink=$user->rights->fournisseur->facture->creer; // Used by the include of actions_dellink.inc.php $permissionedit=$user->rights->fournisseur->facture->creer; // Used by the include of actions_lineupdown.inc.php From 8fbf5b1f338819fe4aa1ee097ebcccd697acb2d4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 29 Oct 2018 18:28:19 +0100 Subject: [PATCH 15/17] FIX deletion on draft is allowed if we are allwoed to create --- htdocs/compta/facture/card.php | 3 ++- htdocs/fourn/facture/card.php | 3 ++- htdocs/modulebuilder/template/myobject_card.php | 10 +++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index aa1176e0295..4ab316e638d 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -115,7 +115,8 @@ $permissiontoedit = $user->rights->facture->creer; // Used by the include of act // Security check $fieldid = (! empty($ref) ? 'facnumber' : 'rowid'); if ($user->societe_id) $socid = $user->societe_id; -$result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid, null, (($object->statut == Facture::STATUS_DRAFT) ? 1 : 0)); +$isdraft = (($object->statut == Facture::STATUS_DRAFT) ? 1 : 0); +$result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid, null, $isdraft); /* diff --git a/htdocs/fourn/facture/card.php b/htdocs/fourn/facture/card.php index 29e9f6fe85e..a51da110195 100644 --- a/htdocs/fourn/facture/card.php +++ b/htdocs/fourn/facture/card.php @@ -93,7 +93,8 @@ if ($id > 0 || ! empty($ref)) // Security check $socid=''; if (! empty($user->societe_id)) $socid=$user->societe_id; -$result = restrictedArea($user, 'fournisseur', $id, 'facture_fourn', 'facture', 'fk_soc', 'rowid', null, (($object->statut == FactureFournisseur::STATUS_DRAFT) ? 1 : 0)); +$isdraft = (($object->statut == FactureFournisseur::STATUS_DRAFT) ? 1 : 0); +$result = restrictedArea($user, 'fournisseur', $id, 'facture_fourn', 'facture', 'fk_soc', 'rowid', null, $isdraft); $permissionnote=$user->rights->fournisseur->facture->creer; // Used by the include of actions_setnotes.inc.php $permissiondellink=$user->rights->fournisseur->facture->creer; // Used by the include of actions_dellink.inc.php diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index 6c6324e6e8d..3d811d53381 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -93,14 +93,14 @@ foreach($object->fields as $key => $val) if (empty($action) && empty($id) && empty($ref)) $action='view'; -// Security check - Protection if external user -//if ($user->societe_id > 0) access_forbidden(); -//if ($user->societe_id > 0) $socid = $user->societe_id; -//$result = restrictedArea($user, 'mymodule', $id); - // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$isdraft = (($object->statut == MyObject::STATUS_DRAFT) ? 1 : 0); +//$result = restrictedArea($user, 'mymodule', $id, '', '', 'fk_soc', 'rowid', null, $isdraft); /* From a8e6c3832e4263e514d70dc0423f29eba1464f5d Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Oct 2018 12:30:56 +0100 Subject: [PATCH 16/17] Update list.php --- htdocs/adherents/subscription/list.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/adherents/subscription/list.php b/htdocs/adherents/subscription/list.php index 575bd3a233a..c8f7bce5f95 100644 --- a/htdocs/adherents/subscription/list.php +++ b/htdocs/adherents/subscription/list.php @@ -40,7 +40,7 @@ $search_account=GETPOST('search_account','int'); $search_amount=GETPOST('search_amount','alpha'); $optioncss = GETPOST('optioncss','alpha'); -$date_select=isset($_GET["date_select"])?$_GET["date_select"]:$_POST["date_select"]; +$date_select=GETPOST("date_select",'alpha'); $limit = GETPOST('limit','int')?GETPOST('limit','int'):$conf->liste_limit; $sortfield = GETPOST("sortfield",'alpha'); From 9bb1572e632761c1def90408412f9029cb90dd09 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 30 Oct 2018 12:41:06 +0100 Subject: [PATCH 17/17] Update functions.lib.php --- htdocs/core/lib/functions.lib.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6649bf17bbb..a289c967055 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -6529,7 +6529,7 @@ function get_htmloutput_mesg($mesgstring='',$mesgarray='', $style='ok', $keepemb /** * Get formated error messages to output (Used to show messages on html output). * - * @param string $mesgstring Error message + * @param string $mesgstring Error message * @param array $mesgarray Error messages array * @param int $keepembedded Set to 1 in error message must be kept embedded into its html place (this disable jnotify) * @return string Return html output @@ -6537,7 +6537,7 @@ function get_htmloutput_mesg($mesgstring='',$mesgarray='', $style='ok', $keepemb * @see dol_print_error * @see dol_htmloutput_mesg */ -function get_htmloutput_errors($mesgstring='', $mesgarray='', $keepembedded=0) +function get_htmloutput_errors($mesgstring='', $mesgarray=array(), $keepembedded=0) { return get_htmloutput_mesg($mesgstring, $mesgarray,'error',$keepembedded); } @@ -6547,15 +6547,15 @@ function get_htmloutput_errors($mesgstring='', $mesgarray='', $keepembedded=0) * * @param string $mesgstring Message string or message key * @param string[] $mesgarray Array of message strings or message keys - * @param string $style Which style to use ('ok', 'warning', 'error') - * @param int $keepembedded Set to 1 if message must be kept embedded into its html place (this disable jnotify) - * @return void + * @param string $style Which style to use ('ok', 'warning', 'error') + * @param int $keepembedded Set to 1 if message must be kept embedded into its html place (this disable jnotify) + * @return void * - * @see dol_print_error - * @see dol_htmloutput_errors - * @see setEventMessages + * @see dol_print_error + * @see dol_htmloutput_errors + * @see setEventMessages */ -function dol_htmloutput_mesg($mesgstring = '',$mesgarray = [], $style = 'ok', $keepembedded=0) +function dol_htmloutput_mesg($mesgstring = '',$mesgarray = array(), $style = 'ok', $keepembedded=0) { if (empty($mesgstring) && (! is_array($mesgarray) || count($mesgarray) == 0)) return; @@ -6609,7 +6609,7 @@ function dol_htmloutput_mesg($mesgstring = '',$mesgarray = [], $style = 'ok', $k * @see dol_print_error * @see dol_htmloutput_mesg */ -function dol_htmloutput_errors($mesgstring='', $mesgarray='', $keepembedded=0) +function dol_htmloutput_errors($mesgstring='', $mesgarray=array(), $keepembedded=0) { dol_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded); }