From 6e08115aa2f4794dda3ba330691b1722e87e3710 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 1 Mar 2022 14:52:19 +0100 Subject: [PATCH 01/13] introduce constant INVOICE_CHECK_POSTERIOR_DATE in Facture module --- htdocs/core/modules/modFacture.class.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index fac768b9c60..2d1a742a304 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -106,6 +106,13 @@ class modFacture extends DolibarrModules $this->const[$r][4] = 0; $r++;*/ + $this->const[$r][0] = "INVOICE_CHECK_POSTERIOR_DATE"; + $this->const[$r][1] = "chaine"; + $this->const[$r][2] = 0; + $this->const[$r][3] = "When validating an invoice, check that its date is posterior to last invoice date for invoices of same type."; + $this->const[$r][4] = 0; + $r++; + // Boxes //$this->boxes = array(0=>array(1=>'box_factures_imp.php'),1=>array(1=>'box_factures.php')); From 02693ba5eab08ed1d3de0ce5994a5e0d40c751a0 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 1 Mar 2022 15:22:46 +0100 Subject: [PATCH 02/13] Facture : add config option for INVOICE_CHECK_POSTERIOR_DATE --- htdocs/admin/facture.php | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index 9eec54b03a7..f2ab39f6fb4 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -225,6 +225,12 @@ if ($action == 'updateMask') { setEventMessages($langs->trans("Error"), null, 'errors'); } } +} elseif ($action == 'set_INVOICE_CHECK_POSTERIOR_DATE') { + $check_posterior_date = GETPOST('INVOICE_CHECK_POSTERIOR_DATE', 'int'); + $res = dolibarr_set_const($db, 'INVOICE_CHECK_POSTERIOR_DATE', $check_posterior_date, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } } @@ -761,6 +767,25 @@ print '\n"; print ''; + +print ''.$langs->trans("InvoiceCheckPosteriorDate"). ' ' ; +print $form->textwithpicto('', $langs->trans("InvoiceCheckPosteriorDateHelp"), 1, 'help') . ''; +print ''; +if ($conf->use_javascript_ajax) { + print ajax_constantonoff('INVOICE_CHECK_POSTERIOR_DATE'); +} else { + print '
'; + print ''; + print ''; + $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); + print $form->selectarray("INVOICE_CHECK_POSTERIOR_DATE", $arrval, $conf->global->INVOICE_CHECK_POSTERIOR_DATE); +} +print ''; +print ''; +print ''; +print '
'; +print ''; + print ''; print ''; From ad416ef7925bc28c70f9bef882b971d6d5a72006 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 1 Mar 2022 16:18:34 +0100 Subject: [PATCH 03/13] Facture: create method willBeLastOfSameType() --- htdocs/compta/facture/class/facture.class.php | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 70aebe6932c..10bc1b0af62 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -5123,6 +5123,38 @@ class Facture extends CommonInvoice return $error; } } + + /** + * See if current invoice date is posterior to the last invoice date among validated invoices of same type. + * @param bool $strict compare precise time or only days. + * @return boolean + */ + public function willBeLastOfSameType() + { + // get date of last validated invoices of same type + $sql = 'SELECT datef'; + $sql .= ' FROM '.MAIN_DB_PREFIX.'facture'; + $sql .= ' WHERE type = ' . (int) $this->type ; + $sql .= ' AND date_valid IS NOT NULL'; + $sql .= ' ORDER BY datef DESC LIMIT 1'; + + $result = $this->db->query($sql); + if ($result) { + // compare with current validation date + if ($this->db->num_rows($result)) { + $obj = $this->db->fetch_object($result); + $last_date = $this->db->jdate($obj->datef); + $invoice_date = $this->date; + + return [$invoice_date >= $last_date, $last_date]; + } else { + // element is first of type to be validated + return [true]; + } + } else { + dol_print_error($this->db); + } + } } /** From eda9622c9ca769ac3a6782b3e5d57d949aac415b Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 2 Mar 2022 10:16:14 +0100 Subject: [PATCH 04/13] Facture: enhance validation by adding INVOICE_CHECK_POSTERIOR_DATE option --- htdocs/compta/facture/class/facture.class.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 10bc1b0af62..569f677e66b 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2671,6 +2671,13 @@ class Facture extends CommonInvoice dol_syslog(get_class($this)."::validate ".$this->error.' MAIN_USE_ADVANCED_PERMS='.$conf->global->MAIN_USE_ADVANCED_PERMS, LOG_ERR); return -1; } + if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) { + $last_of_type = $this->willBeLastOfSameType(); + if (!$last_of_type[0]) { + $this->error = $langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $this->ref , dol_print_date($this->date, 'day'), dol_print_date($last_of_type[1], 'day')); + return -1; + } + } $this->db->begin(); From 7c866ce6a2086355fbac0af97b1cb28a048fa783 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 1 Mar 2022 17:18:29 +0100 Subject: [PATCH 05/13] facture/card.php: avoid validating invoices with date anterior to last invoice date --- htdocs/compta/facture/card.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index a4d85c257f8..f980d1c6bde 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -302,6 +302,15 @@ if (empty($reshook)) { // Validation $object->fetch($id); + if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) { + $last_of_type = $object->willBeLastOfSameType(); + if (empty($object->date_validation) && !$last_of_type[0]) { + setEventMessages($langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $object->ref , dol_print_date($object->date, 'day'), dol_print_date($last_of_type[1], 'day')), null, 'errors'); + header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id); + exit; + } + } + // On verifie signe facture if ($object->type == Facture::TYPE_CREDIT_NOTE) { // Si avoir, le signe doit etre negatif From 288663be3682dbd9bdab5600ce45338a4b082abc Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 2 Mar 2022 10:16:48 +0100 Subject: [PATCH 06/13] Facture mass validation: sort by date to avoid conflicts --- htdocs/core/actions_massactions.inc.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 5a4ec3bf02f..4a5fe519acb 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1209,6 +1209,26 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) { setEventMessages($langs->trans('ErrorMassValidationNotAllowedWhenStockIncreaseOnAction'), null, 'errors'); $error++; } + if ($objecttmp->element == 'facture') { + if (!empty($toselect) && !empty($conf->global->INVOICE_CHECK_POSTERIOR_DATE)) { + // order $toselect by date + $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture'; + $sql .= ' WHERE rowid IN ('.$db->escape(implode(', ', $toselect)).')'; + $sql .= ' ORDER BY datef'; + + $resql = $db->query($sql); + if ($resql) { + $toselectnew = []; + while ( !empty($arr = $db->fetch_row($resql))) { + $toselectnew[] = $arr[0]; + } + $toselect = (empty($toselectnew)) ? $toselect : $toselectnew; + } else { + dol_print_error($db); + $error++; + } + } + } if (!$error) { $db->begin(); From 07672b23b92ca503e840c1b721632f1565e7d195 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 1 Mar 2022 17:24:28 +0100 Subject: [PATCH 07/13] Langs/bills.lang: add error string for invoice date check --- htdocs/langs/en_US/admin.lang | 2 ++ htdocs/langs/en_US/bills.lang | 1 + 2 files changed, 3 insertions(+) diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index cffd3532c05..fd86b2e7788 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -1421,6 +1421,8 @@ WatermarkOnDraftInvoices=Watermark on draft invoices (none if empty) PaymentsNumberingModule=Payments numbering model SuppliersPayment=Vendor payments SupplierPaymentSetup=Vendor payments setup +InvoiceCheckPosteriorDate=Check facture date before validation +InvoiceCheckPosteriorDateHelp=Validating an invoice will be forbidden if its date is anterior to the date of last invoice of same type. ##### Proposals ##### PropalSetup=Commercial proposals module setup ProposalsNumberingModules=Commercial proposal numbering models diff --git a/htdocs/langs/en_US/bills.lang b/htdocs/langs/en_US/bills.lang index 851323cadd9..993f5a21b2b 100644 --- a/htdocs/langs/en_US/bills.lang +++ b/htdocs/langs/en_US/bills.lang @@ -156,6 +156,7 @@ ErrorInvoiceAvoirMustBeNegative=Error, correct invoice must have a negative amou ErrorInvoiceOfThisTypeMustBePositive=Error, this type of invoice must have an amount excluding tax positive (or null) ErrorCantCancelIfReplacementInvoiceNotValidated=Error, can't cancel an invoice that has been replaced by another invoice that is still in draft status ErrorThisPartOrAnotherIsAlreadyUsedSoDiscountSerieCantBeRemoved=This part or another is already used so discount series cannot be removed. +ErrorInvoiceIsNotLastOfSameType=Error: The date of invoice %s is %s. It must be posterior or equal to last date for same type invoices (%s). Please change the invoice date. BillFrom=From BillTo=To ActionsOnBill=Actions on invoice From 9ce51ba4b73d8cdcdda5c858784faad004f9029b Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 2 Mar 2022 12:07:40 +0100 Subject: [PATCH 08/13] admin/facture: don't show the modify button if not in an HTML form --- htdocs/admin/facture.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/htdocs/admin/facture.php b/htdocs/admin/facture.php index f2ab39f6fb4..599aac27c3f 100644 --- a/htdocs/admin/facture.php +++ b/htdocs/admin/facture.php @@ -779,11 +779,11 @@ if ($conf->use_javascript_ajax) { print ''; $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); print $form->selectarray("INVOICE_CHECK_POSTERIOR_DATE", $arrval, $conf->global->INVOICE_CHECK_POSTERIOR_DATE); + print ''; + print ''; + print ''; + print ''; } -print ''; -print ''; -print ''; -print ''; print ''; print ''; From 4ad92a04fc78c45b4654710ef56eb55f62ac4ddb Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 2 Mar 2022 12:53:44 +0100 Subject: [PATCH 09/13] stickler corrections --- htdocs/compta/facture/card.php | 2 +- htdocs/compta/facture/class/facture.class.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index f980d1c6bde..1540846d99a 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -305,7 +305,7 @@ if (empty($reshook)) { if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) { $last_of_type = $object->willBeLastOfSameType(); if (empty($object->date_validation) && !$last_of_type[0]) { - setEventMessages($langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $object->ref , dol_print_date($object->date, 'day'), dol_print_date($last_of_type[1], 'day')), null, 'errors'); + setEventMessages($langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $object->ref, dol_print_date($object->date, 'day'), dol_print_date($last_of_type[1], 'day')), null, 'errors'); header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id); exit; } diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 569f677e66b..0d52e4b9fd0 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2674,7 +2674,7 @@ class Facture extends CommonInvoice if (!empty($conf->global-> INVOICE_CHECK_POSTERIOR_DATE)) { $last_of_type = $this->willBeLastOfSameType(); if (!$last_of_type[0]) { - $this->error = $langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $this->ref , dol_print_date($this->date, 'day'), dol_print_date($last_of_type[1], 'day')); + $this->error = $langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $this->ref, dol_print_date($this->date, 'day'), dol_print_date($last_of_type[1], 'day')); return -1; } } @@ -5133,7 +5133,6 @@ class Facture extends CommonInvoice /** * See if current invoice date is posterior to the last invoice date among validated invoices of same type. - * @param bool $strict compare precise time or only days. * @return boolean */ public function willBeLastOfSameType() From 93765add38e9ad9754df340a6f20faf5a34b4429 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 2 Mar 2022 13:08:42 +0100 Subject: [PATCH 10/13] Travis fix, hopefully. --- htdocs/core/actions_massactions.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index 4a5fe519acb..bdf13214717 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1213,7 +1213,7 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) { if (!empty($toselect) && !empty($conf->global->INVOICE_CHECK_POSTERIOR_DATE)) { // order $toselect by date $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture'; - $sql .= ' WHERE rowid IN ('.$db->escape(implode(', ', $toselect)).')'; + $sql .= ' WHERE rowid IN ('.$db->sanitize(implode(',', $toselect)).')'; $sql .= ' ORDER BY datef'; $resql = $db->query($sql); From 7f527b85b0c3bc83ee00d8df94a6de6a06a8455b Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 9 Mar 2022 09:34:50 +0100 Subject: [PATCH 11/13] use double quotes to compose SQL requests --- htdocs/compta/facture/class/facture.class.php | 10 +++++----- htdocs/core/actions_massactions.inc.php | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 0d52e4b9fd0..5ca66ac0cd3 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -5138,11 +5138,11 @@ class Facture extends CommonInvoice public function willBeLastOfSameType() { // get date of last validated invoices of same type - $sql = 'SELECT datef'; - $sql .= ' FROM '.MAIN_DB_PREFIX.'facture'; - $sql .= ' WHERE type = ' . (int) $this->type ; - $sql .= ' AND date_valid IS NOT NULL'; - $sql .= ' ORDER BY datef DESC LIMIT 1'; + $sql = "SELECT datef"; + $sql .= " FROM ".MAIN_DB_PREFIX."facture"; + $sql .= " WHERE type = " . (int) $this->type ; + $sql .= " AND date_valid IS NOT NULL"; + $sql .= " ORDER BY datef DESC LIMIT 1"; $result = $this->db->query($sql); if ($result) { diff --git a/htdocs/core/actions_massactions.inc.php b/htdocs/core/actions_massactions.inc.php index bdf13214717..39d99c4a03b 100644 --- a/htdocs/core/actions_massactions.inc.php +++ b/htdocs/core/actions_massactions.inc.php @@ -1212,9 +1212,9 @@ if (!$error && $massaction == 'validate' && $permissiontoadd) { if ($objecttmp->element == 'facture') { if (!empty($toselect) && !empty($conf->global->INVOICE_CHECK_POSTERIOR_DATE)) { // order $toselect by date - $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX.'facture'; - $sql .= ' WHERE rowid IN ('.$db->sanitize(implode(',', $toselect)).')'; - $sql .= ' ORDER BY datef'; + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."facture"; + $sql .= " WHERE rowid IN (".$db->sanitize(implode(",", $toselect)).")"; + $sql .= " ORDER BY datef"; $resql = $db->query($sql); if ($resql) { From 6dfad5d69fc97ae12f681e1ab974db66dc621b3d Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 24 Mar 2022 11:09:39 +0100 Subject: [PATCH 12/13] facture/card.php: replace redirection by = '' --- htdocs/compta/facture/card.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/htdocs/compta/facture/card.php b/htdocs/compta/facture/card.php index 1540846d99a..02120c57d99 100644 --- a/htdocs/compta/facture/card.php +++ b/htdocs/compta/facture/card.php @@ -306,8 +306,7 @@ if (empty($reshook)) { $last_of_type = $object->willBeLastOfSameType(); if (empty($object->date_validation) && !$last_of_type[0]) { setEventMessages($langs->transnoentities("ErrorInvoiceIsNotLastOfSameType", $object->ref, dol_print_date($object->date, 'day'), dol_print_date($last_of_type[1], 'day')), null, 'errors'); - header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id); - exit; + $action = ''; } } From 8e7b1455101a603b60d05c1e1e88c55ff1efbd83 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 29 Mar 2022 16:05:41 +0200 Subject: [PATCH 13/13] Update modFacture.class.php --- htdocs/core/modules/modFacture.class.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/htdocs/core/modules/modFacture.class.php b/htdocs/core/modules/modFacture.class.php index 2d1a742a304..72838e92079 100644 --- a/htdocs/core/modules/modFacture.class.php +++ b/htdocs/core/modules/modFacture.class.php @@ -99,21 +99,6 @@ class modFacture extends DolibarrModules $this->const[$r][4] = 0; $r++; - /*$this->const[$r][0] = "FACTURE_DRAFT_WATERMARK"; - $this->const[$r][1] = "chaine"; - $this->const[$r][2] = "__(Draft)__"; - $this->const[$r][3] = 'Watermark to show on draft invoices'; - $this->const[$r][4] = 0; - $r++;*/ - - $this->const[$r][0] = "INVOICE_CHECK_POSTERIOR_DATE"; - $this->const[$r][1] = "chaine"; - $this->const[$r][2] = 0; - $this->const[$r][3] = "When validating an invoice, check that its date is posterior to last invoice date for invoices of same type."; - $this->const[$r][4] = 0; - $r++; - - // Boxes //$this->boxes = array(0=>array(1=>'box_factures_imp.php'),1=>array(1=>'box_factures.php')); $this->boxes = array(