diff --git a/apps/note/models/transactions.py b/apps/note/models/transactions.py
index 0e40edf699cf9653e9a814f1d2a8895d73038a2e..93d1071adc82bf76da8be6426c00f7b08688f8c5 100644
--- a/apps/note/models/transactions.py
+++ b/apps/note/models/transactions.py
@@ -115,11 +115,19 @@ class Transaction(PolymorphicModel):
         verbose_name=_('reason'),
         max_length=255,
     )
+
     valid = models.BooleanField(
         verbose_name=_('valid'),
         default=True,
     )
 
+    invalidity_reason = models.CharField(
+        verbose_name=_('invalidity reason'),
+        max_length=255,
+        default=None,
+        null=True,
+    )
+
     class Meta:
         verbose_name = _("transaction")
         verbose_name_plural = _("transactions")
@@ -152,6 +160,10 @@ class Transaction(PolymorphicModel):
             self.source.balance -= to_transfer
             self.destination.balance += to_transfer
 
+            # When a transaction is declared valid, we ensure that the invalidity reason is null, if it was
+            # previously invalid
+            self.invalidity_reason = None
+
         # We save first the transaction, in case of the user has no right to transfer money
         super().save(*args, **kwargs)
 
diff --git a/apps/note/tables.py b/apps/note/tables.py
index 20054d2cf52fbb79a2dfd277b3bab0243dcd0c18..ea7bdaa7cd44ff22cf6b405e0ed7273d7f6f0fdc 100644
--- a/apps/note/tables.py
+++ b/apps/note/tables.py
@@ -5,6 +5,7 @@ import html
 
 import django_tables2 as tables
 from django.db.models import F
+from django.utils.html import format_html
 from django_tables2.utils import A
 from django.utils.translation import gettext_lazy as _
 
@@ -20,19 +21,26 @@ class HistoryTable(tables.Table):
                 'table table-condensed table-striped table-hover'
         }
         model = Transaction
-        exclude = ("id", "polymorphic_ctype", )
+        exclude = ("id", "polymorphic_ctype", "invalidity_reason")
         template_name = 'django_tables2/bootstrap4.html'
-        sequence = ('...', 'type', 'total', 'valid', )
+        sequence = ('...', 'type', 'total', 'valid',)
         orderable = False
 
     type = tables.Column()
 
     total = tables.Column()  # will use Transaction.total() !!
 
-    valid = tables.Column(attrs={"td": {"id": lambda record: "validate_" + str(record.id),
-                                        "class": lambda record: str(record.valid).lower() + ' validate',
-                                        "onclick": lambda record: 'de_validate(' + str(record.id) + ', '
-                                                                  + str(record.valid).lower() + ')'}})
+    valid = tables.Column(
+        attrs={
+            "td": {
+                "id": lambda record: "validate_" + str(record.id),
+                "class": lambda record: str(record.valid).lower() + ' validate',
+                "onclick": lambda record: 'in_validate(' + str(record.id) + ', ' + str(record.valid).lower() + ')',
+                "onmouseover": lambda record: 'hover_validation_btn(' + str(record.id) + ', true)',
+                "onmouseout": lambda record: 'hover_validation_btn(' + str(record.id) + ', false)',
+            }
+        }
+    )
 
     def order_total(self, queryset, is_descending):
         # needed for rendering
@@ -53,8 +61,13 @@ class HistoryTable(tables.Table):
     def render_reason(self, value):
         return html.unescape(value)
 
-    def render_valid(self, value):
-        return "✔" if value else "✖"
+    def render_valid(self, value, record):
+        val = "✔" if value else "✖"
+        val += "<br><input type='text' class='form-control' id='invalidity_reason_" + str(record.id) \
+               + "' value='" + (record.invalidity_reason.replace('\'', '&apos;') if record.invalidity_reason else "") \
+               + "'" + ("" if value else " disabled") \
+               + " style='display: none;'>"
+        return format_html(val)
 
 
 # function delete_button(id) provided in template file
diff --git a/static/js/base.js b/static/js/base.js
index f70858500cf97aa61d45fe019429999df51c9c35..4a78e81138c586c401f8fed8a919040291325d2d 100644
--- a/static/js/base.js
+++ b/static/js/base.js
@@ -260,8 +260,29 @@ function autoCompleteNote(field_id, alias_matched_id, note_list_id, notes, notes
     });
 }
 
+function hover_validation_btn(id, show) {
+    let reason_obj = $("#invalidity_reason_" + id);
+    console.log(reason_obj.val());
+
+    if (show) {
+        reason_obj.show();
+        reason_obj.focus();
+    }
+    else
+        reason_obj.hide();
+}
+
 // When a validate button is clicked, we switch the validation status
-function de_validate(id, validated) {
+function in_validate(id, validated) {
+
+    let invalidity_reason;
+    let reason_obj = $("#invalidity_reason_" + id);
+
+    if (validated)
+        invalidity_reason = reason_obj.val();
+    else
+        invalidity_reason = null;
+
     $("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳ ...</strong>");
 
     // Perform a PATCH request to the API in order to update the transaction
@@ -274,12 +295,13 @@ function de_validate(id, validated) {
             "X-CSRFTOKEN": CSRF_TOKEN
         },
         data: {
-            "resourcetype": "RecurrentTransaction",
-            valid: !validated
+            resourcetype: "RecurrentTransaction",
+            valid: !validated,
+            invalidity_reason: invalidity_reason,
         },
         success: function () {
             // Refresh jQuery objects
-            $(".validate").click(de_validate);
+            $(".validate").click(in_validate);
 
             refreshBalance();
             // error if this method doesn't exist. Please define it.