diff --git a/core/xml/actions_pages.xml b/core/xml/actions_pages.xml
index 9b75658ed2e82105f5661a9d1e02dd3cb7a3d8a8..f9b5992c883245f288413402aec75855cd064bdb 100755
--- a/core/xml/actions_pages.xml
+++ b/core/xml/actions_pages.xml
@@ -309,7 +309,7 @@ An action page is described in a ACTIONPAGE tag :
         <LABEL>_VALIDATE_RECOMMENDATION</LABEL>
         <NAME>validate_recommendation</NAME>
         <DESC>_VALIDATE_RECOMMENDATION_DESC</DESC>
-        <component>v1Action</component>
+        <component>validateRecommendationAction</component>
         <ORIGIN>module</ORIGIN>
         <MODULE>avis</MODULE>
         <FLAG_CREATE>false</FLAG_CREATE>
diff --git a/migration/20.03/2003.sql b/migration/20.03/2003.sql
index 7ad82c81f35e9cf7318607ff59df1deb1711e4fc..6137732b6f7ee778a3d0faf104d266a656a28907 100644
--- a/migration/20.03/2003.sql
+++ b/migration/20.03/2003.sql
@@ -99,6 +99,7 @@ UPDATE actions SET component = 'sendToOpinionCircuitAction' WHERE action_page =
 UPDATE actions SET component = 'continueOpinionCircuitAction' WHERE action_page = 'avis_workflow';
 UPDATE actions SET component = 'giveOpinionParallelAction' WHERE action_page = 'avis_workflow_simple';
 UPDATE actions SET component = 'sendToParallelOpinion' WHERE action_page = 'send_docs_to_recommendation';
+UPDATE actions SET component = 'validateRecommendationAction' WHERE action_page = 'validate_recommendation';
 
 DELETE FROM actions_groupbaskets WHERE id_action IN (SELECT id FROM actions WHERE action_page = 'put_in_copy');
 DELETE FROM actions_categories WHERE action_id IN (SELECT id FROM actions WHERE action_page = 'put_in_copy');
diff --git a/src/app/action/controllers/ActionMethodController.php b/src/app/action/controllers/ActionMethodController.php
index 156203acc737aa000cbbca6e83afbe63c34b75d2..515d24523e8171c2da1649c831d9fb3da645d21e 100644
--- a/src/app/action/controllers/ActionMethodController.php
+++ b/src/app/action/controllers/ActionMethodController.php
@@ -66,6 +66,7 @@ class ActionMethodController
         'sendToOpinionCircuitAction'            => 'sendToOpinionCircuit',
         'continueOpinionCircuitAction'          => 'continueOpinionCircuit',
         'giveOpinionParallelAction'             => 'giveOpinionParallel',
+        'validateRecommendationAction'             => 'validateRecommendation',
         'noConfirmAction'                       => null
     ];
 
@@ -562,7 +563,7 @@ class ActionMethodController
         $opinionLimitDate = new \DateTime($args['data']['opinionLimitDate']);
         $today = new \DateTime('today');
         if ($opinionLimitDate < $today) {
-            return ['errors' => "Opinion limit date is not a valid date"];
+            return ['errors' => ["Opinion limit date is not a valid date"]];
         }
 
         ResModel::update([
@@ -591,7 +592,7 @@ class ActionMethodController
         $opinionLimitDate = new \DateTime($args['data']['opinionLimitDate']);
         $today = new \DateTime('today');
         if ($opinionLimitDate < $today) {
-            return ['errors' => "Opinion limit date is not a valid date"];
+            return ['errors' => ["Opinion limit date is not a valid date"]];
         }
 
         if (empty($args['data']['opinionCircuit'])) {
@@ -734,4 +735,53 @@ class ActionMethodController
 
         return true;
     }
+
+    public static function validateRecommendation(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['resId']);
+        ValidatorModel::intVal($args, ['resId']);
+
+        if (empty($args['data']['opinionLimitDate'])) {
+            return ["errors" => ["Opinion limit date is missing"]];
+        }
+
+        $opinionLimitDate = new \DateTime($args['data']['opinionLimitDate']);
+        $today = new \DateTime('today');
+        if ($opinionLimitDate < $today) {
+            return ['errors' => ["Opinion limit date is not a valid date"]];
+        }
+
+        $latestNote = NoteModel::get([
+            'where'  => ['identifier = ?', "note_text like '[" . _TO_AVIS . "]%'"],
+            'data'   => [$args['resId']],
+            'oderBy' => ['creation_date desc'],
+            'limit'  => 1
+        ]);
+
+        if (empty($latestNote)) {
+            return ["errors" => ["No note for opinion available"]];
+        }
+        $latestNote = $latestNote[0];
+
+        $newNote = $args['data']['note'];
+
+        NoteModel::delete([
+            'where' => ['id = ?'],
+            'data' => [$latestNote['id']]
+        ]);
+
+        NoteModel::create([
+            'resId'     => $args['resId'],
+            'user_id'   => $GLOBALS['id'],
+            'note_text' => $newNote
+        ]);
+
+        ResModel::update([
+            'set'   => ['opinion_limit_date' => $args['data']['opinionLimitDate']],
+            'where' => ['res_id = ?'],
+            'data'  => [$args['resId']]
+        ]);
+
+        return true;
+    }
 }
diff --git a/src/core/lang/lang-en.php b/src/core/lang/lang-en.php
index 22f45fc3ecf249bcd49385e75d332d2ddcfe162d..eeb229c26a241005e0aa82707d1196fa39bcd455 100755
--- a/src/core/lang/lang-en.php
+++ b/src/core/lang/lang-en.php
@@ -447,3 +447,4 @@ define("_HAS_INTERRUPTED_WORKFLOW", "Has interrupted the workflow ");
 
 define("_AVIS_SENT", "Notice given");
 define("_BY", "by");
+define("_TO_AVIS", "For recommendation");
diff --git a/src/core/lang/lang-fr.php b/src/core/lang/lang-fr.php
index dda7b515e058bf09437030417a4ccd81726321f1..39c80092ba8a1b02eac0d34107ce24efcfb5f356 100755
--- a/src/core/lang/lang-fr.php
+++ b/src/core/lang/lang-fr.php
@@ -446,3 +446,4 @@ define("_HAS_INTERRUPTED_WORKFLOW", "A terminé le circuit");
 
 define("_AVIS_SENT", "Avis donné");
 define("_BY", "par");
+define("_TO_AVIS", "POUR AVIS");
diff --git a/src/core/lang/lang-nl.php b/src/core/lang/lang-nl.php
index fab10426c51203b991c4fd3995fddc833b0880a1..5d647688843c40c158c0d69fb764d9e06636222f 100755
--- a/src/core/lang/lang-nl.php
+++ b/src/core/lang/lang-nl.php
@@ -452,3 +452,4 @@ define("_HAS_INTERRUPTED_WORKFLOW", "Has interrupted the workflow "); //TO TRANS
 
 define('_AVIS_SENT', 'Gegeven bericht');
 define('_BY', 'door');
+define('_TO_AVIS', 'VOOR BERICHT');