From 1e86a1ce5ead6d241d4906e5861fcd722a307638 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Mon, 30 May 2022 10:26:34 +0200
Subject: [PATCH] #163 Checked icons improvement

* adds a second star icon on currently unchecked but previously checked entries
   --> can be detected easier for another check run
* simplifies some related code parts
* moves some translation string into message_templates.py
* enables session timeout after 60 minutes
* improves comment card layout sizing
* adds/updates translations
---
 compensation/tables.py                        |  29 ++-
 .../detail/compensation/view.html             |   5 +
 compensation/views/compensation.py            |   9 +-
 ema/tables.py                                 |   5 +-
 intervention/tables.py                        |  22 ++-
 .../templates/intervention/detail/view.html   |   5 +
 intervention/views.py                         |   8 +-
 konova/models/object.py                       |  14 ++
 konova/sub_settings/django_settings.py        |   4 +-
 .../konova/includes/comment_card.html         |   2 +-
 konova/utils/message_templates.py             |   5 +
 konova/utils/tables.py                        |  11 ++
 locale/de/LC_MESSAGES/django.mo               | Bin 42213 -> 42537 bytes
 locale/de/LC_MESSAGES/django.po               | 176 +++++++++---------
 user/models/user_action.py                    |  11 ++
 15 files changed, 186 insertions(+), 120 deletions(-)

diff --git a/compensation/tables.py b/compensation/tables.py
index 401a7416..1373f2cd 100644
--- a/compensation/tables.py
+++ b/compensation/tables.py
@@ -5,17 +5,15 @@ Contact: michel.peltriaux@sgdnord.rlp.de
 Created on: 01.12.20
 
 """
-from user.models import User
+from konova.utils.message_templates import DATA_IS_UNCHECKED, DATA_CHECKED_ON_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE
 from django.http import HttpRequest
 from django.template.loader import render_to_string
 from django.urls import reverse
 from django.utils.html import format_html
-from django.utils.timezone import localtime
 from django.utils.translation import gettext_lazy as _
 
 from compensation.filters import CompensationTableFilter, EcoAccountTableFilter
 from compensation.models import Compensation, EcoAccount
-from konova.sub_settings.django_settings import DEFAULT_DATE_TIME_FORMAT
 from konova.utils.tables import BaseTable, TableRenderMixin
 import django_tables2 as tables
 
@@ -111,16 +109,21 @@ class CompensationTable(BaseTable, TableRenderMixin):
         """
         html = ""
         checked = value is not None
-        tooltip = _("Not checked yet")
+        tooltip = DATA_IS_UNCHECKED
+        previously_checked = record.intervention.get_last_checked_action()
         if checked:
-            value = value.timestamp
-            value = localtime(value)
-            checked_on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
-            tooltip = _("Checked on {} by {}").format(checked_on, record.intervention.checked.user)
+            checked_on = value.get_timestamp_str_formatted()
+            tooltip = DATA_CHECKED_ON_TEMPLATE.format(checked_on, record.intervention.checked.user)
         html += self.render_checked_star(
             tooltip=tooltip,
             icn_filled=checked,
         )
+        if previously_checked and not checked:
+            checked_on = previously_checked.get_timestamp_str_formatted()
+            tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(checked_on, previously_checked.user)
+            html += self.render_previously_checked_star(
+                tooltip=tooltip,
+            )
         return format_html(html)
 
     def render_d(self, value, record: Compensation):
@@ -159,9 +162,7 @@ class CompensationTable(BaseTable, TableRenderMixin):
         recorded = value is not None
         tooltip = _("Not recorded yet")
         if recorded:
-            value = value.timestamp
-            value = localtime(value)
-            on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
+            on = value.get_timestamp_str_formatted()
             tooltip = _("Recorded on {} by {}").format(on, record.intervention.recorded.user)
         html += self.render_bookmark(
             tooltip=tooltip,
@@ -179,8 +180,6 @@ class CompensationTable(BaseTable, TableRenderMixin):
         Returns:
 
         """
-        if value is None:
-            value = User.objects.none()
         has_access = record.is_shared_with(self.user)
 
         html = self.render_icn(
@@ -318,9 +317,7 @@ class EcoAccountTable(BaseTable, TableRenderMixin):
         checked = value is not None
         tooltip = _("Not recorded yet. Can not be used for deductions, yet.")
         if checked:
-            value = value.timestamp
-            value = localtime(value)
-            on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
+            on = value.get_timestamp_str_formatted()
             tooltip = _("Recorded on {} by {}").format(on, record.recorded.user)
         html += self.render_bookmark(
             tooltip=tooltip,
diff --git a/compensation/templates/compensation/detail/compensation/view.html b/compensation/templates/compensation/detail/compensation/view.html
index 026a6ff6..be8dd3b9 100644
--- a/compensation/templates/compensation/detail/compensation/view.html
+++ b/compensation/templates/compensation/detail/compensation/view.html
@@ -66,6 +66,11 @@
                                 <span>
                                     {% fa5_icon 'star' 'far' %}
                                 </span>
+                                {% if last_checked %}
+                                    <span class="rlp-gd-inv" title="{{last_checked_tooltip}}">
+                                        {% fa5_icon 'star' 'fas' %}
+                                    </span>
+                                {% endif %}
                             {% else %}
                                 <span class="check-star" title="{% trans 'Checked on '%} {{obj.intervention.checked.timestamp}} {% trans 'by' %} {{obj.intervention.checked.user}}">
                                     {% fa5_icon 'star' %}
diff --git a/compensation/views/compensation.py b/compensation/views/compensation.py
index c3d3e2b5..31087ed7 100644
--- a/compensation/views/compensation.py
+++ b/compensation/views/compensation.py
@@ -23,7 +23,7 @@ from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DA
     CHECKED_RECORDED_RESET, COMPENSATION_ADDED_TEMPLATE, COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED, \
     COMPENSATION_STATE_REMOVED, COMPENSATION_STATE_ADDED, COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_ADDED, \
     DEADLINE_ADDED, DEADLINE_REMOVED, DOCUMENT_EDITED, COMPENSATION_STATE_EDITED, COMPENSATION_ACTION_EDITED, \
-    DEADLINE_EDITED, RECORDED_BLOCKS_EDIT, PARAMS_INVALID
+    DEADLINE_EDITED, RECORDED_BLOCKS_EDIT, PARAMS_INVALID, DATA_CHECKED_PREVIOUSLY_TEMPLATE
 from konova.utils.user_checks import in_group
 
 
@@ -217,8 +217,15 @@ def detail_view(request: HttpRequest, id: str):
 
     request = comp.set_status_messages(request)
 
+    last_checked = comp.intervention.get_last_checked_action()
+    last_checked_tooltip = ""
+    if last_checked:
+        last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(last_checked.get_timestamp_str_formatted(), last_checked.user)
+
     context = {
         "obj": comp,
+        "last_checked": last_checked,
+        "last_checked_tooltip": last_checked_tooltip,
         "geom_form": geom_form,
         "parcels": parcels,
         "has_access": is_data_shared,
diff --git a/ema/tables.py b/ema/tables.py
index 38d8a8c0..d26a31dc 100644
--- a/ema/tables.py
+++ b/ema/tables.py
@@ -115,7 +115,6 @@ class EmaTable(BaseTable, TableRenderMixin):
         )
         return html
 
-
     def render_r(self, value, record: Ema):
         """ Renders the registered column for a EMA
 
@@ -130,9 +129,7 @@ class EmaTable(BaseTable, TableRenderMixin):
         recorded = value is not None
         tooltip = _("Not recorded yet")
         if recorded:
-            value = value.timestamp
-            value = localtime(value)
-            on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
+            on = value.get_timestamp_str_formatted()
             tooltip = _("Recorded on {} by {}").format(on, record.recorded.user)
         html += self.render_bookmark(
             tooltip=tooltip,
diff --git a/intervention/tables.py b/intervention/tables.py
index 8f312099..cff9391c 100644
--- a/intervention/tables.py
+++ b/intervention/tables.py
@@ -9,12 +9,11 @@ from django.http import HttpRequest
 from django.template.loader import render_to_string
 from django.urls import reverse
 from django.utils.html import format_html
-from django.utils.timezone import localtime
 from django.utils.translation import gettext_lazy as _
 
 from intervention.filters import InterventionTableFilter
 from intervention.models import Intervention
-from konova.sub_settings.django_settings import DEFAULT_DATE_TIME_FORMAT, DEFAULT_DATE_FORMAT
+from konova.utils.message_templates import DATA_CHECKED_ON_TEMPLATE, DATA_IS_UNCHECKED, DATA_CHECKED_PREVIOUSLY_TEMPLATE
 from konova.utils.tables import BaseTable, TableRenderMixin
 import django_tables2 as tables
 
@@ -108,16 +107,21 @@ class InterventionTable(BaseTable, TableRenderMixin):
         """
         html = ""
         checked = value is not None
-        tooltip = _("Not checked yet")
+        previously_checked = record.get_last_checked_action()
+        tooltip = DATA_IS_UNCHECKED
         if checked:
-            value = value.timestamp
-            value = localtime(value)
-            checked_on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
-            tooltip = _("Checked on {} by {}").format(checked_on, record.checked.user)
+            checked_on = value.get_timestamp_str_formatted()
+            tooltip = DATA_CHECKED_ON_TEMPLATE.format(checked_on, record.checked.user)
         html += self.render_checked_star(
             tooltip=tooltip,
             icn_filled=checked,
         )
+        if previously_checked and not checked:
+            checked_on = previously_checked.get_timestamp_str_formatted()
+            tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(checked_on, previously_checked.user)
+            html += self.render_previously_checked_star(
+                tooltip=tooltip,
+            )
         return format_html(html)
 
     def render_d(self, value, record: Intervention):
@@ -156,9 +160,7 @@ class InterventionTable(BaseTable, TableRenderMixin):
         checked = value is not None
         tooltip = _("Not recorded yet")
         if checked:
-            value = value.timestamp
-            value = localtime(value)
-            on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
+            on = value.get_timestamp_str_formatted()
             tooltip = _("Recorded on {} by {}").format(on, record.recorded.user)
         html += self.render_bookmark(
             tooltip=tooltip,
diff --git a/intervention/templates/intervention/detail/view.html b/intervention/templates/intervention/detail/view.html
index 55c9db99..55d57f68 100644
--- a/intervention/templates/intervention/detail/view.html
+++ b/intervention/templates/intervention/detail/view.html
@@ -70,6 +70,11 @@
                                 <span>
                                     {% fa5_icon 'star' 'far' %}
                                 </span>
+                                {% if last_checked %}
+                                    <span class="rlp-gd-inv" title="{{last_checked_tooltip}}">
+                                        {% fa5_icon 'star' 'fas' %}
+                                    </span>
+                                {% endif %}
                             {% else %}
                                 <span class="check-star" title="{% trans 'Checked on '%} {{obj.checked.timestamp}} {% trans 'by' %} {{obj.checked.user}}">
                                     {% fa5_icon 'star' %}
diff --git a/intervention/views.py b/intervention/views.py
index 15388dbf..36577202 100644
--- a/intervention/views.py
+++ b/intervention/views.py
@@ -19,7 +19,7 @@ from konova.utils.generators import generate_qr_code
 from konova.utils.message_templates import INTERVENTION_INVALID, FORM_INVALID, IDENTIFIER_REPLACED, \
     CHECKED_RECORDED_RESET, DEDUCTION_REMOVED, DEDUCTION_ADDED, REVOCATION_ADDED, REVOCATION_REMOVED, \
     COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED, DEDUCTION_EDITED, REVOCATION_EDITED, DOCUMENT_EDITED, \
-    RECORDED_BLOCKS_EDIT
+    RECORDED_BLOCKS_EDIT, DATA_CHECKED_PREVIOUSLY_TEMPLATE
 from konova.utils.user_checks import in_group
 
 
@@ -265,9 +265,15 @@ def detail_view(request: HttpRequest, id: str):
     geom_form = SimpleGeomForm(
         instance=intervention,
     )
+    last_checked = intervention.get_last_checked_action()
+    last_checked_tooltip = ""
+    if last_checked:
+        last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(last_checked.get_timestamp_str_formatted(), last_checked.user)
 
     context = {
         "obj": intervention,
+        "last_checked": last_checked,
+        "last_checked_tooltip": last_checked_tooltip,
         "compensations": compensations,
         "has_access": is_data_shared,
         "geom_form": geom_form,
diff --git a/konova/models/object.py b/konova/models/object.py
index 780a0c2f..325762f4 100644
--- a/konova/models/object.py
+++ b/konova/models/object.py
@@ -408,6 +408,20 @@ class CheckableObjectMixin(models.Model):
         self.log.add(action)
         return action
 
+    def get_last_checked_action(self):
+        """ Getter for the most recent checked action on the log
+
+        Returns:
+            previously_checked (UserActionLogEntry): The most recent checked action
+        """
+        from user.models import UserAction
+        previously_checked = self.log.filter(
+            action=UserAction.CHECKED
+        ).order_by(
+            "-timestamp"
+        ).first()
+        return previously_checked
+
 
 class ShareableObjectMixin(models.Model):
     # Users having access on this object
diff --git a/konova/sub_settings/django_settings.py b/konova/sub_settings/django_settings.py
index e5de97a0..746df289 100644
--- a/konova/sub_settings/django_settings.py
+++ b/konova/sub_settings/django_settings.py
@@ -46,8 +46,8 @@ ALLOWED_HOSTS = [
 LOGIN_URL = "/login/"
 
 # Session settings
-#SESSION_COOKIE_AGE = 30 * 60  # 30 minutes
-#SESSION_SAVE_EVERY_REQUEST = True
+SESSION_COOKIE_AGE = 60 * 60  # 60 minutes
+SESSION_SAVE_EVERY_REQUEST = True
 
 # Application definition
 
diff --git a/konova/templates/konova/includes/comment_card.html b/konova/templates/konova/includes/comment_card.html
index a84f378e..d9ea59bc 100644
--- a/konova/templates/konova/includes/comment_card.html
+++ b/konova/templates/konova/includes/comment_card.html
@@ -6,7 +6,7 @@
 
 
 {% if obj.comment %}
-<div class="w-100">
+<div class="col-sm-12">
     <div class="card mt-3">
         <div class="card-header rlp-gd">
             <div class="row">
diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py
index e062005a..f6e3ca18 100644
--- a/konova/utils/message_templates.py
+++ b/konova/utils/message_templates.py
@@ -81,3 +81,8 @@ GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}")
 
 # INTERVENTION
 INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations")
+
+# CHECKED
+DATA_CHECKED_ON_TEMPLATE = _("Checked on {} by {}")
+DATA_CHECKED_PREVIOUSLY_TEMPLATE = _("Data has changed since last check on {} by {}")
+DATA_IS_UNCHECKED = _("Current data not checked yet")
diff --git a/konova/utils/tables.py b/konova/utils/tables.py
index d3a0406b..d7468725 100644
--- a/konova/utils/tables.py
+++ b/konova/utils/tables.py
@@ -112,6 +112,17 @@ class BaseTable(tables.tables.Table):
             icon
         )
 
+    def render_previously_checked_star(self, tooltip: str = None):
+        """
+        Returns a star icon for a check action in the past
+        """
+        icon = "fas fa-star rlp-gd-inv"
+        return format_html(
+            "<em title='{}' class='{}'></em>",
+            tooltip,
+            icon
+        )
+
     def render_bookmark(self, tooltip: str = None, icn_filled: bool = False):
         """
         Returns a bookmark icon
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index fd65919aecc67a938a81e04d655b90f05ec01ecb..5e1ebe07b800b2394d8be056876cb8984367e376 100644
GIT binary patch
delta 12135
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
F{{^xd6kz}W

delta 11806
zcmZA72Y5)=|HttwB1S}Hkcg3xS`o3g3NeBhF=Le)sTDC2E5$Xcw%WT=n^sku)~+gw
zs;xz-@GDiVwn{0g_`g3nN1r_Z`#fK-?>YD0bIv{I+?&vDIpOis*B)-Bzvp6yqm+l^
z6vIeA$GJ*gzm#enXM07*@y+2lALByGUq(5O59Lmk9On$>zLg!PGghzSILSB*+u%R=
z7PhGBIK}Z4*2Ld1KZaLx9Dm1goysIWR5UgfPCN9X+z-8Ru&p1Bx^X6s!lkJD3REYs
zn6(1xzPcEW&20T345U033*ub#qkkveR(y=UoH&R9cn$;c7OLZ?sE+c~aGb&zWR1ci
zl$&BO_Cj4Z#ySmoQfCR4!7Z2z&tMe&I~PcFLoVhgCk7(3>ja}_qB(BCwy1$UK@G^K
zmYIPNEKIo^24OVj#ROzEo!+Q+Qc(A$S*M|!kBUXMA{~P$Z?)yas2k5B%kNx5Z40m3
zW~RzxZpwAAEH*;T#6Z*%OhFC!9qT&GLwP6az5}(He@)FXDl`LEP$T>mHT92B4dkz5
zHc=Sri5g%bj7L5B8yJM+QF~%B2ID$ZNBdCiA4aYHc~rYM>oETzB#)^G#elk|qiU!d
z+o49>)t399ZXARf$OP03%|q>-rKk=zq3+*>n&AVefqjFX_&w^uGhKV)9%_UyPz@ER
zXBsMjTFXkPfz-h`j6qhznTxaV2<pD}_04^KPy<Xs4PYv&{dpLI>8Js^dr0&I2W`dI
zsI@zbMe!=C<0q)4@p#pgeNjsgjA}RvHGo%918$9KHvu(}p7#7ORQnT=_FQK+iKb?`
zy<ih+O?R3LoKskg@)gv`AEVYbpn=&Vk*I+*LJcqh)j>a0JHxOnPQyt22(^SiU|YTa
zf0AfT8b+HZX^MK{j;OVK4b@;W>Pga21D<VNVe2=e)^rbQASY2Xav8M*zoKU5A!_Ph
zU>=twcSAE(1yLgl!p2wuo8wSa$GcD;j^n7QJ%bwPMbuJVM?J{Dr~&6_WFE)|bzL#k
z_oX!I{_^PRhRP)BxCUzEEv%hUPtX_jdZnNmnuYofEJ8K3)4CruGhd;e_&lopOzREg
zjdpHhJ1iN){PR_HQew;vn^9|=fy3|=*2HM0qYIA0WIT-}ut5{Y3B%X0I8H##)GE}2
zY(ouvFY0@89yL?9u?TuLW&X8!N;EZ_r8@Sc9EW<6_feZ|7iw+KqMrCBYR2whNqm9o
zpky<%wl&d{asz8))WDjf_CPmO`~6%Jt;q;`VifAeiJ0}?+WL96yaILo2K2%$s3qBs
z8qjXc+I*Oc@@3TZ*HN49ChGd%Y}tKCqFw&XS|HYJno!h;qc9R1VnrN+YH%fbVLEES
z8&OmH0d~cssLfrnIS+?xP){D%!aR8iWT{;zk|c~1v8aXz*b9;{H{~?cCY+3#kp-v$
zzl&LGjCm>Vwe?@w@&(j~={nZHyQqPdZplXsBe1ZBSdm1VqzN{`9=5y&wKsO7Zaj?|
z$hWADZ(?4&hZ@jR)Mm{eXYOl^TH~&$z0n`FMB^~)Q;fMaMd>7(>P@HyccTV$2(|gH
zpuS`etlq86`BK=L`nsqmoQ~yjKdR%~r~&_N>%F*GGg=w>nme`8Wzfz@d*T3U(;P#+
z9;Z-id>b|5yXb?@F+b*SW1hSSsy+hiVr^SaL3KFEmS<oA%1cpuWn&xWU*GnFRA{8v
zP`mRkdgEi%06g28*UTH^DObc4oPZtiK6b!ZPHJE)Q3Kj+%R5l*9745w9M#W-c;;Uf
z*X)INP;2!VwIn|6%$kK_DCKIn8atpGypIL(397?<?alSU=u0`$S|1BgZiRl>9W~G)
zE{O(^hHCI_)E=0Fn!2T^rASA0wA*?d^HIKn>gblO{~OgoZl=Q@i=f(%wB_2U_Tx}*
zo7;&*Q_&T*%ln`P(jWDSO~wG6gW7~^Y<U-|qZ6nBW}-IhW2+zQqWdFIpY#@}P1+Cj
z#aw|5%yssW=-Yh^wd-%88hVb=7}Uv}Pe6Y3J0np~oPm1X4q+_*gL;sd&Sn$Gp=PKZ
zY9@MMAsmW@acWkX^<PC2K*cB4BN#~eG8V?Ws44VHFdh4&W~vlw2Fjv3u7kQS2DKLw
zP-~uO%c-c>b293_t(c$wo&6;0;2TxoMN|VfZTY?}zd$wU)5ZKnq8Mro8>5yi7PV*E
zpa$3()oypxn)gSwKODQ`1au=vE|ZMMTzt4o;S_9#8?g*NwuW{ypXz4T{-`OPjzPE@
zU%?$%9j~B1GzIBRPu?1P;b_#rFLr1BHFa00&<Jm$K0tq<zR?e`EIvYQrqCYdd;?Si
zO;AtV9QDNUsCGKpaxZ(nAF7`u)Xa`V?Tsltn15}ixm4&$R-+pF6gAbmQEPP!wTUjH
z8u%U6;8WBTd%kAs3!(;80yV%gr~yS_Ev$}pFbTtPqf1hg<T&bv96il$&xLwT!ckM%
z6tz@o7>OG&70;mt7R$WKZq^~FO+69y0E=w>Mq9tz>YlVG{)d{02UgG5%?BqCH4~*#
z9aKjxO)P4uT4FH9qaI)&Y6gbb@<{7gTR$GP38y0Mxy}L--M9hO@D{9qTdkK+Pwd&7
z&o5R%O<^KNVLIx*Q&=9)Vsm_oZLmonGr)xyLV2q#AI;Kroa-b-IPnCFVnAQBIVxc|
z<+@l2d!o+IMXmY!s7<s3wI{yBm>m3`fLAH|C-Ng5|HKEl><#lTCUg3mf%P1~z4Y&V
zNRoj420G5?xDQKW+91bih^tU*cooaxUDVnJ4>t9Yn1^x$)IegbolqaJzPJq2Fc1Th
z%zfq1)tc5N(T%N9Pud+dRkN@-ZbYr|VOxLI`q<V73^CV5q6Xd))o~IA;S|&lua%g!
z1or&VA*{bflu3n_;4jo`=#y-2495zT>!A<!N4+g0Q3KzKdR@Q3GI$uZDevH?cn>vz
zjYG}m-j5o{DbxV34Q2lIWPekU4}FK3sSUxLl%r4`SH)Mbp*0cnQl5!fua_-vv~EZ3
zl|86|T|jmC47F5&!+E2yxJ#lDHpcwe9gE=rRL4_MuhT+QhbyrlZa_cWfx7P)>H)q(
z&A@fkjNU?BuiwGdt{-X%qEHX+wje1$(g!u-;i!h@pa!<gx*h!}AH(u^8B3sNifJeu
zHPHI#g-uWci$e{h3##K0sF|IE{(ArClW1zzqo!uB^)UKUK8bpwtElU4*z^CO8qS$&
z23j0-z6J(hD^z>0V@Dil-H&=30!He3)_*HWAQgv@5jmI88}Fc|?h$I_c}AHA!>y61
zC8>dW(rDBkX@wf_aMS~gMh#>dYDVW_A>51sdjI#6sG)PHss91BIex}md{BHwn+^iT
zm?sNEEk$)}GgO0JQ1>TeVH}I4a31ObGEg&i3N?`1nDy^}&R8=5Z`6rGs5P#LRWJcH
zGc%Bnm$M4hk!PBjIbYOfeZ`imT4PZI>49oD1+_G@tm$dYzdkS-RH%cqs2gtD@>A3l
z7I@RlKnc{+R6q@&78b=Atb;wV8!kh&_ZMnry~Y^}qBdy=YQ{>9WB#>PwW-h=HbA`%
zai}Nih8{Qob>m>v?oGj3I2yG_K0@7h0M+qnR0ltz2JjebqQ`jCP94-+(#R!IN6k@B
z)EPCP-l#8If2@m1*a0_T96m)2D0YJRy`U}5rksW`sJ~cF#g@1W&!E1fGbWnfs6IoL
z-K!)TdEQB8mj<Jrs3hvGsEXQ*u~;03U@*=?E!BGLg?mv?T6D6hFO6F3`l!tsZ|#F&
zlv9navzSCvu><wQpIZ;2Iyj1&(oE|;)b*ZIOb6bmnFvKaNLg!5)Ppp|oY)!l8g{ew
zeKAn)e=3Qle1`QM%t?7MYDt!(Hr;yEb=y%L?Lh6BudL@#oAnw-;9ZQukhjbpYJnPf
zE7XH_z+n1!x{xH{aMT)R;sPAZ0&2w1Q8SSHZL`}$uo~r>m=gz~29%6ivhk>aEU@)!
zQA_YK>VXcS_S`9Sb>k1V;tuLPeS+HEe$&j8w?I$IolqTg!y-5o+u#gazJxK9?_&<E
zG2JXtE!0xPq5A8ATH3+Wng8Y_lc~@Xeq+r<ZMJ);8+>P&Cn|xtDMz6;TTRr`G{i`3
zg%xouM&Tx`gcndBGOwBDZ$7oL8RbPYng6OJSE$ek3(PVD3B`t#t72YE!OA!uqj4MN
z!9T2zFod$!Pcu~%HRWNb`>R^(qh_!fs=w|oNjymsdgJG)C;S?9;aSwo+`_D-LH*eE
zn`1htj9Tj$RLAYn3lp$B_C&rt&U9Rbx#sfg7_P;3=$3iMY=$wYFV@?r4p*TD^bzVw
z_S*7E)RKH}y^W!iA7L2`nrH5BfU0kYCviAx#-it&J<;6gIz33V8HS-6o`!z7#JU+Z
zusybX26f$!sF}Kl+SN}`9e6G<zv=j3Y044khw-Qf>VtY~k}+8C{|FKdU>0i1*P;*Z
z%({U08~rI~q6gkXb^HLew*R80+-srj7}a3}>PuN4wKqCpK^%tK+>@{n{X6L-#qcxK
z+MYvA<vnbO!Hdl6))h6d6x57NLUpth)$kV7>$eB>K+muW1}-*xq!~t2?u-p_3A$?V
zB8jH%C(Mt3pc;6J8j$}I^EaU?sB$MPim9l9&$IO(T2G(`bO!_RUsU^kOU+D%p!%t}
zl=)Xfb*U(XozWMQQ1#=mA}&MSaKw5Z)$n!n$A_qy$g|9>aR{oNG8l$6QSBt4mT)R+
z38yb({*}z5La)y<)Q#_=*7ifxX4{El@Ca7L=;h{@$PuX5%zFht8L<YI!*$jZ7)JRa
zR=~n5&CJH2He*+pL^mX2EY8JNcmbPWI4^Ay4nU3kJJfE!gc{%tR71a`cJ&jij?XX@
ztG;WlYmd6W2WlyLp{{oakmw1MP&4r+s^KZ9hUcKBcDXHofJG_qMD2z1sNH`bwdPMy
zOO<c6S(+f!9*aN?yf*55W8`|*i6>FVy-_0^h#FxM*1(Zi8$Uqp=9^d-3#Xgw+hG{x
zju?(3Q8T(6>)}Dv+w>eKVCnbFQm@a_<+ZUD+pHO=so7=A`%nY=5;f4{s3$&$+B4r<
zGf}@E+(6y`3+npcZTTT)eW*~I*K-Zm(Z5rKL>CrEHCS3FFap(J6sp7Os2l6q^YN(b
zJEC@XSB%1GSQ&R<9sC&^V9B+n{&iIQ^U>9b#U$<VTTH;R>&%zSMZK2GFbub0Nj#0=
zc+XmBz1b^uP@mkUSP2JXD6T~9vAw80b=;OOtY`gmP~k}|C7G#$J=)q_Pke&>j;&9!
z4tpu*CfIBF5<7j#&l0W3x8Q4pz7a2v+LT`&pXbp0b9_Q<=Y%&AMBV~>>jcMT^3E8H
z8*n^!C3LWZolK%8<p_KeI}+E(hv3I}oA{P|4|;g8+~lQjANFziqaVSi-U+7ib<`0?
zJ`r{PA7UucK_@sqB=3Xyi6TTH%Gr-sDf@E2j_Ty|a4de4?Ydvcf1y6>_di|ukf>-c
z_y`Nx2DVY3!`ACH(s9a`P09R1F_pT$RPg#cN5~uEF1$*3(^fIOLEWpwkHk*|hnw|J
zWRJ<Jaly-DhRwHHr{i8uen;pP8bG<Zz1YhRRK;ZKFW?}1Up#qXqB!N;*{)keS#O5=
z|L>S=vk?58sK-UEu{X9Nbj%`}*t~=qB;svZ=LeH}5rM=&q8(9ECpelCPl?;qttJX{
zZ;ICUO)76;8_Y@NB`itVkI;LsLtm~9l>Lc)<c(0@c^#+8_1?da|KKfRKA}Ue?|q^u
z@i%db(4l`<cuu%=`Qw49`|r;))UBX&4znNgDE~pl2lxW(5-o{I#C7VX5x<k`*kQ=}
zf5$pe|2Cnc4E}}s?)=9$rr>09vKcXk@=x{#eHm{OV{{`?le`P@9r@1-=a&iSU4raK
z;^i@#L_aCMv=y^CSDt82+$3}?CiE#fNz5SDQQz90>t>}o>pxvjTbQeCxce)m#>B&H
zXY;aJ^{AVet*$IN-#2GRwz_x8%Mn$nPbQ8LCAqf%b=S!^WxMtb%HxSfgpTjcIkQpw
zQ{h3yD6Bw)&`5dwnz|C0fd`38gpQGfzQjE!=i}M|<Yx&TZyTH!_S$i{g1B$X`ZE7Y
z{6JLIhcb``ic)xw8`lzx$x|_mh$O#5<l!0}q2%+4SR#RVpSq2xV=z&Uh#~%^?g<e}
zu451RAiRdJ5XH#9z&~C7c!$Cg;#2b7_&<Dv2T=19gRiNc*han!vmebU)S*5N^Wt&h
z2lC(W<uQf)DuvA$ZY$H#ZKDbzz&@eQ%_Pn#u}5Lf4<Rp2_>k|%RhUM^k+(!0If<`{
zt;AvC2K7F)n+H9y1$8?7h~lO{*O|=8Alvy<^4VFJF#Y6*iQ1HlaXyY*M;;;{`7&&)
z3XZ!5=Nazj-0wtxB7pEDj#EFKNF@IZ&l9JKtlx?+QkhOf5&jFSL<Hy`ubodQeT&_R
zTy$T6SV^wq8R!20G1OM9;amuj(_T{$uMmlx|B(3D*8hP=i6hiiv2|*qn$~<N$ylPe
zYB(wqzQpTXSdf8KCSOeyB~PWU2f2=*Yz_HwZl|esN>l$4`7C?B7P*f-mqgt{;uz7B
zy4*Py##9J#FHo#SbfW4J?j+6=(e}3P<dcY(#~PBah`*_8Pdp~(5_^d))JI?iBA9$7
zGCF4g>iCU_B)Ssysk^8-*i7N&F^9^p?8R@rti%Sk?qyXa%K3>`sQ8}fMcxe$;S!=D
zp<|KZzdtKeKb*+Hs7hsB!+ZCsJ-rSyh~1oMN*o|xPP|2a5WmFy+}IeeP|ii95UYrv
zi3Fl2=X3-ZoX)m9mvX44!X6#*xpKYtqwGbORlzaUkoD(Cd+w;M`^=VA{DK&ft-LH-
z{sHHD5pPg;m&i+ApD0V*Bjyk%2)70&-yzl#I__EDv!0=@262dZK;57C^4L!Dgy=wh
z7vdz*&Ys+e{}Q9Aize0+%ZYK+712!O3)7Ktv0^cwT&Y6`Cnm3JT(6*a-vNnz2PgIm
z8=IJ#(IC#tBV&B)n`L|(4Ne`In3R+_BCMmX%=js_N1*@Ez5~LN2lgG18rDB?*oZ^>
S-bl@eo^jYCqy6lQMg9*TrK+I-

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index cc23fe5d..e735ce6c 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -18,15 +18,15 @@
 #: konova/filters/mixins.py:277 konova/filters/mixins.py:323
 #: konova/filters/mixins.py:361 konova/filters/mixins.py:362
 #: konova/filters/mixins.py:393 konova/filters/mixins.py:394
-#: konova/forms.py:179 konova/forms.py:281 konova/forms.py:382
-#: konova/forms.py:426 konova/forms.py:436 konova/forms.py:449
-#: konova/forms.py:461 konova/forms.py:479 user/forms.py:42
+#: konova/forms.py:179 konova/forms.py:281 konova/forms.py:395
+#: konova/forms.py:439 konova/forms.py:449 konova/forms.py:462
+#: konova/forms.py:474 konova/forms.py:492 user/forms.py:42
 #, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-05-11 13:41+0200\n"
+"POT-Creation-Date: 2022-05-30 09:16+0200\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -138,9 +138,9 @@ msgstr "Zuständigkeitsbereich"
 #: analysis/templates/analysis/reports/includes/intervention/amount.html:17
 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:8
 #: analysis/templates/analysis/reports/includes/intervention/laws.html:17
-#: compensation/tables.py:40
+#: compensation/tables.py:41
 #: compensation/templates/compensation/detail/compensation/view.html:64
-#: intervention/tables.py:39
+#: intervention/tables.py:40
 #: intervention/templates/intervention/detail/view.html:68
 #: user/models/user_action.py:20
 msgid "Checked"
@@ -154,12 +154,12 @@ msgstr "Geprüft"
 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:9
 #: analysis/templates/analysis/reports/includes/intervention/laws.html:20
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:18
-#: compensation/tables.py:46 compensation/tables.py:220
+#: compensation/tables.py:47 compensation/tables.py:230
 #: compensation/templates/compensation/detail/compensation/view.html:78
 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:31
 #: compensation/templates/compensation/detail/eco_account/view.html:45
 #: ema/tables.py:44 ema/templates/ema/detail/view.html:35
-#: intervention/tables.py:45
+#: intervention/tables.py:46
 #: intervention/templates/intervention/detail/view.html:82
 #: user/models/user_action.py:21
 msgid "Recorded"
@@ -198,7 +198,7 @@ msgid "Other registration office"
 msgstr "Andere Zulassungsbehörden"
 
 #: analysis/templates/analysis/reports/includes/compensation/card_compensation.html:11
-#: compensation/tables.py:67
+#: compensation/tables.py:68
 #: intervention/templates/intervention/detail/includes/compensations.html:8
 #: intervention/templates/intervention/report/report.html:45
 msgid "Compensations"
@@ -227,7 +227,7 @@ msgid "Surface"
 msgstr "Fläche"
 
 #: analysis/templates/analysis/reports/includes/intervention/card_intervention.html:10
-#: intervention/tables.py:66
+#: intervention/tables.py:67
 msgid "Interventions"
 msgstr "Eingriffe"
 
@@ -285,8 +285,8 @@ msgid "Type"
 msgstr "Typ"
 
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:24
-#: compensation/tables.py:89 intervention/forms/modalForms.py:375
-#: intervention/forms/modalForms.py:382 intervention/tables.py:88
+#: compensation/tables.py:90 intervention/forms/modalForms.py:375
+#: intervention/forms/modalForms.py:382 intervention/tables.py:89
 #: intervention/templates/intervention/detail/view.html:19
 #: konova/templates/konova/includes/quickstart/interventions.html:4
 #: templates/navbars/navbar.html:22
@@ -294,7 +294,7 @@ msgid "Intervention"
 msgstr "Eingriff"
 
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
-#: compensation/tables.py:264
+#: compensation/tables.py:274
 #: compensation/templates/compensation/detail/eco_account/view.html:20
 #: intervention/forms/modalForms.py:348 intervention/forms/modalForms.py:355
 #: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
@@ -314,9 +314,9 @@ msgstr "Vor"
 msgid "Show only unrecorded"
 msgstr "Nur unverzeichnete anzeigen"
 
-#: compensation/forms/forms.py:32 compensation/tables.py:25
-#: compensation/tables.py:195 ema/tables.py:29 intervention/forms/forms.py:28
-#: intervention/tables.py:24
+#: compensation/forms/forms.py:32 compensation/tables.py:26
+#: compensation/tables.py:205 ema/tables.py:29 intervention/forms/forms.py:28
+#: intervention/tables.py:25
 #: intervention/templates/intervention/detail/includes/compensations.html:30
 msgid "Identifier"
 msgstr "Kennung"
@@ -326,8 +326,8 @@ msgstr "Kennung"
 msgid "Generated automatically"
 msgstr "Automatisch generiert"
 
-#: compensation/forms/forms.py:44 compensation/tables.py:30
-#: compensation/tables.py:200
+#: compensation/forms/forms.py:44 compensation/tables.py:31
+#: compensation/tables.py:210
 #: compensation/templates/compensation/detail/compensation/includes/documents.html:28
 #: compensation/templates/compensation/detail/compensation/view.html:32
 #: compensation/templates/compensation/detail/eco_account/includes/documents.html:28
@@ -337,12 +337,12 @@ msgstr "Automatisch generiert"
 #: ema/tables.py:34 ema/templates/ema/detail/includes/documents.html:28
 #: ema/templates/ema/detail/view.html:31
 #: ema/templates/ema/report/report.html:12 intervention/forms/forms.py:40
-#: intervention/tables.py:29
+#: intervention/tables.py:30
 #: intervention/templates/intervention/detail/includes/compensations.html:33
 #: intervention/templates/intervention/detail/includes/documents.html:28
 #: intervention/templates/intervention/detail/view.html:31
 #: intervention/templates/intervention/report/report.html:12
-#: konova/forms.py:425
+#: konova/forms.py:438
 msgid "Title"
 msgstr "Bezeichnung"
 
@@ -369,7 +369,7 @@ msgstr "Kompensation XY; Flur ABC"
 #: intervention/templates/intervention/detail/includes/documents.html:34
 #: intervention/templates/intervention/detail/includes/payments.html:34
 #: intervention/templates/intervention/detail/includes/revocation.html:38
-#: konova/forms.py:460 konova/templates/konova/includes/comment_card.html:16
+#: konova/forms.py:473 konova/templates/konova/includes/comment_card.html:16
 msgid "Comment"
 msgstr "Kommentar"
 
@@ -493,7 +493,7 @@ msgid "Due on which date"
 msgstr "Zahlung wird an diesem Datum erwartet"
 
 #: compensation/forms/modalForms.py:65 compensation/forms/modalForms.py:363
-#: intervention/forms/modalForms.py:177 konova/forms.py:462
+#: intervention/forms/modalForms.py:177 konova/forms.py:475
 msgid "Additional comment, maximum {} letters"
 msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 
@@ -675,70 +675,62 @@ msgstr ""
 "Es wurde bereits mehr Fläche abgebucht, als Sie nun als abbuchbar einstellen "
 "wollen. Kontaktieren Sie die für die Abbuchungen verantwortlichen Nutzer!"
 
-#: compensation/tables.py:35 compensation/tables.py:205 ema/tables.py:39
-#: intervention/tables.py:34 konova/filters/mixins.py:98
+#: compensation/tables.py:36 compensation/tables.py:215 ema/tables.py:39
+#: intervention/tables.py:35 konova/filters/mixins.py:98
 msgid "Parcel gmrkng"
 msgstr "Gemarkung"
 
-#: compensation/tables.py:52 compensation/tables.py:226 ema/tables.py:50
-#: intervention/tables.py:51
+#: compensation/tables.py:53 compensation/tables.py:236 ema/tables.py:50
+#: intervention/tables.py:52
 msgid "Editable"
 msgstr "Freigegeben"
 
-#: compensation/tables.py:58 compensation/tables.py:232 ema/tables.py:56
-#: intervention/tables.py:57
+#: compensation/tables.py:59 compensation/tables.py:242 ema/tables.py:56
+#: intervention/tables.py:58
 msgid "Last edit"
 msgstr "Zuletzt bearbeitet"
 
-#: compensation/tables.py:89 compensation/tables.py:264 ema/tables.py:89
-#: intervention/tables.py:88
+#: compensation/tables.py:90 compensation/tables.py:274 ema/tables.py:89
+#: intervention/tables.py:89
 msgid "Open {}"
 msgstr "Öffne {}"
 
-#: compensation/tables.py:114 intervention/tables.py:111
-msgid "Not checked yet"
-msgstr "Noch nicht geprüft"
-
-#: compensation/tables.py:119 intervention/tables.py:116
-msgid "Checked on {} by {}"
-msgstr "Am {} von {} geprüft worden"
-
-#: compensation/tables.py:160
+#: compensation/tables.py:170
 #: compensation/templates/compensation/detail/compensation/view.html:81
 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:58
 #: compensation/templates/compensation/detail/eco_account/view.html:48
 #: ema/tables.py:131 ema/templates/ema/detail/view.html:38
-#: intervention/tables.py:157
+#: intervention/tables.py:167
 #: intervention/templates/intervention/detail/view.html:85
 msgid "Not recorded yet"
 msgstr "Noch nicht verzeichnet"
 
-#: compensation/tables.py:165 compensation/tables.py:324 ema/tables.py:136
-#: intervention/tables.py:162
+#: compensation/tables.py:175 compensation/tables.py:334 ema/tables.py:136
+#: intervention/tables.py:172
 msgid "Recorded on {} by {}"
 msgstr "Am {} von {} verzeichnet worden"
 
-#: compensation/tables.py:187 compensation/tables.py:346 ema/tables.py:157
-#: intervention/tables.py:183
+#: compensation/tables.py:197 compensation/tables.py:356 ema/tables.py:157
+#: intervention/tables.py:193
 msgid "Full access granted"
 msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
 
-#: compensation/tables.py:187 compensation/tables.py:346 ema/tables.py:157
-#: intervention/tables.py:183
+#: compensation/tables.py:197 compensation/tables.py:356 ema/tables.py:157
+#: intervention/tables.py:193
 msgid "Access not granted"
 msgstr "Nicht freigegeben - Datensatz nur lesbar"
 
-#: compensation/tables.py:210
+#: compensation/tables.py:220
 #: compensation/templates/compensation/detail/eco_account/view.html:36
 #: konova/templates/konova/widgets/progressbar.html:3
 msgid "Available"
 msgstr "Verfügbar"
 
-#: compensation/tables.py:241
+#: compensation/tables.py:251
 msgid "Eco Accounts"
 msgstr "Ökokonten"
 
-#: compensation/tables.py:319
+#: compensation/tables.py:329
 msgid "Not recorded yet. Can not be used for deductions, yet."
 msgstr ""
 "Noch nicht verzeichnet. Kann noch nicht für Abbuchungen genutzt werden."
@@ -871,7 +863,7 @@ msgstr "Dokumente"
 #: compensation/templates/compensation/detail/eco_account/includes/documents.html:14
 #: ema/templates/ema/detail/includes/documents.html:14
 #: intervention/templates/intervention/detail/includes/documents.html:14
-#: konova/forms.py:478
+#: konova/forms.py:491
 msgid "Add new document"
 msgstr "Neues Dokument hinzufügen"
 
@@ -879,7 +871,7 @@ msgstr "Neues Dokument hinzufügen"
 #: compensation/templates/compensation/detail/eco_account/includes/documents.html:31
 #: ema/templates/ema/detail/includes/documents.html:31
 #: intervention/templates/intervention/detail/includes/documents.html:31
-#: konova/forms.py:435
+#: konova/forms.py:448
 msgid "Created on"
 msgstr "Erstellt"
 
@@ -887,7 +879,7 @@ msgstr "Erstellt"
 #: compensation/templates/compensation/detail/eco_account/includes/documents.html:61
 #: ema/templates/ema/detail/includes/documents.html:61
 #: intervention/templates/intervention/detail/includes/documents.html:65
-#: konova/forms.py:540
+#: konova/forms.py:553
 msgid "Edit document"
 msgstr "Dokument bearbeiten"
 
@@ -1150,17 +1142,17 @@ msgid "Compensation {} edited"
 msgstr "Kompensation {} bearbeitet"
 
 #: compensation/views/compensation.py:182 compensation/views/eco_account.py:173
-#: ema/views.py:240 intervention/views.py:334
+#: ema/views.py:240 intervention/views.py:332
 msgid "Edit {}"
 msgstr "Bearbeite {}"
 
 #: compensation/views/compensation.py:261 compensation/views/eco_account.py:359
-#: ema/views.py:194 intervention/views.py:538
+#: ema/views.py:194 intervention/views.py:536
 msgid "Log"
 msgstr "Log"
 
 #: compensation/views/compensation.py:605 compensation/views/eco_account.py:727
-#: ema/views.py:558 intervention/views.py:684
+#: ema/views.py:558 intervention/views.py:682
 msgid "Report {}"
 msgstr "Bericht {}"
 
@@ -1181,32 +1173,32 @@ msgid "Eco-account removed"
 msgstr "Ökokonto entfernt"
 
 #: compensation/views/eco_account.py:380 ema/views.py:282
-#: intervention/views.py:637
+#: intervention/views.py:635
 msgid "{} unrecorded"
 msgstr "{} entzeichnet"
 
 #: compensation/views/eco_account.py:380 ema/views.py:282
-#: intervention/views.py:637
+#: intervention/views.py:635
 msgid "{} recorded"
 msgstr "{} verzeichnet"
 
 #: compensation/views/eco_account.py:804 ema/views.py:628
-#: intervention/views.py:435
+#: intervention/views.py:433
 msgid "{} has already been shared with you"
 msgstr "{} wurde bereits für Sie freigegeben"
 
 #: compensation/views/eco_account.py:809 ema/views.py:633
-#: intervention/views.py:440
+#: intervention/views.py:438
 msgid "{} has been shared with you"
 msgstr "{} ist nun für Sie freigegeben"
 
 #: compensation/views/eco_account.py:816 ema/views.py:640
-#: intervention/views.py:447
+#: intervention/views.py:445
 msgid "Share link invalid"
 msgstr "Freigabelink ungültig"
 
 #: compensation/views/eco_account.py:839 ema/views.py:663
-#: intervention/views.py:470
+#: intervention/views.py:468
 msgid "Share settings updated"
 msgstr "Freigabe Einstellungen aktualisiert"
 
@@ -1312,7 +1304,7 @@ msgstr "Datum Zulassung bzw. Satzungsbeschluss"
 msgid "Binding on"
 msgstr "Datum Bestandskraft bzw. Rechtskraft"
 
-#: intervention/forms/forms.py:211 intervention/views.py:97
+#: intervention/forms/forms.py:211 intervention/views.py:95
 msgid "New intervention"
 msgstr "Neuer Eingriff"
 
@@ -1392,7 +1384,7 @@ msgstr "Kompensationen und Zahlungen geprüft"
 msgid "Run check"
 msgstr "Prüfung vornehmen"
 
-#: intervention/forms/modalForms.py:264 konova/forms.py:581
+#: intervention/forms/modalForms.py:264 konova/forms.py:594
 msgid ""
 "I, {} {}, confirm that all necessary control steps have been performed by "
 "myself."
@@ -1532,27 +1524,27 @@ msgstr ""
 "Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, "
 "Abbuchung)"
 
-#: intervention/views.py:54
+#: intervention/views.py:52
 msgid "Interventions - Overview"
 msgstr "Eingriffe - Übersicht"
 
-#: intervention/views.py:87
+#: intervention/views.py:85
 msgid "Intervention {} added"
 msgstr "Eingriff {} hinzugefügt"
 
-#: intervention/views.py:322
+#: intervention/views.py:320
 msgid "Intervention {} edited"
 msgstr "Eingriff {} bearbeitet"
 
-#: intervention/views.py:358
+#: intervention/views.py:356
 msgid "{} removed"
 msgstr "{} entfernt"
 
-#: intervention/views.py:491
+#: intervention/views.py:489
 msgid "Check performed"
 msgstr "Prüfung durchgeführt"
 
-#: intervention/views.py:642
+#: intervention/views.py:640
 msgid "There are errors on this intervention:"
 msgstr "Es liegen Fehler in diesem Eingriff vor:"
 
@@ -1645,11 +1637,11 @@ msgstr "Speichern"
 msgid "Not editable"
 msgstr "Nicht editierbar"
 
-#: konova/forms.py:178 konova/forms.py:381
+#: konova/forms.py:178 konova/forms.py:394
 msgid "Confirm"
 msgstr "Bestätige"
 
-#: konova/forms.py:190 konova/forms.py:390
+#: konova/forms.py:190 konova/forms.py:403
 msgid "Remove"
 msgstr "Löschen"
 
@@ -1662,48 +1654,49 @@ msgstr "Sie sind dabei {} {} zu löschen"
 msgid "Geometry"
 msgstr "Geometrie"
 
-#: konova/forms.py:325
+#: konova/forms.py:331
 msgid "Only surfaces allowed. Points or lines must be buffered."
-msgstr "Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
+msgstr ""
+"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
 
-#: konova/forms.py:391
+#: konova/forms.py:404
 msgid "Are you sure?"
 msgstr "Sind Sie sicher?"
 
-#: konova/forms.py:437
+#: konova/forms.py:450
 msgid "When has this file been created? Important for photos."
 msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
 
-#: konova/forms.py:448
+#: konova/forms.py:461
 #: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231
 msgid "File"
 msgstr "Datei"
 
-#: konova/forms.py:450
+#: konova/forms.py:463
 msgid "Allowed formats: pdf, jpg, png. Max size 15 MB."
 msgstr "Formate: pdf, jpg, png. Maximal 15 MB."
 
-#: konova/forms.py:515
+#: konova/forms.py:528
 msgid "Added document"
 msgstr "Dokument hinzugefügt"
 
-#: konova/forms.py:572
+#: konova/forms.py:585
 msgid "Confirm record"
 msgstr "Verzeichnen bestätigen"
 
-#: konova/forms.py:580
+#: konova/forms.py:593
 msgid "Record data"
 msgstr "Daten verzeichnen"
 
-#: konova/forms.py:587
+#: konova/forms.py:600
 msgid "Confirm unrecord"
 msgstr "Entzeichnen bestätigen"
 
-#: konova/forms.py:588
+#: konova/forms.py:601
 msgid "Unrecord data"
 msgstr "Daten entzeichnen"
 
-#: konova/forms.py:589
+#: konova/forms.py:602
 msgid "I, {} {}, confirm that this data must be unrecorded."
 msgstr ""
 "Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
@@ -2059,6 +2052,18 @@ msgstr "Geometriekonflikt mit folgenden Einträgen erkannt: {}"
 msgid "This intervention has {} revocations"
 msgstr "Dem Eingriff liegen {} Widersprüche vor"
 
+#: konova/utils/message_templates.py:86
+msgid "Checked on {} by {}"
+msgstr "Am {} von {} geprüft worden"
+
+#: konova/utils/message_templates.py:87
+msgid "Data has changed since last check on {} by {}"
+msgstr "Daten wurden nach der letzten Prüfung geändert. Letzte Prüfung am {} durch {}"
+
+#: konova/utils/message_templates.py:88
+msgid "Current data not checked yet"
+msgstr "Momentane Daten noch nicht geprüft"
+
 #: konova/utils/messenger.py:70
 msgid "{} checked"
 msgstr "{} geprüft"
@@ -2489,8 +2494,9 @@ msgid ""
 msgstr ""
 "\n"
 "            Diese Daten sind noch nicht veröffentlicht und/oder haben das "
-"Bestands-/Rechtskraftdatum noch nicht erreicht. Sie können daher aktuell nicht "
-"eingesehen werden. Schauen Sie zu einem späteren Zeitpunkt wieder vorbei. \n"
+"Bestands-/Rechtskraftdatum noch nicht erreicht. Sie können daher aktuell "
+"nicht eingesehen werden. Schauen Sie zu einem späteren Zeitpunkt wieder "
+"vorbei. \n"
 "            "
 
 #: templates/table/gmrkng_col.html:6
diff --git a/user/models/user_action.py b/user/models/user_action.py
index d797bb2c..198ff2fd 100644
--- a/user/models/user_action.py
+++ b/user/models/user_action.py
@@ -8,6 +8,7 @@ Created on: 15.11.21
 import uuid
 
 from django.db import models
+from django.utils.timezone import localtime
 from django.utils.translation import gettext_lazy as _
 
 from konova.sub_settings.django_settings import DEFAULT_DATE_TIME_FORMAT
@@ -122,3 +123,13 @@ class UserActionLogEntry(models.Model):
             comment=comment,
         )
         return action
+
+    def get_timestamp_str_formatted(self):
+        """ Getter for formatted timestamp string of the entry
+
+        Returns:
+            val (str): The formatted timestamp as string
+        """
+        val = self.timestamp
+        val = localtime(val)
+        return val.strftime(DEFAULT_DATE_TIME_FORMAT)