From 6baada7f2f9a9f691adc85654bedb80a714ea500 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Mon, 8 Jan 2024 12:06:53 +0100 Subject: [PATCH 01/12] Update societe.class.php - Use isValidSiret() --- htdocs/societe/class/societe.class.php | 37 ++++---------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index a5dc591b4e4..38046c52920 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3847,43 +3847,16 @@ class Societe extends CommonObject return 1; } - // Check SIREN if country FR + // Check SIREN if ($idprof == 1 && $soc->country_code == 'FR' && !isValidSiren($this->idprof1)) { return -1; } - // Verifie SIRET si pays FR - if ($idprof == 2 && $soc->country_code == 'FR') { - $chaine = trim($this->idprof2); - $chaine = preg_replace('/(\s)/', '', $chaine); - - if (!is_numeric($chaine)) { - return -1; - } - if (dol_strlen($chaine) != 14) { - return -1; - } - - // on prend chaque chiffre un par un - // si son index (position dans la chaîne en commence à 0 au premier caractère) est pair - // on double sa valeur et si cette dernière est supérieure à 9, on lui retranche 9 - // on ajoute cette valeur à la somme totale - $sum = 0; - for ($index = 0; $index < 14; $index++) { - $number = (int) $chaine[$index]; - if (($index % 2) == 0) { - if (($number *= 2) > 9) { - $number -= 9; - } - } - $sum += $number; - } - - // le numéro est valide si la somme des chiffres est multiple de 10 - if ($sum % 10 != 0) { - return -1; - } + // Check SIRET + if ($idprof == 2 && $soc->country_code == 'FR' && !isValidSiret($this->idprof2)) { + return -1; } + //Verify CIF/NIF/NIE if pays ES //Returns: 1 if NIF ok, 2 if CIF ok, 3 if NIE ok, -1 if NIF bad, -2 if CIF bad, -3 if NIE bad, 0 if unexpected bad From a7dc286784fd84da03978b72f35619ac91b40786 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Mon, 8 Jan 2024 14:01:37 +0100 Subject: [PATCH 02/12] Update profid.lib.php - Copy the algorithm to validate a SIRET --- htdocs/core/lib/profid.lib.php | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/htdocs/core/lib/profid.lib.php b/htdocs/core/lib/profid.lib.php index 98990266a42..413694ec83a 100644 --- a/htdocs/core/lib/profid.lib.php +++ b/htdocs/core/lib/profid.lib.php @@ -38,6 +38,8 @@ function isValidSiren($siren) return false; } + // TODO : use the Luhn algorithm instead + // we take each figure one by one and: // - if its index is odd then we double its value, // - if the latter is higher than 9 then we substract 9 from it, @@ -56,3 +58,41 @@ function isValidSiren($siren) // the siren is valid if the sum is a multiple of 10 return (($sum % 10) == 0) ? true : false; } + + +/** + * Check the validity of a SIRET. + * + * @param string $siret SIRET to check + * @return boolean True if valid, False otherwise + */ +function isValidSiret($siret) +{ + $siret = trim($siret); + $siret = preg_replace('/(\s)/', '', $siret); + + if (!is_numeric($siret) || dol_strlen($siret) != 14) { + return false; + } + + // TODO: use the Luhn algorithm instead + // TODO: handle the exception of "La Poste" (356 000 000 #####) + + // we take each figure one by one and: + // - if its index is even then we double its value, + // - if the latter is higher than 9 then we substract 9 from it, + // - and finally we add the result to the overall sum. + $sum = 0; + for ($index = 0; $index < 14; $index++) { + $number = (int) $siret[$index]; + if ($index % 2 == 0) { + if (($number *= 2) > 9) { + $number -= 9; + } + } + $sum += $number; + } + + // the SIRET is valid if the sum is a multiple of 10 + return $sum % 10 == 0; +} From 37871169ba83f5d3a37fb52ce044b1f42f13f0aa Mon Sep 17 00:00:00 2001 From: thibdrev Date: Mon, 8 Jan 2024 14:08:49 +0100 Subject: [PATCH 03/12] phpcs --- htdocs/core/lib/profid.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/lib/profid.lib.php b/htdocs/core/lib/profid.lib.php index 413694ec83a..f167a8f3713 100644 --- a/htdocs/core/lib/profid.lib.php +++ b/htdocs/core/lib/profid.lib.php @@ -67,7 +67,7 @@ function isValidSiren($siren) * @return boolean True if valid, False otherwise */ function isValidSiret($siret) -{ +{ $siret = trim($siret); $siret = preg_replace('/(\s)/', '', $siret); From 636d8ed01bceef84ff01f3ac2319a0f06b9171e3 Mon Sep 17 00:00:00 2001 From: thibdrev Date: Mon, 8 Jan 2024 14:10:13 +0100 Subject: [PATCH 04/12] phpcs --- htdocs/societe/class/societe.class.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 38046c52920..de44b1fcb79 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3856,7 +3856,6 @@ class Societe extends CommonObject if ($idprof == 2 && $soc->country_code == 'FR' && !isValidSiret($this->idprof2)) { return -1; } - //Verify CIF/NIF/NIE if pays ES //Returns: 1 if NIF ok, 2 if CIF ok, 3 if NIE ok, -1 if NIF bad, -2 if CIF bad, -3 if NIE bad, 0 if unexpected bad From 3f1f4829e477fcae08d2bd54aee8979e5a6794d3 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 09:07:28 +0100 Subject: [PATCH 05/12] Added cancel status & setCancel method --- htdocs/comm/propal/class/propal.class.php | 56 ++++++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 28d62bafb87..011bda8a035 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -136,14 +136,14 @@ class Propal extends CommonObject * Status of the quote * @var int * @deprecated Try to use $status now - * @see Propal::STATUS_DRAFT, Propal::STATUS_VALIDATED, Propal::STATUS_SIGNED, Propal::STATUS_NOTSIGNED, Propal::STATUS_BILLED + * @see Propal::STATUS_DRAFT, Propal::STATUS_VALIDATED, Propal::STATUS_SIGNED, Propal::STATUS_NOTSIGNED, Propal::STATUS_BILLED, Propal::STATUS_CANCELED */ public $statut; /** * Status of the quote * @var int - * @see Propal::STATUS_DRAFT, Propal::STATUS_VALIDATED, Propal::STATUS_SIGNED, Propal::STATUS_NOTSIGNED, Propal::STATUS_BILLED + * @see Propal::STATUS_DRAFT, Propal::STATUS_VALIDATED, Propal::STATUS_SIGNED, Propal::STATUS_NOTSIGNED, Propal::STATUS_BILLED, Propal::STATUS_CANCELED */ public $status; @@ -373,6 +373,10 @@ class Propal extends CommonObject ); // END MODULEBUILDER PROPERTIES + /** + * Canceled status + */ + const STATUS_CANCELED = -1; /** * Draft status */ @@ -2859,6 +2863,54 @@ class Propal extends CommonObject } } + /** + * Cancel the proposal + * + * @return int Return integer if KO <0 , if OK >0 + */ + public function setCancel() + { + global $user; + + $error = 0; + + $this->db->begin(); + + $sql = "UPDATE ". MAIN_DB_PREFIX . "propal"; + $sql .= " SET fk_statut = " . self::STATUS_CANCELED . ","; + $sql .= " fk_user_modif = " . ((int) $user->id); + $sql .= " WHERE rowid = " . ((int) $this->id); + + dol_syslog(get_class($this)."::cancel", LOG_DEBUG); + if ($this->db->query($sql)) { + if (!$error) { + // Call trigger + $result = $this->call_trigger('PROPAL_CANCEL', $user); + if ($result < 0) { + $error++; + } + // End call triggers + } + + if (!$error) { + $this->status = self::STATUS_CANCELED; + $this->db->commit(); + return 1; + } else { + foreach ($this->errors as $errmsg) { + dol_syslog(get_class($this)."::cancel ".$errmsg, LOG_ERR); + $this->error .= ($this->error ? ', '.$errmsg : $errmsg); + } + $this->db->rollback(); + return -1; + } + } else { + $this->error = $this->db->error(); + $this->db->rollback(); + return -1; + } + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Set draft status From 0f2415a75c72642ec15cc2f83fbc1e2a2af04c21 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 09:29:23 +0100 Subject: [PATCH 06/12] Added cancel & confirm_cancel actions. Cleaned code. --- htdocs/comm/propal/card.php | 17 +++++++++++++++++ htdocs/comm/propal/class/propal.class.php | 7 +++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index e8a7f461672..ee94bbb7979 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -235,6 +235,15 @@ if (empty($reshook)) { } } } + } elseif ($action == 'confirm_cancel' && $confirm == 'yes' && $usercanclose) { + // Cancel proposal + $result = $object->setCancel($user); + if ($result > 0) { + header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + } else { + $langs->load("errors"); + setEventMessages($object->error, $object->errors, 'errors'); + } } elseif ($action == 'confirm_delete' && $confirm == 'yes' && $usercandelete) { // Delete proposal $result = $object->delete($user); @@ -2383,6 +2392,9 @@ if ($action == 'create') { } else { $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?statut=3&id=' . $object->id, $langs->trans('Close'), '', 'confirm_closeas', $formquestion, '', 1, 250); } + } elseif ($action == 'cancel') { + // Confirm cancel + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans("Cancel"), $langs->trans('ConfirmCancelPropal', $object->ref), 'confirm_cancel', '', 0, 1); } elseif ($action == 'delete') { // Confirm delete $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteProp'), $langs->trans('ConfirmDeleteProp', $object->ref), 'confirm_delete', '', 0, 1); @@ -3085,6 +3097,11 @@ if ($action == 'create') { } } + // Cancel propal + if ($object->status > Propal::STATUS_DRAFT && $usercanclose) { + print ''.$langs->trans("CancelPropal").''; + } + // Clone if ($usercancreate) { print ''.$langs->trans("ToClone").''; diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 011bda8a035..07e3168a4ce 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2866,12 +2866,11 @@ class Propal extends CommonObject /** * Cancel the proposal * - * @return int Return integer if KO <0 , if OK >0 + * @param User $user Object user + * @return int Return integer if KO <0 , if OK >0 */ - public function setCancel() + public function setCancel(User $user) { - global $user; - $error = 0; $this->db->begin(); From c691549f430c3d66633e2ae135316ff9ba7c3116 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 09:40:56 +0100 Subject: [PATCH 07/12] Refactored code --- htdocs/comm/propal/card.php | 4 ++-- htdocs/comm/propal/class/propal.class.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index ee94bbb7979..d92661fc4e7 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -794,7 +794,7 @@ if (empty($reshook)) { } elseif ($action == 'confirm_reopen' && $usercanclose && !GETPOST('cancel', 'alpha')) { // Reopen proposal // prevent browser refresh from reopening proposal several times - if ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED) { + if ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED || $object->statut == Propal::STATUS_CANCELED) { $db->begin(); $result = $object->reopen($user, !getDolGlobalString('PROPAL_SKIP_ACCEPT_REFUSE')); @@ -3017,7 +3017,7 @@ if ($action == 'create') { } // ReOpen - if (((getDolGlobalString('PROPAL_REOPEN_UNSIGNED_ONLY') && $object->statut == Propal::STATUS_NOTSIGNED) || (!getDolGlobalString('PROPAL_REOPEN_UNSIGNED_ONLY') && ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED))) && $usercanclose) { + if (((getDolGlobalString('PROPAL_REOPEN_UNSIGNED_ONLY') && $object->statut == Propal::STATUS_NOTSIGNED) || (!getDolGlobalString('PROPAL_REOPEN_UNSIGNED_ONLY') && ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED || $object->statut == Propal::STATUS_CANCELED))) && $usercanclose) { print ''.$langs->trans('ReOpen').''; } diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 07e3168a4ce..6091539a783 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -2892,7 +2892,7 @@ class Propal extends CommonObject } if (!$error) { - $this->status = self::STATUS_CANCELED; + $this->statut = self::STATUS_CANCELED; $this->db->commit(); return 1; } else { From feba8d3e622aab817fd782c4f42ec131c9632df9 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 12:26:15 +0100 Subject: [PATCH 08/12] Added canceled status label --- htdocs/comm/propal/class/propal.class.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 6091539a783..a0258f122bc 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -3461,11 +3461,13 @@ class Propal extends CommonObject if (empty($this->labelStatus) || empty($this->labelStatusShort)) { global $langs; $langs->load("propal"); + $this->labelStatus[-1] = $langs->transnoentitiesnoconv("PropalStatusCanceled"); $this->labelStatus[0] = $langs->transnoentitiesnoconv("PropalStatusDraft"); $this->labelStatus[1] = $langs->transnoentitiesnoconv("PropalStatusValidated"); $this->labelStatus[2] = $langs->transnoentitiesnoconv("PropalStatusSigned"); $this->labelStatus[3] = $langs->transnoentitiesnoconv("PropalStatusNotSigned"); $this->labelStatus[4] = $langs->transnoentitiesnoconv("PropalStatusBilled"); + $this->labelStatusShort[-1] = $langs->transnoentitiesnoconv("PropalStatusCanceledShort"); $this->labelStatusShort[0] = $langs->transnoentitiesnoconv("PropalStatusDraftShort"); $this->labelStatusShort[1] = $langs->transnoentitiesnoconv("PropalStatusValidatedShort"); $this->labelStatusShort[2] = $langs->transnoentitiesnoconv("PropalStatusSignedShort"); From 54af5c0f965edb262e11e3d4736baab8636e96c3 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 12:26:36 +0100 Subject: [PATCH 09/12] Updated localization --- htdocs/comm/propal/card.php | 2 +- htdocs/langs/en_US/propal.lang | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index d92661fc4e7..08292be5c80 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -2394,7 +2394,7 @@ if ($action == 'create') { } } elseif ($action == 'cancel') { // Confirm cancel - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans("Cancel"), $langs->trans('ConfirmCancelPropal', $object->ref), 'confirm_cancel', '', 0, 1); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans("CancelPropal"), $langs->trans('ConfirmCancelPropal', $object->ref), 'confirm_cancel', '', 0, 1); } elseif ($action == 'delete') { // Confirm delete $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id, $langs->trans('DeleteProp'), $langs->trans('ConfirmDeleteProp', $object->ref), 'confirm_delete', '', 0, 1); diff --git a/htdocs/langs/en_US/propal.lang b/htdocs/langs/en_US/propal.lang index c50f6d27c3c..f97a755dba9 100644 --- a/htdocs/langs/en_US/propal.lang +++ b/htdocs/langs/en_US/propal.lang @@ -12,9 +12,11 @@ NewPropal=New proposal Prospect=Prospect DeleteProp=Delete commercial proposal ValidateProp=Validate commercial proposal +CancelPropal=Cancel AddProp=Create proposal ConfirmDeleteProp=Are you sure you want to delete this commercial proposal? ConfirmValidateProp=Are you sure you want to validate this commercial proposal under name %s? +ConfirmCancelPropal=Are you sure you want to cancel commercial proposal %s? LastPropals=Latest %s proposals LastModifiedProposals=Latest %s modified proposals AllPropals=All proposals @@ -27,11 +29,13 @@ NbOfProposals=Number of commercial proposals ShowPropal=Show proposal PropalsDraft=Drafts PropalsOpened=Open +PropalStatusCanceled=Canceled (Abandoned) PropalStatusDraft=Draft (needs to be validated) PropalStatusValidated=Validated (proposal is open) PropalStatusSigned=Signed (needs billing) PropalStatusNotSigned=Not signed (closed) PropalStatusBilled=Billed +PropalStatusCanceledShort=Canceled PropalStatusDraftShort=Draft PropalStatusValidatedShort=Validated (open) PropalStatusClosedShort=Closed From 855723ab4044cf0f56b2b839cacd308ba5ef0e45 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 12:28:36 +0100 Subject: [PATCH 10/12] Added contributor details --- htdocs/comm/propal/card.php | 1 + htdocs/comm/propal/class/propal.class.php | 1 + 2 files changed, 2 insertions(+) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index 08292be5c80..39e63707e2a 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -16,6 +16,7 @@ * Copyright (C) 2020 Nicolas ZABOURI * Copyright (C) 2022 Gauthier VERDOL * Copyright (C) 2023 Lenin Rivas + * Copyright (C) 2023 William Mead * * 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 diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index a0258f122bc..0d63ae2324e 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -18,6 +18,7 @@ * Copyright (C) 2022 ATM Consulting * Copyright (C) 2022 OpenDSI * Copyright (C) 2022 Gauthier VERDOL + * Copyright (C) 2023 William Mead * * 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 From e64b942a0684324e0b18a8592a38edb81b62da79 Mon Sep 17 00:00:00 2001 From: William Mead Date: Wed, 10 Jan 2024 12:33:58 +0100 Subject: [PATCH 11/12] Added status type --- htdocs/comm/propal/class/propal.class.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 0d63ae2324e..da70e894763 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -3477,7 +3477,9 @@ class Propal extends CommonObject } $statusType = ''; - if ($status == self::STATUS_DRAFT) { + if ($status == self::STATUS_CANCELED) { + $statusType = 'status9'; + } elseif ($status == self::STATUS_DRAFT) { $statusType = 'status0'; } elseif ($status == self::STATUS_VALIDATED) { $statusType = 'status1'; From 46fb5b94002a0392b433c68644078a8e59be13e7 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 10 Jan 2024 15:01:32 +0100 Subject: [PATCH 12/12] Update card.php --- htdocs/comm/propal/card.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/comm/propal/card.php b/htdocs/comm/propal/card.php index fc977b053cb..9e861d863f9 100644 --- a/htdocs/comm/propal/card.php +++ b/htdocs/comm/propal/card.php @@ -241,6 +241,7 @@ if (empty($reshook)) { $result = $object->setCancel($user); if ($result > 0) { header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id); + exit(); } else { $langs->load("errors"); setEventMessages($object->error, $object->errors, 'errors');