From f9f70e484f1bd4f52bef75b54480c341bf3d234c Mon Sep 17 00:00:00 2001
From: Jean-Laurent <jean-laurent.duzant@xelians.fr>
Date: Thu, 4 Aug 2022 15:35:32 +0200
Subject: [PATCH] FIX #19580 TIME 1:00 rollback chrono parameters,
 create/update/delete sequence for chronos && fix reset_chronos sql function

---
 sql/data_fr.sql                               |  6 +-
 sql/sample.sql                                |  6 ++
 sql/structure.sql                             | 31 +++++----
 .../controllers/ParameterController.php       | 13 ++++
 src/app/resource/models/ChronoModel.php       | 15 ++--
 src/core/models/DatabaseModel.php             | 69 +++++++++++++++++--
 6 files changed, 110 insertions(+), 30 deletions(-)

diff --git a/sql/data_fr.sql b/sql/data_fr.sql
index 740ff4a1291..2c70a7ba684 100755
--- a/sql/data_fr.sql
+++ b/sql/data_fr.sql
@@ -705,10 +705,8 @@ INSERT INTO parameters (id, description, param_value_string, param_value_int, pa
 INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) VALUES ('homepage_message', '', '<p><span style="font-size: 14pt;">Bienvenue sur <strong>Maarch Courrier 21.03</strong> </span><br /><span style="font-size: 14pt;">Suivez le <a title="notre guide de visite" href="https://docs.maarch.org/" target="_blank" rel="noopener"><span style="color: #f99830;"><strong>guide de visite en ligne</strong></span></a></span></p>', NULL, NULL);
 INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) VALUES ('loginpage_message', '', '<p><span style="font-size: 14pt; color: #ecf0f1;"><span style="color: #000000;"><strong>Acc&eacute;der au</strong> </span><a style="color: ##3598db;" title="le guide de visite" href="https://docs.maarch.org/gitbook/html/MaarchCourrier/21.03/guu/home.html" target="_blank" rel="noopener"><strong>guide de visite en ligne</strong></a></span></p>', NULL, NULL);
 INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) VALUES ('traffic_record_summary_sheet', '', '', NULL, NULL);
-
-CREATE SEQUENCE chrono_outgoing_2021_seq INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 3 CACHE 1;
-CREATE SEQUENCE chrono_incoming_2021_seq INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 4 CACHE 1;
-
+INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) VALUES ('chrono_outgoing_2021', '', NULL, 3, NULL);
+INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) VALUES ('chrono_incoming_2021', '', NULL, 4, NULL);
 INSERT INTO parameters (id, description, param_value_int) VALUES ('suggest_links_n_days_ago', 'Le nombre de jours sur lequel sont cherchés les courriers à lier', 0);
 
 INSERT INTO password_rules (id, label, value, enabled) VALUES (1, 'minLength', 6, true);
diff --git a/sql/sample.sql b/sql/sample.sql
index 45bc9151bec..52c1724e91d 100644
--- a/sql/sample.sql
+++ b/sql/sample.sql
@@ -99,6 +99,12 @@ INSERT INTO user_signatures (id, user_serial_id, signature_label, signature_path
 Select setval('user_signatures_id_seq', (select max(id)+1 from user_signatures), false);
 
 --update parameters for chrono
+DELETE FROM parameters WHERE id = 'chrono_incoming_2021' OR  id = 'chrono_outgoing_2021';
+INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) 
+VALUES ('chrono_incoming_2021', NULL, NULL, 100, NULL);
+INSERT INTO parameters (id, description, param_value_string, param_value_int, param_value_date) 
+VALUES ('chrono_outgoing_2021', NULL, NULL, 100, NULL);
+
 DROP SEQUENCE IF EXISTS chrono_outgoing_2021_seq;
 DROP SEQUENCE IF EXISTS chrono_incoming_2021_seq;
 CREATE SEQUENCE chrono_outgoing_2021_seq INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 100 CACHE 1;
diff --git a/sql/structure.sql b/sql/structure.sql
index 9fa6899ded4..895f570b35b 100755
--- a/sql/structure.sql
+++ b/sql/structure.sql
@@ -1555,22 +1555,8 @@ CREATE TABLE address_sectors
 )
     WITH (OIDS=FALSE);
 
-DROP FUNCTION IF EXISTS increase_chrono;
-CREATE OR REPLACE FUNCTION increase_chrono(chrono_id_seq text) returns table (retval bigint) as $$
-DECLARE
-    retval bigint;
-BEGIN
-    IF NOT EXISTS (SELECT 0 FROM pg_class where relname = chrono_id_seq ) THEN
-      EXECUTE 'CREATE SEQUENCE ' || chrono_id_seq || ' INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START 100 CACHE 1;';
-    END IF;
-    SELECT nextval(chrono_id_seq) INTO retval;
-    RETURN QUERY SELECT retval;
-END;
-$$ LANGUAGE plpgsql;
-
-DROP FUNCTION IF EXISTS reset_chronos;
 -- Create a sequence for chronos and update value in parameters table
-CREATE OR REPLACE FUNCTION public.reset_chronos(chrono_seq_name text, chrono_id_name text) returns table (chrono_id bigint) as $$
+CREATE OR REPLACE FUNCTION public.increase_chrono(chrono_seq_name text, chrono_id_name text) returns table (chrono_id bigint) as $$
 DECLARE
     retval bigint;
 BEGIN
@@ -1588,3 +1574,18 @@ BEGIN
 	  RETURN QUERY SELECT retval;
 END;
 $$ LANGUAGE plpgsql;
+
+-- reset les chronos
+DROP FUNCTION IF EXISTS reset_chronos;
+-- Create a sequence for chronos and update value in parameters table
+CREATE OR REPLACE FUNCTION public.reset_chronos() returns void as $$
+DECLARE
+  chrono record;
+BEGIN
+  -- Loop through each chrono found in parameters table
+	FOR chrono IN (SELECT * FROM parameters WHERE id LIKE '%_' || extract(YEAR FROM current_date)) LOOP
+    EXECUTE 'SELECT setVal(''' || CONCAT(chrono.id, '_seq') || ''', 1)';
+    UPDATE parameters SET param_value_int = '1' WHERE id = chrono.id;
+  END LOOP;
+END
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/src/app/parameter/controllers/ParameterController.php b/src/app/parameter/controllers/ParameterController.php
index 05544560414..37b0fefb905 100755
--- a/src/app/parameter/controllers/ParameterController.php
+++ b/src/app/parameter/controllers/ParameterController.php
@@ -24,6 +24,7 @@ use Respect\Validation\Validator;
 use Slim\Http\Request;
 use Slim\Http\Response;
 use SrcCore\models\CoreConfigModel;
+use SrcCore\models\DatabaseModel;
 
 class ParameterController
 {
@@ -109,6 +110,9 @@ class ParameterController
         }
 
         ParameterModel::create($data);
+        if (strpos($data['id'], 'chrono_') !== false) {
+            DatabaseModel::createSequence(['id' => $data['id'] . '_seq', 'value' => $data['param_value_int']]);
+        }
         HistoryController::add([
             'tableName' => 'parameters',
             'recordId'  => $data['id'],
@@ -213,6 +217,9 @@ class ParameterController
                     return $response->withStatus(400)->withJson(['errors' => 'Parameter not found']);
                 }
                 ParameterModel::create(['id' => $args['id']]);
+                if (strpos($args['id'], 'chrono_') !== false) {
+                    DatabaseModel::createSequence(['id' => $args['id'] . '_seq']);
+                }
             }
 
             $check = (empty($body['param_value_int']) || Validator::intVal()->validate($body['param_value_int']));
@@ -223,6 +230,9 @@ class ParameterController
 
             $body['id'] = $args['id'];
             ParameterModel::update($body);
+            if (strpos($body['id'], 'chrono_') !== false) {
+                DatabaseModel::updateSequence(['id' => $body['id'] . '_seq', 'value' => $body['param_value_int']]);
+            }
         }
 
         HistoryController::add([
@@ -244,6 +254,9 @@ class ParameterController
         }
 
         ParameterModel::delete(['id' => $aArgs['id']]);
+        if (strpos($aArgs['id'], 'chrono_') !== false) {
+            DatabaseModel::deleteSequence(['id' => $aArgs['id'] . '_seq']);
+        }
         HistoryController::add([
             'tableName' => 'parameters',
             'recordId'  => $aArgs['id'],
diff --git a/src/app/resource/models/ChronoModel.php b/src/app/resource/models/ChronoModel.php
index 32a02b6ef69..88892c38afd 100755
--- a/src/app/resource/models/ChronoModel.php
+++ b/src/app/resource/models/ChronoModel.php
@@ -87,8 +87,9 @@ class ChronoModel
      */
     public static function getChronoGlobal()
     {
-        $chronoSeqName  = 'chrono_global_' . date('Y') . "_seq";
-        $chrono = DatabaseModel::createOrIncreaseChrono(['chronoSeqName' => $chronoSeqName]);
+        $chronoIdName  = 'chrono_global_' . date('Y');
+        $chronoSeqName = $chronoIdName . "_seq";
+        $chrono = DatabaseModel::createOrIncreaseChrono(['chronoIdName' => $chronoIdName, 'chronoSeqName' => $chronoSeqName]);
         return $chrono;
     }
 
@@ -97,15 +98,17 @@ class ChronoModel
      */
     public static function getChronoEntity($entityId)
     {
-        $chronoSeqName  = "chrono_{$categoryId}_" . date('Y') . "_seq";
-        $chrono = DatabaseModel::createOrIncreaseChrono(['chronoSeqName' => $chronoSeqName]);
+        $chronoIdName  = "chrono_{$entityId}_" . date('Y');
+        $chronoSeqName = $chronoIdName . "_seq";
+        $chrono = DatabaseModel::createOrIncreaseChrono(['chronoIdName' => $chronoIdName, 'chronoSeqName' => $chronoSeqName]);
         return $entityId . "/" . $chrono;
     }
 
     public static function getChronoCategory($categoryId)
     {
-        $chronoSeqName  = "chrono_{$categoryId}_" . date('Y') . "_seq";
-        $chrono = DatabaseModel::createOrIncreaseChrono(['chronoSeqName' => $chronoSeqName]);
+        $chronoIdName  = "chrono_{$categoryId}_" . date('Y');
+        $chronoSeqName = $chronoIdName . "_seq";
+        $chrono = DatabaseModel::createOrIncreaseChrono(['chronoIdName' => $chronoIdName, 'chronoSeqName' => $chronoSeqName]);
         return "/" . $chrono;
     }
 
diff --git a/src/core/models/DatabaseModel.php b/src/core/models/DatabaseModel.php
index 8b335a0f2e1..eb7ab0c43e8 100755
--- a/src/core/models/DatabaseModel.php
+++ b/src/core/models/DatabaseModel.php
@@ -16,7 +16,67 @@ namespace SrcCore\models;
 
 class DatabaseModel
 {
-        /**
+    /**
+     * Database create a new sequence
+     * @param array $args
+     *
+     * @return bool
+     * @throws \Exception
+     */
+    public static function createSequence(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['id']);
+        ValidatorModel::stringType($args, ['id']);
+
+        $args['value'] = empty($args['value'] ?? null) ? 1 : $args['value'];
+        $query = "CREATE SEQUENCE {$args['id']} INCREMENT 1 MINVALUE 1 MAXVALUE 9223372036854775807 START {$args['value']} CACHE 1";
+
+        $db = new DatabasePDO();
+        $db->query($query);
+        return true;
+    }
+
+    /**
+     * Database update an existing sequence
+     * @param array $args
+     *
+     * @return int
+     * @throws \Exception
+     */
+    public static function updateSequence(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['id', 'value']);
+        ValidatorModel::stringType($args, ['id']);
+        ValidatorModel::intType($args, ['value']);
+
+        $query = "SELECT setval('{$args['id']}', {$args['value']})";
+
+        $db = new DatabasePDO();
+        $stmt = $db->query($query);
+        $row = $stmt->fetch(\PDO::FETCH_ASSOC);
+        return $row['setval'];
+    }
+
+    /**
+     * Database delete an existing sequence
+     * @param array $args
+     *
+     * @return bool
+     * @throws \Exception
+     */
+    public static function deleteSequence(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['id']);
+        ValidatorModel::stringType($args, ['id']);
+
+        $query = "DROP SEQUENCE IF EXISTS {$args['id']}";
+
+        $db = new DatabasePDO();
+        $db->query($query);
+        return true;
+    }
+
+    /**
      * Database increase_chrono function
      * @param array $args
      *
@@ -25,10 +85,10 @@ class DatabaseModel
      */
     public static function createOrIncreaseChrono(array $args)
     {
-        ValidatorModel::notEmpty($args, ['chronoSeqName']);
-        ValidatorModel::stringType($args, ['chronoSeqName']);
+        ValidatorModel::notEmpty($args, ['chronoIdName', 'chronoSeqName']);
+        ValidatorModel::stringType($args, ['chronoIdName', 'chronoSeqName']);
 
-        $query = "SELECT increase_chrono('" . $args['chronoSeqName'] . "')";
+        $query = "SELECT increase_chrono('{$args['chronoSeqName']}' ,'{$args['chronoIdName']}')";
 
         $db = new DatabasePDO();
         $stmt = $db->query($query);
@@ -36,7 +96,6 @@ class DatabaseModel
         return $row['increase_chrono'];
     }
 
-
     /**
      * Database Nextval Sequence Function
      * @param array $args
-- 
GitLab