From e7454e558d163732a98e529fb5010e195225bf14 Mon Sep 17 00:00:00 2001
From: mpeltriaux <Michel.Peltriaux@sgdnord.rlp.de>
Date: Thu, 10 Feb 2022 14:01:59 +0100
Subject: [PATCH 01/26] # 110 Biotope codelists

* adds codelist 654 to settings
* adds codelist to update_codelist command
---
 codelist/management/commands/update_codelist.py | 3 ++-
 codelist/settings.py                            | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/codelist/management/commands/update_codelist.py b/codelist/management/commands/update_codelist.py
index 85c90324..3fd4c6c3 100644
--- a/codelist/management/commands/update_codelist.py
+++ b/codelist/management/commands/update_codelist.py
@@ -14,7 +14,7 @@ from codelist.settings import CODELIST_INTERVENTION_HANDLER_ID, CODELIST_CONSERV
     CODELIST_REGISTRATION_OFFICE_ID, CODELIST_BIOTOPES_ID, CODELIST_LAW_ID, CODELIST_COMPENSATION_HANDLER_ID, \
     CODELIST_COMPENSATION_ACTION_ID, CODELIST_COMPENSATION_ACTION_CLASS_ID, CODELIST_COMPENSATION_ADDITIONAL_TYPE_ID, \
     CODELIST_BASE_URL, CODELIST_PROCESS_TYPE_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
-    CODELIST_COMPENSATION_ACTION_DETAIL_ID
+    CODELIST_COMPENSATION_ACTION_DETAIL_ID, CODELIST_AFTER_STATE_BIOTOPES__ID
 from konova.management.commands.setup import BaseKonovaCommand
 from konova.settings import PROXIES
 
@@ -34,6 +34,7 @@ class Command(BaseKonovaCommand):
                 CODELIST_CONSERVATION_OFFICE_ID,
                 CODELIST_REGISTRATION_OFFICE_ID,
                 CODELIST_BIOTOPES_ID,
+                CODELIST_AFTER_STATE_BIOTOPES__ID,
                 CODELIST_BIOTOPES_EXTRA_CODES_ID,
                 CODELIST_LAW_ID,
                 CODELIST_COMPENSATION_HANDLER_ID,
diff --git a/codelist/settings.py b/codelist/settings.py
index 598a3a66..53cef730 100644
--- a/codelist/settings.py
+++ b/codelist/settings.py
@@ -13,7 +13,8 @@ CODELIST_BASE_URL = "https://codelisten.naturschutz.rlp.de/repository/referenzli
 CODELIST_INTERVENTION_HANDLER_ID = 903  # CLMassnahmeträger
 CODELIST_CONSERVATION_OFFICE_ID = 907  # CLNaturschutzbehörden
 CODELIST_REGISTRATION_OFFICE_ID = 1053  # CLZulassungsbehörden
-CODELIST_BIOTOPES_ID = 974  # CL_EIV_Biotoptypen
+CODELIST_BIOTOPES_ID = 654  # CL_Biotoptypen
+CODELIST_AFTER_STATE_BIOTOPES__ID = 974  # CL-KSP_ZielBiotoptypen
 CODELIST_BIOTOPES_EXTRA_CODES_ID = 975  # CLZusatzbezeichnung
 CODELIST_LAW_ID = 1048  # CLVerfahrensrecht
 CODELIST_PROCESS_TYPE_ID = 44382  # CLVerfahrenstyp

From 2b66189590e32a9faeb113446c4883d4b64333ed Mon Sep 17 00:00:00 2001
From: mpeltriaux <Michel.Peltriaux@sgdnord.rlp.de>
Date: Thu, 10 Feb 2022 14:45:00 +0100
Subject: [PATCH 02/26] #112 WIP: Restructure CompensationAction

* changes action_type from ForeignKey into M2M
* adds migration
* changes form widget
* WIP: changes rendering on detail view of compensation
* TEST NOT CHECKED YET!
---
 compensation/forms/modalForms.py              |  8 ++--
 compensation/managers.py                      | 11 ------
 .../migrations/0004_auto_20220210_1402.py     | 39 +++++++++++++++++++
 compensation/models/action.py                 | 10 +----
 compensation/models/compensation.py           |  2 +-
 .../detail/compensation/includes/actions.html |  6 ++-
 .../detail/eco_account/includes/actions.html  |  6 ++-
 .../ema/detail/includes/actions.html          |  6 ++-
 8 files changed, 61 insertions(+), 27 deletions(-)
 create mode 100644 compensation/migrations/0004_auto_20220210_1402.py

diff --git a/compensation/forms/modalForms.py b/compensation/forms/modalForms.py
index 804ebad4..90b0b64c 100644
--- a/compensation/forms/modalForms.py
+++ b/compensation/forms/modalForms.py
@@ -405,7 +405,7 @@ class NewActionModalForm(BaseModalForm):
 
     """
     from compensation.models import UnitChoices
-    action_type = forms.ModelChoiceField(
+    action_type = forms.ModelMultipleChoiceField(
         label=_("Action Type"),
         label_suffix="",
         required=True,
@@ -415,7 +415,7 @@ class NewActionModalForm(BaseModalForm):
             is_leaf=True,
             code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
         ),
-        widget=autocomplete.ModelSelect2(
+        widget=autocomplete.ModelSelect2Multiple(
             url="codes-compensation-action-autocomplete",
             attrs={
                 "data-placeholder": _("Action"),
@@ -496,7 +496,7 @@ class EditCompensationActionModalForm(NewActionModalForm):
         self.action = kwargs.pop("action", None)
         super().__init__(*args, **kwargs)
         form_data = {
-            "action_type": self.action.action_type,
+            "action_type": self.action.action_type.all(),
             "action_type_details": self.action.action_type_details.all(),
             "amount": self.action.amount,
             "unit": self.action.unit,
@@ -506,7 +506,7 @@ class EditCompensationActionModalForm(NewActionModalForm):
 
     def save(self):
         action = self.action
-        action.action_type = self.cleaned_data.get("action_type", None)
+        action.action_type.set(self.cleaned_data.get("action_type", []))
         action.action_type_details.set(self.cleaned_data.get("action_type_details", []))
         action.amount = self.cleaned_data.get("amount", None)
         action.unit = self.cleaned_data.get("unit", None)
diff --git a/compensation/managers.py b/compensation/managers.py
index c97cd518..b496eb1e 100644
--- a/compensation/managers.py
+++ b/compensation/managers.py
@@ -8,17 +8,6 @@ Created on: 14.10.21
 from django.db import models
 
 
-class CompensationActionManager(models.Manager):
-    """ Holds default db fetch setting for this model type
-
-    """
-    def get_queryset(self):
-        return super().get_queryset().select_related(
-            "action_type",
-            "action_type__parent"
-        )
-
-
 class CompensationStateManager(models.Manager):
     """ Holds default db fetch setting for this model type
 
diff --git a/compensation/migrations/0004_auto_20220210_1402.py b/compensation/migrations/0004_auto_20220210_1402.py
new file mode 100644
index 00000000..44d43cbe
--- /dev/null
+++ b/compensation/migrations/0004_auto_20220210_1402.py
@@ -0,0 +1,39 @@
+# Generated by Django 3.1.3 on 2022-02-10 13:02
+
+from django.db import migrations, models
+
+
+def migrate_actions(apps, schema_editor):
+    CompensationAction = apps.get_model('compensation', 'CompensationAction')
+    actions = CompensationAction.objects.all()
+
+    for action in actions:
+        action_type = action.action_type or []
+        action.action_type_tmp.set(action_type)
+        action.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('codelist', '0001_initial'),
+        ('compensation', '0003_auto_20220202_0846'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='compensationaction',
+            name='action_type_tmp',
+            field=models.ManyToManyField(blank=True, limit_choices_to={'code_lists__in': [1026], 'is_archived': False, 'is_selectable': True}, related_name='_compensationaction_action_type_+', to='codelist.KonovaCode'),
+        ),
+        migrations.RunPython(migrate_actions),
+        migrations.RemoveField(
+            model_name='compensationaction',
+            name='action_type',
+        ),
+        migrations.RenameField(
+            model_name='compensationaction',
+            old_name='action_type_tmp',
+            new_name='action_type',
+        )
+    ]
diff --git a/compensation/models/action.py b/compensation/models/action.py
index a5579159..e54f53d3 100644
--- a/compensation/models/action.py
+++ b/compensation/models/action.py
@@ -10,9 +10,7 @@ from django.utils.translation import gettext_lazy as _
 
 from codelist.models import KonovaCode
 from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_COMPENSATION_ACTION_DETAIL_ID
-from compensation.managers import CompensationActionManager
 from konova.models import BaseResource
-from konova.utils.message_templates import COMPENSATION_ACTION_REMOVED
 
 
 class UnitChoices(models.TextChoices):
@@ -31,10 +29,8 @@ class CompensationAction(BaseResource):
     """
     Compensations include actions like planting trees, refreshing rivers and so on.
     """
-    action_type = models.ForeignKey(
+    action_type = models.ManyToManyField(
         KonovaCode,
-        on_delete=models.SET_NULL,
-        null=True,
         blank=True,
         limit_choices_to={
             "code_lists__in": [CODELIST_COMPENSATION_ACTION_ID],
@@ -57,10 +53,8 @@ class CompensationAction(BaseResource):
     unit = models.CharField(max_length=100, null=True, blank=True, choices=UnitChoices.choices)
     comment = models.TextField(blank=True, null=True, help_text="Additional comment")
 
-    objects = CompensationActionManager()
-
     def __str__(self):
-        return f"{self.action_type} | {self.amount} {self.unit}"
+        return f"{self.action_type.all()} | {self.amount} {self.unit}"
 
     @property
     def unit_humanize(self):
diff --git a/compensation/models/compensation.py b/compensation/models/compensation.py
index 4dd2b4c2..7a10aa0b 100644
--- a/compensation/models/compensation.py
+++ b/compensation/models/compensation.py
@@ -104,12 +104,12 @@ class AbstractCompensation(BaseObject, GeoReferencedMixin):
         with transaction.atomic():
             user_action = UserActionLogEntry.get_created_action(user)
             comp_action = CompensationAction.objects.create(
-                action_type=form_data["action_type"],
                 amount=form_data["amount"],
                 unit=form_data["unit"],
                 comment=form_data["comment"],
                 created=user_action,
             )
+            comp_action.action_type.set(form_data.get("action_type", []))
             comp_action_details = form_data["action_type_details"]
             comp_action.action_type_details.set(comp_action_details)
             self.actions.add(comp_action)
diff --git a/compensation/templates/compensation/detail/compensation/includes/actions.html b/compensation/templates/compensation/detail/compensation/includes/actions.html
index 33037ecf..18e9304b 100644
--- a/compensation/templates/compensation/detail/compensation/includes/actions.html
+++ b/compensation/templates/compensation/detail/compensation/includes/actions.html
@@ -47,7 +47,11 @@
             {% for action in actions %}
             <tr>
                 <td class="">
-                    <span>{{ action.action_type }}</span>
+                    <ul>
+                        {% for type in action.action_type.all %}
+                        <li> {{type}} </li>
+                        {% endfor %}
+                    </ul>
                     {% if action.action_type_details.count > 0 %}
                         <br>
                         {% for detail in action.action_type_details.all %}
diff --git a/compensation/templates/compensation/detail/eco_account/includes/actions.html b/compensation/templates/compensation/detail/eco_account/includes/actions.html
index add698e0..092c5e8d 100644
--- a/compensation/templates/compensation/detail/eco_account/includes/actions.html
+++ b/compensation/templates/compensation/detail/eco_account/includes/actions.html
@@ -46,7 +46,11 @@
             {% for action in actions %}
             <tr>
                 <td class="">
-                    <span>{{ action.action_type }}</span>
+                    <ul>
+                        {% for type in action.action_type.all%}
+                        <li> {{type.long_name}} </li>
+                        {% endfor %}
+                    </ul>
                     {% if action.action_type_details.count > 0 %}
                         <br>
                         {% for detail in action.action_type_details.all %}
diff --git a/ema/templates/ema/detail/includes/actions.html b/ema/templates/ema/detail/includes/actions.html
index 02772b36..9d91caf0 100644
--- a/ema/templates/ema/detail/includes/actions.html
+++ b/ema/templates/ema/detail/includes/actions.html
@@ -44,7 +44,11 @@
             {% for action in obj.actions.all %}
             <tr>
                 <td class="">
-                    <span>{{ action.action_type }}</span>
+                    <ul>
+                        {% for type in action.action_type.all%}
+                        <li> {{type}} </li>
+                        {% endfor %}
+                    </ul>
                     {% if action.action_type_details.count > 0 %}
                         <br>
                         {% for detail in action.action_type_details.all %}

From afb78fa670303834637e0769620a1e4f369929f3 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 11 Feb 2022 08:43:21 +0100
Subject: [PATCH 03/26] #112 Migration enhance

* fixes bug in migration
* adds check to migration which raises error before data loss might happen
---
 compensation/migrations/0004_auto_20220210_1402.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/compensation/migrations/0004_auto_20220210_1402.py b/compensation/migrations/0004_auto_20220210_1402.py
index 44d43cbe..7cc8126c 100644
--- a/compensation/migrations/0004_auto_20220210_1402.py
+++ b/compensation/migrations/0004_auto_20220210_1402.py
@@ -9,9 +9,12 @@ def migrate_actions(apps, schema_editor):
 
     for action in actions:
         action_type = action.action_type or []
-        action.action_type_tmp.set(action_type)
+        action.action_type_tmp.set([action_type])
         action.save()
 
+        if not action.action_type_tmp.count() > 0:
+            raise ValueError("Migration of actions did not work! Stoped before data loss!")
+
 
 class Migration(migrations.Migration):
 

From 62e452c62567064f047e81940487e80131567094 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 11 Feb 2022 14:13:42 +0100
Subject: [PATCH 04/26] WIP: CompensationAction using jstree

---
 compensation/forms/modalForms.py              | 20 ++++++---
 .../detail/compensation/view.html             |  5 +++
 .../compensation/detail/eco_account/view.html |  5 +++
 ema/templates/ema/detail/view.html            |  5 +++
 intervention/inputs.py                        | 15 +++++++
 .../widgets/checkbox-tree-select-base.html    | 45 +++++++++++++++++++
 .../widgets/checkbox-tree-select-content.html |  9 ++++
 konova/urls.py                                |  4 +-
 konova/views.py                               | 24 ++++++++++
 templates/form/scripts/jstree-scripts.html    |  2 +
 10 files changed, 126 insertions(+), 8 deletions(-)
 create mode 100644 konova/templates/konova/widgets/checkbox-tree-select-base.html
 create mode 100644 konova/templates/konova/widgets/checkbox-tree-select-content.html
 create mode 100644 templates/form/scripts/jstree-scripts.html

diff --git a/compensation/forms/modalForms.py b/compensation/forms/modalForms.py
index 90b0b64c..20ff5ddc 100644
--- a/compensation/forms/modalForms.py
+++ b/compensation/forms/modalForms.py
@@ -11,12 +11,14 @@ from django import forms
 from django.contrib import messages
 from django.http import HttpRequest, HttpResponseRedirect
 from django.shortcuts import render
+from django.urls import reverse
 from django.utils.translation import pgettext_lazy as _con, gettext_lazy as _
 
 from codelist.models import KonovaCode
 from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
     CODELIST_COMPENSATION_ACTION_DETAIL_ID
 from compensation.models import CompensationDocument, EcoAccountDocument
+from intervention.inputs import TreeSelectMultiple
 from konova.contexts import BaseContext
 from konova.forms import BaseModalForm, NewDocumentModalForm, RemoveModalForm
 from konova.models import DeadlineType
@@ -411,15 +413,11 @@ class NewActionModalForm(BaseModalForm):
         required=True,
         help_text=_("Select the action type"),
         queryset=KonovaCode.objects.filter(
-            is_archived=False,
-            is_leaf=True,
             code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
+            is_archived=False,
         ),
-        widget=autocomplete.ModelSelect2Multiple(
-            url="codes-compensation-action-autocomplete",
-            attrs={
-                "data-placeholder": _("Action"),
-            }
+        widget=TreeSelectMultiple(
+            url=None,
         ),
     )
     action_type_details = forms.ModelMultipleChoiceField(
@@ -482,6 +480,14 @@ class NewActionModalForm(BaseModalForm):
         super().__init__(*args, **kwargs)
         self.form_title = _("New action")
         self.form_caption = _("Insert data for the new action")
+        url = reverse("codes-action-children")
+        self.fields["action_type"].widget.attrs = {
+            "url": url,
+        }
+
+    def is_valid(self):
+        super_valid = super().is_valid()
+        return super_valid
 
     def save(self):
         action = self.instance.add_action(self)
diff --git a/compensation/templates/compensation/detail/compensation/view.html b/compensation/templates/compensation/detail/compensation/view.html
index 3f843c0a..17f79bc8 100644
--- a/compensation/templates/compensation/detail/compensation/view.html
+++ b/compensation/templates/compensation/detail/compensation/view.html
@@ -2,6 +2,11 @@
 {% load i18n l10n static fontawesome_5 humanize ksp_filters %}
 
 {% block head %}
+    {% comment %}
+        Needed for custom Checkbox Tree Select Widget
+    {% endcomment %}
+    {% include 'form/scripts/jstree-scripts.html' %}
+
     {% comment %}
         dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
         This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
diff --git a/compensation/templates/compensation/detail/eco_account/view.html b/compensation/templates/compensation/detail/eco_account/view.html
index f276f931..132e0b61 100644
--- a/compensation/templates/compensation/detail/eco_account/view.html
+++ b/compensation/templates/compensation/detail/eco_account/view.html
@@ -2,6 +2,11 @@
 {% load i18n l10n static fontawesome_5 humanize %}
 
 {% block head %}
+    {% comment %}
+        Needed for custom Checkbox Tree Select Widget
+    {% endcomment %}
+    {% include 'form/scripts/jstree-scripts.html' %}
+
     {% comment %}
         dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
         This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
diff --git a/ema/templates/ema/detail/view.html b/ema/templates/ema/detail/view.html
index 32ddd66b..cdab570d 100644
--- a/ema/templates/ema/detail/view.html
+++ b/ema/templates/ema/detail/view.html
@@ -2,6 +2,11 @@
 {% load i18n l10n static fontawesome_5 humanize %}
 
 {% block head %}
+    {% comment %}
+        Needed for custom Checkbox Tree Select Widget
+    {% endcomment %}
+    {% include 'form/scripts/jstree-scripts.html' %}
+
     {% comment %}
         dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
         This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
diff --git a/intervention/inputs.py b/intervention/inputs.py
index 2e84edc5..9cf8e5ab 100644
--- a/intervention/inputs.py
+++ b/intervention/inputs.py
@@ -1,4 +1,5 @@
 from django import forms
+from django.urls import reverse
 
 
 class DummyFilterInput(forms.HiddenInput):
@@ -30,3 +31,17 @@ class GenerateInput(forms.TextInput):
 
     """
     template_name = "konova/widgets/generate-content-input.html"
+
+
+class TreeSelectMultiple(forms.SelectMultiple):
+    """ Provides multiple selection of parent-child data
+
+    """
+    template_name = "konova/widgets/checkbox-tree-select-base.html"
+    url = None
+
+    def __init__(self, *args, **kwargs):
+        self.url = kwargs.pop("url", None)
+        if self.url:
+            self.url = reverse(self.url)
+        super().__init__(*args, **kwargs)
diff --git a/konova/templates/konova/widgets/checkbox-tree-select-base.html b/konova/templates/konova/widgets/checkbox-tree-select-base.html
new file mode 100644
index 00000000..793ab83f
--- /dev/null
+++ b/konova/templates/konova/widgets/checkbox-tree-select-base.html
@@ -0,0 +1,45 @@
+
+<div id="jstree">
+</div>
+
+<input id="jstree-input" name="{{ widget.name }}[]" hidden="hidden"/>
+
+<script>
+    $(function () {
+        $('#jstree').jstree({
+            'plugins': [
+                'checkbox',
+            ],
+            'checkbox': {
+                'whole_node': false,
+            },
+            'core' : {
+                'data' : {
+                    'url' : '{{ widget.attrs.url }}',
+                    'data' : function (node) {
+                        return { 'id' : node.id };
+                    }
+                }
+            }
+        });
+        $('#jstree')
+            .on('deselect_node.jstree', function (e, data) {
+                $(data.selected).each(function (val){
+                    console.log(val)
+                    console.log(this)
+                    $(this).after(
+                        "<input name='{{widget.name}}[]' value="+val+"/>"
+                    )
+                });
+                //$('#jstree-input').val(data.selected);
+            })
+            .on('select_node.jstree', function (e, data) {
+                $(data.selected).each(function (val){
+                    $(this).after(
+                        "<input name='{{widget.name}}[]' value="+val+"/>"
+                    )
+                });
+                //$('#jstree-input').val(data.selected);
+            })
+    });
+</script>
\ No newline at end of file
diff --git a/konova/templates/konova/widgets/checkbox-tree-select-content.html b/konova/templates/konova/widgets/checkbox-tree-select-content.html
new file mode 100644
index 00000000..13b3a34d
--- /dev/null
+++ b/konova/templates/konova/widgets/checkbox-tree-select-content.html
@@ -0,0 +1,9 @@
+{% load l10n %}
+
+<ul>
+    {% for code in codes %}
+    <li id="{{code.pk|unlocalize}}" class="{% if code.is_leaf%}jstree-leaf{% else %}jstree-closed{% endif %}">
+        {{code.long_name}}
+    </li>
+    {% endfor %}
+</ul>
\ No newline at end of file
diff --git a/konova/urls.py b/konova/urls.py
index 68256e7a..734be3cd 100644
--- a/konova/urls.py
+++ b/konova/urls.py
@@ -23,7 +23,7 @@ from konova.autocompletes import EcoAccountAutocomplete, \
     ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete
 from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
 from konova.sso.sso import KonovaSSOClient
-from konova.views import logout_view, home_view
+from konova.views import logout_view, home_view, get_konova_code_action_children
 
 sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
 urlpatterns = [
@@ -40,6 +40,8 @@ urlpatterns = [
     path('analysis/', include("analysis.urls")),
     path('api/', include("api.urls")),
 
+    path("codes/comp/action/children", get_konova_code_action_children, name="codes-action-children"),
+
     # Autocomplete paths for all apps
     path("atcmplt/eco-accounts", EcoAccountAutocomplete.as_view(), name="accounts-autocomplete"),
     path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="interventions-autocomplete"),
diff --git a/konova/views.py b/konova/views.py
index 2a4c8ad5..2eac8b20 100644
--- a/konova/views.py
+++ b/konova/views.py
@@ -9,9 +9,12 @@ from django.contrib.auth import logout
 from django.contrib.auth.decorators import login_required
 from django.http import HttpRequest, FileResponse
 from django.shortcuts import redirect, render, get_object_or_404
+from django.template.loader import render_to_string
 from django.utils import timezone
 from django.utils.translation import gettext_lazy as _
 
+from codelist.models import KonovaCode
+from codelist.settings import CODELIST_COMPENSATION_ACTION_ID
 from compensation.models import Compensation, EcoAccount
 from intervention.models import Intervention
 from konova.contexts import BaseContext
@@ -124,3 +127,24 @@ def get_500_view(request: HttpRequest):
     """
     context = BaseContext.context
     return render(request, "500.html", context, status=500)
+
+
+@login_required
+def get_konova_code_action_children(request: HttpRequest):
+    template = "konova/widgets/checkbox-tree-select-content.html"
+    _id = request.GET.get("id", None)
+    if _id == "#":
+        # Return all!
+        codes = KonovaCode.objects.filter(
+            code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
+            parent=None,
+        )
+    else:
+        codes = KonovaCode.objects.filter(
+            code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
+            parent__id=_id,
+        )
+    context = {
+        "codes": codes
+    }
+    return render(request, template, context)
\ No newline at end of file
diff --git a/templates/form/scripts/jstree-scripts.html b/templates/form/scripts/jstree-scripts.html
new file mode 100644
index 00000000..c9367609
--- /dev/null
+++ b/templates/form/scripts/jstree-scripts.html
@@ -0,0 +1,2 @@
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
+<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
\ No newline at end of file

From d04d02380f6ec763ff24fe61babd2aa2e6c9344b Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 11 Feb 2022 16:21:44 +0100
Subject: [PATCH 05/26] WIP: #112 Restructure CompensationAction

---
 compensation/forms/modalForms.py              |  2 +-
 .../widgets/checkbox-tree-select-base.html    | 26 ++++---------------
 2 files changed, 6 insertions(+), 22 deletions(-)

diff --git a/compensation/forms/modalForms.py b/compensation/forms/modalForms.py
index 20ff5ddc..6dc0c98e 100644
--- a/compensation/forms/modalForms.py
+++ b/compensation/forms/modalForms.py
@@ -22,7 +22,7 @@ from intervention.inputs import TreeSelectMultiple
 from konova.contexts import BaseContext
 from konova.forms import BaseModalForm, NewDocumentModalForm, RemoveModalForm
 from konova.models import DeadlineType
-from konova.utils.message_templates import FORM_INVALID, ADDED_COMPENSATION_STATE, ADDED_DEADLINE, \
+from konova.utils.message_templates import FORM_INVALID, ADDED_COMPENSATION_STATE, \
     ADDED_COMPENSATION_ACTION, PAYMENT_EDITED, COMPENSATION_STATE_EDITED, COMPENSATION_ACTION_EDITED, DEADLINE_EDITED
 
 
diff --git a/konova/templates/konova/widgets/checkbox-tree-select-base.html b/konova/templates/konova/widgets/checkbox-tree-select-base.html
index 793ab83f..6a10ff02 100644
--- a/konova/templates/konova/widgets/checkbox-tree-select-base.html
+++ b/konova/templates/konova/widgets/checkbox-tree-select-base.html
@@ -1,18 +1,14 @@
 
-<div id="jstree">
-</div>
-
-<input id="jstree-input" name="{{ widget.name }}[]" hidden="hidden"/>
+<div id="jstree"></div>
+<input id="jstree-input" name="{{ widget.name }}" hidden="hidden"/>
 
 <script>
     $(function () {
         $('#jstree').jstree({
             'plugins': [
                 'checkbox',
+                'wholerow',
             ],
-            'checkbox': {
-                'whole_node': false,
-            },
             'core' : {
                 'data' : {
                     'url' : '{{ widget.attrs.url }}',
@@ -24,22 +20,10 @@
         });
         $('#jstree')
             .on('deselect_node.jstree', function (e, data) {
-                $(data.selected).each(function (val){
-                    console.log(val)
-                    console.log(this)
-                    $(this).after(
-                        "<input name='{{widget.name}}[]' value="+val+"/>"
-                    )
-                });
-                //$('#jstree-input').val(data.selected);
+                $('#jstree-input').val(data.selected);
             })
             .on('select_node.jstree', function (e, data) {
-                $(data.selected).each(function (val){
-                    $(this).after(
-                        "<input name='{{widget.name}}[]' value="+val+"/>"
-                    )
-                });
-                //$('#jstree-input').val(data.selected);
+                $('#jstree-input').val(data.selected);
             })
     });
 </script>
\ No newline at end of file

From 95856c9ee94cdb999b48d245f5cea0026081d88e Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Tue, 15 Feb 2022 10:48:01 +0100
Subject: [PATCH 06/26] #112 CompensationAction Tree

* implements generic HTML based and Django compatible TreeView
* enhances listing of CompensationActions on DetailView
---
 codelist/models.py                            |  20 ++
 compensation/forms/modalForms.py              |  34 ++-
 .../detail/compensation/includes/actions.html |  20 +-
 .../detail/compensation/view.html             |   4 -
 .../detail/eco_account/includes/actions.html  |  20 +-
 .../compensation/detail/eco_account/view.html |   4 -
 .../ema/detail/includes/actions.html          |  20 +-
 ema/templates/ema/detail/view.html            |   5 -
 intervention/inputs.py                        |  49 +++-
 .../widgets/checkbox-tree-select-base.html    |  29 ---
 .../widgets/checkbox-tree-select-content.html |   9 -
 .../konova/widgets/checkbox-tree-select.html  |  23 ++
 konova/urls.py                                |   4 +-
 konova/views.py                               |  21 --
 locale/de/LC_MESSAGES/django.mo               | Bin 37463 -> 37523 bytes
 locale/de/LC_MESSAGES/django.po               | 235 +++++++++---------
 templates/form/scripts/jstree-scripts.html    |   2 -
 17 files changed, 246 insertions(+), 253 deletions(-)
 delete mode 100644 konova/templates/konova/widgets/checkbox-tree-select-base.html
 delete mode 100644 konova/templates/konova/widgets/checkbox-tree-select-content.html
 create mode 100644 konova/templates/konova/widgets/checkbox-tree-select.html
 delete mode 100644 templates/form/scripts/jstree-scripts.html

diff --git a/codelist/models.py b/codelist/models.py
index d5be5b10..de7a2100 100644
--- a/codelist/models.py
+++ b/codelist/models.py
@@ -65,6 +65,26 @@ class KonovaCode(models.Model):
             ret_val += ", " + self.parent.long_name
         return ret_val
 
+    def add_children(self):
+        """ Adds all children (resurcively until leaf) as .children to the KonovaCode
+
+        Returns:
+            code (KonovaCode): The manipulated KonovaCode instance
+        """
+        if self.is_leaf:
+            return None
+
+        children = KonovaCode.objects.filter(
+            code_lists__in=self.code_lists.all(),
+            parent=self
+        ).order_by(
+            "long_name"
+        )
+        self.children = children
+        for child in children:
+            child.add_children()
+        return self
+
 
 class KonovaCodeList(models.Model):
     """
diff --git a/compensation/forms/modalForms.py b/compensation/forms/modalForms.py
index 6dc0c98e..a8d38aa2 100644
--- a/compensation/forms/modalForms.py
+++ b/compensation/forms/modalForms.py
@@ -11,14 +11,13 @@ from django import forms
 from django.contrib import messages
 from django.http import HttpRequest, HttpResponseRedirect
 from django.shortcuts import render
-from django.urls import reverse
 from django.utils.translation import pgettext_lazy as _con, gettext_lazy as _
 
 from codelist.models import KonovaCode
 from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
     CODELIST_COMPENSATION_ACTION_DETAIL_ID
 from compensation.models import CompensationDocument, EcoAccountDocument
-from intervention.inputs import TreeSelectMultiple
+from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple
 from konova.contexts import BaseContext
 from konova.forms import BaseModalForm, NewDocumentModalForm, RemoveModalForm
 from konova.models import DeadlineType
@@ -407,18 +406,13 @@ class NewActionModalForm(BaseModalForm):
 
     """
     from compensation.models import UnitChoices
-    action_type = forms.ModelMultipleChoiceField(
+    action_type = forms.MultipleChoiceField(
         label=_("Action Type"),
         label_suffix="",
         required=True,
         help_text=_("Select the action type"),
-        queryset=KonovaCode.objects.filter(
-            code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
-            is_archived=False,
-        ),
-        widget=TreeSelectMultiple(
-            url=None,
-        ),
+        choices=[],
+        widget=CompensationActionTreeCheckboxSelectMultiple(),
     )
     action_type_details = forms.ModelMultipleChoiceField(
         label=_("Action Type detail"),
@@ -480,14 +474,16 @@ class NewActionModalForm(BaseModalForm):
         super().__init__(*args, **kwargs)
         self.form_title = _("New action")
         self.form_caption = _("Insert data for the new action")
-        url = reverse("codes-action-children")
-        self.fields["action_type"].widget.attrs = {
-            "url": url,
-        }
-
-    def is_valid(self):
-        super_valid = super().is_valid()
-        return super_valid
+        choices =KonovaCode.objects.filter(
+            code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
+            is_archived=False,
+            is_leaf=True,
+        ).values_list("id", flat=True)
+        choices = [
+            (choice, choice)
+            for choice in choices
+        ]
+        self.fields["action_type"].choices = choices
 
     def save(self):
         action = self.instance.add_action(self)
@@ -502,7 +498,7 @@ class EditCompensationActionModalForm(NewActionModalForm):
         self.action = kwargs.pop("action", None)
         super().__init__(*args, **kwargs)
         form_data = {
-            "action_type": self.action.action_type.all(),
+            "action_type": list(self.action.action_type.values_list("id", flat=True)),
             "action_type_details": self.action.action_type_details.all(),
             "amount": self.action.amount,
             "unit": self.action.unit,
diff --git a/compensation/templates/compensation/detail/compensation/includes/actions.html b/compensation/templates/compensation/detail/compensation/includes/actions.html
index 18e9304b..87f49141 100644
--- a/compensation/templates/compensation/detail/compensation/includes/actions.html
+++ b/compensation/templates/compensation/detail/compensation/includes/actions.html
@@ -47,17 +47,15 @@
             {% for action in actions %}
             <tr>
                 <td class="">
-                    <ul>
-                        {% for type in action.action_type.all %}
-                        <li> {{type}} </li>
-                        {% endfor %}
-                    </ul>
-                    {% if action.action_type_details.count > 0 %}
-                        <br>
-                        {% for detail in action.action_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    {% for type in action.action_type.all %}
+                    <div> {{type.parent.parent.long_name}} {% fa5_icon 'angle-right' %} {{type.parent.long_name}} {% fa5_icon 'angle-right' %} {{type.long_name}} </div>
+                    <hr>
+                    {% endfor %}
+                    {% for detail in action.action_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No action type details' %}">{% trans 'No action type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td class="">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td>
                 <td class="">
diff --git a/compensation/templates/compensation/detail/compensation/view.html b/compensation/templates/compensation/detail/compensation/view.html
index 17f79bc8..c5ff41d6 100644
--- a/compensation/templates/compensation/detail/compensation/view.html
+++ b/compensation/templates/compensation/detail/compensation/view.html
@@ -2,10 +2,6 @@
 {% load i18n l10n static fontawesome_5 humanize ksp_filters %}
 
 {% block head %}
-    {% comment %}
-        Needed for custom Checkbox Tree Select Widget
-    {% endcomment %}
-    {% include 'form/scripts/jstree-scripts.html' %}
 
     {% comment %}
         dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
diff --git a/compensation/templates/compensation/detail/eco_account/includes/actions.html b/compensation/templates/compensation/detail/eco_account/includes/actions.html
index 092c5e8d..8ae7c8fd 100644
--- a/compensation/templates/compensation/detail/eco_account/includes/actions.html
+++ b/compensation/templates/compensation/detail/eco_account/includes/actions.html
@@ -46,17 +46,15 @@
             {% for action in actions %}
             <tr>
                 <td class="">
-                    <ul>
-                        {% for type in action.action_type.all%}
-                        <li> {{type.long_name}} </li>
-                        {% endfor %}
-                    </ul>
-                    {% if action.action_type_details.count > 0 %}
-                        <br>
-                        {% for detail in action.action_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    {% for type in action.action_type.all %}
+                    <div> {{type.parent.parent.long_name}} {% fa5_icon 'angle-right' %} {{type.parent.long_name}} {% fa5_icon 'angle-right' %} {{type.long_name}} </div>
+                    <hr>
+                    {% endfor %}
+                    {% for detail in action.action_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No action type details' %}">{% trans 'No action type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td class="">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td>
                 <td class="">
diff --git a/compensation/templates/compensation/detail/eco_account/view.html b/compensation/templates/compensation/detail/eco_account/view.html
index 132e0b61..288b971d 100644
--- a/compensation/templates/compensation/detail/eco_account/view.html
+++ b/compensation/templates/compensation/detail/eco_account/view.html
@@ -2,10 +2,6 @@
 {% load i18n l10n static fontawesome_5 humanize %}
 
 {% block head %}
-    {% comment %}
-        Needed for custom Checkbox Tree Select Widget
-    {% endcomment %}
-    {% include 'form/scripts/jstree-scripts.html' %}
 
     {% comment %}
         dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
diff --git a/ema/templates/ema/detail/includes/actions.html b/ema/templates/ema/detail/includes/actions.html
index 9d91caf0..0c352c11 100644
--- a/ema/templates/ema/detail/includes/actions.html
+++ b/ema/templates/ema/detail/includes/actions.html
@@ -44,17 +44,15 @@
             {% for action in obj.actions.all %}
             <tr>
                 <td class="">
-                    <ul>
-                        {% for type in action.action_type.all%}
-                        <li> {{type}} </li>
-                        {% endfor %}
-                    </ul>
-                    {% if action.action_type_details.count > 0 %}
-                        <br>
-                        {% for detail in action.action_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    {% for type in action.action_type.all %}
+                    <div> {{type.parent.parent.long_name}} {% fa5_icon 'angle-right' %} {{type.parent.long_name}} {% fa5_icon 'angle-right' %} {{type.long_name}} </div>
+                    <hr>
+                    {% endfor %}
+                    {% for detail in action.action_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No action type details' %}">{% trans 'No action type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td class="">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td>
                 <td class="">
diff --git a/ema/templates/ema/detail/view.html b/ema/templates/ema/detail/view.html
index cdab570d..32ddd66b 100644
--- a/ema/templates/ema/detail/view.html
+++ b/ema/templates/ema/detail/view.html
@@ -2,11 +2,6 @@
 {% load i18n l10n static fontawesome_5 humanize %}
 
 {% block head %}
-    {% comment %}
-        Needed for custom Checkbox Tree Select Widget
-    {% endcomment %}
-    {% include 'form/scripts/jstree-scripts.html' %}
-
     {% comment %}
         dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
         This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
diff --git a/intervention/inputs.py b/intervention/inputs.py
index 9cf8e5ab..34fe0434 100644
--- a/intervention/inputs.py
+++ b/intervention/inputs.py
@@ -1,5 +1,6 @@
 from django import forms
-from django.urls import reverse
+from codelist.models import KonovaCode
+from codelist.settings import CODELIST_COMPENSATION_ACTION_ID
 
 
 class DummyFilterInput(forms.HiddenInput):
@@ -33,15 +34,49 @@ class GenerateInput(forms.TextInput):
     template_name = "konova/widgets/generate-content-input.html"
 
 
-class TreeSelectMultiple(forms.SelectMultiple):
+class TreeCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
     """ Provides multiple selection of parent-child data
 
     """
-    template_name = "konova/widgets/checkbox-tree-select-base.html"
-    url = None
+    template_name = "konova/widgets/checkbox-tree-select.html"
+
+    class meta:
+        abstract = True
+
+
+class KonovaCodeTreeCheckboxSelectMultiple(TreeCheckboxSelectMultiple):
+    """ Provides multiple selection of KonovaCodes
+
+    """
+    filter = None
 
     def __init__(self, *args, **kwargs):
-        self.url = kwargs.pop("url", None)
-        if self.url:
-            self.url = reverse(self.url)
+        self.code_list = kwargs.pop("code_list", None)
+        self.filter = kwargs.pop("filter", {})
         super().__init__(*args, **kwargs)
+
+    def get_context(self, name, value, attrs):
+        context = super().get_context(name, value, attrs)
+        codes = KonovaCode.objects.filter(
+            **self.filter,
+        )
+        codes = [
+            parent_code.add_children()
+            for parent_code in codes
+        ]
+        context["codes"] = codes
+        return context
+
+
+class CompensationActionTreeCheckboxSelectMultiple(KonovaCodeTreeCheckboxSelectMultiple):
+    """ Provides multiple selection of CompensationActions
+
+    """
+    filter = None
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.filter = {
+            "code_lists__in": [CODELIST_COMPENSATION_ACTION_ID],
+            "parent": None,
+        }
\ No newline at end of file
diff --git a/konova/templates/konova/widgets/checkbox-tree-select-base.html b/konova/templates/konova/widgets/checkbox-tree-select-base.html
deleted file mode 100644
index 6a10ff02..00000000
--- a/konova/templates/konova/widgets/checkbox-tree-select-base.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-<div id="jstree"></div>
-<input id="jstree-input" name="{{ widget.name }}" hidden="hidden"/>
-
-<script>
-    $(function () {
-        $('#jstree').jstree({
-            'plugins': [
-                'checkbox',
-                'wholerow',
-            ],
-            'core' : {
-                'data' : {
-                    'url' : '{{ widget.attrs.url }}',
-                    'data' : function (node) {
-                        return { 'id' : node.id };
-                    }
-                }
-            }
-        });
-        $('#jstree')
-            .on('deselect_node.jstree', function (e, data) {
-                $('#jstree-input').val(data.selected);
-            })
-            .on('select_node.jstree', function (e, data) {
-                $('#jstree-input').val(data.selected);
-            })
-    });
-</script>
\ No newline at end of file
diff --git a/konova/templates/konova/widgets/checkbox-tree-select-content.html b/konova/templates/konova/widgets/checkbox-tree-select-content.html
deleted file mode 100644
index 13b3a34d..00000000
--- a/konova/templates/konova/widgets/checkbox-tree-select-content.html
+++ /dev/null
@@ -1,9 +0,0 @@
-{% load l10n %}
-
-<ul>
-    {% for code in codes %}
-    <li id="{{code.pk|unlocalize}}" class="{% if code.is_leaf%}jstree-leaf{% else %}jstree-closed{% endif %}">
-        {{code.long_name}}
-    </li>
-    {% endfor %}
-</ul>
\ No newline at end of file
diff --git a/konova/templates/konova/widgets/checkbox-tree-select.html b/konova/templates/konova/widgets/checkbox-tree-select.html
new file mode 100644
index 00000000..5b40d3f1
--- /dev/null
+++ b/konova/templates/konova/widgets/checkbox-tree-select.html
@@ -0,0 +1,23 @@
+{% load l10n fontawesome_5 %}
+
+<div>
+    {% for code in codes %}
+    <div class="ml-4">
+        <label role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
+            {% if code.is_leaf%}
+                <input id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="checkbox" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
+            {% else %}
+                {% fa5_icon 'angle-right' %}
+            {% endif %}
+            {{code.long_name}}
+        </label>
+        {% if not code.is_leaf %}
+            <div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse">
+                {% with code.children as codes %}
+                    {% include 'konova/widgets/checkbox-tree-select.html' %}
+                {% endwith %}
+            </div>
+        {% endif %}
+    </div>
+    {% endfor %}
+</div>
\ No newline at end of file
diff --git a/konova/urls.py b/konova/urls.py
index 734be3cd..68256e7a 100644
--- a/konova/urls.py
+++ b/konova/urls.py
@@ -23,7 +23,7 @@ from konova.autocompletes import EcoAccountAutocomplete, \
     ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete
 from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
 from konova.sso.sso import KonovaSSOClient
-from konova.views import logout_view, home_view, get_konova_code_action_children
+from konova.views import logout_view, home_view
 
 sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
 urlpatterns = [
@@ -40,8 +40,6 @@ urlpatterns = [
     path('analysis/', include("analysis.urls")),
     path('api/', include("api.urls")),
 
-    path("codes/comp/action/children", get_konova_code_action_children, name="codes-action-children"),
-
     # Autocomplete paths for all apps
     path("atcmplt/eco-accounts", EcoAccountAutocomplete.as_view(), name="accounts-autocomplete"),
     path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="interventions-autocomplete"),
diff --git a/konova/views.py b/konova/views.py
index 2eac8b20..f3c53f01 100644
--- a/konova/views.py
+++ b/konova/views.py
@@ -127,24 +127,3 @@ def get_500_view(request: HttpRequest):
     """
     context = BaseContext.context
     return render(request, "500.html", context, status=500)
-
-
-@login_required
-def get_konova_code_action_children(request: HttpRequest):
-    template = "konova/widgets/checkbox-tree-select-content.html"
-    _id = request.GET.get("id", None)
-    if _id == "#":
-        # Return all!
-        codes = KonovaCode.objects.filter(
-            code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
-            parent=None,
-        )
-    else:
-        codes = KonovaCode.objects.filter(
-            code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
-            parent__id=_id,
-        )
-    context = {
-        "codes": codes
-    }
-    return render(request, template, context)
\ No newline at end of file
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index 99058358253ae1eb76a6a5f21466ae886d82ccaf..e9a94ccb374f1fcb49ae6b60cf0df3131a61819d 100644
GIT binary patch
delta 10418
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
HR_Ff!*^K44

delta 10343
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

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index cd7cd88f..9e5c6bb4 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -3,9 +3,9 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
-#: compensation/filters.py:122 compensation/forms/modalForms.py:35
-#: compensation/forms/modalForms.py:46 compensation/forms/modalForms.py:62
-#: compensation/forms/modalForms.py:355 compensation/forms/modalForms.py:471
+#: compensation/filters.py:122 compensation/forms/modalForms.py:37
+#: compensation/forms/modalForms.py:48 compensation/forms/modalForms.py:64
+#: compensation/forms/modalForms.py:357 compensation/forms/modalForms.py:469
 #: intervention/forms/forms.py:54 intervention/forms/forms.py:156
 #: intervention/forms/forms.py:168 intervention/forms/modalForms.py:127
 #: intervention/forms/modalForms.py:140 intervention/forms/modalForms.py:153
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-10 13:31+0100\n"
+"POT-Creation-Date: 2022-02-15 10:08+0100\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"
@@ -45,7 +45,7 @@ msgid "To"
 msgstr "Bis"
 
 #: analysis/forms.py:47 compensation/forms/forms.py:77
-#: compensation/templates/compensation/detail/eco_account/view.html:58
+#: compensation/templates/compensation/detail/eco_account/view.html:59
 #: compensation/templates/compensation/report/eco_account/report.html:16
 #: compensation/utils/quality.py:100 ema/templates/ema/detail/view.html:49
 #: ema/templates/ema/report/report.html:16 ema/utils/quality.py:26
@@ -95,7 +95,7 @@ msgstr ""
 #: analysis/templates/analysis/reports/includes/eco_account/amount.html:3
 #: analysis/templates/analysis/reports/includes/intervention/amount.html:3
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:3
-#: compensation/forms/modalForms.py:455
+#: compensation/forms/modalForms.py:453
 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
 #: intervention/templates/intervention/detail/includes/deductions.html:31
 msgid "Amount"
@@ -137,7 +137,7 @@ msgstr "Zuständigkeitsbereich"
 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:8
 #: analysis/templates/analysis/reports/includes/intervention/laws.html:17
 #: compensation/tables.py:40
-#: compensation/templates/compensation/detail/compensation/view.html:63
+#: compensation/templates/compensation/detail/compensation/view.html:64
 #: intervention/tables.py:39
 #: intervention/templates/intervention/detail/view.html:68
 #: user/models/user_action.py:20
@@ -153,9 +153,9 @@ msgstr "Geprüft"
 #: 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:222
-#: compensation/templates/compensation/detail/compensation/view.html:77
+#: 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:44
+#: 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/templates/intervention/detail/view.html:82
@@ -213,7 +213,7 @@ msgstr "Abbuchungen"
 
 #: analysis/templates/analysis/reports/includes/eco_account/deductions.html:9
 #: analysis/templates/analysis/reports/includes/eco_account/deductions.html:11
-#: compensation/forms/modalForms.py:193
+#: compensation/forms/modalForms.py:195
 #: compensation/templates/compensation/detail/compensation/includes/states-after.html:36
 #: compensation/templates/compensation/detail/compensation/includes/states-before.html:36
 #: compensation/templates/compensation/detail/eco_account/includes/states-after.html:36
@@ -239,14 +239,14 @@ msgstr "Kompensationsart"
 
 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:15
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:29
-#: compensation/templates/compensation/detail/compensation/view.html:19
+#: compensation/templates/compensation/detail/compensation/view.html:20
 #: konova/templates/konova/includes/quickstart/compensations.html:4
 #: templates/navbars/navbar.html:28
 msgid "Compensation"
 msgstr "Kompensation"
 
 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:21
-#: compensation/forms/modalForms.py:75
+#: compensation/forms/modalForms.py:77
 msgid "Payment"
 msgstr "Zahlung"
 
@@ -293,7 +293,7 @@ msgstr "Eingriff"
 
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
 #: compensation/tables.py:266
-#: compensation/templates/compensation/detail/eco_account/view.html:19
+#: compensation/templates/compensation/detail/eco_account/view.html:20
 #: intervention/forms/modalForms.py:322 intervention/forms/modalForms.py:329
 #: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
 #: templates/navbars/navbar.html:34
@@ -327,9 +327,9 @@ msgstr "Automatisch generiert"
 #: compensation/forms/forms.py:44 compensation/tables.py:30
 #: compensation/tables.py:202
 #: compensation/templates/compensation/detail/compensation/includes/documents.html:28
-#: compensation/templates/compensation/detail/compensation/view.html:31
+#: compensation/templates/compensation/detail/compensation/view.html:32
 #: compensation/templates/compensation/detail/eco_account/includes/documents.html:28
-#: compensation/templates/compensation/detail/eco_account/view.html:31
+#: compensation/templates/compensation/detail/eco_account/view.html:32
 #: compensation/templates/compensation/report/compensation/report.html:12
 #: compensation/templates/compensation/report/eco_account/report.html:12
 #: ema/tables.py:34 ema/templates/ema/detail/includes/documents.html:28
@@ -352,8 +352,8 @@ msgstr "Aussagekräftiger Titel"
 msgid "Compensation XY; Location ABC"
 msgstr "Kompensation XY; Flur ABC"
 
-#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:61
-#: compensation/forms/modalForms.py:354 compensation/forms/modalForms.py:470
+#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:63
+#: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:468
 #: compensation/templates/compensation/detail/compensation/includes/actions.html:35
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:34
 #: compensation/templates/compensation/detail/compensation/includes/documents.html:34
@@ -371,13 +371,13 @@ msgstr "Kompensation XY; Flur ABC"
 msgid "Comment"
 msgstr "Kommentar"
 
-#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:472
+#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:470
 #: intervention/forms/forms.py:182
 msgid "Additional comment"
 msgstr "Zusätzlicher Kommentar"
 
 #: compensation/forms/forms.py:93
-#: compensation/templates/compensation/detail/eco_account/view.html:62
+#: compensation/templates/compensation/detail/eco_account/view.html:63
 #: compensation/templates/compensation/report/eco_account/report.html:20
 #: compensation/utils/quality.py:102 ema/templates/ema/detail/view.html:53
 #: ema/templates/ema/report/report.html:20 ema/utils/quality.py:28
@@ -422,7 +422,7 @@ msgid ""
 msgstr "Optional: Handelt es sich um eine Kohärenzsicherungsmaßnahme?"
 
 #: compensation/forms/forms.py:156
-#: compensation/templates/compensation/detail/compensation/view.html:35
+#: compensation/templates/compensation/detail/compensation/view.html:36
 #: compensation/templates/compensation/report/compensation/report.html:16
 msgid "compensates intervention"
 msgstr "kompensiert Eingriff"
@@ -448,7 +448,7 @@ msgid "The amount that can be used for deductions"
 msgstr "Die für Abbuchungen zur Verfügung stehende Menge"
 
 #: compensation/forms/forms.py:328
-#: compensation/templates/compensation/detail/eco_account/view.html:66
+#: compensation/templates/compensation/detail/eco_account/view.html:67
 #: compensation/utils/quality.py:72
 msgid "Agreement date"
 msgstr "Vereinbarungsdatum"
@@ -469,73 +469,73 @@ msgstr "Ökokonto XY; Flur ABC"
 msgid "Edit Eco-Account"
 msgstr "Ökokonto bearbeiten"
 
-#: compensation/forms/modalForms.py:36
+#: compensation/forms/modalForms.py:38
 msgid "in Euro"
 msgstr "in Euro"
 
-#: compensation/forms/modalForms.py:45
+#: compensation/forms/modalForms.py:47
 #: intervention/templates/intervention/detail/includes/payments.html:31
 msgid "Due on"
 msgstr "Fällig am"
 
-#: compensation/forms/modalForms.py:48
+#: compensation/forms/modalForms.py:50
 msgid "Due on which date"
 msgstr "Zahlung wird an diesem Datum erwartet"
 
-#: compensation/forms/modalForms.py:63 compensation/forms/modalForms.py:356
+#: compensation/forms/modalForms.py:65 compensation/forms/modalForms.py:358
 #: intervention/forms/modalForms.py:154 konova/forms.py:395
 msgid "Additional comment, maximum {} letters"
 msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 
-#: compensation/forms/modalForms.py:76
+#: compensation/forms/modalForms.py:78
 msgid "Add a payment for intervention '{}'"
 msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen"
 
-#: compensation/forms/modalForms.py:96
+#: compensation/forms/modalForms.py:98
 msgid "If there is no date you can enter, please explain why."
 msgstr "Falls Sie kein Datum angeben können, erklären Sie bitte weshalb."
 
-#: compensation/forms/modalForms.py:157 compensation/forms/modalForms.py:169
+#: compensation/forms/modalForms.py:159 compensation/forms/modalForms.py:171
 msgid "Biotope Type"
 msgstr "Biotoptyp"
 
-#: compensation/forms/modalForms.py:160
+#: compensation/forms/modalForms.py:162
 msgid "Select the biotope type"
 msgstr "Biotoptyp wählen"
 
-#: compensation/forms/modalForms.py:174 compensation/forms/modalForms.py:186
+#: compensation/forms/modalForms.py:176 compensation/forms/modalForms.py:188
 msgid "Biotope additional type"
 msgstr "Zusatzbezeichnung"
 
-#: compensation/forms/modalForms.py:177
+#: compensation/forms/modalForms.py:179
 msgid "Select an additional biotope type"
 msgstr "Zusatzbezeichnung wählen"
 
-#: compensation/forms/modalForms.py:196 intervention/forms/modalForms.py:340
+#: compensation/forms/modalForms.py:198 intervention/forms/modalForms.py:340
 msgid "in m²"
 msgstr ""
 
-#: compensation/forms/modalForms.py:207
+#: compensation/forms/modalForms.py:209
 msgid "New state"
 msgstr "Neuer Zustand"
 
-#: compensation/forms/modalForms.py:208
+#: compensation/forms/modalForms.py:210
 msgid "Insert data for the new state"
 msgstr "Geben Sie die Daten des neuen Zustandes ein"
 
-#: compensation/forms/modalForms.py:215 konova/forms.py:193
+#: compensation/forms/modalForms.py:217 konova/forms.py:193
 msgid "Object removed"
 msgstr "Objekt entfernt"
 
-#: compensation/forms/modalForms.py:326
+#: compensation/forms/modalForms.py:328
 msgid "Deadline Type"
 msgstr "Fristart"
 
-#: compensation/forms/modalForms.py:329
+#: compensation/forms/modalForms.py:331
 msgid "Select the deadline type"
 msgstr "Fristart wählen"
 
-#: compensation/forms/modalForms.py:338
+#: compensation/forms/modalForms.py:340
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
 #: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
 #: ema/templates/ema/detail/includes/deadlines.html:31
@@ -543,101 +543,75 @@ msgstr "Fristart wählen"
 msgid "Date"
 msgstr "Datum"
 
-#: compensation/forms/modalForms.py:341
+#: compensation/forms/modalForms.py:343
 msgid "Select date"
 msgstr "Datum wählen"
 
-#: compensation/forms/modalForms.py:368
+#: compensation/forms/modalForms.py:370
 msgid "New deadline"
 msgstr "Neue Frist"
 
-#: compensation/forms/modalForms.py:369
+#: compensation/forms/modalForms.py:371
 msgid "Insert data for the new deadline"
 msgstr "Geben Sie die Daten der neuen Frist ein"
 
-#: compensation/forms/modalForms.py:409
+#: compensation/forms/modalForms.py:411
 msgid "Action Type"
 msgstr "Maßnahmentyp"
 
-#: compensation/forms/modalForms.py:412
+#: compensation/forms/modalForms.py:414
 msgid "Select the action type"
 msgstr "Maßnahmentyp wählen"
 
-#: compensation/forms/modalForms.py:421
-#: compensation/templates/compensation/detail/compensation/includes/actions.html:40
-#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:39
-#: compensation/templates/compensation/detail/compensation/includes/documents.html:39
-#: compensation/templates/compensation/detail/compensation/includes/states-after.html:41
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:41
-#: compensation/templates/compensation/detail/eco_account/includes/actions.html:39
-#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:38
-#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:41
-#: compensation/templates/compensation/detail/eco_account/includes/documents.html:38
-#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:41
-#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:41
-#: ema/templates/ema/detail/includes/actions.html:38
-#: ema/templates/ema/detail/includes/deadlines.html:38
-#: ema/templates/ema/detail/includes/documents.html:38
-#: ema/templates/ema/detail/includes/states-after.html:40
-#: ema/templates/ema/detail/includes/states-before.html:40
-#: intervention/templates/intervention/detail/includes/compensations.html:38
-#: intervention/templates/intervention/detail/includes/deductions.html:39
-#: intervention/templates/intervention/detail/includes/documents.html:39
-#: intervention/templates/intervention/detail/includes/payments.html:39
-#: intervention/templates/intervention/detail/includes/revocation.html:43
-#: templates/log.html:10
-msgid "Action"
-msgstr "Aktionen"
-
-#: compensation/forms/modalForms.py:426 compensation/forms/modalForms.py:438
+#: compensation/forms/modalForms.py:424 compensation/forms/modalForms.py:436
 msgid "Action Type detail"
 msgstr "Zusatzmerkmal"
 
-#: compensation/forms/modalForms.py:429
+#: compensation/forms/modalForms.py:427
 msgid "Select the action type detail"
 msgstr "Zusatzmerkmal wählen"
 
-#: compensation/forms/modalForms.py:443
+#: compensation/forms/modalForms.py:441
 msgid "Unit"
 msgstr "Einheit"
 
-#: compensation/forms/modalForms.py:446
+#: compensation/forms/modalForms.py:444
 msgid "Select the unit"
 msgstr "Einheit wählen"
 
-#: compensation/forms/modalForms.py:458
+#: compensation/forms/modalForms.py:456
 msgid "Insert the amount"
 msgstr "Menge eingeben"
 
-#: compensation/forms/modalForms.py:483
+#: compensation/forms/modalForms.py:481
 msgid "New action"
 msgstr "Neue Maßnahme"
 
-#: compensation/forms/modalForms.py:484
+#: compensation/forms/modalForms.py:482
 msgid "Insert data for the new action"
 msgstr "Geben Sie die Daten der neuen Maßnahme ein"
 
-#: compensation/models/action.py:22
+#: compensation/models/action.py:20
 msgid "cm"
 msgstr ""
 
-#: compensation/models/action.py:23
+#: compensation/models/action.py:21
 msgid "m"
 msgstr ""
 
-#: compensation/models/action.py:24
+#: compensation/models/action.py:22
 msgid "km"
 msgstr ""
 
-#: compensation/models/action.py:25
+#: compensation/models/action.py:23
 msgid "m²"
 msgstr ""
 
-#: compensation/models/action.py:26
+#: compensation/models/action.py:24
 msgid "ha"
 msgstr ""
 
-#: compensation/models/action.py:27
+#: compensation/models/action.py:25
 msgid "Pieces"
 msgstr "Stück"
 
@@ -685,9 +659,9 @@ msgid "Checked on {} by {}"
 msgstr "Am {} von {} geprüft worden"
 
 #: compensation/tables.py:160
-#: compensation/templates/compensation/detail/compensation/view.html:80
+#: 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:47
+#: 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/templates/intervention/detail/view.html:85
@@ -710,7 +684,7 @@ msgid "Access not granted"
 msgstr "Nicht freigegeben - Datensatz nur lesbar"
 
 #: compensation/tables.py:212
-#: compensation/templates/compensation/detail/eco_account/view.html:35
+#: compensation/templates/compensation/detail/eco_account/view.html:36
 #: konova/templates/konova/widgets/progressbar.html:3
 msgid "Available"
 msgstr "Verfügbar"
@@ -750,15 +724,45 @@ msgctxt "Compensation"
 msgid "Amount"
 msgstr "Menge"
 
-#: compensation/templates/compensation/detail/compensation/includes/actions.html:66
-#: compensation/templates/compensation/detail/eco_account/includes/actions.html:65
-#: ema/templates/ema/detail/includes/actions.html:63
+#: compensation/templates/compensation/detail/compensation/includes/actions.html:40
+#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:39
+#: compensation/templates/compensation/detail/compensation/includes/documents.html:39
+#: compensation/templates/compensation/detail/compensation/includes/states-after.html:41
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:41
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:39
+#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:38
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:41
+#: compensation/templates/compensation/detail/eco_account/includes/documents.html:38
+#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:41
+#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:41
+#: ema/templates/ema/detail/includes/actions.html:38
+#: ema/templates/ema/detail/includes/deadlines.html:38
+#: ema/templates/ema/detail/includes/documents.html:38
+#: ema/templates/ema/detail/includes/states-after.html:40
+#: ema/templates/ema/detail/includes/states-before.html:40
+#: intervention/templates/intervention/detail/includes/compensations.html:38
+#: intervention/templates/intervention/detail/includes/deductions.html:39
+#: intervention/templates/intervention/detail/includes/documents.html:39
+#: intervention/templates/intervention/detail/includes/payments.html:39
+#: intervention/templates/intervention/detail/includes/revocation.html:43
+#: templates/log.html:10
+msgid "Action"
+msgstr "Aktionen"
+
+#: compensation/templates/compensation/detail/compensation/includes/actions.html:57
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:56
+msgid "No action type details"
+msgstr "Keine Zusatzmerkmale"
+
+#: compensation/templates/compensation/detail/compensation/includes/actions.html:68
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:67
+#: ema/templates/ema/detail/includes/actions.html:67
 msgid "Edit action"
 msgstr "Maßnahme bearbeiten"
 
-#: compensation/templates/compensation/detail/compensation/includes/actions.html:69
-#: compensation/templates/compensation/detail/eco_account/includes/actions.html:68
-#: ema/templates/ema/detail/includes/actions.html:66
+#: compensation/templates/compensation/detail/compensation/includes/actions.html:71
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:70
+#: ema/templates/ema/detail/includes/actions.html:70
 msgid "Remove action"
 msgstr "Maßnahme entfernen"
 
@@ -924,50 +928,50 @@ msgstr "Neuen Ausgangszustand hinzufügen"
 msgid "Missing surfaces according to states after: "
 msgstr "Fehlende Flächenmengen laut Zielzustand: "
 
-#: compensation/templates/compensation/detail/compensation/view.html:43
+#: compensation/templates/compensation/detail/compensation/view.html:44
 msgid "Is CEF compensation"
 msgstr "Ist CEF Maßnahme"
 
-#: compensation/templates/compensation/detail/compensation/view.html:46
-#: compensation/templates/compensation/detail/compensation/view.html:56
+#: compensation/templates/compensation/detail/compensation/view.html:47
+#: compensation/templates/compensation/detail/compensation/view.html:57
 #: venv/lib/python3.7/site-packages/django/forms/widgets.py:710
 msgid "Yes"
 msgstr "Ja"
 
-#: compensation/templates/compensation/detail/compensation/view.html:48
-#: compensation/templates/compensation/detail/compensation/view.html:58
+#: compensation/templates/compensation/detail/compensation/view.html:49
+#: compensation/templates/compensation/detail/compensation/view.html:59
 #: venv/lib/python3.7/site-packages/django/forms/widgets.py:711
 msgid "No"
 msgstr "Nein"
 
-#: compensation/templates/compensation/detail/compensation/view.html:53
+#: compensation/templates/compensation/detail/compensation/view.html:54
 msgid "Is Coherence keeping compensation"
 msgstr "Ist Kohärenzsicherungsmaßnahme"
 
-#: compensation/templates/compensation/detail/compensation/view.html:70
+#: compensation/templates/compensation/detail/compensation/view.html:71
 #: intervention/templates/intervention/detail/view.html:75
 msgid "Checked on "
 msgstr "Geprüft am "
 
-#: compensation/templates/compensation/detail/compensation/view.html:70
-#: compensation/templates/compensation/detail/compensation/view.html:84
+#: compensation/templates/compensation/detail/compensation/view.html:71
+#: compensation/templates/compensation/detail/compensation/view.html:85
 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:56
-#: compensation/templates/compensation/detail/eco_account/view.html:51
+#: compensation/templates/compensation/detail/eco_account/view.html:52
 #: ema/templates/ema/detail/view.html:42
 #: intervention/templates/intervention/detail/view.html:75
 #: intervention/templates/intervention/detail/view.html:89
 msgid "by"
 msgstr "von"
 
-#: compensation/templates/compensation/detail/compensation/view.html:84
-#: compensation/templates/compensation/detail/eco_account/view.html:51
+#: compensation/templates/compensation/detail/compensation/view.html:85
+#: compensation/templates/compensation/detail/eco_account/view.html:52
 #: ema/templates/ema/detail/view.html:42
 #: intervention/templates/intervention/detail/view.html:89
 msgid "Recorded on "
 msgstr "Verzeichnet am"
 
-#: compensation/templates/compensation/detail/compensation/view.html:91
-#: compensation/templates/compensation/detail/eco_account/view.html:74
+#: compensation/templates/compensation/detail/compensation/view.html:92
+#: compensation/templates/compensation/detail/eco_account/view.html:75
 #: compensation/templates/compensation/report/compensation/report.html:24
 #: compensation/templates/compensation/report/eco_account/report.html:41
 #: ema/templates/ema/detail/view.html:61
@@ -977,8 +981,8 @@ msgstr "Verzeichnet am"
 msgid "Last modified"
 msgstr "Zuletzt bearbeitet"
 
-#: compensation/templates/compensation/detail/compensation/view.html:99
-#: compensation/templates/compensation/detail/eco_account/view.html:82
+#: compensation/templates/compensation/detail/compensation/view.html:100
+#: compensation/templates/compensation/detail/eco_account/view.html:83
 #: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:56
 #: intervention/templates/intervention/detail/view.html:116
 msgid "Shared with"
@@ -1037,14 +1041,14 @@ msgstr "Abbuchung bearbeiten"
 msgid "Remove Deduction"
 msgstr "Abbuchung entfernen"
 
-#: compensation/templates/compensation/detail/eco_account/view.html:34
+#: compensation/templates/compensation/detail/eco_account/view.html:35
 msgid "No surface deductable"
 msgstr "Keine Flächenmenge für Abbuchungen eingegeben. Bitte bearbeiten."
 
-#: compensation/templates/compensation/detail/eco_account/view.html:57
-#: compensation/templates/compensation/detail/eco_account/view.html:61
-#: compensation/templates/compensation/detail/eco_account/view.html:65
-#: compensation/templates/compensation/detail/eco_account/view.html:69
+#: compensation/templates/compensation/detail/eco_account/view.html:58
+#: compensation/templates/compensation/detail/eco_account/view.html:62
+#: compensation/templates/compensation/detail/eco_account/view.html:66
+#: compensation/templates/compensation/detail/eco_account/view.html:70
 #: ema/templates/ema/detail/view.html:48 ema/templates/ema/detail/view.html:52
 #: ema/templates/ema/detail/view.html:56
 #: intervention/templates/intervention/detail/view.html:30
@@ -1060,7 +1064,7 @@ msgstr "Keine Flächenmenge für Abbuchungen eingegeben. Bitte bearbeiten."
 msgid "Missing"
 msgstr "fehlt"
 
-#: compensation/templates/compensation/detail/eco_account/view.html:70
+#: compensation/templates/compensation/detail/eco_account/view.html:71
 #: compensation/templates/compensation/report/eco_account/report.html:24
 #: ema/templates/ema/detail/view.html:57
 #: ema/templates/ema/report/report.html:24
@@ -1976,7 +1980,7 @@ msgstr "{} wurde erfolgreich vom Nutzer {} geprüft! {}"
 msgid "missing"
 msgstr "fehlt"
 
-#: konova/views.py:96 templates/navbars/navbar.html:16
+#: konova/views.py:99 templates/navbars/navbar.html:16
 msgid "Home"
 msgstr "Home"
 
@@ -3993,9 +3997,6 @@ msgstr ""
 #~ msgid "General data edited"
 #~ msgstr "Allgemeine Daten bearbeitet"
 
-#~ msgid "Action type details"
-#~ msgstr "Zusatzmerkmale"
-
 #~ msgid "On registered data edited"
 #~ msgstr "Wenn meine freigegebenen Daten bearbeitet wurden"
 
diff --git a/templates/form/scripts/jstree-scripts.html b/templates/form/scripts/jstree-scripts.html
deleted file mode 100644
index c9367609..00000000
--- a/templates/form/scripts/jstree-scripts.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/themes/default/style.min.css" />
-<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.2.1/jstree.min.js"></script>
\ No newline at end of file

From c0de1ae28d5331b692b0816eca501c1fb22b184a Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Tue, 15 Feb 2022 10:56:49 +0100
Subject: [PATCH 07/26] #112 AbstractCompensation rendering enhancements

* minor changes to detail view rendering of EMA, Compensation and EcoAccount
---
 .../compensation/includes/states-after.html   |  14 +--
 .../compensation/includes/states-before.html  |  14 +--
 .../eco_account/includes/states-after.html    |  14 +--
 .../eco_account/includes/states-before.html   |  14 +--
 .../ema/detail/includes/states-after.html     |  14 +--
 .../ema/detail/includes/states-before.html    |  14 +--
 locale/de/LC_MESSAGES/django.mo               | Bin 37523 -> 37589 bytes
 locale/de/LC_MESSAGES/django.po               |  91 +++++++++---------
 8 files changed, 90 insertions(+), 85 deletions(-)

diff --git a/compensation/templates/compensation/detail/compensation/includes/states-after.html b/compensation/templates/compensation/detail/compensation/includes/states-after.html
index 2c95ca1a..7faa0f1e 100644
--- a/compensation/templates/compensation/detail/compensation/includes/states-after.html
+++ b/compensation/templates/compensation/detail/compensation/includes/states-after.html
@@ -48,13 +48,13 @@
             {% for state in after_states %}
             <tr>
                 <td>
-                    <span>{{ state.biotope_type }}</span>
-                    {% if state.biotope_type_details.count > 0 %}
-                        <br>
-                        {% for detail in state.biotope_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    <span>{{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})</span>
+                    <br>
+                    {% for detail in state.biotope_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No biotope type details' %}">{% trans 'No biotope type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td>{{ state.surface|floatformat:2 }} m²</td>
                 <td class="align-middle float-right">
diff --git a/compensation/templates/compensation/detail/compensation/includes/states-before.html b/compensation/templates/compensation/detail/compensation/includes/states-before.html
index d2ba3697..23faed43 100644
--- a/compensation/templates/compensation/detail/compensation/includes/states-before.html
+++ b/compensation/templates/compensation/detail/compensation/includes/states-before.html
@@ -48,13 +48,13 @@
             {% for state in before_states %}
             <tr>
                 <td>
-                    <span>{{ state.biotope_type }}</span>
-                    {% if state.biotope_type_details.count > 0 %}
-                        <br>
-                        {% for detail in state.biotope_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    <span>{{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})</span>
+                    <br>
+                    {% for detail in state.biotope_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No biotope type details' %}">{% trans 'No biotope type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td>{{ state.surface|floatformat:2 }} m²</td>
                 <td class="align-middle float-right">
diff --git a/compensation/templates/compensation/detail/eco_account/includes/states-after.html b/compensation/templates/compensation/detail/eco_account/includes/states-after.html
index bead6f2b..4fce2f0f 100644
--- a/compensation/templates/compensation/detail/eco_account/includes/states-after.html
+++ b/compensation/templates/compensation/detail/eco_account/includes/states-after.html
@@ -48,13 +48,13 @@
             {% for state in after_states %}
             <tr>
                 <td>
-                    <span>{{ state.biotope_type }}</span>
-                    {% if state.biotope_type_details.count > 0 %}
-                        <br>
-                        {% for detail in state.biotope_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    <span>{{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})</span>
+                    <br>
+                    {% for detail in state.biotope_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No biotope type details' %}">{% trans 'No biotope type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td>{{ state.surface|floatformat:2 }} m²</td>
                 <td class="align-middle float-right">
diff --git a/compensation/templates/compensation/detail/eco_account/includes/states-before.html b/compensation/templates/compensation/detail/eco_account/includes/states-before.html
index c19b4049..1c6311cb 100644
--- a/compensation/templates/compensation/detail/eco_account/includes/states-before.html
+++ b/compensation/templates/compensation/detail/eco_account/includes/states-before.html
@@ -48,13 +48,13 @@
             {% for state in before_states %}
             <tr>
                 <td>
-                    <span>{{ state.biotope_type }}</span>
-                    {% if state.biotope_type_details.count > 0 %}
-                        <br>
-                        {% for detail in state.biotope_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    <span>{{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})</span>
+                    <br>
+                    {% for detail in state.biotope_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No biotope type details' %}">{% trans 'No biotope type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td>{{ state.surface|floatformat:2 }} m²</td>
                 <td class="align-middle float-right">
diff --git a/ema/templates/ema/detail/includes/states-after.html b/ema/templates/ema/detail/includes/states-after.html
index e09f4ba5..56e87be1 100644
--- a/ema/templates/ema/detail/includes/states-after.html
+++ b/ema/templates/ema/detail/includes/states-after.html
@@ -46,13 +46,13 @@
             {% for state in after_states %}
             <tr>
                 <td>
-                    <span>{{ state.biotope_type }}</span>
-                    {% if state.biotope_type_details.count > 0 %}
-                        <br>
-                        {% for detail in state.biotope_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    <span>{{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})</span>
+                    <br>
+                    {% for detail in state.biotope_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No biotope type details' %}">{% trans 'No biotope type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td>{{ state.surface|floatformat:2 }} m²</td>
                 <td class="align-middle float-right">
diff --git a/ema/templates/ema/detail/includes/states-before.html b/ema/templates/ema/detail/includes/states-before.html
index 1369829b..2fd7c359 100644
--- a/ema/templates/ema/detail/includes/states-before.html
+++ b/ema/templates/ema/detail/includes/states-before.html
@@ -46,13 +46,13 @@
             {% for state in before_states %}
             <tr>
                 <td>
-                    <span>{{ state.biotope_type }}</span>
-                    {% if state.biotope_type_details.count > 0 %}
-                        <br>
-                        {% for detail in state.biotope_type_details.all %}
-                            <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
-                        {% endfor %}
-                    {% endif %}
+                    <span>{{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})</span>
+                    <br>
+                    {% for detail in state.biotope_type_details.all %}
+                        <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
+                    {% empty %}
+                        <span class="badge badge-pill rlp-r-outline" title="{% trans 'No biotope type details' %}">{% trans 'No biotope type details' %}</span>
+                    {% endfor %}
                 </td>
                 <td>{{ state.surface|floatformat:2 }} m²</td>
                 <td class="align-middle float-right">
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index e9a94ccb374f1fcb49ae6b60cf0df3131a61819d..cbbff8e8beb3e75746f17607296ed15d29eb4fd1 100644
GIT binary patch
delta 10433
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

delta 10403
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
Ul~NnT?H<tK#iqNHXY8u-fBnhVIsgCw

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 9e5c6bb4..90beb1c0 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -3,9 +3,9 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
-#: compensation/filters.py:122 compensation/forms/modalForms.py:37
-#: compensation/forms/modalForms.py:48 compensation/forms/modalForms.py:64
-#: compensation/forms/modalForms.py:357 compensation/forms/modalForms.py:469
+#: compensation/filters.py:122 compensation/forms/modalForms.py:36
+#: compensation/forms/modalForms.py:47 compensation/forms/modalForms.py:63
+#: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:463
 #: intervention/forms/forms.py:54 intervention/forms/forms.py:156
 #: intervention/forms/forms.py:168 intervention/forms/modalForms.py:127
 #: intervention/forms/modalForms.py:140 intervention/forms/modalForms.py:153
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-15 10:08+0100\n"
+"POT-Creation-Date: 2022-02-15 10:53+0100\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"
@@ -95,7 +95,7 @@ msgstr ""
 #: analysis/templates/analysis/reports/includes/eco_account/amount.html:3
 #: analysis/templates/analysis/reports/includes/intervention/amount.html:3
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:3
-#: compensation/forms/modalForms.py:453
+#: compensation/forms/modalForms.py:447
 #: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
 #: intervention/templates/intervention/detail/includes/deductions.html:31
 msgid "Amount"
@@ -213,7 +213,7 @@ msgstr "Abbuchungen"
 
 #: analysis/templates/analysis/reports/includes/eco_account/deductions.html:9
 #: analysis/templates/analysis/reports/includes/eco_account/deductions.html:11
-#: compensation/forms/modalForms.py:195
+#: compensation/forms/modalForms.py:194
 #: compensation/templates/compensation/detail/compensation/includes/states-after.html:36
 #: compensation/templates/compensation/detail/compensation/includes/states-before.html:36
 #: compensation/templates/compensation/detail/eco_account/includes/states-after.html:36
@@ -246,7 +246,7 @@ msgid "Compensation"
 msgstr "Kompensation"
 
 #: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:21
-#: compensation/forms/modalForms.py:77
+#: compensation/forms/modalForms.py:76
 msgid "Payment"
 msgstr "Zahlung"
 
@@ -352,8 +352,8 @@ msgstr "Aussagekräftiger Titel"
 msgid "Compensation XY; Location ABC"
 msgstr "Kompensation XY; Flur ABC"
 
-#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:63
-#: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:468
+#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:62
+#: compensation/forms/modalForms.py:355 compensation/forms/modalForms.py:462
 #: compensation/templates/compensation/detail/compensation/includes/actions.html:35
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:34
 #: compensation/templates/compensation/detail/compensation/includes/documents.html:34
@@ -371,7 +371,7 @@ msgstr "Kompensation XY; Flur ABC"
 msgid "Comment"
 msgstr "Kommentar"
 
-#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:470
+#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:464
 #: intervention/forms/forms.py:182
 msgid "Additional comment"
 msgstr "Zusätzlicher Kommentar"
@@ -469,73 +469,73 @@ msgstr "Ökokonto XY; Flur ABC"
 msgid "Edit Eco-Account"
 msgstr "Ökokonto bearbeiten"
 
-#: compensation/forms/modalForms.py:38
+#: compensation/forms/modalForms.py:37
 msgid "in Euro"
 msgstr "in Euro"
 
-#: compensation/forms/modalForms.py:47
+#: compensation/forms/modalForms.py:46
 #: intervention/templates/intervention/detail/includes/payments.html:31
 msgid "Due on"
 msgstr "Fällig am"
 
-#: compensation/forms/modalForms.py:50
+#: compensation/forms/modalForms.py:49
 msgid "Due on which date"
 msgstr "Zahlung wird an diesem Datum erwartet"
 
-#: compensation/forms/modalForms.py:65 compensation/forms/modalForms.py:358
+#: compensation/forms/modalForms.py:64 compensation/forms/modalForms.py:357
 #: intervention/forms/modalForms.py:154 konova/forms.py:395
 msgid "Additional comment, maximum {} letters"
 msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 
-#: compensation/forms/modalForms.py:78
+#: compensation/forms/modalForms.py:77
 msgid "Add a payment for intervention '{}'"
 msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen"
 
-#: compensation/forms/modalForms.py:98
+#: compensation/forms/modalForms.py:97
 msgid "If there is no date you can enter, please explain why."
 msgstr "Falls Sie kein Datum angeben können, erklären Sie bitte weshalb."
 
-#: compensation/forms/modalForms.py:159 compensation/forms/modalForms.py:171
+#: compensation/forms/modalForms.py:158 compensation/forms/modalForms.py:170
 msgid "Biotope Type"
 msgstr "Biotoptyp"
 
-#: compensation/forms/modalForms.py:162
+#: compensation/forms/modalForms.py:161
 msgid "Select the biotope type"
 msgstr "Biotoptyp wählen"
 
-#: compensation/forms/modalForms.py:176 compensation/forms/modalForms.py:188
+#: compensation/forms/modalForms.py:175 compensation/forms/modalForms.py:187
 msgid "Biotope additional type"
 msgstr "Zusatzbezeichnung"
 
-#: compensation/forms/modalForms.py:179
+#: compensation/forms/modalForms.py:178
 msgid "Select an additional biotope type"
 msgstr "Zusatzbezeichnung wählen"
 
-#: compensation/forms/modalForms.py:198 intervention/forms/modalForms.py:340
+#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:340
 msgid "in m²"
 msgstr ""
 
-#: compensation/forms/modalForms.py:209
+#: compensation/forms/modalForms.py:208
 msgid "New state"
 msgstr "Neuer Zustand"
 
-#: compensation/forms/modalForms.py:210
+#: compensation/forms/modalForms.py:209
 msgid "Insert data for the new state"
 msgstr "Geben Sie die Daten des neuen Zustandes ein"
 
-#: compensation/forms/modalForms.py:217 konova/forms.py:193
+#: compensation/forms/modalForms.py:216 konova/forms.py:193
 msgid "Object removed"
 msgstr "Objekt entfernt"
 
-#: compensation/forms/modalForms.py:328
+#: compensation/forms/modalForms.py:327
 msgid "Deadline Type"
 msgstr "Fristart"
 
-#: compensation/forms/modalForms.py:331
+#: compensation/forms/modalForms.py:330
 msgid "Select the deadline type"
 msgstr "Fristart wählen"
 
-#: compensation/forms/modalForms.py:340
+#: compensation/forms/modalForms.py:339
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
 #: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
 #: ema/templates/ema/detail/includes/deadlines.html:31
@@ -543,51 +543,51 @@ msgstr "Fristart wählen"
 msgid "Date"
 msgstr "Datum"
 
-#: compensation/forms/modalForms.py:343
+#: compensation/forms/modalForms.py:342
 msgid "Select date"
 msgstr "Datum wählen"
 
-#: compensation/forms/modalForms.py:370
+#: compensation/forms/modalForms.py:369
 msgid "New deadline"
 msgstr "Neue Frist"
 
-#: compensation/forms/modalForms.py:371
+#: compensation/forms/modalForms.py:370
 msgid "Insert data for the new deadline"
 msgstr "Geben Sie die Daten der neuen Frist ein"
 
-#: compensation/forms/modalForms.py:411
+#: compensation/forms/modalForms.py:410
 msgid "Action Type"
 msgstr "Maßnahmentyp"
 
-#: compensation/forms/modalForms.py:414
+#: compensation/forms/modalForms.py:413
 msgid "Select the action type"
 msgstr "Maßnahmentyp wählen"
 
-#: compensation/forms/modalForms.py:424 compensation/forms/modalForms.py:436
+#: compensation/forms/modalForms.py:418 compensation/forms/modalForms.py:430
 msgid "Action Type detail"
 msgstr "Zusatzmerkmal"
 
-#: compensation/forms/modalForms.py:427
+#: compensation/forms/modalForms.py:421
 msgid "Select the action type detail"
 msgstr "Zusatzmerkmal wählen"
 
-#: compensation/forms/modalForms.py:441
+#: compensation/forms/modalForms.py:435
 msgid "Unit"
 msgstr "Einheit"
 
-#: compensation/forms/modalForms.py:444
+#: compensation/forms/modalForms.py:438
 msgid "Select the unit"
 msgstr "Einheit wählen"
 
-#: compensation/forms/modalForms.py:456
+#: compensation/forms/modalForms.py:450
 msgid "Insert the amount"
 msgstr "Menge eingeben"
 
-#: compensation/forms/modalForms.py:481
+#: compensation/forms/modalForms.py:475
 msgid "New action"
 msgstr "Neue Maßnahme"
 
-#: compensation/forms/modalForms.py:482
+#: compensation/forms/modalForms.py:476
 msgid "Insert data for the new action"
 msgstr "Geben Sie die Daten der neuen Maßnahme ein"
 
@@ -751,18 +751,19 @@ msgstr "Aktionen"
 
 #: compensation/templates/compensation/detail/compensation/includes/actions.html:57
 #: compensation/templates/compensation/detail/eco_account/includes/actions.html:56
+#: ema/templates/ema/detail/includes/actions.html:54
 msgid "No action type details"
 msgstr "Keine Zusatzmerkmale"
 
 #: compensation/templates/compensation/detail/compensation/includes/actions.html:68
 #: compensation/templates/compensation/detail/eco_account/includes/actions.html:67
-#: ema/templates/ema/detail/includes/actions.html:67
+#: ema/templates/ema/detail/includes/actions.html:65
 msgid "Edit action"
 msgstr "Maßnahme bearbeiten"
 
 #: compensation/templates/compensation/detail/compensation/includes/actions.html:71
 #: compensation/templates/compensation/detail/eco_account/includes/actions.html:70
-#: ema/templates/ema/detail/includes/actions.html:70
+#: ema/templates/ema/detail/includes/actions.html:68
 msgid "Remove action"
 msgstr "Maßnahme entfernen"
 
@@ -892,7 +893,7 @@ msgid "Biotope type"
 msgstr "Biotoptyp"
 
 #: compensation/templates/compensation/detail/compensation/includes/states-after.html:62
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:62
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:64
 #: compensation/templates/compensation/detail/eco_account/includes/states-after.html:62
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:62
 #: ema/templates/ema/detail/includes/states-after.html:60
@@ -901,7 +902,7 @@ msgid "Edit state"
 msgstr "Zustand bearbeiten"
 
 #: compensation/templates/compensation/detail/compensation/includes/states-after.html:65
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:65
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:67
 #: compensation/templates/compensation/detail/eco_account/includes/states-after.html:65
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:65
 #: ema/templates/ema/detail/includes/states-after.html:63
@@ -928,6 +929,10 @@ msgstr "Neuen Ausgangszustand hinzufügen"
 msgid "Missing surfaces according to states after: "
 msgstr "Fehlende Flächenmengen laut Zielzustand: "
 
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:57
+msgid "No biotope type details"
+msgstr "Keine Zusatzbezeichnungen"
+
 #: compensation/templates/compensation/detail/compensation/view.html:44
 msgid "Is CEF compensation"
 msgstr "Ist CEF Maßnahme"

From 4be26fbc226d005f0171fbb79800efb2f6140799 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Tue, 15 Feb 2022 11:32:20 +0100
Subject: [PATCH 08/26] #112 CompensationAction explanation

* updates the help_text for action_type on NewActionModalForm to give a better explanation
---
 compensation/forms/modalForms.py |   2 +-
 locale/de/LC_MESSAGES/django.mo  | Bin 37589 -> 37895 bytes
 locale/de/LC_MESSAGES/django.po  |  31 ++++++++++++++++++++++---------
 3 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/compensation/forms/modalForms.py b/compensation/forms/modalForms.py
index a8d38aa2..cdcc26e9 100644
--- a/compensation/forms/modalForms.py
+++ b/compensation/forms/modalForms.py
@@ -410,7 +410,7 @@ class NewActionModalForm(BaseModalForm):
         label=_("Action Type"),
         label_suffix="",
         required=True,
-        help_text=_("Select the action type"),
+        help_text=_("An action can consist of multiple different action types. All the selected action types are expected to be performed according to the amount and unit below on this form."),
         choices=[],
         widget=CompensationActionTreeCheckboxSelectMultiple(),
     )
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index cbbff8e8beb3e75746f17607296ed15d29eb4fd1..87e1e03a5d6b5139726bf84ca2cdc849f3fe98fe 100644
GIT binary patch
delta 10588
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
Q+CDe!yleaHXZlt9KiXhlYybcN

delta 10252
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
IP449Te<U*2M*si-

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 90beb1c0..b5eae122 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-15 10:53+0100\n"
+"POT-Creation-Date: 2022-02-15 11:27+0100\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"
@@ -560,8 +560,13 @@ msgid "Action Type"
 msgstr "Maßnahmentyp"
 
 #: compensation/forms/modalForms.py:413
-msgid "Select the action type"
-msgstr "Maßnahmentyp wählen"
+msgid ""
+"An action can consist of multiple different action types. All the selected "
+"action types are expected to be performed according to the amount and unit "
+"below on this form."
+msgstr ""
+"Eine Maßnahme kann aus mehreren verschiedenen Maßnahmentypen bestehen. Alle hier gewählten "
+"Einträge sollen mit der weiter unten angegebenen Einheit und Menge umgesetzt werden. "
 
 #: compensation/forms/modalForms.py:418 compensation/forms/modalForms.py:430
 msgid "Action Type detail"
@@ -892,8 +897,17 @@ msgstr "Fehlende Flächenmengen laut Ausgangszustand: "
 msgid "Biotope type"
 msgstr "Biotoptyp"
 
+#: compensation/templates/compensation/detail/compensation/includes/states-after.html:56
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:56
+#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:56
+#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:56
+#: ema/templates/ema/detail/includes/states-after.html:54
+#: ema/templates/ema/detail/includes/states-before.html:54
+msgid "No biotope type details"
+msgstr "Keine Zusatzbezeichnungen"
+
 #: compensation/templates/compensation/detail/compensation/includes/states-after.html:62
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:64
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:62
 #: compensation/templates/compensation/detail/eco_account/includes/states-after.html:62
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:62
 #: ema/templates/ema/detail/includes/states-after.html:60
@@ -902,7 +916,7 @@ msgid "Edit state"
 msgstr "Zustand bearbeiten"
 
 #: compensation/templates/compensation/detail/compensation/includes/states-after.html:65
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:67
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:65
 #: compensation/templates/compensation/detail/eco_account/includes/states-after.html:65
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:65
 #: ema/templates/ema/detail/includes/states-after.html:63
@@ -929,10 +943,6 @@ msgstr "Neuen Ausgangszustand hinzufügen"
 msgid "Missing surfaces according to states after: "
 msgstr "Fehlende Flächenmengen laut Zielzustand: "
 
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:57
-msgid "No biotope type details"
-msgstr "Keine Zusatzbezeichnungen"
-
 #: compensation/templates/compensation/detail/compensation/view.html:44
 msgid "Is CEF compensation"
 msgstr "Ist CEF Maßnahme"
@@ -3993,6 +4003,9 @@ msgstr ""
 msgid "Unable to connect to qpid with SASL mechanism %s"
 msgstr ""
 
+#~ msgid "Select the action type"
+#~ msgstr "Maßnahmentyp wählen"
+
 #~ msgid "No revocation"
 #~ msgstr "Kein Widerspruch"
 

From 6d5e2b8d1508bf753f934eb23016aaa0f96414d9 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Tue, 15 Feb 2022 13:23:15 +0100
Subject: [PATCH 09/26] #112 TreeWidget JS

* adds visual support on (de-)selecting checkboxes
* adds same support on initialization of checked checkboxes e.g. on edit forms
---
 .../widgets/checkbox-tree-select-content.html | 21 +++++++
 .../konova/widgets/checkbox-tree-select.html  | 63 ++++++++++++-------
 2 files changed, 62 insertions(+), 22 deletions(-)
 create mode 100644 konova/templates/konova/widgets/checkbox-tree-select-content.html

diff --git a/konova/templates/konova/widgets/checkbox-tree-select-content.html b/konova/templates/konova/widgets/checkbox-tree-select-content.html
new file mode 100644
index 00000000..9bf57253
--- /dev/null
+++ b/konova/templates/konova/widgets/checkbox-tree-select-content.html
@@ -0,0 +1,21 @@
+{% load l10n fontawesome_5 %}
+
+{% for code in codes %}
+<div class="ml-4 tree-element">
+    <label class="tree-label" role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
+        {% if code.is_leaf%}
+        <input class="tree-input" id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="checkbox" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
+        {% else %}
+        {% fa5_icon 'angle-right' %}
+        {% endif %}
+        {{code.long_name}}
+    </label>
+    {% if not code.is_leaf %}
+    <div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse tree-element-children">
+        {% with code.children as codes %}
+        {% include 'konova/widgets/checkbox-tree-select-content.html' %}
+        {% endwith %}
+    </div>
+    {% endif %}
+</div>
+{% endfor %}
\ No newline at end of file
diff --git a/konova/templates/konova/widgets/checkbox-tree-select.html b/konova/templates/konova/widgets/checkbox-tree-select.html
index 5b40d3f1..ddcc60c0 100644
--- a/konova/templates/konova/widgets/checkbox-tree-select.html
+++ b/konova/templates/konova/widgets/checkbox-tree-select.html
@@ -1,23 +1,42 @@
-{% load l10n fontawesome_5 %}
+<div id="tree-root">
+    {% include 'konova/widgets/checkbox-tree-select-content.html' %}
+</div>
 
-<div>
-    {% for code in codes %}
-    <div class="ml-4">
-        <label role="{% if not code.is_leaf%}button{% endif %}" for="input_{{code.pk|unlocalize}}" id="{{code.pk|unlocalize}}" data-toggle="collapse" data-target="#children_{{code.pk|unlocalize}}" aria-expanded="true" aria-controls="children_{{code.pk|unlocalize}}">
-            {% if code.is_leaf%}
-                <input id="input_{{code.pk|unlocalize}}" name="{{ widget.name }}" type="checkbox" value="{{code.pk|unlocalize}}" {% if code.pk|unlocalize in widget.value %}checked{% endif %}/>
-            {% else %}
-                {% fa5_icon 'angle-right' %}
-            {% endif %}
-            {{code.long_name}}
-        </label>
-        {% if not code.is_leaf %}
-            <div id="children_{{code.pk|unlocalize}}" data-toggle="collapse" class="collapse">
-                {% with code.children as codes %}
-                    {% include 'konova/widgets/checkbox-tree-select.html' %}
-                {% endwith %}
-            </div>
-        {% endif %}
-    </div>
-    {% endfor %}
-</div>
\ No newline at end of file
+<script>
+    function toggleSelectedCssClass(element){
+        element = $(element);
+        var cssClass = "badge rlp-r"
+
+        var directParent = element.closest(".tree-element-children")
+        var root = element.parents(".tree-element-children")
+
+        var otherCheckedInputsOfParent = directParent.find('.tree-input:checked');
+        var otherCheckedInputsOfRoot = root.find('.tree-input:checked');
+
+        if(otherCheckedInputsOfParent.length == 0){
+            var parentLabel = directParent.siblings(".tree-label");
+            parentLabel.removeClass(cssClass)
+            if(otherCheckedInputsOfRoot.length == 0){
+                var rootLabel = root.siblings(".tree-label")
+                rootLabel.removeClass(cssClass)
+            }
+        }else{
+            var rootAndParentLabel = root.siblings(".tree-label");
+            rootAndParentLabel.addClass(cssClass);
+        }
+
+    }
+
+    function changeHandler(event){
+        toggleSelectedCssClass(this);
+    }
+
+    // Add event listener on changed checkboxes
+    $(".tree-input").change(changeHandler);
+
+    // initialize all pre-checked checkboxes (e.g. on an edit form)
+    var preCheckedElements = $(".tree-input:checked");
+    preCheckedElements.each(function (index, element){
+        toggleSelectedCssClass(element);
+    })
+</script>
\ No newline at end of file

From 1ea5b4fc39b33a5b6a503cd5e70833c3e957c663 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Tue, 15 Feb 2022 14:35:49 +0100
Subject: [PATCH 10/26] # 112 Search input for TreeWidget

* adds search input field for js-filtering by input
---
 .../konova/widgets/checkbox-tree-select.html  | 22 +++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/konova/templates/konova/widgets/checkbox-tree-select.html b/konova/templates/konova/widgets/checkbox-tree-select.html
index ddcc60c0..3129be8a 100644
--- a/konova/templates/konova/widgets/checkbox-tree-select.html
+++ b/konova/templates/konova/widgets/checkbox-tree-select.html
@@ -1,3 +1,9 @@
+{% load i18n %}
+
+<div class="ml-4 mb-4">
+    <input id="tree-search-input" class="form-control" type="text" placeholder="{% trans 'Search' %}"/>
+</div>
+
 <div id="tree-root">
     {% include 'konova/widgets/checkbox-tree-select-content.html' %}
 </div>
@@ -31,6 +37,22 @@
         toggleSelectedCssClass(this);
     }
 
+    function searchInputHandler(event){
+        var elem = $(this);
+        var val = elem.val()
+        var allTreeElements = $(".tree-element")
+        var allTreeElementsContain = $(".tree-element:contains(" + val + ")")
+        if(val.length > 0){
+            allTreeElements.hide()
+            allTreeElementsContain.show()
+        }else{
+            allTreeElements.show()
+        }
+    }
+
+    // Add event listener on search input
+    $("#tree-search-input").keyup(searchInputHandler)
+
     // Add event listener on changed checkboxes
     $(".tree-input").change(changeHandler);
 

From a160f3fe6ca1caeb4082d7c526ec03c04403b883 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Tue, 15 Feb 2022 15:33:25 +0100
Subject: [PATCH 11/26] #112 Autocomplete enhancements

* enhances filtering for Autocomplete -> parent_parent will be searched for match as well
* adds rendering of parent_parent group for BiotopeAutocomplete
* enhances ordering of registration office autocomplete
---
 konova/autocompletes.py           |  49 +++++++++++++++++++++++++++++-
 konova/static/css/konova.css      |  13 ++++++--
 konova/utils/message_templates.py |   2 +-
 locale/de/LC_MESSAGES/django.mo   | Bin 37895 -> 37936 bytes
 locale/de/LC_MESSAGES/django.po   |  20 +++++++-----
 5 files changed, 73 insertions(+), 11 deletions(-)

diff --git a/konova/autocompletes.py b/konova/autocompletes.py
index 3a79ab68..b07e2088 100644
--- a/konova/autocompletes.py
+++ b/konova/autocompletes.py
@@ -5,7 +5,12 @@ Contact: michel.peltriaux@sgdnord.rlp.de
 Created on: 07.12.20
 
 """
+import collections
+
 from dal_select2.views import Select2QuerySetView, Select2GroupQuerySetView
+from django.core.exceptions import ImproperlyConfigured
+
+from konova.utils.message_templates import UNGROUPED
 from user.models import User
 from django.db.models import Q
 
@@ -139,6 +144,8 @@ class KonovaCodeAutocomplete(Select2GroupQuerySetView):
                 q_or |= Q(short_name__icontains=keyword)
                 q_or |= Q(parent__long_name__icontains=keyword)
                 q_or |= Q(parent__short_name__icontains=keyword)
+                q_or |= Q(parent__parent__long_name__icontains=keyword)
+                q_or |= Q(parent__parent__short_name__icontains=keyword)
                 _filter.add(q_or, Q.AND)
             qs = qs.filter(_filter).distinct()
         return qs
@@ -214,6 +221,41 @@ class BiotopeCodeAutocomplete(KonovaCodeAutocomplete):
     def get_result_label(self, result):
         return f"{result.long_name} ({result.short_name})"
 
+    def get_results(self, context):
+        """Return the options grouped by a common related model.
+
+        Raises ImproperlyConfigured if self.group_by_name is not configured
+        """
+        if not self.group_by_related:
+            raise ImproperlyConfigured("Missing group_by_related.")
+
+        super_groups = collections.OrderedDict()
+
+        object_list = context['object_list']
+
+        for result in object_list:
+            group = result.parent if result.parent else None
+            group_name = f"{group.long_name} ({group.short_name})" if group else UNGROUPED
+            super_group = result.parent.parent if result.parent else None
+            super_group_name = f"{super_group.long_name} ({super_group.short_name})" if super_group else UNGROUPED
+            super_groups.setdefault(super_group_name, {})
+            super_groups[super_group_name].setdefault(group_name, [])
+            super_groups[super_group_name][group_name].append(result)
+
+        return [{
+            'id': None,
+            'text': super_group,
+            'children': [{
+                "id": None,
+                "text": group,
+                "children": [{
+                    'id': self.get_result_value(result),
+                    'text': self.get_result_label(result),
+                    'selected_text': self.get_selected_result_label(result),
+                } for result in results]
+            } for group, results in groups.items()]
+        } for super_group, groups in super_groups.items()]
+
 
 class BiotopeExtraCodeAutocomplete(KonovaCodeAutocomplete):
     """
@@ -284,6 +326,11 @@ class RegistrationOfficeCodeAutocomplete(KonovaCodeAutocomplete):
         self.c = CODELIST_REGISTRATION_OFFICE_ID
         super().__init__(*args, **kwargs)
 
+    def order_by(self, qs):
+        return qs.order_by(
+            "parent__long_name"
+        )
+
 
 class ConservationOfficeCodeAutocomplete(KonovaCodeAutocomplete):
     """
@@ -297,4 +344,4 @@ class ConservationOfficeCodeAutocomplete(KonovaCodeAutocomplete):
         super().__init__(*args, **kwargs)
 
     def get_result_label(self, result):
-        return f"{result.long_name} ({result.short_name})"
\ No newline at end of file
+        return f"{result.long_name} ({result.short_name})"
diff --git a/konova/static/css/konova.css b/konova/static/css/konova.css
index 709d3eb3..7e7f3fd1 100644
--- a/konova/static/css/konova.css
+++ b/konova/static/css/konova.css
@@ -242,15 +242,24 @@ Similar to bootstraps 'shadow-lg'
 .select2-results__option--highlighted{
     background-color: var(--rlp-red) !important;
 }
+/*
 .select2-container--default .select2-results__group{
     background-color: var(--rlp-gray-light);
 }
 .select2-container--default .select2-results__option .select2-results__option{
-    padding-left: 2em !important;
+    padding-left: 1em !important;
+}
+
+ */
+.select2-results__options--nested{
+    padding-left: 1em !important;
 }
 .select2-container--default .select2-results > .select2-results__options{
     max-height: 500px !important;
 }
+/*
 .select2-container--default .select2-results__option .select2-results__option{
     padding-left: 2em;
-}
\ No newline at end of file
+}
+
+ */
\ No newline at end of file
diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py
index c7a2be00..5809b3b6 100644
--- a/konova/utils/message_templates.py
+++ b/konova/utils/message_templates.py
@@ -7,7 +7,7 @@ Created on: 02.08.21
 """
 from django.utils.translation import gettext_lazy as _
 
-
+UNGROUPED = _("Ungrouped")
 FORM_INVALID = _("There was an error on this form.")
 PARAMS_INVALID = _("Invalid parameters")
 INTERVENTION_INVALID = _("There are errors in this intervention.")
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index 87e1e03a5d6b5139726bf84ca2cdc849f3fe98fe..022e9e1a728d186a0e8be95eee8ae29ea5928bee 100644
GIT binary patch
delta 8795
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
A4*&oF

delta 8770
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

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index b5eae122..16b2cd4f 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-15 11:27+0100\n"
+"POT-Creation-Date: 2022-02-15 15:29+0100\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"
@@ -565,8 +565,9 @@ msgid ""
 "action types are expected to be performed according to the amount and unit "
 "below on this form."
 msgstr ""
-"Eine Maßnahme kann aus mehreren verschiedenen Maßnahmentypen bestehen. Alle hier gewählten "
-"Einträge sollen mit der weiter unten angegebenen Einheit und Menge umgesetzt werden. "
+"Eine Maßnahme kann aus mehreren verschiedenen Maßnahmentypen bestehen. Alle "
+"hier gewählten Einträge sollen mit der weiter unten angegebenen Einheit und "
+"Menge umgesetzt werden. "
 
 #: compensation/forms/modalForms.py:418 compensation/forms/modalForms.py:430
 msgid "Action Type detail"
@@ -1765,6 +1766,11 @@ msgstr "Neu"
 msgid "Show"
 msgstr "Anzeigen"
 
+#: konova/templates/konova/widgets/checkbox-tree-select.html:4
+#: templates/generic_index.html:56
+msgid "Search"
+msgstr "Suchen"
+
 #: konova/templates/konova/widgets/generate-content-input.html:6
 msgid "Generate new"
 msgstr "Neu generieren"
@@ -1805,6 +1811,10 @@ msgstr "{} - Freigegebene Daten geprüft"
 msgid "Request for new API token"
 msgstr "Anfrage für neuen API Token"
 
+#: konova/utils/message_templates.py:10
+msgid "Ungrouped"
+msgstr "Ohne Zuordnung"
+
 #: konova/utils/message_templates.py:11
 msgid "There was an error on this form."
 msgstr "Es gab einen Fehler im Formular."
@@ -2270,10 +2280,6 @@ msgstr "Neu"
 msgid "Search for keywords"
 msgstr "Nach Schlagwörtern suchen"
 
-#: templates/generic_index.html:56
-msgid "Search"
-msgstr "Suchen"
-
 #: templates/generic_index.html:57
 msgid "Start search"
 msgstr "Starte Suche"

From ed27d8d589fd298be47bf835c56a605a96048753 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Wed, 16 Feb 2022 08:26:24 +0100
Subject: [PATCH 12/26] #112 Order enhancement

* enhances ordering for action details and biotope details
---
 konova/autocompletes.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/konova/autocompletes.py b/konova/autocompletes.py
index b07e2088..432df614 100644
--- a/konova/autocompletes.py
+++ b/konova/autocompletes.py
@@ -188,7 +188,7 @@ class CompensationActionDetailCodeAutocomplete(KonovaCodeAutocomplete):
 
     def order_by(self, qs):
         return qs.order_by(
-            "parent__long_name"
+            "long_name"
         )
 
 
@@ -281,7 +281,7 @@ class BiotopeExtraCodeAutocomplete(KonovaCodeAutocomplete):
             qs (QuerySet): The ordered queryset
         """
         return qs.order_by(
-            "parent__long_name",
+            "long_name",
         )
 
     def get_result_label(self, result):

From 91185ef847c02d68bd9f2f91248747bdd429d07f Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Wed, 16 Feb 2022 08:31:18 +0100
Subject: [PATCH 13/26] #112 Tree filter case insensitive search

* adds case insensitive search for TreeWidget
---
 konova/templates/konova/widgets/checkbox-tree-select.html | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/konova/templates/konova/widgets/checkbox-tree-select.html b/konova/templates/konova/widgets/checkbox-tree-select.html
index 3129be8a..c2b107cc 100644
--- a/konova/templates/konova/widgets/checkbox-tree-select.html
+++ b/konova/templates/konova/widgets/checkbox-tree-select.html
@@ -41,7 +41,11 @@
         var elem = $(this);
         var val = elem.val()
         var allTreeElements = $(".tree-element")
-        var allTreeElementsContain = $(".tree-element:contains(" + val + ")")
+        var allTreeElementsContain = $(".tree-element").filter(function(){
+            var reg = new RegExp(val, "i");
+            return reg.test($(this).text());
+            }
+        );
         if(val.length > 0){
             allTreeElements.hide()
             allTreeElementsContain.show()

From 8224f4c8c5bc45bb95e815e87d718166ccef089a Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Wed, 16 Feb 2022 09:08:11 +0100
Subject: [PATCH 14/26] # 110 Biotope codes

* removes list 974 from update_codelist.py command
* adds migration for existing biotope states to be changed into proper list
---
 .../management/commands/update_codelist.py    |  3 +-
 codelist/settings.py                          |  2 +-
 konova/migrations/0005_auto_20220216_0856.py  | 40 +++++++++++++++++++
 3 files changed, 42 insertions(+), 3 deletions(-)
 create mode 100644 konova/migrations/0005_auto_20220216_0856.py

diff --git a/codelist/management/commands/update_codelist.py b/codelist/management/commands/update_codelist.py
index 3fd4c6c3..85c90324 100644
--- a/codelist/management/commands/update_codelist.py
+++ b/codelist/management/commands/update_codelist.py
@@ -14,7 +14,7 @@ from codelist.settings import CODELIST_INTERVENTION_HANDLER_ID, CODELIST_CONSERV
     CODELIST_REGISTRATION_OFFICE_ID, CODELIST_BIOTOPES_ID, CODELIST_LAW_ID, CODELIST_COMPENSATION_HANDLER_ID, \
     CODELIST_COMPENSATION_ACTION_ID, CODELIST_COMPENSATION_ACTION_CLASS_ID, CODELIST_COMPENSATION_ADDITIONAL_TYPE_ID, \
     CODELIST_BASE_URL, CODELIST_PROCESS_TYPE_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
-    CODELIST_COMPENSATION_ACTION_DETAIL_ID, CODELIST_AFTER_STATE_BIOTOPES__ID
+    CODELIST_COMPENSATION_ACTION_DETAIL_ID
 from konova.management.commands.setup import BaseKonovaCommand
 from konova.settings import PROXIES
 
@@ -34,7 +34,6 @@ class Command(BaseKonovaCommand):
                 CODELIST_CONSERVATION_OFFICE_ID,
                 CODELIST_REGISTRATION_OFFICE_ID,
                 CODELIST_BIOTOPES_ID,
-                CODELIST_AFTER_STATE_BIOTOPES__ID,
                 CODELIST_BIOTOPES_EXTRA_CODES_ID,
                 CODELIST_LAW_ID,
                 CODELIST_COMPENSATION_HANDLER_ID,
diff --git a/codelist/settings.py b/codelist/settings.py
index 53cef730..b4226b5e 100644
--- a/codelist/settings.py
+++ b/codelist/settings.py
@@ -14,7 +14,7 @@ CODELIST_INTERVENTION_HANDLER_ID = 903  # CLMassnahmeträger
 CODELIST_CONSERVATION_OFFICE_ID = 907  # CLNaturschutzbehörden
 CODELIST_REGISTRATION_OFFICE_ID = 1053  # CLZulassungsbehörden
 CODELIST_BIOTOPES_ID = 654  # CL_Biotoptypen
-CODELIST_AFTER_STATE_BIOTOPES__ID = 974  # CL-KSP_ZielBiotoptypen
+CODELIST_AFTER_STATE_BIOTOPES__ID = 974  # CL-KSP_ZielBiotoptypen - USAGE HAS BEEN DROPPED IN 2022 IN FAVOR OF 654
 CODELIST_BIOTOPES_EXTRA_CODES_ID = 975  # CLZusatzbezeichnung
 CODELIST_LAW_ID = 1048  # CLVerfahrensrecht
 CODELIST_PROCESS_TYPE_ID = 44382  # CLVerfahrenstyp
diff --git a/konova/migrations/0005_auto_20220216_0856.py b/konova/migrations/0005_auto_20220216_0856.py
new file mode 100644
index 00000000..43c518ae
--- /dev/null
+++ b/konova/migrations/0005_auto_20220216_0856.py
@@ -0,0 +1,40 @@
+# Generated by Django 3.1.3 on 2022-02-16 07:56
+
+from django.db import migrations, transaction
+
+from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_AFTER_STATE_BIOTOPES__ID
+
+
+def migrate_biotopes_from_974_to_654(apps, schema_editor):
+    KonovaCode = apps.get_model("codelist", "KonovaCode")
+    CompensationState = apps.get_model("compensation", "CompensationState")
+    all_states = CompensationState.objects.all()
+
+    with transaction.atomic():
+        for state in all_states:
+            new_biotope_code = KonovaCode.objects.get(
+                code_lists__in=[CODELIST_BIOTOPES_ID],
+                is_selectable=True,
+                is_archived=False,
+                short_name=state.biotope_type.short_name,
+            )
+            state.biotope_type = new_biotope_code
+            state.save()
+
+        all_states = CompensationState.objects.all()
+        after_state_list_elements = all_states.filter(
+            biotope_type__code_lists__in=[CODELIST_AFTER_STATE_BIOTOPES__ID]
+        )
+        if after_state_list_elements.count() > 0:
+            raise Exception("Still states with wrong codelist entries!")
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('konova', '0004_auto_20220209_0839'),
+    ]
+
+    operations = [
+        migrations.RunPython(migrate_biotopes_from_974_to_654),
+    ]

From 0677cec709a5d68e66b4e58c6cb874707fee0e8b Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Wed, 16 Feb 2022 09:44:56 +0100
Subject: [PATCH 15/26] #118 API ActionTypes

* adds support for multiple action_type entries on one CompensationAction
---
 api/utils/serializer/v1/serializer.py | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/api/utils/serializer/v1/serializer.py b/api/utils/serializer/v1/serializer.py
index f56db81b..caae2de3 100644
--- a/api/utils/serializer/v1/serializer.py
+++ b/api/utils/serializer/v1/serializer.py
@@ -367,7 +367,9 @@ class AbstractCompensationAPISerializerV1Mixin:
         """
         actions = []
         for entry in actions_data:
-            action = entry["action"]
+            action_types = [
+                self._konova_code_from_json(e, CODELIST_COMPENSATION_ACTION_ID) for e in entry["action_types"]
+            ]
             action_details = [
                 self._konova_code_from_json(e, CODELIST_COMPENSATION_ACTION_DETAIL_ID) for e in entry["action_details"]
             ]
@@ -384,7 +386,7 @@ class AbstractCompensationAPISerializerV1Mixin:
             # If this exact data is already existing, we do not create it new. Instead put it's id in the list of
             # entries, we will use to set the new actions
             action_entry = obj.actions.filter(
-                action_type__atom_id=action,
+                action_type__in=action_types,
                 amount=amount,
                 unit=unit,
                 comment=comment,
@@ -396,13 +398,13 @@ class AbstractCompensationAPISerializerV1Mixin:
             else:
                 # Create and add id to list
                 action_entry = CompensationAction.objects.create(
-                    action_type=self._konova_code_from_json(action, CODELIST_COMPENSATION_ACTION_ID),
                     amount=amount,
                     unit=unit,
                     comment=comment,
                 )
                 actions.append(action_entry.id)
 
+            action_entry.action_type.set(action_types)
             action_entry.action_type_details.set(action_details)
         obj.actions.set(actions)
         return obj
@@ -438,7 +440,9 @@ class AbstractCompensationAPISerializerV1Mixin:
         """
         return [
             {
-                "action": self._konova_code_to_json(entry.action_type),
+                "action_types": [
+                    self._konova_code_to_json(action) for action in entry.action_type.all()
+                ],
                 "action_details": [
                     self._konova_code_to_json(detail) for detail in entry.action_type_details.all()
                 ],

From c7382f1e54f35e82bfa49f38865725f9af0955c3 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Wed, 16 Feb 2022 11:38:24 +0100
Subject: [PATCH 16/26] #118 API pagination

* adds pagination and related parameters to GET apis
* updates api GET test
---
 api/tests/v1/get/test_api_get.py   |  7 ++++-
 api/utils/serializer/serializer.py | 12 +++++--
 api/views/v1/views.py              | 17 ++++++----
 api/views/views.py                 | 50 ++++++++++++++++++++++++++----
 4 files changed, 71 insertions(+), 15 deletions(-)

diff --git a/api/tests/v1/get/test_api_get.py b/api/tests/v1/get/test_api_get.py
index 38af864b..3c464542 100644
--- a/api/tests/v1/get/test_api_get.py
+++ b/api/tests/v1/get/test_api_get.py
@@ -36,7 +36,12 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         """
         response = self._run_get_request(url)
         content = json.loads(response.content)
-        geojson = content[str(obj.id)]
+        self.assertIn("rpp", content)
+        self.assertIn("p", content)
+        self.assertIn("next", content)
+        self.assertIn("results", content)
+        paginated_content = content["results"]
+        geojson = paginated_content[str(obj.id)]
         self.assertEqual(response.status_code, 200, msg=response.content)
         return geojson
 
diff --git a/api/utils/serializer/serializer.py b/api/utils/serializer/serializer.py
index 443e10c5..8d618e44 100644
--- a/api/utils/serializer/serializer.py
+++ b/api/utils/serializer/serializer.py
@@ -10,6 +10,7 @@ from abc import abstractmethod
 
 from django.contrib.gis import geos
 from django.contrib.gis.geos import GEOSGeometry
+from django.core.paginator import Paginator
 
 from konova.utils.message_templates import DATA_UNSHARED
 
@@ -19,6 +20,10 @@ class AbstractModelAPISerializer:
     lookup = None
     properties_data = None
 
+    rpp = None
+    page_number = None
+    paginator = None
+
     class Meta:
         abstract = True
 
@@ -80,9 +85,12 @@ class AbstractModelAPISerializer:
         Returns:
             serialized_data (dict)
         """
-        entries = self.model.objects.filter(**self.lookup)
+        entries = self.model.objects.filter(**self.lookup).order_by("id")
+        self.paginator = Paginator(entries, self.rpp)
+        requested_entries = self.paginator.page(self.page_number)
+
         serialized_data = {}
-        for entry in entries:
+        for entry in requested_entries.object_list:
             serialized_data[str(entry.id)] = self._model_to_geo_json(entry)
         return serialized_data
 
diff --git a/api/views/v1/views.py b/api/views/v1/views.py
index 7789680f..8da5d49e 100644
--- a/api/views/v1/views.py
+++ b/api/views/v1/views.py
@@ -21,7 +21,6 @@ class AbstractAPIViewV1(AbstractAPIView):
     """ Holds general serialization functions for API v1
 
     """
-    serializer = None
 
     def __init__(self, *args, **kwargs):
         self.lookup = {
@@ -45,11 +44,17 @@ class AbstractAPIViewV1(AbstractAPIView):
             response (JsonResponse)
         """
         try:
+            self.rpp = int(request.GET.get("rpp", self.rpp))
+            self.page_number = int(request.GET.get("p", self.page_number))
+
+            self.serializer.rpp = self.rpp
+            self.serializer.page_number = self.page_number
+
             self.serializer.prepare_lookup(id, self.user)
             data = self.serializer.fetch_and_serialize()
         except Exception as e:
-            return self.return_error_response(e, 500)
-        return JsonResponse(data)
+            return self._return_error_response(e, 500)
+        return self._return_response(request, data)
 
     def post(self, request: HttpRequest):
         """ Handles the POST request
@@ -67,7 +72,7 @@ class AbstractAPIViewV1(AbstractAPIView):
             body = json.loads(body)
             created_id = self.serializer.create_model_from_json(body, self.user)
         except Exception as e:
-            return self.return_error_response(e, 500)
+            return self._return_error_response(e, 500)
         return JsonResponse({"id": created_id})
 
     def put(self, request: HttpRequest, id=None):
@@ -87,7 +92,7 @@ class AbstractAPIViewV1(AbstractAPIView):
             body = json.loads(body)
             updated_id = self.serializer.update_model_from_json(id, body, self.user)
         except Exception as e:
-            return self.return_error_response(e, 500)
+            return self._return_error_response(e, 500)
         return JsonResponse({"id": updated_id})
 
     def delete(self, request: HttpRequest, id=None):
@@ -104,7 +109,7 @@ class AbstractAPIViewV1(AbstractAPIView):
         try:
             success = self.serializer.delete_entry(id, self.user)
         except Exception as e:
-            return self.return_error_response(e, 500)
+            return self._return_error_response(e, 500)
         return JsonResponse(
             {
                 "success": success,
diff --git a/api/views/views.py b/api/views/views.py
index fb4f6df1..35c54fee 100644
--- a/api/views/views.py
+++ b/api/views/views.py
@@ -31,10 +31,22 @@ class AbstractAPIView(View):
 
     """
     user = None
+    serializer = None
+    rpp = 5  # Results per page default
+    page_number = 1  # Page number default
 
     class Meta:
         abstract = True
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.response_body_base = {
+            "rpp": None,
+            "p": None,
+            "next": None,
+            "results": None
+        }
+
     @csrf_exempt
     def dispatch(self, request, *args, **kwargs):
         try:
@@ -42,13 +54,14 @@ class AbstractAPIView(View):
             ksp_token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
             ksp_user = request.headers.get(KSP_USER_HEADER_IDENTIFIER, None)
             self.user = APIUserToken.get_user_from_token(ksp_token, ksp_user)
+            request.user = self.user
             if not self.user.is_default_user():
                 raise PermissionError("Default permissions required")
         except PermissionError as e:
-            return self.return_error_response(e, 403)
+            return self._return_error_response(e, 403)
         return super().dispatch(request, *args, **kwargs)
 
-    def return_error_response(self, error, status_code=500):
+    def _return_error_response(self, error, status_code=500):
         """ Returns an error as JsonReponse
 
         Args:
@@ -68,6 +81,31 @@ class AbstractAPIView(View):
             status=status_code
         )
 
+    def _return_response(self, request: HttpRequest, data):
+        """ Returns all important data into a response object
+
+        Args:
+            request (HttpRequest): The incoming request
+            data (dict): The serialized data
+
+        Returns:
+            response (JsonResponse): The response to be returned
+        """
+        response = self.response_body_base
+        next_page = self.page_number + 1
+        next_page = next_page if next_page in self.serializer.paginator.page_range else None
+        if next_page is not None:
+            next_url = request.build_absolute_uri(
+                request.path + f"?rpp={self.rpp}&p={next_page}"
+            )
+        else:
+            next_url = None
+        response["rpp"] = self.rpp
+        response["p"] = self.page_number
+        response["next"] = next_url
+        response["results"] = data
+        return JsonResponse(response)
+
 
 class InterventionCheckAPIView(AbstractAPIView):
 
@@ -82,14 +120,14 @@ class InterventionCheckAPIView(AbstractAPIView):
             response (JsonResponse)
         """
         if not self.user.is_zb_user():
-            return self.return_error_response("Permission not granted", 403)
+            return self._return_error_response("Permission not granted", 403)
         try:
             obj = Intervention.objects.get(
                 id=id,
                 users__in=[self.user]
             )
         except Exception as e:
-            return self.return_error_response(e)
+            return self._return_error_response(e)
 
         all_valid, check_details = self.run_quality_checks(obj)
 
@@ -161,7 +199,7 @@ class AbstractModelShareAPIView(AbstractAPIView):
         try:
             users = self._get_shared_users_of_object(id)
         except Exception as e:
-            return self.return_error_response(e)
+            return self._return_error_response(e)
 
         data = {
             "users": [
@@ -185,7 +223,7 @@ class AbstractModelShareAPIView(AbstractAPIView):
         try:
             success = self._process_put_body(request.body, id)
         except Exception as e:
-            return self.return_error_response(e)
+            return self._return_error_response(e)
         data = {
             "success": success,
         }

From 5ccb63d27b18fa3d06e335421d88b88f70767728 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Wed, 16 Feb 2022 12:35:19 +0100
Subject: [PATCH 17/26] #114 Unshared Account Deductions

* enables deducting from unshared eco accounts
   * account must be recorded and not deleted, so users can use it for deductions
---
 .../detail/eco_account/includes/deductions.html   |  4 ++--
 compensation/tests/ecoaccount/test_workflow.py    |  2 ++
 compensation/views/eco_account.py                 |  9 ++++++---
 intervention/tests/test_workflow.py               | 15 ++-------------
 konova/autocompletes.py                           |  3 +--
 5 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/compensation/templates/compensation/detail/eco_account/includes/deductions.html b/compensation/templates/compensation/detail/eco_account/includes/deductions.html
index 10f177ea..b91fb21f 100644
--- a/compensation/templates/compensation/detail/eco_account/includes/deductions.html
+++ b/compensation/templates/compensation/detail/eco_account/includes/deductions.html
@@ -10,7 +10,7 @@
             </div>
             <div class="col-sm-6">
                 <div class="d-flex justify-content-end">
-                    {% if is_default_member and has_access  %}
+                    {% if is_default_member and obj.recorded %}
                     <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-deduction' obj.id %}" title="{% trans 'Add new deduction' %}">
                         {% fa5_icon 'plus' %}
                         {% fa5_icon 'tree' %}
@@ -61,7 +61,7 @@
                 <td class="align-middle">{{ deduction.surface|floatformat:2|intcomma }} m²</td>
                 <td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
                 <td class="align-middle float-right">
-                    {% if is_default_member and has_access  %}
+                    {% if is_default_member and has_access or is_default_member and user in deduction.intervention.shared_users  %}
                     <button data-form-url="{% url 'compensation:acc:edit-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit Deduction' %}">
                         {% fa5_icon 'edit' %}
                     </button>
diff --git a/compensation/tests/ecoaccount/test_workflow.py b/compensation/tests/ecoaccount/test_workflow.py
index 1cdb0308..afc4111e 100644
--- a/compensation/tests/ecoaccount/test_workflow.py
+++ b/compensation/tests/ecoaccount/test_workflow.py
@@ -231,7 +231,9 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
     def test_edit_deduction(self):
         test_surface = self.eco_account.get_available_rest()[0]
         self.eco_account.set_recorded(self.superuser)
+        self.intervention.share_with(self.superuser)
         self.eco_account.refresh_from_db()
+        self.assertIn(self.superuser, self.intervention.is_shared_with(self.superuser))
 
         deduction = EcoAccountDeduction.objects.create(
             intervention=self.intervention,
diff --git a/compensation/views/eco_account.py b/compensation/views/eco_account.py
index cf5f3288..d291218f 100644
--- a/compensation/views/eco_account.py
+++ b/compensation/views/eco_account.py
@@ -272,7 +272,6 @@ def remove_view(request: HttpRequest, id: str):
 
 @login_required
 @default_group_required
-@shared_access_required(EcoAccount, "id")
 def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
     """ Renders a modal view for removing deductions
 
@@ -287,6 +286,8 @@ def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
     acc = get_object_or_404(EcoAccount, id=id)
     try:
         eco_deduction = acc.deductions.get(id=deduction_id)
+        if not eco_deduction.intervention.is_shared_with(request.user):
+            raise ObjectDoesNotExist()
     except ObjectDoesNotExist:
         raise Http404("Unknown deduction")
 
@@ -300,7 +301,6 @@ def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
 
 @login_required
 @default_group_required
-@shared_access_required(EcoAccount, "id")
 def deduction_edit_view(request: HttpRequest, id: str, deduction_id: str):
     """ Renders a modal view for editing deductions
 
@@ -315,6 +315,8 @@ def deduction_edit_view(request: HttpRequest, id: str, deduction_id: str):
     acc = get_object_or_404(EcoAccount, id=id)
     try:
         eco_deduction = acc.deductions.get(id=deduction_id)
+        if not eco_deduction.intervention.is_shared_with(request.user):
+            raise ObjectDoesNotExist
     except ObjectDoesNotExist:
         raise Http404("Unknown deduction")
 
@@ -679,7 +681,6 @@ def remove_document_view(request: HttpRequest, id: str, doc_id: str):
 
 @login_required
 @default_group_required
-@shared_access_required(EcoAccount, "id")
 def new_deduction_view(request: HttpRequest, id: str):
     """ Renders a modal form view for creating deductions
 
@@ -691,6 +692,8 @@ def new_deduction_view(request: HttpRequest, id: str):
 
     """
     acc = get_object_or_404(EcoAccount, id=id)
+    if not acc.recorded:
+        raise Http404()
     form = NewDeductionModalForm(request.POST or None, instance=acc, request=request)
     return form.process_request(
         request,
diff --git a/intervention/tests/test_workflow.py b/intervention/tests/test_workflow.py
index 69f606f0..1a66245c 100644
--- a/intervention/tests/test_workflow.py
+++ b/intervention/tests/test_workflow.py
@@ -303,7 +303,6 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
         Reasons for failing are:
             * EcoAccount does not provide enough 'deductable_surface'
             * EcoAccount is not recorded (not "approved"), yet
-            * EcoAccount is not shared with performing user
 
         Args:
             new_url (str): The url to send the post data to
@@ -315,7 +314,6 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
         # Before running fail positive tests, we need to have an account in a (normally) fine working state
         self.assertIsNotNone(self.eco_account.recorded)  # -> is recorded
         self.assertGreater(self.eco_account.deductable_surface, test_surface)  # -> has more deductable surface than we need
-        self.assertIn(self.superuser, self.eco_account.users.all())  # -> is shared with the performing user
 
         # Count the number of already existing deductions in total and for the account for later comparison
         num_deductions = self.eco_account.deductions.count()
@@ -333,20 +331,11 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
         self.assertEqual(num_deductions, self.eco_account.deductions.count())
         self.assertEqual(num_deductions_total, EcoAccountDeduction.objects.count())
 
-        # Now restore the deductable surface to a valid size back again but remove the user from the shared list
+        # Now restore the deductable surface to a valid size back again
         self.eco_account.deductable_surface = test_surface + 100.00
-        self.eco_account.share_with_list([])
         self.eco_account.save()
 
-        # Now perform the (expected) failing request (again)
-        self.client_user.post(new_url, post_data)
-
-        # Expect no changes at all, since the account is not shared
-        self.assertEqual(num_deductions, self.eco_account.deductions.count())
-        self.assertEqual(num_deductions_total, EcoAccountDeduction.objects.count())
-
-        # Restore the sharing but remove the recording state
-        self.eco_account.share_with_list([self.superuser])
+        # Remove the recording state
         self.eco_account.recorded.delete()
         self.eco_account.refresh_from_db()
         self.eco_account.save()
diff --git a/konova/autocompletes.py b/konova/autocompletes.py
index 432df614..f1775b5f 100644
--- a/konova/autocompletes.py
+++ b/konova/autocompletes.py
@@ -25,7 +25,7 @@ from intervention.models import Intervention
 class EcoAccountAutocomplete(Select2QuerySetView):
     """ Autocomplete for ecoAccount entries
 
-    Only returns entries that are accessible for the requesting user and already are recorded
+    Only returns entries that are already recorded and not deleted
 
     """
     def get_queryset(self):
@@ -34,7 +34,6 @@ class EcoAccountAutocomplete(Select2QuerySetView):
         qs = EcoAccount.objects.filter(
             deleted=None,
             recorded__isnull=False,
-            users__in=[self.request.user],
         ).order_by(
             "identifier"
         )

From 75c70ff8dcf7d7a6bbb093871dd73a51d5f36e09 Mon Sep 17 00:00:00 2001
From: mpeltriaux <Michel.Peltriaux@sgdnord.rlp.de>
Date: Thu, 17 Feb 2022 13:13:32 +0100
Subject: [PATCH 18/26] #101 Team settings

* adds first implementation for team managing
---
 intervention/forms/modalForms.py    |   6 +-
 konova/models/object.py             |  41 ++++++-----
 user/forms.py                       | 110 +++++++++++++++++++++++++++-
 user/models/__init__.py             |   7 +-
 user/models/team.py                 |  16 ++++
 user/templates/user/index.html      |   8 ++
 user/templates/user/team/index.html |  67 +++++++++++++++++
 user/urls.py                        |   4 +
 user/views.py                       |  58 ++++++++++++++-
 9 files changed, 285 insertions(+), 32 deletions(-)
 create mode 100644 user/models/team.py
 create mode 100644 user/templates/user/team/index.html

diff --git a/intervention/forms/modalForms.py b/intervention/forms/modalForms.py
index a8fa98de..0b72ae84 100644
--- a/intervention/forms/modalForms.py
+++ b/intervention/forms/modalForms.py
@@ -7,11 +7,11 @@ Created on: 27.09.21
 """
 from dal import autocomplete
 from django.core.exceptions import ObjectDoesNotExist
-from django.db.models.fields.files import FieldFile
 
 from konova.utils.message_templates import DEDUCTION_ADDED, REVOCATION_ADDED, DEDUCTION_REMOVED, DEDUCTION_EDITED, \
-    REVOCATION_EDITED, FILE_TYPE_UNSUPPORTED, FILE_SIZE_TOO_LARGE
-from user.models import User, UserActionLogEntry
+    REVOCATION_EDITED
+from user.models import User
+from user.models import UserActionLogEntry
 from django.db import transaction
 from django import forms
 from django.utils.translation import gettext_lazy as _
diff --git a/konova/models/object.py b/konova/models/object.py
index a6164f5a..69a0a2e7 100644
--- a/konova/models/object.py
+++ b/konova/models/object.py
@@ -16,7 +16,6 @@ from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP, LANIS_ZOOM_LUT,
 from konova.tasks import celery_send_mail_shared_access_removed, celery_send_mail_shared_access_given, \
     celery_send_mail_shared_data_recorded, celery_send_mail_shared_data_unrecorded, \
     celery_send_mail_shared_data_deleted, celery_send_mail_shared_data_checked
-from user.models import User
 from django.core.exceptions import ObjectDoesNotExist
 from django.http import HttpRequest
 from django.utils.timezone import now
@@ -28,7 +27,6 @@ from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_I
 from konova.utils import generators
 from konova.utils.generators import generate_random_string
 from konova.utils.message_templates import CHECKED_RECORDED_RESET, GEOMETRY_CONFLICT_WITH_TEMPLATE
-from user.models import UserActionLogEntry, UserAction
 
 
 class UuidModel(models.Model):
@@ -50,14 +48,14 @@ class BaseResource(UuidModel):
     A basic resource model, which defines attributes for every derived model
     """
     created = models.ForeignKey(
-        UserActionLogEntry,
+        "user.UserActionLogEntry",
         on_delete=models.SET_NULL,
         null=True,
         blank=True,
         related_name='+'
     )
     modified = models.ForeignKey(
-        UserActionLogEntry,
+        "user.UserActionLogEntry",
         on_delete=models.SET_NULL,
         null=True,
         blank=True,
@@ -94,9 +92,9 @@ class BaseObject(BaseResource):
     """
     identifier = models.CharField(max_length=1000, null=True, blank=True)
     title = models.CharField(max_length=1000, null=True, blank=True)
-    deleted = models.ForeignKey(UserActionLogEntry, on_delete=models.SET_NULL, null=True, blank=True, related_name='+')
+    deleted = models.ForeignKey("user.UserActionLogEntry", on_delete=models.SET_NULL, null=True, blank=True, related_name='+')
     comment = models.TextField(null=True, blank=True)
-    log = models.ManyToManyField(UserActionLogEntry, blank=True, help_text="Keeps all user actions of an object", editable=False)
+    log = models.ManyToManyField("user.UserActionLogEntry", blank=True, help_text="Keeps all user actions of an object", editable=False)
 
     class Meta:
         abstract = True
@@ -105,7 +103,7 @@ class BaseObject(BaseResource):
     def set_status_messages(self, request: HttpRequest):
         raise NotImplementedError
 
-    def mark_as_deleted(self, user: User, send_mail: bool = True):
+    def mark_as_deleted(self, user, send_mail: bool = True):
         """ Mark an entry as deleted
 
         Does not delete from database but sets a timestamp for being deleted on and which user deleted the object
@@ -116,6 +114,7 @@ class BaseObject(BaseResource):
         Returns:
 
         """
+        from user.models import UserActionLogEntry
         if self.deleted:
             # Nothing to do here
             return
@@ -133,7 +132,7 @@ class BaseObject(BaseResource):
 
             self.save()
 
-    def mark_as_edited(self, performing_user: User, request: HttpRequest = None, edit_comment: str = None):
+    def mark_as_edited(self, performing_user, request: HttpRequest = None, edit_comment: str = None):
         """ In case the object or a related object changed the log history needs to be updated
 
         Args:
@@ -144,13 +143,14 @@ class BaseObject(BaseResource):
         Returns:
 
         """
+        from user.models import UserActionLogEntry
         edit_action = UserActionLogEntry.get_edited_action(performing_user, edit_comment)
         self.modified = edit_action
         self.log.add(edit_action)
         self.save()
         return edit_action
 
-    def add_log_entry(self, action: UserAction, user: User, comment: str):
+    def add_log_entry(self, action, user, comment: str):
         """ Wraps adding of UserActionLogEntry to log
 
         Args:
@@ -161,6 +161,7 @@ class BaseObject(BaseResource):
         Returns:
 
         """
+        from user.models import UserActionLogEntry
         user_action = UserActionLogEntry.objects.create(
             user=user,
             action=action,
@@ -229,7 +230,7 @@ class RecordableObjectMixin(models.Model):
     """
     # Refers to "verzeichnen"
     recorded = models.OneToOneField(
-        UserActionLogEntry,
+        "user.UserActionLogEntry",
         on_delete=models.SET_NULL,
         null=True,
         blank=True,
@@ -240,7 +241,7 @@ class RecordableObjectMixin(models.Model):
     class Meta:
         abstract = True
 
-    def set_unrecorded(self, user: User):
+    def set_unrecorded(self, user):
         """ Perform unrecording
 
         Args:
@@ -249,6 +250,7 @@ class RecordableObjectMixin(models.Model):
         Returns:
 
         """
+        from user.models import UserActionLogEntry
         if not self.recorded:
             return None
         action = UserActionLogEntry.get_unrecorded_action(user)
@@ -262,7 +264,7 @@ class RecordableObjectMixin(models.Model):
 
         return action
 
-    def set_recorded(self, user: User):
+    def set_recorded(self, user):
         """ Perform recording
 
         Args:
@@ -271,6 +273,7 @@ class RecordableObjectMixin(models.Model):
         Returns:
 
         """
+        from user.models import UserActionLogEntry
         if self.recorded:
             return None
         action = UserActionLogEntry.get_recorded_action(user)
@@ -284,7 +287,7 @@ class RecordableObjectMixin(models.Model):
 
         return action
 
-    def unrecord(self, performing_user: User, request: HttpRequest = None):
+    def unrecord(self, performing_user, request: HttpRequest = None):
         """ Unrecords a dataset
 
         Args:
@@ -318,7 +321,7 @@ class RecordableObjectMixin(models.Model):
 class CheckableObjectMixin(models.Model):
     # Checks - Refers to "Genehmigen" but optional
     checked = models.OneToOneField(
-        UserActionLogEntry,
+        "user.UserActionLogEntry",
         on_delete=models.SET_NULL,
         null=True,
         blank=True,
@@ -346,7 +349,7 @@ class CheckableObjectMixin(models.Model):
         self.save()
         return None
 
-    def set_checked(self, user: User) -> UserActionLogEntry:
+    def set_checked(self, user):
         """ Perform checking
 
         Args:
@@ -355,6 +358,7 @@ class CheckableObjectMixin(models.Model):
         Returns:
 
         """
+        from user.models import UserActionLogEntry
         if self.checked:
             # Nothing to do
             return
@@ -373,7 +377,7 @@ class CheckableObjectMixin(models.Model):
 
 class ShareableObjectMixin(models.Model):
     # Users having access on this object
-    users = models.ManyToManyField(User, help_text="Users having access (data shared with)")
+    users = models.ManyToManyField("user.User", help_text="Users having access (data shared with)")
     access_token = models.CharField(
         max_length=255,
         null=True,
@@ -420,7 +424,7 @@ class ShareableObjectMixin(models.Model):
             self.access_token = token
             self.save()
 
-    def is_shared_with(self, user: User):
+    def is_shared_with(self, user):
         """ Access check
 
         Checks whether a given user has access to this object
@@ -433,7 +437,7 @@ class ShareableObjectMixin(models.Model):
         """
         return self.users.filter(id=user.id)
 
-    def share_with(self, user: User):
+    def share_with(self, user):
         """ Adds user to list of shared access users
 
         Args:
@@ -465,6 +469,7 @@ class ShareableObjectMixin(models.Model):
         Returns:
 
         """
+        from user.models import User
         form_data = form.cleaned_data
 
         keep_accessing_users = form_data["users"]
diff --git a/user/forms.py b/user/forms.py
index fd66a916..1b509bad 100644
--- a/user/forms.py
+++ b/user/forms.py
@@ -5,17 +5,17 @@ Contact: michel.peltriaux@sgdnord.rlp.de
 Created on: 08.07.21
 
 """
+from dal import autocomplete
 from django import forms
-from django.db import IntegrityError
+from django.db import IntegrityError, transaction
 from django.urls import reverse, reverse_lazy
 from django.utils.translation import gettext_lazy as _
 
 from api.models import APIUserToken
 from intervention.inputs import GenerateInput
-from user.models import User
+from user.models import User, UserNotification, Team
 
-from konova.forms import BaseForm, BaseModalForm
-from user.models import UserNotification
+from konova.forms import BaseForm, BaseModalForm, RemoveModalForm
 
 
 class UserNotificationForm(BaseForm):
@@ -160,3 +160,105 @@ class UserAPITokenForm(BaseForm):
         user.api_token = new_token
         user.save()
         return new_token
+
+
+class NewTeamModalForm(BaseModalForm):
+    name = forms.CharField(
+        label_suffix="",
+        label=_("Team name"),
+        max_length=500,
+        widget=forms.TextInput(
+            attrs={
+                "placeholder": _("Team name"),
+                "class": "form-control",
+            }
+        )
+    )
+    description = forms.CharField(
+        label_suffix="",
+        label=_("Description"),
+        widget=forms.Textarea(
+            attrs={
+                "rows": 5,
+                "class": "form-control"
+            }
+        )
+    )
+    members = forms.ModelMultipleChoiceField(
+        label=_("Manage team members"),
+        label_suffix="",
+        help_text=_("Multiple selection possible - You can only select users which are not already a team member. Enter the full username or e-mail."),
+        required=True,
+        queryset=User.objects.all(),
+        widget=autocomplete.ModelSelect2Multiple(
+            url="share-user-autocomplete",
+            attrs={
+                "data-placeholder": _("Click for selection"),
+                "data-minimum-input-length": 3,
+            },
+        ),
+    )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.form_title = _("Create new team")
+        self.form_caption = _("You will become the administrator for this group by default. You do not need to add yourself to the list of members.")
+        self.action_url = reverse("user:team-new")
+        self.cancel_redirect = reverse("user:team-index")
+
+    def save(self):
+        with transaction.atomic():
+            team = Team.objects.create(
+                name=self.cleaned_data.get("name", None),
+                description=self.cleaned_data.get("description", None),
+                admin=self.user,
+            )
+            members = self.cleaned_data.get("members", User.objects.none())
+            if self.user.id not in members:
+                members = members.union(
+                    User.objects.filter(
+                        id=self.user.id
+                    )
+                )
+            team.users.set(members)
+        return team
+
+
+class EditTeamModalForm(NewTeamModalForm):
+    admin = forms.ModelChoiceField(
+        label_suffix="",
+        label=_("Admin"),
+        help_text=_("Administrators manage team details and members"),
+        queryset=User.objects.none(),
+        empty_label=None,
+    )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.form_title = _("Edit team")
+        self.form_caption = None
+        self.action_url = reverse("user:team-edit", args=(self.instance.id,))
+        self.cancel_redirect = reverse("user:team-index")
+
+        members = self.instance.users.all()
+        self.fields["admin"].queryset = members
+
+        form_data = {
+            "members": members,
+            "name": self.instance.name,
+            "description": self.instance.description,
+            "admin": self.instance.admin,
+        }
+        self.load_initial_data(form_data)
+
+    def save(self):
+        with transaction.atomic():
+            self.instance.name = self.cleaned_data.get("name", None)
+            self.instance.description = self.cleaned_data.get("description", None)
+            self.instance.save()
+            self.instance.users.set(self.cleaned_data.get("members", []))
+        return self.instance
+
+
+class RemoveTeamModalForm(RemoveModalForm):
+    pass
diff --git a/user/models/__init__.py b/user/models/__init__.py
index 7788d8e4..06dbe738 100644
--- a/user/models/__init__.py
+++ b/user/models/__init__.py
@@ -5,6 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
 Created on: 15.11.21
 
 """
-from .user_action import *
-from .user import *
-from .notification import *
+from .user_action import UserActionLogEntry, UserAction
+from .user import User
+from .notification import UserNotification, UserNotificationEnum
+from .team import Team
diff --git a/user/models/team.py b/user/models/team.py
new file mode 100644
index 00000000..c26af3c6
--- /dev/null
+++ b/user/models/team.py
@@ -0,0 +1,16 @@
+from django.db import models
+
+from konova.models import UuidModel
+
+
+class Team(UuidModel):
+    """ Groups users in self managed teams. Can be used for multi-sharing of data
+
+    """
+    name = models.CharField(max_length=500, null=True, blank=True)
+    description = models.TextField(null=True, blank=True)
+    users = models.ManyToManyField("user.User", blank=True, related_name="teams")
+    admin = models.ForeignKey("user.User", blank=True, null=True, related_name="+", on_delete=models.SET_NULL)
+
+    def __str__(self):
+        return self.name
diff --git a/user/templates/user/index.html b/user/templates/user/index.html
index 1193340c..c31de94f 100644
--- a/user/templates/user/index.html
+++ b/user/templates/user/index.html
@@ -62,6 +62,14 @@
                         </button>
                     </a>
                 </div>
+                <div class="row mb-2">
+                    <a href="{% url 'user:team-index' %}" title="{% trans 'Manage teams' %}">
+                        <button class="btn btn-default">
+                            {% fa5_icon 'users' %}
+                            <span>{% trans 'Teams' %}</span>
+                        </button>
+                    </a>
+                </div>
             </div>
         </div>
     </div>
diff --git a/user/templates/user/team/index.html b/user/templates/user/team/index.html
new file mode 100644
index 00000000..c8ce113d
--- /dev/null
+++ b/user/templates/user/team/index.html
@@ -0,0 +1,67 @@
+{% extends 'base.html' %}
+{% load i18n fontawesome_5 %}
+
+{% block head %}
+
+    {% comment %}
+        dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
+        This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
+        Therefore the script linkages from form.media have been extracted and put inside dal/scripts.html to ensure
+        these scripts are loaded when needed.
+    {% endcomment %}
+    {% include 'dal/scripts.html' %}
+{% endblock %}
+
+{% block body %}
+<h4>{% trans 'Teams' %}</h4>
+<div class="col-md">
+    <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-new' %}" title="{% trans 'Add new team' %}">
+        {% fa5_icon 'plus' %}
+        {% trans 'New' %}
+    </button>
+</div>
+<div class="table-container">
+    <table class="table table-hover">
+        <thead>
+            <tr>
+                <th scope="col" class="align-middle">{% trans 'Name' %}</th>
+                <th scope="col" class="align-middle w-20">{% trans 'Description' %}</th>
+                <th scope="col" class="align-middle">{% trans 'Members' %}</th>
+                <th scope="col" class="align-middle">{% trans 'Actions' %}</th>
+            </tr>
+        </thead>
+        <tbody>
+            {% for team in teams %}
+                <tr>
+                    <td>{{team.name}}</td>
+                    <td>
+                        <div class="scroll-150">
+                            {{team.description}}
+                        </div>
+                    </td>
+                    <td>
+                        {% for member in team.users.all %}
+                            <span class="badge badge-pill rlp-r">{{member.username}}</span>
+                        {% endfor %}
+                    </td>
+                    <td>
+                        {% if team.admin == user %}
+                            <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-edit' team.id %}" title="{% trans 'Edit team' %}">
+                                {% fa5_icon 'edit' %}
+                            </button>
+                            <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-remove' team.id %}" title="{% trans 'Remove team' %}">
+                                {% fa5_icon 'trash' %}
+                            </button>
+                        {% endif %}
+                    </td>
+                </tr>
+            {% endfor %}
+        </tbody>
+    </table>
+</div>
+
+{% with 'btn-modal' as btn_class %}
+    {% include 'modal/modal_form_script.html' %}
+{% endwith %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/user/urls.py b/user/urls.py
index e312a63b..76a86623 100644
--- a/user/urls.py
+++ b/user/urls.py
@@ -15,5 +15,9 @@ urlpatterns = [
     path("notifications/", notifications_view, name="notifications"),
     path("token/api", api_token_view, name="api-token"),
     path("contact/<id>", contact_view, name="contact"),
+    path("team/", index_team_view, name="team-index"),
+    path("team/new", new_team_view, name="team-new"),
+    path("team/<id>/edit", edit_team_view, name="team-edit"),
+    path("team/<id>/remove", remove_team_view, name="team-remove"),
 
 ]
\ No newline at end of file
diff --git a/user/views.py b/user/views.py
index ee6aee50..afed5726 100644
--- a/user/views.py
+++ b/user/views.py
@@ -1,17 +1,19 @@
 from django.contrib import messages
 from django.contrib.auth.decorators import login_required
+from django.urls import reverse
 
 from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 from konova.utils.mailer import Mailer
 from konova.utils.message_templates import FORM_INVALID
-from user.models import User
-from django.http import HttpRequest
+from user.models import User, Team
+from django.http import HttpRequest, Http404
 from django.shortcuts import render, redirect, get_object_or_404
 from django.utils.translation import gettext_lazy as _
 
 from konova.contexts import BaseContext
 from konova.decorators import any_group_check, default_group_required
-from user.forms import UserNotificationForm, UserContactForm, UserAPITokenForm
+from user.forms import UserNotificationForm, UserContactForm, UserAPITokenForm, NewTeamModalForm, EditTeamModalForm, \
+    RemoveTeamModalForm
 
 
 @login_required
@@ -128,4 +130,52 @@ def contact_view(request: HttpRequest, id: str):
         request,
         template,
         context
-    )
\ No newline at end of file
+    )
+
+
+@login_required
+def index_team_view(request: HttpRequest):
+    template = "user/team/index.html"
+    user = request.user
+    context = {
+        "teams": user.teams.all(),
+        "tab_title": _("Teams"),
+    }
+    context = BaseContext(request, context).context
+    return render(request, template, context)
+
+
+@login_required
+def new_team_view(request: HttpRequest):
+    form = NewTeamModalForm(request.POST or None, request=request)
+    return form.process_request(
+        request,
+        _("New team added"),
+        redirect_url=reverse("user:team-index")
+    )
+
+
+@login_required
+def edit_team_view(request: HttpRequest, id: str):
+    team = get_object_or_404(Team, id=id)
+    if request.user != team.admin:
+        raise Http404()
+    form = EditTeamModalForm(request.POST or None, instance=team, request=request)
+    return form.process_request(
+        request,
+        _("Team edited"),
+        redirect_url=reverse("user:team-index")
+    )
+
+
+@login_required
+def remove_team_view(request: HttpRequest, id: str):
+    team = get_object_or_404(Team, id=id)
+    if request.user != team.admin:
+        raise Http404()
+    form = RemoveTeamModalForm(request.POST or None, instance=team, request=request)
+    return form.process_request(
+        request,
+        _("Team removed"),
+        redirect_url=reverse("user:team-index")
+    )

From 9fec85b68804be115e8de66cd90da33e38a86db6 Mon Sep 17 00:00:00 2001
From: mpeltriaux <Michel.Peltriaux@sgdnord.rlp.de>
Date: Thu, 17 Feb 2022 13:44:32 +0100
Subject: [PATCH 19/26] #101 Team enhancements

* visual enhancement for team index rendering
* adds validity check for admin-membership of a team
---
 locale/de/LC_MESSAGES/django.mo     | Bin 37936 -> 39382 bytes
 locale/de/LC_MESSAGES/django.po     | 116 ++++++++++++++++++++++++----
 user/forms.py                       |  20 ++++-
 user/templates/user/team/index.html |  88 ++++++++++-----------
 4 files changed, 163 insertions(+), 61 deletions(-)

diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index 022e9e1a728d186a0e8be95eee8ae29ea5928bee..ca93bc886faec14fea82f27aa2689b03373d5b42 100644
GIT binary patch
delta 12271
zcmZYF2Yggj-p28pMhYa5P(leX2m%2Tnv|e)si8>|76p^cBqSsmoS6`cVFVOJK-`2T
zpaK#Q6-7q@0a=%zAYxg81*u{e7etU<8@j(|?#XN1_kQ-D?>Xn*)6cyG+#Sz`{xcBj
zKc5i3(&CB^wX7s`*0QWONWb7vsby_wYgsizENdf{k$<_JWi7-3DV8-KkK%Y7nQB>u
zxCKXG-S(FC5IV6jeuG^xvV&#Sz+RYOS$->>L@Wi9?E)(wtC9C(bzEr5OHmceaR$DE
zs+Zi+vf{9taUiPRIBbp?ru<>7Lw*I;!fhB&|JEK;a1?8D;~dt;%cu$=o$QY5p*m`g
z^{^8*z#&*4v&{Vmj7u<q^0n9!w_^kzM;6ICjdApEMR&HWFszTPl9hy7fnm4}$6#%|
ziCTg9+w7S)K@FrGCSre##z`2DE>t_ksCsjaOE8A~8uaVNGbGf&4)efaRK*j>_F8B0
z7L4g)uTTm`lJAMFZ~$s03Q$YG2sPj`<5r9!zZX^SASU3^F08+n^a2GM$Q7)Ezn~hZ
z#fj13X@QziKdg&mu^#5320jmU7M?(D#a2{DZ=%{ijN0>)sCK``hWKk&*1su<#BO#+
z-B1<Bp+<bK$!DV~7NQ0+AGJa&P-kWxs)OfI_4lEc_#kRvA7D71L(TkCQ+~rwLL&_8
zZa0*GYUmc!UUo(eq$j51K%|OQic9baY5?QY?0VU#0T!bMuo%_;3e=3BK@D&}Y6AYZ
zO~HGpy*q*G@S^b&YRRvo8j9{=cUT`az}BdSI-xpFGxyU`?M*^$Z4PQBeCGaqtf%+C
z)I6{a^#R(6Is?a09e-`^|AuO?`tA1KCt@q|si>_PkL@te<X7WJ^3S7|{uk5)tUK%p
z*2G$R|Lc=b!^x-_bU}@Dka3(T&qD285o$({pq73mYN^XnE3yN%#CuRHc>uLS@1h3!
z5%$L~F<$R~o1XTE;SSV;{ZJK$U?Uujnn59IpkCBW{HW(1Lw!G1qw23iJ--Rn;a1eZ
z_M!&<mhmI>YX%ocB;t3d1|xgf?|Us&gPn~%P%G0H)xk*PSmYd96Y(xAMLrqU=ctuw
z(Az$IEpR&d-pCth?dZ+=PayFX1%=qBk7YH%m(YRlV`KadwKcJQ?HM#h4Y(cZtlWt@
zD-)4JWw}uUU5NE@1#0WIqbBqwYGn@f^;=dm5@#q-LpM=-m(b6iVMAk6)VI3@Y9MV;
zOL_;Yqk*U`7;DNWpjIdowE{Wjz6Ujc8K{*m@srR<7NYiMEvlofs0O#A2J|wj!s{k~
z0QH?XVmyO76aPXD@E2@{v7EFN?15@;Drx}vr~&%DBy`ATB8y?IKo8cr)84a17)E{*
zYNlII19}y8cJ`rWcoa3Dlc<S&jas1_ru=u4uQk9PXhZCxE|W=w^WYQ=MJH+xb5MIc
z7pZHlGWjzY{2-y~MGv$G5{K%z3993^r~!3B9kzj}dL^idlwloBc_RsJ!A{f?9zo6U
zW7JY!L^XIFHK3cQLsfT>J<wF+0Mz|^keOLNOvdL>9Ue!m*r%ra8b)f#lLiMrN>&RT
zN<IT4@db>)SFr)^!D@IMHPADthA$a^MAfS{#4e9RJ(q;q;<lKCgHQu;qCbj+kAyxf
zC8!P-quz?gaTLCSUJPS&W3d>=;8E0)JJRhAQ&9QaQSA)I>NpbB&m@y~qMn<c&id=M
zE1^J3U5eU@&Da!o<5PGF)nM^3dr#-0X1*NT;*+R)@1SOO&UhKM0yk0Z*BEYh+ytwW
zZ#$gzSHs;Xh{j&1B^-=e@=>TmlxLiSG31w`I$CYYx1u`Ojr!0WL3MD><iA0+|10Wk
zsy4!2kr+P-o#NW4fz(HR0h^*`)C=`Cj5hgPR7WMK0WL=!#%;y}sQPEHA^wayjCDua
zTbhm<SOMzG>YqhIr*<`}p_i~X9ySj|aRB&Z!D@*$(TRGUe8>T|o=5HNb<|<~6}3X4
zciAfui+b%GsEKqn`QgX}{Z^Kpu!>P<VF~KN4XBasLUmk$TB&0gkEc)_UqaQpj<Fau
z+O{4hlW&1~egxLQ`!Kiy!94pvi-amJG!LvW`HdJy`AgUm_oMdi3)EJ9gE}i$Q4Rix
z+T-vsc1LkIiF_k$gT+{aoA4HN@G9L!|5kqz>R_dDA3Df?W(*%^Z_%yTg7Tht8)hQE
zLs+X(Gd+$|@Hf;zCy%#RC=)fXX{aqKLVaoHpuZJ~xg>OGwwMRrLN)L%YK9-6mi{EF
zp|d9cC29-4MXlfu7~K22?JbMNx|BCY)$fd2(e9`%8FV-MpFm<F1!^E4)!=N@k}fdi
z%TWV)5;d@L)Ihdja|~ctJc;_!#Z9nJcN^66gH3)IYUT1!Tk`Y-*1sKzBNX`XKd1ra
zPqg(LOR+ZP<*1RrZpz;^<>!spOnJ4x*elS$n2fckmxfw_p%|RFpM>@zAGJ4btdB*g
zkw1o-d8x^-H9lp^H=$1TbEbS3s=d9~7WW%3p(a|76WJO2V=DTKNvOgW)FIl2gYg(@
zAW8SwACfMp{3v5CHXuJA8{vA?-tR_jNd>mYugv|#d+jaljC!s&vgLkjD2aX{mNfy-
zabw+Ne*3{$9Oaj>*?pAZF&u&J4F0Ib{m6D(MVb7A1-^&Pa7mVB^}+3^t-6A((Q?{b
zn2aj#iBa@#jU=JNH^G>V^~n2h4KBet*urI3OhfHmI;!4e)J*fSA+E>9xC^ynCrtSj
zV|2D%-U1ubztxk3Mm`DEaS0~k3e*z6V9MV{4dk3DzlM6fYUJ3@--6on9;kt3quvT1
zYQWE9IPS-mSb_cs5|>E4idRt`mru1%?;EI7`yOgw=TS4df!f2kTzg3yU>NxnRL31n
zd2izwjHWyXwe<I!{DNH8UpJOfphL78HL?Jz!_ydr-{Y<LGird2Jp0sl$0YItP#tGt
zBu>X@oQayid{oC}sJEpYWAK$c)?X{|1_fH`3RH!2sD`hg_O$vmd*&@s?{9C^fJa~q
z=Ai~wWL$>oupE<d7wQXp5w(I=zCF+eeiGHlH$#oAHEJMTP#up%Eo~lZ4+~K%GY_>g
zYm6IFe@Z@wn$RB9b8njaCsFNwf*R=0=Dt6nz`Pcy27BUI9B5pJdJC?i8eCjxAHof&
z0lkLR@i1!Tj-v+t1*$#EZ5xf+k_4=QNytF?{og#$9yPM=s8c-(^~udfRh*4l>W5Hg
zVL3*GFaT78d#BsaA4V<xS>qK{d)EDS{d%a0G{XjZ|GSe=$D_>yd8iJHOt~MmhpRCj
z|BfB;7-|I~Je+K-j~d{EsMmA}#^MH(f6-Wh8o((`)cgM(3C%RpYugC*0cnp3I2={s
zK9euTn&clv&3r9t3$~&L5I`Ny{g{TQQSH?6*%NDJ?1+B7F1M4=67@$No{6Z2r(hiB
zqh>M(Lvb;x-cr=zT!Gzi4Qk~+#9DY7RsUPm0DeaG6I*0I*Sv`J?@B=m1!~ZVdK>al
z9ePm%nuq#wEy5nS6vyBpOvgqu?D{#_hP)e>;#%y7t%@z{Va&tbcoo~?wwbJdD-tJW
z+66aJBTk-WpW5!Ine@dvI2!9?4%Wj5Q8Qj`@*A->`Q50qa@2Sp9ptYX<7e9w?c^t+
znWY(fp=R74)xi+d(%onDqE=`js-tD7mD`9K=r+`r>_NSL`%U>F)C5kU+P`e{Unijo
zKcNoKP1IqEnqxm$2el#%QD-9A*cEjM`=ge845s2-)EU{18t4wx1b3lUZXarEPGG6t
z|I7#M(|Q9nkoXe2!@8&uw?K82X3B@4mUaSaz<H>%Qe^HgF!@qUq<jN*!`-NfT}2J(
zR}B9BKV+``X{?7MxY5Dn{iwt91oEA+&Z3t5JZh=0p;ji0Go-Cbz`>Y|+A@#vVQfr(
z4eI%ws0qD=!N32XAfZEa4mHBBupM5<6m&djFYO3yPrd~80oslO@d9?jmh<d^O+*bK
z5Bp#Vs{Q@g0S{wu{0W19|4*B5AC`XDkQ?c!CCWxE^)yriC8(J%LLIs_s4d!n>hLwx
zk{`w<_z9~1@2DBaFR<HfhB_N97wG#>B839B-?|&u<8kDF*8LCJ|DbpSwa0^aiR<Dx
zREN`0D>fI^(W5569<|iZ8h2q+@^52H{1R0^b|Fiw8;*timV<pzuT9({d#@9XZBa|s
z8@1PdR0pe29hVz-p$7Pl$zMP{_dQ0U^@x3Fqfq_S_LE2=k%YHm8mhr5sF~f5VOWBC
zedeJCuokuSFQZoGZFB!PYG#))6s^T}$6=@~td3gxx~P8rNhH)^8mfbI)ERK1_S%m+
zy^o`2_9Cj{LDU{!L@lZHsD0R4VFR*LQ3IQgs`ogmpDn0%cVj=Ax85P48P!-~pX%nQ
z!!i!F<Sy)m<){Wf$0)pp`XK#+svpHyMFVPz&9RrsXJRAr^H2kS(v<HB%Km>$LL>SS
zwWQI@><*fsma-Mrz#gcE2BBt@W%9Eyh5Sm?a}~x9QSF^WwQ~)%0uhhdTbqbA>ECKj
z!hxMJ1;?WHZa(VJJZxNsTA7s?jpZ1JFX2qwkDajFa{E`dJWM7Z_Bj9EgDKb=*BK9@
z-$B7;5^XW=ulC4#pdK8EgV2q`a2MW*;ibV}V67pjf$qc@d>u8ggIFEkM;+eNcpIL_
zrdYeoey(#F`>zIiQlLHUgQ_qDHM8NU6}Si0pcCV9y2;N+ZOLP(y?+jMy5GTC_#tXb
zE@A>+!B`AgVGp?G3f5l_G^9WkTA@1Zjv81W)WG^<M;wMdaIW!n)Z6g`>iL9~_Ey$K
ztzcKY9jBn)l65#251_uVef_KK#6V-ZaTIDL#+m#?)IcVq2AG4IsoUJ2VVr{zls|~7
zzYz8Oqb6U9+NxDp2mKq(jh(0m_n=00z?2_CHTW*7!+)6aQ>f?8q7LmvOvRe3?LTCC
zVH$b2$#28pS-@VDpU2U9{~NEdKRna1E;kmV1E0ob_$D^TPmR@{u+Ksp)EBcWw#R!=
zhifV7?7V<FGkZ<`5QdO{k{{ZFfvCTKS|e4;b%yxZq?KQ!ALe?F^2?;(!4l#H(ihFM
z`B<BL2kdRiZj$drdYQ>ThLb3}8?O^fNPk2;PyfN|8imi1T7gAGBjP;KnX-=w7m-CA
zBy^y37{B0tbK-TPJ@FKwOaGekDb7VF@nx`-ts(tSlTIhC%kMS`Wq#8SE}dvyyUe}Q
zIEl~+e$bTlHEzeDl>dv^K&&Nyh&V=C*F(fG@>hvAq`kOaH@NabwEkQ#QrL~qEBI8f
zgg-FI>y@f{`6>I6SU^0;jo*o{h`$rME>O<7vaSSk_K#VVogo^L-KhJ-XM|qk<LY1U
ze<=k$i4LSWXTkph2G$nJe!;(?t`BUi^Tzp<4>ajh=9y^Jt937-16cK{S2d$_<^JDJ
zr5DM+Pc$_R>AtS(Ho>2>xwnJ3jokgje@JIkx!;w%u4*jZ3Doz0tSO7a{p1Ikd>rb(
zKUn)r!D7;3CjD2^-H6Jo2jx?VUx`o6GnMx$eS^eX#B}aY$ECzf^XzM+hY|YSB9yWw
zcDdi0O@S_bOdh7N4{<B;F!{s8t;8<k6fuFg$-OB!gy=)uM_yN0mBW%|%2Fx6Ou8TP
z#kCy7Q9{>H%5${-@0o{N;5On0kwNt4q0y*+WSB;JD~`hkL_SeWemPN2`cC{iv5rV1
z-;=mT=vqRV*G>liBlk|y5hnjP?f-b9F%MN<i>stJk^YFdw@TT!q@N(Zp~Am#B@w~w
z+mYW*T2~f+Poxl!5Fx}i$`1wa+F#aMl=+|54+<Z`%Ih(cXhzu`q}vi>i2+0?9W}u_
ziFD#W#9^KrgNej_#QWsmAUYCT$iGKCLmVf64%eWr&nw^m@5nqr{Kkzzc!|*U7Wr53
zC8C0~{v0SHbk!jLDo!NyN9{?XC1tIM{X`k@A)!B<<`I=w9*Gbpkq|6k>Rm}3<iVvx
zIiV|?m_fM6w<bO(y@1d)g?wk?F5)NR0pcFY&k_wu>-ySQ7iW?GH$IIQiB3d+@+XMk
z(vMK0%C(8~V9GwkjfBtK`-QSzq{HzCQ+9;(D@5frp7iTvo;3wS$VZy=5xm1Z`zGE(
z-oKv2%S1eJKk+1m1Mm}KD(Mm;isjO^miPzd9-{L4M`Z%vB$k<cA<smc^arG!q<t7k
zTeq3|nVSE6Zmcp7=5iyGh$a6n@q>BrS=>tgJDf)RXr7NZzJskydb_cbUZxG@113EN
z>yvL2!v5=*huuW73W>ACX7a_vD$=?Z;Xc&=OHx;oDgO)UM3WBQ;KwcG<4k4`>1=a<
zFMeXmpD_NcSMM2a1n}Rc@NH~C#1NxQ<zGp+C4Dzm5GP6R!6@Q?ub)kw;rJ6bBe6Sv
zQRTsElwBeGGx(7}=(>dMh<U_jBHYZ@zRRbRGF=<+HDZp*cgNwB_a_eM0dpncyWD$;
zC?b7>C@^(mu)5y=w@K{f#!RB}x?mEMu@3hg#Pfu%SB;agfc#FJgMEq9#4&UKEBu<g
zo6wa*zAla=CX)UP!-DT0iF+t`9BUG~9wC+!cM;!kZxsHH|L->viq26!7-Myx>i~8!
z=~P@u*;QgRQJefYVh8C7*i`#pkAy{Z0bSLIM^$F7m+_xf@-I|L>yc9PoOqP@3-?#x
zw?qTd3yJSZuOt3S`b)x!aRjeG_coqtQH8EzhtHK!P*&a{(7{=dTWIyw&s?w1li_oF
zypDp5!i*eO@EM2G<;%#;_c}5PosI%mL1th~$4%j3)DC>zrCn%@%bVrNo$kwZ7X}i#
zp9l?CyMc>6K8T3_qX|`WdAw!Y`!tLQrUD21Gz{sR;c+<%-9AS~zQ>i}oaM-{JG7rp
zbqpx<xjYWvRF@;WC_mp(<aK!pGYVV|x5wd1DPT;gfv5Y{2#KacM~2hsat6x#MMOmx
zxM$cS4{ROUC+xO-SC-G^<N+q=Xg#MS*-_|nIlT^_+mY#_OS?CRJDZ+zDW<j5z~{q9
zhBi~XE@v*at+7h0b35g6sS{_Q<EV2H{)z4)M{zC#%yebB8J-3l?5%P+9odXH*m#b|
zT{PX1Ig2&T&M3<Fr8-pE=?<=fhNV$46~`=hk;m)GXH4#3d-=4bA)19uwK6g@J+2w4
zjska}{`kn)m=Ufbm)D_TmL+6exbsij`RC1b6*^|PJjEILK2pwHSFn;ZL%AY$czCWa
zCqLKaba?_-vkr&H*^RRK`K}ySVIVMdeQ1q-?D<rWD>t*KFefl#T4s2-Iu2}h4~=a9
zNBuv#vC=a<K9@DTVzXzqH9RBN`s1O%%^A@lZ8eNSch*!#VQ$t`UzIUvfL=2(ufv;L
z=q&3tvvpaZI5F^9ahs6ZW^_|?3uhPQxUwtu<@f?ovwFnX1M0S5dRXs4uHuT#Q<<&D
z@uyX>&q6_w*XwX`GAf6}*4T~G9p$NkEepR7Z5`bIOjm{{)5Ur4*{5K{|DA^%SANA#
z*2EWBwKyWuKZfZPyF5;o)a&E5$?!M}DmGU<ots1J|2vGTGfZ`;YC*+5uUB<h3<i;(
k$==%wGrP#+7{*a>1>30{GED{-K+|^>rdok@kFN~-FGSp%I{*Lx

delta 11048
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

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 16b2cd4f..d1da918b 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-15 15:29+0100\n"
+"POT-Creation-Date: 2022-02-17 13:42+0100\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"
@@ -64,6 +64,7 @@ msgstr "Verantwortliche Stelle"
 #: compensation/forms/forms.py:165 intervention/forms/forms.py:64
 #: intervention/forms/forms.py:81 intervention/forms/forms.py:97
 #: intervention/forms/forms.py:113 intervention/forms/modalForms.py:49
+#: user/forms.py:196
 msgid "Click for selection"
 msgstr "Auswählen..."
 
@@ -751,7 +752,7 @@ msgstr "Menge"
 #: intervention/templates/intervention/detail/includes/documents.html:39
 #: intervention/templates/intervention/detail/includes/payments.html:39
 #: intervention/templates/intervention/detail/includes/revocation.html:43
-#: templates/log.html:10
+#: templates/log.html:10 user/templates/user/team/index.html:33
 msgid "Action"
 msgstr "Aktionen"
 
@@ -1150,12 +1151,12 @@ msgstr "Kompensation {} bearbeitet"
 msgid "Edit {}"
 msgstr "Bearbeite {}"
 
-#: compensation/views/compensation.py:240 compensation/views/eco_account.py:349
+#: compensation/views/compensation.py:240 compensation/views/eco_account.py:351
 #: ema/views.py:194 intervention/views.py:531
 msgid "Log"
 msgstr "Log"
 
-#: compensation/views/compensation.py:584 compensation/views/eco_account.py:716
+#: compensation/views/compensation.py:584 compensation/views/eco_account.py:719
 #: ema/views.py:551 intervention/views.py:677
 msgid "Report {}"
 msgstr "Bericht {}"
@@ -1176,32 +1177,32 @@ msgstr "Ökokonto {} bearbeitet"
 msgid "Eco-account removed"
 msgstr "Ökokonto entfernt"
 
-#: compensation/views/eco_account.py:370 ema/views.py:275
+#: compensation/views/eco_account.py:372 ema/views.py:275
 #: intervention/views.py:630
 msgid "{} unrecorded"
 msgstr "{} entzeichnet"
 
-#: compensation/views/eco_account.py:370 ema/views.py:275
+#: compensation/views/eco_account.py:372 ema/views.py:275
 #: intervention/views.py:630
 msgid "{} recorded"
 msgstr "{} verzeichnet"
 
-#: compensation/views/eco_account.py:789 ema/views.py:617
+#: compensation/views/eco_account.py:792 ema/views.py:617
 #: intervention/views.py:428
 msgid "{} has already been shared with you"
 msgstr "{} wurde bereits für Sie freigegeben"
 
-#: compensation/views/eco_account.py:794 ema/views.py:622
+#: compensation/views/eco_account.py:797 ema/views.py:622
 #: intervention/views.py:433
 msgid "{} has been shared with you"
 msgstr "{} ist nun für Sie freigegeben"
 
-#: compensation/views/eco_account.py:801 ema/views.py:629
+#: compensation/views/eco_account.py:804 ema/views.py:629
 #: intervention/views.py:440
 msgid "Share link invalid"
 msgstr "Freigabelink ungültig"
 
-#: compensation/views/eco_account.py:824 ema/views.py:652
+#: compensation/views/eco_account.py:827 ema/views.py:652
 #: intervention/views.py:463
 msgid "Share settings updated"
 msgstr "Freigabe Einstellungen aktualisiert"
@@ -2272,7 +2273,7 @@ msgstr "* sind Pflichtfelder."
 msgid "New entry"
 msgstr "Neuer Eintrag"
 
-#: templates/generic_index.html:41
+#: templates/generic_index.html:41 user/templates/user/team/index.html:23
 msgid "New"
 msgstr "Neu"
 
@@ -2401,6 +2402,54 @@ msgstr "Neuen Token generieren"
 msgid "A new token needs to be validated by an administrator!"
 msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
 
+#: user/forms.py:168 user/forms.py:172
+msgid "Team name"
+msgstr "Team Name"
+
+#: user/forms.py:179 user/templates/user/team/index.html:31
+msgid "Description"
+msgstr "Beschreibung"
+
+#: user/forms.py:188
+msgid "Manage team members"
+msgstr "Mitglieder verwalten"
+
+#: user/forms.py:190
+msgid ""
+"Multiple selection possible - You can only select users which are not "
+"already a team member. Enter the full username or e-mail."
+msgstr ""
+"Mehrfachauswahl möglich - Sie können nur Nutzer wählen, die noch nicht "
+"Mitglieder dieses Teams sind. Geben Sie den ganzen Nutzernamen an."
+
+#: user/forms.py:204
+msgid "Create new team"
+msgstr "Neues Team anlegen"
+
+#: user/forms.py:205
+msgid ""
+"You will become the administrator for this group by default. You do not need "
+"to add yourself to the list of members."
+msgstr ""
+"Sie werden standardmäßig der Administrator dieses Teams. Sie müssen sich "
+"selbst nicht zur Liste der Mitglieder hinzufügen."
+
+#: user/forms.py:230
+msgid "Admin"
+msgstr "Administrator"
+
+#: user/forms.py:231
+msgid "Administrators manage team details and members"
+msgstr "Administratoren verwalten die Teamdaten und Mitglieder"
+
+#: user/forms.py:244
+msgid "Selected admin ({}) needs to be a member of this team."
+msgstr "Gewählter Administrator ({}) muss ein Mitglied des Teams sein."
+
+#: user/forms.py:256 user/templates/user/team/index.html:52
+msgid "Edit team"
+msgstr "Team bearbeiten"
+
 #: user/models/user_action.py:22
 msgid "Unrecorded"
 msgstr "Entzeichnet"
@@ -2417,7 +2466,7 @@ msgstr "Gelöscht"
 msgid "Show contact data"
 msgstr "Zeige Kontaktdaten"
 
-#: user/templates/user/index.html:13
+#: user/templates/user/index.html:13 user/templates/user/team/index.html:30
 msgid "Name"
 msgstr ""
 
@@ -2462,6 +2511,27 @@ msgstr "API token einsehen oder neu generieren"
 msgid "API"
 msgstr ""
 
+#: user/templates/user/index.html:66
+msgid "Manage teams"
+msgstr ""
+
+#: user/templates/user/index.html:69 user/templates/user/team/index.html:19
+#: user/views.py:142
+msgid "Teams"
+msgstr ""
+
+#: user/templates/user/team/index.html:21
+msgid "Add new team"
+msgstr "Neues Team hinzufügen"
+
+#: user/templates/user/team/index.html:32
+msgid "Members"
+msgstr "Mitglieder"
+
+#: user/templates/user/team/index.html:55
+msgid "Remove team"
+msgstr "Team entfernen"
+
 #: user/templates/user/token.html:6
 msgid "API settings"
 msgstr "API Einstellungen"
@@ -2486,26 +2556,38 @@ msgstr "Token noch nicht freigeschaltet"
 msgid "Valid until"
 msgstr "Läuft ab am"
 
-#: user/views.py:31
+#: user/views.py:33
 msgid "User settings"
 msgstr "Einstellungen"
 
-#: user/views.py:57
+#: user/views.py:59
 msgid "Notifications edited"
 msgstr "Benachrichtigungen bearbeitet"
 
-#: user/views.py:69
+#: user/views.py:71
 msgid "User notifications"
 msgstr "Benachrichtigungen"
 
-#: user/views.py:92
+#: user/views.py:94
 msgid "New token generated. Administrators need to validate."
 msgstr "Neuer Token generiert. Administratoren sind informiert."
 
-#: user/views.py:103
+#: user/views.py:105
 msgid "User API token"
 msgstr "API Nutzer Token"
 
+#: user/views.py:153
+msgid "New team added"
+msgstr "Neues Team hinzugefügt"
+
+#: user/views.py:166
+msgid "Team edited"
+msgstr "Team bearbeitet"
+
+#: user/views.py:179
+msgid "Team removed"
+msgstr "Team gelöscht"
+
 #: venv/lib/python3.7/site-packages/bootstrap4/components.py:17
 #: venv/lib/python3.7/site-packages/bootstrap4/templates/bootstrap4/form_errors.html:3
 #: venv/lib/python3.7/site-packages/bootstrap4/templates/bootstrap4/messages.html:4
diff --git a/user/forms.py b/user/forms.py
index 1b509bad..35c1e82e 100644
--- a/user/forms.py
+++ b/user/forms.py
@@ -233,10 +233,27 @@ class EditTeamModalForm(NewTeamModalForm):
         empty_label=None,
     )
 
+    def __is_admin_valid(self):
+        admin = self.cleaned_data.get("admin", None)
+        members = self.cleaned_data.get("members", None)
+        _is_valid = admin in members
+
+        if not _is_valid:
+            self.add_error(
+                "members",
+                _("Selected admin ({}) needs to be a member of this team.").format(admin.username)
+            )
+
+        return _is_valid
+
+    def is_valid(self):
+        super_valid = super().is_valid()
+        admin_valid = self.__is_admin_valid()
+        return super_valid and admin_valid
+
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.form_title = _("Edit team")
-        self.form_caption = None
         self.action_url = reverse("user:team-edit", args=(self.instance.id,))
         self.cancel_redirect = reverse("user:team-index")
 
@@ -255,6 +272,7 @@ class EditTeamModalForm(NewTeamModalForm):
         with transaction.atomic():
             self.instance.name = self.cleaned_data.get("name", None)
             self.instance.description = self.cleaned_data.get("description", None)
+            self.instance.admin = self.cleaned_data.get("admin", None)
             self.instance.save()
             self.instance.users.set(self.cleaned_data.get("members", []))
         return self.instance
diff --git a/user/templates/user/team/index.html b/user/templates/user/team/index.html
index c8ce113d..d2040a35 100644
--- a/user/templates/user/team/index.html
+++ b/user/templates/user/team/index.html
@@ -13,51 +13,53 @@
 {% endblock %}
 
 {% block body %}
-<h4>{% trans 'Teams' %}</h4>
-<div class="col-md">
-    <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-new' %}" title="{% trans 'Add new team' %}">
-        {% fa5_icon 'plus' %}
-        {% trans 'New' %}
-    </button>
-</div>
-<div class="table-container">
-    <table class="table table-hover">
-        <thead>
-            <tr>
-                <th scope="col" class="align-middle">{% trans 'Name' %}</th>
-                <th scope="col" class="align-middle w-20">{% trans 'Description' %}</th>
-                <th scope="col" class="align-middle">{% trans 'Members' %}</th>
-                <th scope="col" class="align-middle">{% trans 'Actions' %}</th>
-            </tr>
-        </thead>
-        <tbody>
-            {% for team in teams %}
+<div class="container">
+    <h4>{% trans 'Teams' %}</h4>
+    <div class="col-md">
+        <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-new' %}" title="{% trans 'Add new team' %}">
+            {% fa5_icon 'plus' %}
+            {% trans 'New' %}
+        </button>
+    </div>
+    <div class="table-container">
+        <table class="table table-hover">
+            <thead>
                 <tr>
-                    <td>{{team.name}}</td>
-                    <td>
-                        <div class="scroll-150">
-                            {{team.description}}
-                        </div>
-                    </td>
-                    <td>
-                        {% for member in team.users.all %}
-                            <span class="badge badge-pill rlp-r">{{member.username}}</span>
-                        {% endfor %}
-                    </td>
-                    <td>
-                        {% if team.admin == user %}
-                            <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-edit' team.id %}" title="{% trans 'Edit team' %}">
-                                {% fa5_icon 'edit' %}
-                            </button>
-                            <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-remove' team.id %}" title="{% trans 'Remove team' %}">
-                                {% fa5_icon 'trash' %}
-                            </button>
-                        {% endif %}
-                    </td>
+                    <th scope="col" class="align-middle">{% trans 'Name' %}</th>
+                    <th scope="col" class="align-middle w-20">{% trans 'Description' %}</th>
+                    <th scope="col" class="align-middle">{% trans 'Members' %}</th>
+                    <th scope="col" class="align-middle">{% trans 'Action' %}</th>
                 </tr>
-            {% endfor %}
-        </tbody>
-    </table>
+            </thead>
+            <tbody>
+                {% for team in teams %}
+                    <tr>
+                        <td>{{team.name}}</td>
+                        <td>
+                            <div class="scroll-150">
+                                {{team.description}}
+                            </div>
+                        </td>
+                        <td>
+                            {% for member in team.users.all %}
+                                <span class="badge badge-pill rlp-r">{{member.username}}</span>
+                            {% endfor %}
+                        </td>
+                        <td>
+                            {% if team.admin == user %}
+                                <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-edit' team.id %}" title="{% trans 'Edit team' %}">
+                                    {% fa5_icon 'edit' %}
+                                </button>
+                                <button class="btn rlp-r btn-modal" data-form-url="{% url 'user:team-remove' team.id %}" title="{% trans 'Remove team' %}">
+                                    {% fa5_icon 'trash' %}
+                                </button>
+                            {% endif %}
+                        </td>
+                    </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
 </div>
 
 {% with 'btn-modal' as btn_class %}

From 3878b5dbdb3144aae778cc8298f136ecabaa9745 Mon Sep 17 00:00:00 2001
From: mpeltriaux <Michel.Peltriaux@sgdnord.rlp.de>
Date: Thu, 17 Feb 2022 15:07:25 +0100
Subject: [PATCH 20/26] WIP: #101 Team sharing form

* adds form for sharing via team
---
 intervention/forms/modalForms.py | 23 ++++++++++++++++++++++-
 konova/autocompletes.py          | 22 +++++++++++++++++++---
 konova/urls.py                   |  3 ++-
 user/migrations/0003_team.py     | 29 +++++++++++++++++++++++++++++
 4 files changed, 72 insertions(+), 5 deletions(-)
 create mode 100644 user/migrations/0003_team.py

diff --git a/intervention/forms/modalForms.py b/intervention/forms/modalForms.py
index 0b72ae84..978360da 100644
--- a/intervention/forms/modalForms.py
+++ b/intervention/forms/modalForms.py
@@ -10,7 +10,7 @@ from django.core.exceptions import ObjectDoesNotExist
 
 from konova.utils.message_templates import DEDUCTION_ADDED, REVOCATION_ADDED, DEDUCTION_REMOVED, DEDUCTION_EDITED, \
     REVOCATION_EDITED
-from user.models import User
+from user.models import User, Team
 from user.models import UserActionLogEntry
 from django.db import transaction
 from django import forms
@@ -37,6 +37,20 @@ class ShareModalForm(BaseModalForm):
             }
         )
     )
+    team_select = forms.ModelMultipleChoiceField(
+        label=_("Add team to share with"),
+        label_suffix="",
+        help_text=_("Multiple selection possible - You can only select teams which do not already have access."),
+        required=False,
+        queryset=Team.objects.all(),
+        widget=autocomplete.ModelSelect2Multiple(
+            url="share-team-autocomplete",
+            attrs={
+                "data-placeholder": _("Click for selection"),
+                "data-minimum-input-length": 3,
+            },
+        ),
+    )
     user_select = forms.ModelMultipleChoiceField(
         label=_("Add user to share with"),
         label_suffix="",
@@ -97,6 +111,13 @@ class ShareModalForm(BaseModalForm):
             self.disable_form_field("users")
 
         self._add_user_choices_to_field()
+        self._add_teams_to_field()
+
+    def _add_teams_to_field(self):
+        form_data = {
+            "teams": []
+        }
+        self.load_initial_data(form_data)
 
     def _add_user_choices_to_field(self):
         """ Transforms the instance's sharing users into a list for the form field
diff --git a/konova/autocompletes.py b/konova/autocompletes.py
index f1775b5f..9b1be2d3 100644
--- a/konova/autocompletes.py
+++ b/konova/autocompletes.py
@@ -11,7 +11,7 @@ from dal_select2.views import Select2QuerySetView, Select2GroupQuerySetView
 from django.core.exceptions import ImproperlyConfigured
 
 from konova.utils.message_templates import UNGROUPED
-from user.models import User
+from user.models import User, Team
 from django.db.models import Q
 
 from codelist.models import KonovaCode
@@ -69,9 +69,8 @@ class InterventionAutocomplete(Select2QuerySetView):
 
 
 class ShareUserAutocomplete(Select2QuerySetView):
-    """ Autocomplete for intervention entries
+    """ Autocomplete for share with single users
 
-    Only returns entries that are accessible for the requesting user
 
     """
     def get_queryset(self):
@@ -93,6 +92,23 @@ class ShareUserAutocomplete(Select2QuerySetView):
         return qs
 
 
+class ShareTeamAutocomplete(Select2QuerySetView):
+    """ Autocomplete for share with teams
+
+    """
+    def get_queryset(self):
+        if self.request.user.is_anonymous:
+            return Team.objects.none()
+        if self.q:
+            # Due to privacy concerns only a full username match will return the proper user entry
+            qs = Team.objects.filter(
+                Q(name__icontains=self.q)
+            ).order_by(
+                "name"
+            )
+        return qs
+
+
 class KonovaCodeAutocomplete(Select2GroupQuerySetView):
     """
     Provides simple autocomplete functionality for codes
diff --git a/konova/urls.py b/konova/urls.py
index 68256e7a..1cd8851d 100644
--- a/konova/urls.py
+++ b/konova/urls.py
@@ -20,7 +20,7 @@ from django.urls import path, include
 from konova.autocompletes import EcoAccountAutocomplete, \
     InterventionAutocomplete, CompensationActionCodeAutocomplete, BiotopeCodeAutocomplete, LawCodeAutocomplete, \
     RegistrationOfficeCodeAutocomplete, ConservationOfficeCodeAutocomplete, ProcessTypeCodeAutocomplete, \
-    ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete
+    ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete, ShareTeamAutocomplete
 from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
 from konova.sso.sso import KonovaSSOClient
 from konova.views import logout_view, home_view
@@ -52,6 +52,7 @@ urlpatterns = [
     path("atcmplt/codes/reg-off", RegistrationOfficeCodeAutocomplete.as_view(), name="codes-registration-office-autocomplete"),
     path("atcmplt/codes/cons-off", ConservationOfficeCodeAutocomplete.as_view(), name="codes-conservation-office-autocomplete"),
     path("atcmplt/share/u", ShareUserAutocomplete.as_view(), name="share-user-autocomplete"),
+    path("atcmplt/share/t", ShareTeamAutocomplete.as_view(), name="share-team-autocomplete"),
 ]
 
 if DEBUG:
diff --git a/user/migrations/0003_team.py b/user/migrations/0003_team.py
new file mode 100644
index 00000000..6f7ac90a
--- /dev/null
+++ b/user/migrations/0003_team.py
@@ -0,0 +1,29 @@
+# Generated by Django 3.1.3 on 2022-02-17 10:22
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('user', '0002_user_api_token'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='Team',
+            fields=[
+                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+                ('name', models.CharField(blank=True, max_length=500, null=True)),
+                ('description', models.TextField(blank=True, null=True)),
+                ('admin', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
+                ('users', models.ManyToManyField(blank=True, related_name='teams', to=settings.AUTH_USER_MODEL)),
+            ],
+            options={
+                'abstract': False,
+            },
+        ),
+    ]

From 31f4369236aece7372028923255d8fbea95a1c90 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 18 Feb 2022 09:26:29 +0100
Subject: [PATCH 21/26] Missing migration

* adds a migration which has not been checked in from another branch
---
 .../migrations/0005_auto_20220218_0917.py     | 46 +++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 compensation/migrations/0005_auto_20220218_0917.py

diff --git a/compensation/migrations/0005_auto_20220218_0917.py b/compensation/migrations/0005_auto_20220218_0917.py
new file mode 100644
index 00000000..43e7db9c
--- /dev/null
+++ b/compensation/migrations/0005_auto_20220218_0917.py
@@ -0,0 +1,46 @@
+# Generated by Django 3.1.3 on 2022-02-18 08:17
+
+from django.db import migrations, models, transaction
+import django.db.models.deletion
+
+from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_AFTER_STATE_BIOTOPES__ID
+
+
+def migrate_entries_974_to_654(apps, schema_editor):
+    CompensationState = apps.get_model("compensation", "CompensationState")
+    KonovaCode = apps.get_model("codelist", "KonovaCode")
+    all_states = CompensationState.objects.all()
+
+    with transaction.atomic():
+        for state in all_states:
+            code_from_654 = KonovaCode.objects.get(
+                short_name=state.biotope_type.short_name,
+                code_lists__in=[CODELIST_BIOTOPES_ID],
+                is_archived=False,
+                is_leaf=True,
+            )
+            state.biotope_type = code_from_654
+            state.save()
+
+    old_list_states = CompensationState.objects.filter(
+        biotope_type__code_lists__in=[CODELIST_AFTER_STATE_BIOTOPES__ID]
+    )
+    if old_list_states.count() > 0:
+        raise Exception("Still unmigrated values!")
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('codelist', '0001_initial'),
+        ('compensation', '0004_auto_20220210_1402'),
+    ]
+
+    operations = [
+        migrations.RunPython(migrate_entries_974_to_654),
+        migrations.AlterField(
+            model_name='compensationstate',
+            name='biotope_type',
+            field=models.ForeignKey(blank=True, limit_choices_to={'code_lists__in': [654], 'is_archived': False, 'is_selectable': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='codelist.konovacode'),
+        ),
+    ]

From e152dfd4d70b08cdd983a42d102bcd54794693ad Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 18 Feb 2022 11:02:40 +0100
Subject: [PATCH 22/26] #101 Team sharing form

* adds team sharing field to share form
* splits sharing logic into user based and teams based
* adds TeamAdmin for admin backend
* adds validity check on Team name -> only unused names shall be valid
---
 api/tests/v1/create/test_api_create.py        |   4 +-
 api/tests/v1/delete/test_api_delete.py        |  10 +-
 api/tests/v1/get/test_api_get.py              |  10 +-
 api/tests/v1/update/test_api_update.py        |  12 +--
 api/views/views.py                            |   2 +-
 compensation/forms/forms.py                   |   2 +-
 compensation/tests/compensation/test_views.py |   8 +-
 .../tests/compensation/test_workflow.py       |   2 +-
 compensation/tests/ecoaccount/test_views.py   |   8 +-
 .../tests/ecoaccount/test_workflow.py         |  14 +--
 compensation/tests/payment/test_views.py      |   8 +-
 compensation/tests/payment/test_workflow.py   |   2 +-
 compensation/views/eco_account.py             |   2 +-
 ema/forms.py                                  |   2 +-
 ema/tests/test_views.py                       |   8 +-
 ema/views.py                                  |   2 +-
 intervention/forms/forms.py                   |   2 +-
 intervention/forms/modalForms.py              |   2 +-
 intervention/tests/test_views.py              |  12 +--
 intervention/tests/test_workflow.py           |   4 +-
 intervention/views.py                         |   2 +-
 konova/models/object.py                       |  56 ++++++++--
 locale/de/LC_MESSAGES/django.mo               | Bin 39382 -> 39754 bytes
 locale/de/LC_MESSAGES/django.po               | 102 ++++++++++--------
 user/admin.py                                 |  15 ++-
 user/forms.py                                 |  35 ++++++
 26 files changed, 213 insertions(+), 113 deletions(-)

diff --git a/api/tests/v1/create/test_api_create.py b/api/tests/v1/create/test_api_create.py
index 72ece979..51a82e72 100644
--- a/api/tests/v1/create/test_api_create.py
+++ b/api/tests/v1/create/test_api_create.py
@@ -109,8 +109,8 @@ class APIV1CreateTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.intervention.share_with(self.superuser)
-        self.eco_account.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
+        self.eco_account.share_with_user(self.superuser)
 
         url = reverse("api:v1:deduction")
         json_file_path = "api/tests/v1/create/deduction_create_post_body.json"
diff --git a/api/tests/v1/delete/test_api_delete.py b/api/tests/v1/delete/test_api_delete.py
index cd016cfa..350fdf26 100644
--- a/api/tests/v1/delete/test_api_delete.py
+++ b/api/tests/v1/delete/test_api_delete.py
@@ -57,7 +57,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 
         """
         test_intervention = self.create_dummy_intervention()
-        test_intervention.share_with(self.superuser)
+        test_intervention.share_with_user(self.superuser)
         url = reverse("api:v1:intervention", args=(str(test_intervention.id),))
         self._test_delete_object(test_intervention, url)
 
@@ -68,7 +68,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 
         """
         test_comp = self.create_dummy_compensation()
-        test_comp.share_with(self.superuser)
+        test_comp.share_with_user(self.superuser)
         url = reverse("api:v1:compensation", args=(str(test_comp.id),))
         self._test_delete_object(test_comp, url)
 
@@ -79,7 +79,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 
         """
         test_acc = self.create_dummy_eco_account()
-        test_acc.share_with(self.superuser)
+        test_acc.share_with_user(self.superuser)
         url = reverse("api:v1:ecoaccount", args=(str(test_acc.id),))
         self._test_delete_object(test_acc, url)
 
@@ -90,7 +90,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 
         """
         test_ema = self.create_dummy_ema()
-        test_ema.share_with(self.superuser)
+        test_ema.share_with_user(self.superuser)
         url = reverse("api:v1:ema", args=(str(test_ema.id),))
         self._test_delete_object(test_ema, url)
 
@@ -101,7 +101,7 @@ class APIV1DeleteTestCase(BaseAPIV1TestCase):
 
         """
         test_deduction = self.create_dummy_deduction()
-        test_deduction.intervention.share_with(self.superuser)
+        test_deduction.intervention.share_with_user(self.superuser)
         url = reverse("api:v1:deduction", args=(str(test_deduction.id),))
 
         response = self._run_delete_request(url)
diff --git a/api/tests/v1/get/test_api_get.py b/api/tests/v1/get/test_api_get.py
index 3c464542..5bfd67a1 100644
--- a/api/tests/v1/get/test_api_get.py
+++ b/api/tests/v1/get/test_api_get.py
@@ -64,7 +64,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
         url = reverse("api:v1:intervention", args=(str(self.intervention.id),))
         geojson = self._test_get_object(self.intervention, url)
         self._assert_geojson_format(geojson)
@@ -91,7 +91,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
         self.compensation.intervention = self.intervention
         self.compensation.save()
 
@@ -119,7 +119,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.eco_account.share_with(self.superuser)
+        self.eco_account.share_with_user(self.superuser)
 
         url = reverse("api:v1:ecoaccount", args=(str(self.eco_account.id),))
         geojson = self._test_get_object(self.eco_account, url)
@@ -148,7 +148,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.ema.share_with(self.superuser)
+        self.ema.share_with_user(self.superuser)
 
         url = reverse("api:v1:ema", args=(str(self.ema.id),))
         geojson = self._test_get_object(self.ema, url)
@@ -172,7 +172,7 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.deduction.intervention.share_with(self.superuser)
+        self.deduction.intervention.share_with_user(self.superuser)
 
         url = reverse("api:v1:deduction", args=(str(self.deduction.id),))
         _json = self._test_get_object(self.deduction, url)
diff --git a/api/tests/v1/update/test_api_update.py b/api/tests/v1/update/test_api_update.py
index e371188c..8689fbe3 100644
--- a/api/tests/v1/update/test_api_update.py
+++ b/api/tests/v1/update/test_api_update.py
@@ -52,7 +52,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
         modified_on = self.intervention.modified
         url = reverse("api:v1:intervention", args=(str(self.intervention.id),))
         json_file_path = "api/tests/v1/update/intervention_update_put_body.json"
@@ -79,7 +79,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
         """
         self.compensation.intervention = self.intervention
         self.compensation.save()
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
 
         modified_on = self.compensation.modified
         url = reverse("api:v1:compensation", args=(str(self.compensation.id),))
@@ -108,7 +108,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.eco_account.share_with(self.superuser)
+        self.eco_account.share_with_user(self.superuser)
 
         modified_on = self.eco_account.modified
         url = reverse("api:v1:ecoaccount", args=(str(self.eco_account.id),))
@@ -139,7 +139,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.ema.share_with(self.superuser)
+        self.ema.share_with_user(self.superuser)
 
         modified_on = self.ema.modified
         url = reverse("api:v1:ema", args=(str(self.ema.id),))
@@ -168,8 +168,8 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
         Returns:
 
         """
-        self.deduction.intervention.share_with(self.superuser)
-        self.deduction.account.share_with(self.superuser)
+        self.deduction.intervention.share_with_user(self.superuser)
+        self.deduction.account.share_with_user(self.superuser)
 
         url = reverse("api:v1:deduction", args=(str(self.deduction.id),))
         json_file_path = "api/tests/v1/update/deduction_update_put_body.json"
diff --git a/api/views/views.py b/api/views/views.py
index 35c54fee..db8b8f9e 100644
--- a/api/views/views.py
+++ b/api/views/views.py
@@ -292,7 +292,7 @@ class AbstractModelShareAPIView(AbstractAPIView):
                 id__in=obj.shared_users
             )
             new_users_objs = obj.shared_users.union(new_users_to_be_added)
-        obj.share_with_list(new_users_objs)
+        obj.share_with_user_list(new_users_objs)
         return True
 
 
diff --git a/compensation/forms/forms.py b/compensation/forms/forms.py
index 72b1a714..46b235fa 100644
--- a/compensation/forms/forms.py
+++ b/compensation/forms/forms.py
@@ -400,7 +400,7 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
                 comment=comment,
                 legal=legal
             )
-            acc.share_with(user)
+            acc.share_with_user(user)
 
             # Add the log entry to the main objects log list
             acc.log.add(action)
diff --git a/compensation/tests/compensation/test_views.py b/compensation/tests/compensation/test_views.py
index 27218f2a..1174895c 100644
--- a/compensation/tests/compensation/test_views.py
+++ b/compensation/tests/compensation/test_views.py
@@ -103,7 +103,7 @@ class CompensationViewTestCase(BaseViewTestCase):
         client = Client()
         client.login(username=self.superuser.username, password=self.superuser_pw)
         self.superuser.groups.set([])
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         # Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
         # to a user without access, since the important permissions are missing
@@ -143,7 +143,7 @@ class CompensationViewTestCase(BaseViewTestCase):
         client.login(username=self.superuser.username, password=self.superuser_pw)
         self.superuser.groups.set([])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
         # to a user having shared access, since all important permissions are missing
@@ -185,7 +185,7 @@ class CompensationViewTestCase(BaseViewTestCase):
         group = self.groups.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([group])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -221,7 +221,7 @@ class CompensationViewTestCase(BaseViewTestCase):
         group = self.groups.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([group])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         success_urls = [
             self.index_url,
diff --git a/compensation/tests/compensation/test_workflow.py b/compensation/tests/compensation/test_workflow.py
index 7b73be89..5b7decff 100644
--- a/compensation/tests/compensation/test_workflow.py
+++ b/compensation/tests/compensation/test_workflow.py
@@ -25,7 +25,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
         super().setUp()
 
         # Give the user shared access to the dummy intervention -> inherits the access to the compensation
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
 
         # Make sure the intervention itself would be fine with valid data
         self.intervention = self.fill_out_intervention(self.intervention)
diff --git a/compensation/tests/ecoaccount/test_views.py b/compensation/tests/ecoaccount/test_views.py
index 617f7437..aaa7a4c8 100644
--- a/compensation/tests/ecoaccount/test_views.py
+++ b/compensation/tests/ecoaccount/test_views.py
@@ -78,7 +78,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
         client = Client()
         client.login(username=self.superuser.username, password=self.superuser_pw)
         self.superuser.groups.set([])
-        self.eco_account.share_with_list([self.superuser])
+        self.eco_account.share_with_user_list([self.superuser])
 
         # Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
         # to a user without access, since the important permissions are missing
@@ -119,7 +119,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
         client = Client()
         client.login(username=self.superuser.username, password=self.superuser_pw)
         self.superuser.groups.set([])
-        self.eco_account.share_with_list([])
+        self.eco_account.share_with_user_list([])
 
         # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
         # to a user having shared access, since all important permissions are missing
@@ -163,7 +163,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
         group = self.groups.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([group])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.eco_account.share_with_list([self.superuser])
+        self.eco_account.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -200,7 +200,7 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
         client.login(username=self.superuser.username, password=self.superuser_pw)
         group = self.groups.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([group])
-        self.eco_account.share_with_list([])
+        self.eco_account.share_with_user_list([])
 
         success_urls = [
             self.index_url,
diff --git a/compensation/tests/ecoaccount/test_workflow.py b/compensation/tests/ecoaccount/test_workflow.py
index afc4111e..1b350e9b 100644
--- a/compensation/tests/ecoaccount/test_workflow.py
+++ b/compensation/tests/ecoaccount/test_workflow.py
@@ -27,7 +27,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
         # Add user to conservation office group and give shared access to the account
         self.superuser.groups.add(self.groups.get(name=DEFAULT_GROUP))
         self.superuser.groups.add(self.groups.get(name=ETS_GROUP))
-        self.eco_account.share_with_list([self.superuser])
+        self.eco_account.share_with_user_list([self.superuser])
 
     def test_new(self):
         """ Test the creation of an EcoAccount
@@ -73,7 +73,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
         Returns:
 
         """
-        self.eco_account.share_with(self.superuser)
+        self.eco_account.share_with_user(self.superuser)
 
         url = reverse("compensation:acc:edit", args=(self.eco_account.id,))
         pre_edit_log_count = self.eco_account.log.count()
@@ -129,7 +129,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 
         """
         # Add proper privilege for the user
-        self.eco_account.share_with(self.superuser)
+        self.eco_account.share_with_user(self.superuser)
         pre_record_log_count = self.eco_account.log.count()
 
         # Prepare url and form data
@@ -178,7 +178,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
 
         """
         # Give user shared access to the dummy intervention, which will be needed here
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
         pre_deduction_acc_log_count = self.eco_account.log.count()
         pre_deduction_int_log_count = self.intervention.log.count()
 
@@ -231,7 +231,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
     def test_edit_deduction(self):
         test_surface = self.eco_account.get_available_rest()[0]
         self.eco_account.set_recorded(self.superuser)
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
         self.eco_account.refresh_from_db()
         self.assertIn(self.superuser, self.intervention.is_shared_with(self.superuser))
 
@@ -281,8 +281,8 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
             "confirm": True,
         }
 
-        intervention.share_with(self.superuser)
-        account.share_with(self.superuser)
+        intervention.share_with_user(self.superuser)
+        account.share_with_user(self.superuser)
 
         pre_edit_intervention_log_count = intervention.log.count()
         pre_edit_account_log_count = account.log.count()
diff --git a/compensation/tests/payment/test_views.py b/compensation/tests/payment/test_views.py
index b1eca5ae..30ffa000 100644
--- a/compensation/tests/payment/test_views.py
+++ b/compensation/tests/payment/test_views.py
@@ -64,7 +64,7 @@ class PaymentViewTestCase(BaseViewTestCase):
         client = Client()
         client.login(username=self.superuser.username, password=self.superuser_pw)
         self.superuser.groups.set([])
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         # Since the user has no groups, it does not matter that data has been shared. There SHOULD not be any difference
         # to a user without access, since the important permissions are missing
@@ -91,7 +91,7 @@ class PaymentViewTestCase(BaseViewTestCase):
         client.login(username=self.superuser.username, password=self.superuser_pw)
         self.superuser.groups.set([])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         # Since the user has no groups, it does not matter that data is unshared. There SHOULD not be any difference
         # to a user having shared access, since all important permissions are missing
@@ -120,7 +120,7 @@ class PaymentViewTestCase(BaseViewTestCase):
         group = self.groups.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([group])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         success_urls = [
             self.new_url,
@@ -143,7 +143,7 @@ class PaymentViewTestCase(BaseViewTestCase):
         group = self.groups.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([group])
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         success_urls = [
         ]
diff --git a/compensation/tests/payment/test_workflow.py b/compensation/tests/payment/test_workflow.py
index 790fb619..81259b80 100644
--- a/compensation/tests/payment/test_workflow.py
+++ b/compensation/tests/payment/test_workflow.py
@@ -21,7 +21,7 @@ class PaymentWorkflowTestCase(BaseWorkflowTestCase):
     def setUp(self) -> None:
         super().setUp()
         # Give the user shared access to the dummy intervention
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
 
         self.payment = Payment.objects.get_or_create(
             intervention=self.intervention,
diff --git a/compensation/views/eco_account.py b/compensation/views/eco_account.py
index d291218f..85b13714 100644
--- a/compensation/views/eco_account.py
+++ b/compensation/views/eco_account.py
@@ -796,7 +796,7 @@ def share_view(request: HttpRequest, id: str, token: str):
                 request,
                 _("{} has been shared with you").format(obj.identifier)
             )
-            obj.share_with(user)
+            obj.share_with_user(user)
         return redirect("compensation:acc:detail", id=id)
     else:
         messages.error(
diff --git a/ema/forms.py b/ema/forms.py
index 2f193605..8e6faab7 100644
--- a/ema/forms.py
+++ b/ema/forms.py
@@ -80,7 +80,7 @@ class NewEmaForm(AbstractCompensationForm, CompensationResponsibleFormMixin):
             )
 
             # Add the creating user to the list of shared users
-            acc.share_with(user)
+            acc.share_with_user(user)
 
             # Add the log entry to the main objects log list
             acc.log.add(action)
diff --git a/ema/tests/test_views.py b/ema/tests/test_views.py
index 9654e8f3..b2c23e11 100644
--- a/ema/tests/test_views.py
+++ b/ema/tests/test_views.py
@@ -110,7 +110,7 @@ class EmaViewTestCase(CompensationViewTestCase):
 
         # Sharing does not have any effect in here, since the default group will prohibit further functionality access
         # to this user
-        self.ema.share_with_list([self.superuser])
+        self.ema.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -160,7 +160,7 @@ class EmaViewTestCase(CompensationViewTestCase):
 
         # Sharing does not have any effect in here, since the default group will prohibit further functionality access
         # to this user
-        self.ema.share_with_list([])
+        self.ema.share_with_user_list([])
 
         success_urls = [
             self.index_url,
@@ -203,7 +203,7 @@ class EmaViewTestCase(CompensationViewTestCase):
         groups = self.groups.filter(Q(name=ETS_GROUP)|Q(name=DEFAULT_GROUP))
         self.superuser.groups.set(groups)
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.ema.share_with_list([self.superuser])
+        self.ema.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -243,7 +243,7 @@ class EmaViewTestCase(CompensationViewTestCase):
         groups = self.groups.filter(Q(name=ETS_GROUP)|Q(name=DEFAULT_GROUP))
         self.superuser.groups.set(groups)
         # Sharing is inherited by base intervention for compensation. Therefore configure the interventions share state
-        self.ema.share_with_list([])
+        self.ema.share_with_user_list([])
 
         success_urls = [
             self.index_url,
diff --git a/ema/views.py b/ema/views.py
index e9d0acb6..c145511f 100644
--- a/ema/views.py
+++ b/ema/views.py
@@ -621,7 +621,7 @@ def share_view(request: HttpRequest, id: str, token: str):
                 request,
                 _("{} has been shared with you").format(obj.identifier)
             )
-            obj.share_with(user)
+            obj.share_with_user(user)
         return redirect("ema:detail", id=id)
     else:
         messages.error(
diff --git a/intervention/forms/forms.py b/intervention/forms/forms.py
index 1c5cf1c6..94ff9704 100644
--- a/intervention/forms/forms.py
+++ b/intervention/forms/forms.py
@@ -253,7 +253,7 @@ class NewInterventionForm(BaseForm):
             intervention.log.add(action)
 
             # Add the performing user as the first user having access to the data
-            intervention.share_with(user)
+            intervention.share_with_user(user)
         return intervention
 
 
diff --git a/intervention/forms/modalForms.py b/intervention/forms/modalForms.py
index 978360da..8e44ac2e 100644
--- a/intervention/forms/modalForms.py
+++ b/intervention/forms/modalForms.py
@@ -115,7 +115,7 @@ class ShareModalForm(BaseModalForm):
 
     def _add_teams_to_field(self):
         form_data = {
-            "teams": []
+            "team_select": self.instance.teams.all()
         }
         self.load_initial_data(form_data)
 
diff --git a/intervention/tests/test_views.py b/intervention/tests/test_views.py
index f12ee7a3..a049f3e7 100644
--- a/intervention/tests/test_views.py
+++ b/intervention/tests/test_views.py
@@ -144,7 +144,7 @@ class InterventionViewTestCase(BaseViewTestCase):
         # Add user to default group
         default_group = Group.objects.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([default_group])
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -190,7 +190,7 @@ class InterventionViewTestCase(BaseViewTestCase):
         # Add user to default group
         default_group = Group.objects.get(name=DEFAULT_GROUP)
         self.superuser.groups.set([default_group])
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         success_urls = [
             self.index_url,
@@ -236,7 +236,7 @@ class InterventionViewTestCase(BaseViewTestCase):
         # Add user to zb group
         zb_group = self.groups.get(name=ZB_GROUP)
         self.superuser.groups.set([zb_group])
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -282,7 +282,7 @@ class InterventionViewTestCase(BaseViewTestCase):
         # Add user to zb group
         zb_group = self.groups.get(name=ZB_GROUP)
         self.superuser.groups.set([zb_group])
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         success_urls = [
             self.index_url,
@@ -328,7 +328,7 @@ class InterventionViewTestCase(BaseViewTestCase):
         # Add user to ets group
         ets_group = Group.objects.get(name=ETS_GROUP)
         self.superuser.groups.set([ets_group])
-        self.intervention.share_with_list([self.superuser])
+        self.intervention.share_with_user_list([self.superuser])
 
         success_urls = [
             self.index_url,
@@ -374,7 +374,7 @@ class InterventionViewTestCase(BaseViewTestCase):
         # Add user to default group
         ets_group = Group.objects.get(name=ETS_GROUP)
         self.superuser.groups.set([ets_group])
-        self.intervention.share_with_list([])
+        self.intervention.share_with_user_list([])
 
         success_urls = [
             self.index_url,
diff --git a/intervention/tests/test_workflow.py b/intervention/tests/test_workflow.py
index 1a66245c..c5290503 100644
--- a/intervention/tests/test_workflow.py
+++ b/intervention/tests/test_workflow.py
@@ -30,7 +30,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
         super().setUp()
         # Recreate a new (bare minimum) intervention before each test
         self.intervention = self.create_dummy_intervention()
-        self.intervention.share_with(self.superuser)
+        self.intervention.share_with_user(self.superuser)
 
     def test_new(self):
         """
@@ -365,7 +365,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
         if self.eco_account.recorded is None:
             rec_action = UserActionLogEntry.get_recorded_action(self.superuser)
             self.eco_account.recorded = rec_action
-        self.eco_account.share_with_list([self.superuser])
+        self.eco_account.share_with_user_list([self.superuser])
         self.eco_account.save()
         num_all_deducs = EcoAccountDeduction.objects.count()
 
diff --git a/intervention/views.py b/intervention/views.py
index 00440bb8..3004a79f 100644
--- a/intervention/views.py
+++ b/intervention/views.py
@@ -432,7 +432,7 @@ def share_view(request: HttpRequest, id: str, token: str):
                 request,
                 _("{} has been shared with you").format(intervention.identifier)
             )
-            intervention.share_with(user)
+            intervention.share_with_user(user)
         return redirect("intervention:detail", id=id)
     else:
         messages.error(
diff --git a/konova/models/object.py b/konova/models/object.py
index 69a0a2e7..e6c27a66 100644
--- a/konova/models/object.py
+++ b/konova/models/object.py
@@ -378,6 +378,7 @@ class CheckableObjectMixin(models.Model):
 class ShareableObjectMixin(models.Model):
     # Users having access on this object
     users = models.ManyToManyField("user.User", help_text="Users having access (data shared with)")
+    teams = models.ManyToManyField("user.Team", help_text="Teams having access (data shared with)")
     access_token = models.CharField(
         max_length=255,
         null=True,
@@ -435,9 +436,36 @@ class ShareableObjectMixin(models.Model):
         Returns:
 
         """
-        return self.users.filter(id=user.id)
+        directly_shared = self.users.filter(id=user.id).exists()
+        team_shared = self.teams.filter(
+            users__in=[user]
+        ).exists()
+        is_shared = directly_shared or team_shared
+        return is_shared
 
-    def share_with(self, user):
+    def share_with_team(self, team):
+        """ Adds team to list of shared access teans
+
+        Args:
+            team (Team): The team to be added to the object
+
+        Returns:
+
+        """
+        self.teams.add(team)
+
+    def share_with_team_list(self, team_list: list):
+        """ Sets the list of shared access teams
+
+        Args:
+            team_list (list): The teams to be added to the object
+
+        Returns:
+
+        """
+        self.teams.set(team_list)
+
+    def share_with_user(self, user):
         """ Adds user to list of shared access users
 
         Args:
@@ -449,7 +477,7 @@ class ShareableObjectMixin(models.Model):
         if not self.is_shared_with(user):
             self.users.add(user)
 
-    def share_with_list(self, user_list: list):
+    def share_with_user_list(self, user_list: list):
         """ Sets the list of shared access users
 
         Args:
@@ -472,24 +500,32 @@ class ShareableObjectMixin(models.Model):
         from user.models import User
         form_data = form.cleaned_data
 
-        keep_accessing_users = form_data["users"]
+        # Fetch selected teams and find out which user IDs are in removed teams -> mails need to be sent
+        accessing_teams = form_data["team_select"]
+        removed_team_users = self.teams.all().exclude(
+            id__in=accessing_teams
+        ).values_list("users__id", flat=True)
+
         new_accessing_users = list(form_data["user_select"].values_list("id", flat=True))
+        keep_accessing_users = form_data["users"]
         accessing_users = keep_accessing_users + new_accessing_users
         users = User.objects.filter(
             id__in=accessing_users
         )
         removed_users = self.users.all().exclude(
             id__in=accessing_users
-        ).values("id")
+        ).values_list("id", flat=True)
+        removed_users = removed_users.union(removed_team_users)
 
         # Send mails
-        for user in removed_users:
-            celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user["id"])
-        for user in new_accessing_users:
-            celery_send_mail_shared_access_given.delay(self.identifier, self.title,  user)
+        for user_id in removed_users:
+            celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user_id)
+        for user_id in new_accessing_users:
+            celery_send_mail_shared_access_given.delay(self.identifier, self.title,  user_id)
 
         # Set new shared users
-        self.share_with_list(users)
+        self.share_with_user_list(users)
+        self.share_with_team_list(accessing_teams)
 
     @property
     def shared_users(self) -> QuerySet:
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index ca93bc886faec14fea82f27aa2689b03373d5b42..a20ac2daaaa222c759f4d6a6e75bd9e7c9424ee3 100644
GIT binary patch
delta 11420
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
aY__9&X1XIiGn-Oc_F!eAiUKAb3jIGOTz19)

delta 11211
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
U@_a+OM&>omhzQ8boV-8!f8%^NWB>pF

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index d1da918b..aba79815 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@
 #: compensation/forms/modalForms.py:47 compensation/forms/modalForms.py:63
 #: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:463
 #: intervention/forms/forms.py:54 intervention/forms/forms.py:156
-#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:127
-#: intervention/forms/modalForms.py:140 intervention/forms/modalForms.py:153
+#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:148
+#: intervention/forms/modalForms.py:161 intervention/forms/modalForms.py:174
 #: konova/filters/mixins.py:53 konova/filters/mixins.py:54
 #: konova/filters/mixins.py:81 konova/filters/mixins.py:82
 #: konova/filters/mixins.py:94 konova/filters/mixins.py:95
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-17 13:42+0100\n"
+"POT-Creation-Date: 2022-02-18 09:35+0100\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"
@@ -64,7 +64,7 @@ msgstr "Verantwortliche Stelle"
 #: compensation/forms/forms.py:165 intervention/forms/forms.py:64
 #: intervention/forms/forms.py:81 intervention/forms/forms.py:97
 #: intervention/forms/forms.py:113 intervention/forms/modalForms.py:49
-#: user/forms.py:196
+#: intervention/forms/modalForms.py:63 user/forms.py:196
 msgid "Click for selection"
 msgstr "Auswählen..."
 
@@ -221,7 +221,7 @@ msgstr "Abbuchungen"
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:36
 #: ema/templates/ema/detail/includes/states-after.html:36
 #: ema/templates/ema/detail/includes/states-before.html:36
-#: intervention/forms/modalForms.py:338
+#: intervention/forms/modalForms.py:359
 msgid "Surface"
 msgstr "Fläche"
 
@@ -284,8 +284,8 @@ msgid "Type"
 msgstr "Typ"
 
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:24
-#: compensation/tables.py:89 intervention/forms/modalForms.py:349
-#: intervention/forms/modalForms.py:356 intervention/tables.py:88
+#: compensation/tables.py:89 intervention/forms/modalForms.py:370
+#: intervention/forms/modalForms.py:377 intervention/tables.py:88
 #: intervention/templates/intervention/detail/view.html:19
 #: konova/templates/konova/includes/quickstart/interventions.html:4
 #: templates/navbars/navbar.html:22
@@ -295,7 +295,7 @@ msgstr "Eingriff"
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
 #: compensation/tables.py:266
 #: compensation/templates/compensation/detail/eco_account/view.html:20
-#: intervention/forms/modalForms.py:322 intervention/forms/modalForms.py:329
+#: intervention/forms/modalForms.py:343 intervention/forms/modalForms.py:350
 #: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
 #: templates/navbars/navbar.html:34
 msgid "Eco-account"
@@ -364,7 +364,7 @@ msgstr "Kompensation XY; Flur ABC"
 #: ema/templates/ema/detail/includes/actions.html:34
 #: ema/templates/ema/detail/includes/deadlines.html:34
 #: ema/templates/ema/detail/includes/documents.html:34
-#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:152
+#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:173
 #: intervention/templates/intervention/detail/includes/documents.html:34
 #: intervention/templates/intervention/detail/includes/payments.html:34
 #: intervention/templates/intervention/detail/includes/revocation.html:38
@@ -484,7 +484,7 @@ msgid "Due on which date"
 msgstr "Zahlung wird an diesem Datum erwartet"
 
 #: compensation/forms/modalForms.py:64 compensation/forms/modalForms.py:357
-#: intervention/forms/modalForms.py:154 konova/forms.py:395
+#: intervention/forms/modalForms.py:175 konova/forms.py:395
 msgid "Additional comment, maximum {} letters"
 msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 
@@ -512,7 +512,7 @@ msgstr "Zusatzbezeichnung"
 msgid "Select an additional biotope type"
 msgstr "Zusatzbezeichnung wählen"
 
-#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:340
+#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:361
 msgid "in m²"
 msgstr ""
 
@@ -540,7 +540,7 @@ msgstr "Fristart wählen"
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
 #: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
 #: ema/templates/ema/detail/includes/deadlines.html:31
-#: intervention/forms/modalForms.py:126
+#: intervention/forms/modalForms.py:147
 msgid "Date"
 msgstr "Datum"
 
@@ -752,7 +752,7 @@ msgstr "Menge"
 #: intervention/templates/intervention/detail/includes/documents.html:39
 #: intervention/templates/intervention/detail/includes/payments.html:39
 #: intervention/templates/intervention/detail/includes/revocation.html:43
-#: templates/log.html:10 user/templates/user/team/index.html:33
+#: templates/log.html:10 user/templates/user/team/index.html:32
 msgid "Action"
 msgstr "Aktionen"
 
@@ -1000,14 +1000,14 @@ msgstr "Zuletzt bearbeitet"
 
 #: compensation/templates/compensation/detail/compensation/view.html:100
 #: compensation/templates/compensation/detail/eco_account/view.html:83
-#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:56
+#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:70
 #: intervention/templates/intervention/detail/view.html:116
 msgid "Shared with"
 msgstr "Freigegeben für"
 
 #: compensation/templates/compensation/detail/eco_account/includes/controls.html:15
 #: ema/templates/ema/detail/includes/controls.html:15
-#: intervention/forms/modalForms.py:70
+#: intervention/forms/modalForms.py:84
 #: intervention/templates/intervention/detail/includes/controls.html:15
 msgid "Share"
 msgstr "Freigabe"
@@ -1325,10 +1325,22 @@ msgid "Send this link to users who you want to have writing access on the data"
 msgstr "Andere Nutzer erhalten über diesen Link Zugriff auf die Daten"
 
 #: intervention/forms/modalForms.py:41
+msgid "Add team to share with"
+msgstr "Team hinzufügen"
+
+#: intervention/forms/modalForms.py:43
+msgid ""
+"Multiple selection possible - You can only select teams which do not already "
+"have access."
+msgstr ""
+"Mehrfachauswahl möglich - Sie können nur Teams wählen, für die der Eintrag "
+"noch nicht freigegeben wurde."
+
+#: intervention/forms/modalForms.py:55
 msgid "Add user to share with"
 msgstr "Nutzer direkt hinzufügen"
 
-#: intervention/forms/modalForms.py:43
+#: intervention/forms/modalForms.py:57
 msgid ""
 "Multiple selection possible - You can only select users which do not already "
 "have access. Enter the full username."
@@ -1336,46 +1348,46 @@ msgstr ""
 "Mehrfachauswahl möglich - Sie können nur Nutzer wählen, für die der Eintrag "
 "noch nicht freigegeben wurde. Geben Sie den ganzen Nutzernamen an."
 
-#: intervention/forms/modalForms.py:59
+#: intervention/forms/modalForms.py:73
 msgid "Remove check to remove access for this user"
 msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen"
 
-#: intervention/forms/modalForms.py:71
+#: intervention/forms/modalForms.py:85
 msgid "Share settings for {}"
 msgstr "Freigabe Einstellungen für {}"
 
-#: intervention/forms/modalForms.py:128
+#: intervention/forms/modalForms.py:149
 msgid "Date of revocation"
 msgstr "Datum des Widerspruchs"
 
-#: intervention/forms/modalForms.py:139
+#: intervention/forms/modalForms.py:160
 #: intervention/templates/intervention/detail/includes/revocation.html:35
 msgid "Document"
 msgstr "Dokument"
 
-#: intervention/forms/modalForms.py:142
+#: intervention/forms/modalForms.py:163
 msgid "Must be smaller than 15 Mb"
 msgstr "Muss kleiner als 15 Mb sein"
 
-#: intervention/forms/modalForms.py:167
+#: intervention/forms/modalForms.py:188
 #: intervention/templates/intervention/detail/includes/revocation.html:18
 msgid "Add revocation"
 msgstr "Widerspruch hinzufügen"
 
-#: intervention/forms/modalForms.py:224
+#: intervention/forms/modalForms.py:245
 msgid "Checked intervention data"
 msgstr "Eingriffsdaten geprüft"
 
-#: intervention/forms/modalForms.py:230
+#: intervention/forms/modalForms.py:251
 msgid "Checked compensations data and payments"
 msgstr "Kompensationen und Zahlungen geprüft"
 
-#: intervention/forms/modalForms.py:239
+#: intervention/forms/modalForms.py:260
 #: intervention/templates/intervention/detail/includes/controls.html:19
 msgid "Run check"
 msgstr "Prüfung vornehmen"
 
-#: intervention/forms/modalForms.py:240 konova/forms.py:514
+#: intervention/forms/modalForms.py:261 konova/forms.py:514
 msgid ""
 "I, {} {}, confirm that all necessary control steps have been performed by "
 "myself."
@@ -1383,23 +1395,23 @@ msgstr ""
 "Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt "
 "wurden:"
 
-#: intervention/forms/modalForms.py:324
+#: intervention/forms/modalForms.py:345
 msgid "Only recorded accounts can be selected for deductions"
 msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
 
-#: intervention/forms/modalForms.py:351
+#: intervention/forms/modalForms.py:372
 msgid "Only shared interventions can be selected"
 msgstr "Nur freigegebene Eingriffe können gewählt werden"
 
-#: intervention/forms/modalForms.py:364
+#: intervention/forms/modalForms.py:385
 msgid "New Deduction"
 msgstr "Neue Abbuchung"
 
-#: intervention/forms/modalForms.py:365
+#: intervention/forms/modalForms.py:386
 msgid "Enter the information for a new deduction from a chosen eco-account"
 msgstr "Geben Sie die Informationen für eine neue Abbuchung ein."
 
-#: intervention/forms/modalForms.py:408
+#: intervention/forms/modalForms.py:429
 msgid ""
 "Eco-account {} is not recorded yet. You can only deduct from recorded "
 "accounts."
@@ -1407,7 +1419,7 @@ msgstr ""
 "Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
 "verzeichneten Ökokonten erfolgen."
 
-#: intervention/forms/modalForms.py:418
+#: intervention/forms/modalForms.py:439
 msgid ""
 "The account {} has not enough surface for a deduction of {} m². There are "
 "only {} m² left"
@@ -2273,7 +2285,7 @@ msgstr "* sind Pflichtfelder."
 msgid "New entry"
 msgstr "Neuer Eintrag"
 
-#: templates/generic_index.html:41 user/templates/user/team/index.html:23
+#: templates/generic_index.html:41 user/templates/user/team/index.html:22
 msgid "New"
 msgstr "Neu"
 
@@ -2406,7 +2418,7 @@ msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
 msgid "Team name"
 msgstr "Team Name"
 
-#: user/forms.py:179 user/templates/user/team/index.html:31
+#: user/forms.py:179 user/templates/user/team/index.html:30
 msgid "Description"
 msgstr "Beschreibung"
 
@@ -2434,19 +2446,23 @@ msgstr ""
 "Sie werden standardmäßig der Administrator dieses Teams. Sie müssen sich "
 "selbst nicht zur Liste der Mitglieder hinzufügen."
 
-#: user/forms.py:230
+#: user/forms.py:218 user/forms.py:279
+msgid "Name already taken. Try another."
+msgstr "Name bereits vergeben. Probieren Sie einen anderen."
+
+#: user/forms.py:249
 msgid "Admin"
 msgstr "Administrator"
 
-#: user/forms.py:231
+#: user/forms.py:250
 msgid "Administrators manage team details and members"
 msgstr "Administratoren verwalten die Teamdaten und Mitglieder"
 
-#: user/forms.py:244
+#: user/forms.py:263
 msgid "Selected admin ({}) needs to be a member of this team."
 msgstr "Gewählter Administrator ({}) muss ein Mitglied des Teams sein."
 
-#: user/forms.py:256 user/templates/user/team/index.html:52
+#: user/forms.py:291 user/templates/user/team/index.html:51
 msgid "Edit team"
 msgstr "Team bearbeiten"
 
@@ -2466,7 +2482,7 @@ msgstr "Gelöscht"
 msgid "Show contact data"
 msgstr "Zeige Kontaktdaten"
 
-#: user/templates/user/index.html:13 user/templates/user/team/index.html:30
+#: user/templates/user/index.html:13 user/templates/user/team/index.html:29
 msgid "Name"
 msgstr ""
 
@@ -2515,20 +2531,20 @@ msgstr ""
 msgid "Manage teams"
 msgstr ""
 
-#: user/templates/user/index.html:69 user/templates/user/team/index.html:19
+#: user/templates/user/index.html:69 user/templates/user/team/index.html:18
 #: user/views.py:142
 msgid "Teams"
 msgstr ""
 
-#: user/templates/user/team/index.html:21
+#: user/templates/user/team/index.html:20
 msgid "Add new team"
 msgstr "Neues Team hinzufügen"
 
-#: user/templates/user/team/index.html:32
+#: user/templates/user/team/index.html:31
 msgid "Members"
 msgstr "Mitglieder"
 
-#: user/templates/user/team/index.html:55
+#: user/templates/user/team/index.html:54
 msgid "Remove team"
 msgstr "Team entfernen"
 
diff --git a/user/admin.py b/user/admin.py
index 3e608617..1aeacee3 100644
--- a/user/admin.py
+++ b/user/admin.py
@@ -1,6 +1,6 @@
 from django.contrib import admin
 
-from user.models import UserNotification, UserActionLogEntry, User
+from user.models import UserNotification, UserActionLogEntry, User, Team
 
 
 class UserNotificationAdmin(admin.ModelAdmin):
@@ -64,7 +64,20 @@ class UserActionLogEntryAdmin(admin.ModelAdmin):
     ]
 
 
+class TeamAdmin(admin.ModelAdmin):
+    list_display = [
+        "name",
+        "description",
+        "admin",
+    ]
+    search_fields = [
+        "name",
+        "description",
+    ]
+
+
 admin.site.register(User, UserAdmin)
+admin.site.register(Team, TeamAdmin)
 
 # Outcommented for a cleaner admin backend on production
 #admin.site.register(UserNotification, UserNotificationAdmin)
diff --git a/user/forms.py b/user/forms.py
index 35c1e82e..01ec54b6 100644
--- a/user/forms.py
+++ b/user/forms.py
@@ -206,6 +206,25 @@ class NewTeamModalForm(BaseModalForm):
         self.action_url = reverse("user:team-new")
         self.cancel_redirect = reverse("user:team-index")
 
+    def _is_name_valid(self):
+        name = self.cleaned_data.get("name", None)
+        teams_with_same_name = Team.objects.filter(
+            name=name
+        )
+        name_valid = not teams_with_same_name.exists()
+        if not name_valid:
+            self.add_error(
+                "name",
+                _("Name already taken. Try another.")
+            )
+
+        return name_valid
+
+    def is_valid(self):
+        super_valid = super().is_valid()
+        name_valid = self._is_name_valid()
+        return super_valid and name_valid
+
     def save(self):
         with transaction.atomic():
             team = Team.objects.create(
@@ -246,6 +265,22 @@ class EditTeamModalForm(NewTeamModalForm):
 
         return _is_valid
 
+    def _is_name_valid(self):
+        name = self.cleaned_data.get("name", None)
+        teams_with_same_name = Team.objects.filter(
+            name=name
+        ).exclude(
+            id=self.instance.id
+        )
+        name_valid = not teams_with_same_name.exists()
+        if not name_valid:
+            self.add_error(
+                "name",
+                _("Name already taken. Try another.")
+            )
+
+        return name_valid
+
     def is_valid(self):
         super_valid = super().is_valid()
         admin_valid = self.__is_admin_valid()

From edcf7b3c7832942f5f7fafc6f2acef4d96a4ea46 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 18 Feb 2022 13:52:27 +0100
Subject: [PATCH 23/26] #101 Team sharing tests

* adds tests for team sharing
* extends the API for team sharing support
* adds shared_teams property shortcut for ShareableObjectMixin
* adds full support for team-based sharing to all views and functions
* simplifies ShareModalForm
* adds/updates translations
---
 api/tests/v1/get/test_api_get.py              |  20 ++++
 .../intervention_share_update_put_body.json   |   8 ++
 api/tests/v1/update/test_api_update.py        |  21 ++++
 api/views/views.py                            |  48 ++++++++-
 compensation/filters.py                       |  23 +----
 compensation/models/compensation.py           |  40 +++++++-
 .../tests/ecoaccount/test_workflow.py         |   2 +-
 intervention/forms/modalForms.py              |  92 +++++++++---------
 konova/autocompletes.py                       |  19 ++--
 konova/filters/mixins.py                      |   5 +-
 konova/models/object.py                       |  34 +++++--
 konova/tests/test_autocompletes.py            |   1 +
 konova/tests/test_views.py                    |  21 +++-
 konova/utils/message_templates.py             |   8 +-
 locale/de/LC_MESSAGES/django.mo               | Bin 39754 -> 39816 bytes
 locale/de/LC_MESSAGES/django.po               |  69 +++++++------
 16 files changed, 278 insertions(+), 133 deletions(-)
 create mode 100644 api/tests/v1/update/intervention_share_update_put_body.json

diff --git a/api/tests/v1/get/test_api_get.py b/api/tests/v1/get/test_api_get.py
index 5bfd67a1..953b0f69 100644
--- a/api/tests/v1/get/test_api_get.py
+++ b/api/tests/v1/get/test_api_get.py
@@ -85,6 +85,26 @@ class APIV1GetTestCase(BaseAPIV1TestCase):
         except KeyError as e:
             self.fail(e)
 
+    def test_get_shared(self):
+        """ Tests api GET on shared info of the intervention
+
+        Returns:
+
+        """
+        self.intervention.share_with_user(self.superuser)
+        self.intervention.share_with_team(self.team)
+        url = reverse("api:v1:intervention-share", args=(str(self.intervention.id),))
+        response = self._run_get_request(url)
+        content = json.loads(response.content)
+        self.assertIn("users", content)
+        self.assertIn(self.superuser.username, content["users"])
+        self.assertEqual(1, len(content["users"]))
+        self.assertIn("teams", content)
+        self.assertEqual(1, len(content["teams"]))
+        for team in content["teams"]:
+            self.assertEqual(team["id"], str(self.team.id))
+            self.assertEqual(team["name"], self.team.name)
+
     def test_get_compensation(self):
         """ Tests api GET
 
diff --git a/api/tests/v1/update/intervention_share_update_put_body.json b/api/tests/v1/update/intervention_share_update_put_body.json
new file mode 100644
index 00000000..c160aeea
--- /dev/null
+++ b/api/tests/v1/update/intervention_share_update_put_body.json
@@ -0,0 +1,8 @@
+{
+    "users": [
+        "CHANGE_ME"
+    ],
+    "teams": [
+        "CHANGE_ME"
+    ]
+}
\ No newline at end of file
diff --git a/api/tests/v1/update/test_api_update.py b/api/tests/v1/update/test_api_update.py
index 8689fbe3..500aec24 100644
--- a/api/tests/v1/update/test_api_update.py
+++ b/api/tests/v1/update/test_api_update.py
@@ -184,3 +184,24 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
         self.assertEqual(put_body["intervention"], str(self.deduction.intervention.id))
         self.assertEqual(put_body["eco_account"], str(self.deduction.account.id))
         self.assertEqual(put_body["surface"], self.deduction.surface)
+
+    def test_update_share_intervention(self):
+        self.intervention.share_with_user(self.superuser)
+        url = reverse("api:v1:intervention-share", args=(str(self.intervention.id),))
+        json_file_path = "api/tests/v1/update/intervention_share_update_put_body.json"
+        with open(json_file_path) as json_file:
+            put_body = json.load(fp=json_file)
+            put_body["users"] = [self.user.username]
+            put_body["teams"] = [self.team.name]
+
+        self.assertFalse(self.intervention.is_shared_with(self.user))
+        self.assertEqual(0, self.intervention.shared_teams.count())
+
+        response = self._run_update_request(url, put_body)
+        self.assertEqual(response.status_code, 200, msg=response.content)
+        self.intervention.refresh_from_db()
+
+        self.assertEqual(1, self.intervention.shared_teams.count())
+        self.assertEqual(2, self.intervention.shared_users.count())
+        self.assertEqual(self.team.name, self.intervention.shared_teams.first().name)
+        self.assertTrue(self.intervention.is_shared_with(self.user))
diff --git a/api/views/views.py b/api/views/views.py
index db8b8f9e..75d764e8 100644
--- a/api/views/views.py
+++ b/api/views/views.py
@@ -19,7 +19,7 @@ from ema.models import Ema
 from intervention.models import Intervention
 from konova.utils.message_templates import DATA_UNSHARED
 from konova.utils.user_checks import is_default_group_only
-from user.models import User
+from user.models import User, Team
 
 
 class AbstractAPIView(View):
@@ -198,13 +198,21 @@ class AbstractModelShareAPIView(AbstractAPIView):
         """
         try:
             users = self._get_shared_users_of_object(id)
+            teams = self._get_shared_teams_of_object(id)
         except Exception as e:
             return self._return_error_response(e)
 
         data = {
             "users": [
                 user.username for user in users
-            ]
+            ],
+            "teams": [
+                {
+                    "id": team.id,
+                    "name": team.name,
+                }
+                for team in teams
+            ],
         }
 
         return JsonResponse(data)
@@ -258,6 +266,22 @@ class AbstractModelShareAPIView(AbstractAPIView):
         users = obj.shared_users
         return users
 
+    def _get_shared_teams_of_object(self, id) -> QuerySet:
+        """ Check permissions and get the teams
+
+        Args:
+            id (str): The object's id
+
+        Returns:
+            users (QuerySet)
+        """
+        obj = self.model.objects.get(
+            id=id
+        )
+        self._check_user_has_shared_access(obj)
+        teams = obj.shared_teams
+        return teams
+
     def _process_put_body(self, body: bytes, id: str):
         """ Reads the body data, performs validity checks and sets the new users
 
@@ -271,19 +295,26 @@ class AbstractModelShareAPIView(AbstractAPIView):
         obj = self.model.objects.get(id=id)
         self._check_user_has_shared_access(obj)
 
-        new_users = json.loads(body.decode("utf-8"))
-        new_users = new_users.get("users", [])
+        content = json.loads(body.decode("utf-8"))
+        new_users = content.get("users", [])
         if len(new_users) == 0:
             raise ValueError("Shared user list must not be empty!")
+        new_teams = content.get("teams", [])
 
         # Eliminate duplicates
         new_users = list(dict.fromkeys(new_users))
+        new_teams = list(dict.fromkeys(new_teams))
 
         # Make sure each of these names exist as a user
         new_users_objs = []
         for user in new_users:
             new_users_objs.append(User.objects.get(username=user))
 
+        # Make sure each of these names exist as a user
+        new_teams_objs = []
+        for team_name in new_teams:
+            new_teams_objs.append(Team.objects.get(name=team_name))
+
         if is_default_group_only(self.user):
             # Default only users are not allowed to remove other users from having access. They can only add new ones!
             new_users_to_be_added = User.objects.filter(
@@ -292,7 +323,16 @@ class AbstractModelShareAPIView(AbstractAPIView):
                 id__in=obj.shared_users
             )
             new_users_objs = obj.shared_users.union(new_users_to_be_added)
+
+            new_teams_to_be_added = Team.objects.filter(
+                name__in=new_teams
+            ).exclude(
+                id__in=obj.shared_teams
+            )
+            new_teams_objs = obj.shared_teams.union(new_teams_to_be_added)
+
         obj.share_with_user_list(new_users_objs)
+        obj.share_with_team_list(new_teams_objs)
         return True
 
 
diff --git a/compensation/filters.py b/compensation/filters.py
index d028e3ce..b6377092 100644
--- a/compensation/filters.py
+++ b/compensation/filters.py
@@ -59,8 +59,9 @@ class CheckboxCompensationTableFilter(CheckboxTableFilter):
         """
         if not value:
             return queryset.filter(
-                intervention__users__in=[self.user],  # requesting user has access
-            )
+                Q(intervention__users__in=[self.user]) |  # requesting user has access
+                Q(intervention__teams__users__in=[self.user])
+            ).distinct()
         else:
             return queryset
 
@@ -127,24 +128,6 @@ class CheckboxEcoAccountTableFilter(CheckboxTableFilter):
         )
     )
 
-    def filter_show_all(self, queryset, name, value) -> QuerySet:
-        """ Filters queryset depending on value of 'show_all' setting
-
-        Args:
-            queryset ():
-            name ():
-            value ():
-
-        Returns:
-
-        """
-        if not value:
-            return queryset.filter(
-                users__in=[self.user],  # requesting user has access
-            )
-        else:
-            return queryset
-
     def filter_only_show_unrecorded(self, queryset, name, value) -> QuerySet:
         """ Filters queryset depending on value of 'show_recorded' setting
 
diff --git a/compensation/models/compensation.py b/compensation/models/compensation.py
index 7a10aa0b..ea69cefc 100644
--- a/compensation/models/compensation.py
+++ b/compensation/models/compensation.py
@@ -8,7 +8,7 @@ Created on: 16.11.21
 import shutil
 
 from django.contrib import messages
-from user.models import User
+from user.models import User, Team
 from django.db import models, transaction
 from django.db.models import QuerySet, Sum
 from django.http import HttpRequest
@@ -299,7 +299,7 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
         # Compensations inherit their shared state from the interventions
         return self.intervention.is_shared_with(user)
 
-    def share_with(self, user: User):
+    def share_with_user(self, user: User):
         """ Adds user to list of shared access users
 
         Args:
@@ -308,10 +308,9 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
         Returns:
 
         """
-        if not self.intervention.is_shared_with(user):
-            self.intervention.users.add(user)
+        self.intervention.users.add(user)
 
-    def share_with_list(self, user_list: list):
+    def share_with_user_list(self, user_list: list):
         """ Sets the list of shared access users
 
         Args:
@@ -322,6 +321,28 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
         """
         self.intervention.users.set(user_list)
 
+    def share_with_team(self, team: Team):
+        """ Adds team to list of shared access teams
+
+        Args:
+            team (Team): The team to be added to the object
+
+        Returns:
+
+        """
+        self.intervention.teams.add(team)
+
+    def share_with_team_list(self, team_list: list):
+        """ Sets the list of shared access teams
+
+        Args:
+            team_list (list): The teams to be added to the object
+
+        Returns:
+
+        """
+        self.intervention.teams.set(team_list)
+
     @property
     def shared_users(self) -> QuerySet:
         """ Shortcut for fetching the users which have shared access on this object
@@ -331,6 +352,15 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
         """
         return self.intervention.users.all()
 
+    @property
+    def shared_teams(self) -> QuerySet:
+        """ Shortcut for fetching the teams which have shared access on this object
+
+        Returns:
+            users (QuerySet)
+        """
+        return self.intervention.teams.all()
+
     def get_documents(self) -> QuerySet:
         """ Getter for all documents of a compensation
 
diff --git a/compensation/tests/ecoaccount/test_workflow.py b/compensation/tests/ecoaccount/test_workflow.py
index 1b350e9b..03b4996a 100644
--- a/compensation/tests/ecoaccount/test_workflow.py
+++ b/compensation/tests/ecoaccount/test_workflow.py
@@ -233,7 +233,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
         self.eco_account.set_recorded(self.superuser)
         self.intervention.share_with_user(self.superuser)
         self.eco_account.refresh_from_db()
-        self.assertIn(self.superuser, self.intervention.is_shared_with(self.superuser))
+        self.assertTrue(self.superuser, self.intervention.is_shared_with(self.superuser))
 
         deduction = EcoAccountDeduction.objects.create(
             intervention=self.intervention,
diff --git a/intervention/forms/modalForms.py b/intervention/forms/modalForms.py
index 8e44ac2e..39479388 100644
--- a/intervention/forms/modalForms.py
+++ b/intervention/forms/modalForms.py
@@ -9,7 +9,7 @@ from dal import autocomplete
 from django.core.exceptions import ObjectDoesNotExist
 
 from konova.utils.message_templates import DEDUCTION_ADDED, REVOCATION_ADDED, DEDUCTION_REMOVED, DEDUCTION_EDITED, \
-    REVOCATION_EDITED
+    REVOCATION_EDITED, ENTRY_REMOVE_MISSING_PERMISSION
 from user.models import User, Team
 from user.models import UserActionLogEntry
 from django.db import transaction
@@ -37,7 +37,7 @@ class ShareModalForm(BaseModalForm):
             }
         )
     )
-    team_select = forms.ModelMultipleChoiceField(
+    teams = forms.ModelMultipleChoiceField(
         label=_("Add team to share with"),
         label_suffix="",
         help_text=_("Multiple selection possible - You can only select teams which do not already have access."),
@@ -51,7 +51,7 @@ class ShareModalForm(BaseModalForm):
             },
         ),
     )
-    user_select = forms.ModelMultipleChoiceField(
+    users = forms.ModelMultipleChoiceField(
         label=_("Add user to share with"),
         label_suffix="",
         help_text=_("Multiple selection possible - You can only select users which do not already have access. Enter the full username."),
@@ -63,21 +63,8 @@ class ShareModalForm(BaseModalForm):
                 "data-placeholder": _("Click for selection"),
                 "data-minimum-input-length": 3,
             },
-            forward=["users"]
         ),
     )
-    users = forms.MultipleChoiceField(
-        label=_("Shared with"),
-        label_suffix="",
-        required=True,
-        help_text=_("Remove check to remove access for this user"),
-        widget=forms.CheckboxSelectMultiple(
-            attrs={
-                "class": "list-unstyled",
-            }
-        ),
-        choices=[]
-    )
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -91,6 +78,48 @@ class ShareModalForm(BaseModalForm):
 
         self._init_fields()
 
+    def _user_team_valid(self):
+        """ Checks whether users and teams have been removed by the user and if the user is allowed to do so or not
+
+        Returns:
+
+        """
+        users = self.cleaned_data.get("users", User.objects.none())
+        teams = self.cleaned_data.get("teams", Team.objects.none())
+
+        _is_valid = True
+        if is_default_group_only(self.user):
+            shared_users = self.instance.shared_users
+            shared_teams = self.instance.shared_teams
+
+            shared_users_are_removed = not set(shared_users).issubset(users)
+            shared_teams_are_removed = not set(shared_teams).issubset(teams)
+
+            if shared_users_are_removed:
+                self.add_error(
+                    "users",
+                    ENTRY_REMOVE_MISSING_PERMISSION
+                )
+                _is_valid = False
+            if shared_teams_are_removed:
+                self.add_error(
+                    "teams",
+                    ENTRY_REMOVE_MISSING_PERMISSION
+                )
+                _is_valid = False
+        return _is_valid
+
+    def is_valid(self):
+        """ Extended validity check
+
+        Returns:
+
+        """
+        super_valid = super().is_valid()
+        user_team_valid = self._user_team_valid()
+        _is_valid = super_valid and user_team_valid
+        return _is_valid
+
     def _init_fields(self):
         """ Wraps initializing of fields
 
@@ -105,39 +134,12 @@ class ShareModalForm(BaseModalForm):
             self.share_link
         )
 
-        # Initialize users field
-        # Disable field if user is not in registration or conservation group
-        if is_default_group_only(self.request.user):
-            self.disable_form_field("users")
-
-        self._add_user_choices_to_field()
-        self._add_teams_to_field()
-
-    def _add_teams_to_field(self):
         form_data = {
-            "team_select": self.instance.teams.all()
+            "teams": self.instance.teams.all(),
+            "users": self.instance.users.all(),
         }
         self.load_initial_data(form_data)
 
-    def _add_user_choices_to_field(self):
-        """ Transforms the instance's sharing users into a list for the form field
-
-        Returns:
-
-        """
-        users = self.instance.users.all()
-        choices = []
-        for n in users:
-            choices.append(
-                (n.id, n.username)
-            )
-        self.fields["users"].choices = choices
-        u_ids = list(users.values_list("id", flat=True))
-        self.initialize_form_field(
-            "users",
-            u_ids
-        )
-
     def save(self):
         self.instance.update_sharing_user(self)
 
diff --git a/konova/autocompletes.py b/konova/autocompletes.py
index 9b1be2d3..5ecc50d6 100644
--- a/konova/autocompletes.py
+++ b/konova/autocompletes.py
@@ -76,19 +76,14 @@ class ShareUserAutocomplete(Select2QuerySetView):
     def get_queryset(self):
         if self.request.user.is_anonymous:
             return User.objects.none()
-        exclude_user_ids = self.forwarded.get("users", [])
-        _exclude = {"id__in": exclude_user_ids}
-        qs = User.objects.all().exclude(
-            **_exclude
-        ).order_by(
-            "username"
-        )
+        qs = User.objects.all()
         if self.q:
             # Due to privacy concerns only a full username match will return the proper user entry
             qs = qs.filter(
                 Q(username=self.q) |
                 Q(email=self.q)
             ).distinct()
+        qs = qs.order_by("username")
         return qs
 
 
@@ -99,13 +94,15 @@ class ShareTeamAutocomplete(Select2QuerySetView):
     def get_queryset(self):
         if self.request.user.is_anonymous:
             return Team.objects.none()
+        qs = Team.objects.all()
         if self.q:
             # Due to privacy concerns only a full username match will return the proper user entry
-            qs = Team.objects.filter(
-                Q(name__icontains=self.q)
-            ).order_by(
-                "name"
+            qs = qs.filter(
+                name__icontains=self.q
             )
+        qs = qs.order_by(
+            "name"
+        )
         return qs
 
 
diff --git a/konova/filters/mixins.py b/konova/filters/mixins.py
index 5625ff36..5a07e3c2 100644
--- a/konova/filters/mixins.py
+++ b/konova/filters/mixins.py
@@ -297,8 +297,9 @@ class ShareableTableFilterMixin(django_filters.FilterSet):
         """
         if not value:
             return queryset.filter(
-                users__in=[self.user],  # requesting user has access
-            )
+                Q(users__in=[self.user]) |  # requesting user has access
+                Q(teams__users__in=[self.user])
+            ).distinct()
         else:
             return queryset
 
diff --git a/konova/models/object.py b/konova/models/object.py
index e6c27a66..92b3ccae 100644
--- a/konova/models/object.py
+++ b/konova/models/object.py
@@ -501,30 +501,37 @@ class ShareableObjectMixin(models.Model):
         form_data = form.cleaned_data
 
         # Fetch selected teams and find out which user IDs are in removed teams -> mails need to be sent
-        accessing_teams = form_data["team_select"]
+        accessing_teams = form_data["teams"]
         removed_team_users = self.teams.all().exclude(
             id__in=accessing_teams
         ).values_list("users__id", flat=True)
-
-        new_accessing_users = list(form_data["user_select"].values_list("id", flat=True))
-        keep_accessing_users = form_data["users"]
-        accessing_users = keep_accessing_users + new_accessing_users
-        users = User.objects.filter(
-            id__in=accessing_users
+        accessing_team_users = User.objects.filter(
+            id__in=accessing_teams.values_list("users", flat=True)
         )
+        new_team_users = accessing_team_users.exclude(
+            id__in=self.shared_users
+        ).values_list("id", flat=True)
+
+        # Fetch selected users
+        accessing_users = form_data["users"]
         removed_users = self.users.all().exclude(
             id__in=accessing_users
         ).values_list("id", flat=True)
+        new_users = accessing_users.exclude(
+            id__in=self.shared_users
+        ).values_list("id", flat=True)
+
+        new_users = new_users.union(new_team_users)
         removed_users = removed_users.union(removed_team_users)
 
         # Send mails
         for user_id in removed_users:
             celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user_id)
-        for user_id in new_accessing_users:
+        for user_id in new_users:
             celery_send_mail_shared_access_given.delay(self.identifier, self.title,  user_id)
 
         # Set new shared users
-        self.share_with_user_list(users)
+        self.share_with_user_list(accessing_users)
         self.share_with_team_list(accessing_teams)
 
     @property
@@ -536,6 +543,15 @@ class ShareableObjectMixin(models.Model):
         """
         return self.users.all()
 
+    @property
+    def shared_teams(self) -> QuerySet:
+        """ Shortcut for fetching the teams which have shared access on this object
+
+        Returns:
+            teams (QuerySet)
+        """
+        return self.teams.all()
+
     @abstractmethod
     def get_share_url(self):
         """ Returns the share url for the object
diff --git a/konova/tests/test_autocompletes.py b/konova/tests/test_autocompletes.py
index 7d9e5088..95a3508d 100644
--- a/konova/tests/test_autocompletes.py
+++ b/konova/tests/test_autocompletes.py
@@ -71,6 +71,7 @@ class AutocompleteTestCase(BaseTestCase):
             "codes-registration-office-autocomplete",
             "codes-conservation-office-autocomplete",
             "share-user-autocomplete",
+            "share-team-autocomplete",
         ]
         for test in tests:
             self.client.login(username=self.superuser.username, password=self.superuser_pw)
diff --git a/konova/tests/test_views.py b/konova/tests/test_views.py
index 6218a6c0..ff99ea3c 100644
--- a/konova/tests/test_views.py
+++ b/konova/tests/test_views.py
@@ -9,7 +9,7 @@ import datetime
 
 from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID
 from ema.models import Ema
-from user.models import User
+from user.models import User, Team
 from django.contrib.auth.models import Group
 from django.contrib.gis.geos import MultiPolygon, Polygon
 from django.core.exceptions import ObjectDoesNotExist
@@ -65,6 +65,7 @@ class BaseTestCase(TestCase):
         self.create_dummy_states()
         self.create_dummy_action()
         self.codes = self.create_dummy_codes()
+        self.team = self.create_dummy_team()
 
         # Set the default group as only group for the user
         default_group = self.groups.get(name=DEFAULT_GROUP)
@@ -251,6 +252,24 @@ class BaseTestCase(TestCase):
         ])
         return codes
 
+    def create_dummy_team(self):
+        """ Creates a dummy team
+
+        Returns:
+
+        """
+        if self.superuser is None:
+            self.create_users()
+
+        team = Team.objects.get_or_create(
+            name="Testteam",
+            description="Testdescription",
+            admin=self.superuser,
+        )[0]
+        team.users.add(self.superuser)
+
+        return team
+
     @staticmethod
     def create_dummy_geometry() -> MultiPolygon:
         """ Creates some geometry
diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py
index 5809b3b6..6c0c6148 100644
--- a/konova/utils/message_templates.py
+++ b/konova/utils/message_templates.py
@@ -12,11 +12,13 @@ FORM_INVALID = _("There was an error on this form.")
 PARAMS_INVALID = _("Invalid parameters")
 INTERVENTION_INVALID = _("There are errors in this intervention.")
 IDENTIFIER_REPLACED = _("The identifier '{}' had to be changed to '{}' since another entry has been added in the meanwhile, which uses this identifier")
+ENTRY_REMOVE_MISSING_PERMISSION = _("Only conservation or registration office users are allowed to remove entries.")
+MISSING_GROUP_PERMISSION = _("You need to be part of another user group.")
+CHECKED_RECORDED_RESET = _("Status of Checked and Recorded reseted")
+
+# SHARE
 DATA_UNSHARED = _("This data is not shared with you")
 DATA_UNSHARED_EXPLANATION = _("Remember: This data has not been shared with you, yet. This means you can only read but can not edit or perform any actions like running a check or recording.")
-MISSING_GROUP_PERMISSION = _("You need to be part of another user group.")
-
-CHECKED_RECORDED_RESET = _("Status of Checked and Recorded reseted")
 
 # FILES
 FILE_TYPE_UNSUPPORTED = _("Unsupported file type")
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index a20ac2daaaa222c759f4d6a6e75bd9e7c9424ee3..cbd6f0b09ac2c43691e3e31e27cb6e98f171d3df 100644
GIT binary patch
delta 6607
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

delta 6562
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

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index aba79815..bb96bab4 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@
 #: compensation/forms/modalForms.py:47 compensation/forms/modalForms.py:63
 #: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:463
 #: intervention/forms/forms.py:54 intervention/forms/forms.py:156
-#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:148
-#: intervention/forms/modalForms.py:161 intervention/forms/modalForms.py:174
+#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:154
+#: intervention/forms/modalForms.py:167 intervention/forms/modalForms.py:180
 #: konova/filters/mixins.py:53 konova/filters/mixins.py:54
 #: konova/filters/mixins.py:81 konova/filters/mixins.py:82
 #: konova/filters/mixins.py:94 konova/filters/mixins.py:95
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-18 09:35+0100\n"
+"POT-Creation-Date: 2022-02-18 12:35+0100\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"
@@ -221,7 +221,7 @@ msgstr "Abbuchungen"
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:36
 #: ema/templates/ema/detail/includes/states-after.html:36
 #: ema/templates/ema/detail/includes/states-before.html:36
-#: intervention/forms/modalForms.py:359
+#: intervention/forms/modalForms.py:365
 msgid "Surface"
 msgstr "Fläche"
 
@@ -284,8 +284,8 @@ msgid "Type"
 msgstr "Typ"
 
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:24
-#: compensation/tables.py:89 intervention/forms/modalForms.py:370
-#: intervention/forms/modalForms.py:377 intervention/tables.py:88
+#: compensation/tables.py:89 intervention/forms/modalForms.py:376
+#: intervention/forms/modalForms.py:383 intervention/tables.py:88
 #: intervention/templates/intervention/detail/view.html:19
 #: konova/templates/konova/includes/quickstart/interventions.html:4
 #: templates/navbars/navbar.html:22
@@ -295,7 +295,7 @@ msgstr "Eingriff"
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
 #: compensation/tables.py:266
 #: compensation/templates/compensation/detail/eco_account/view.html:20
-#: intervention/forms/modalForms.py:343 intervention/forms/modalForms.py:350
+#: intervention/forms/modalForms.py:349 intervention/forms/modalForms.py:356
 #: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
 #: templates/navbars/navbar.html:34
 msgid "Eco-account"
@@ -364,7 +364,7 @@ msgstr "Kompensation XY; Flur ABC"
 #: ema/templates/ema/detail/includes/actions.html:34
 #: ema/templates/ema/detail/includes/deadlines.html:34
 #: ema/templates/ema/detail/includes/documents.html:34
-#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:173
+#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:179
 #: intervention/templates/intervention/detail/includes/documents.html:34
 #: intervention/templates/intervention/detail/includes/payments.html:34
 #: intervention/templates/intervention/detail/includes/revocation.html:38
@@ -484,7 +484,7 @@ msgid "Due on which date"
 msgstr "Zahlung wird an diesem Datum erwartet"
 
 #: compensation/forms/modalForms.py:64 compensation/forms/modalForms.py:357
-#: intervention/forms/modalForms.py:175 konova/forms.py:395
+#: intervention/forms/modalForms.py:181 konova/forms.py:395
 msgid "Additional comment, maximum {} letters"
 msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 
@@ -512,7 +512,7 @@ msgstr "Zusatzbezeichnung"
 msgid "Select an additional biotope type"
 msgstr "Zusatzbezeichnung wählen"
 
-#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:361
+#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:367
 msgid "in m²"
 msgstr ""
 
@@ -540,7 +540,7 @@ msgstr "Fristart wählen"
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
 #: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
 #: ema/templates/ema/detail/includes/deadlines.html:31
-#: intervention/forms/modalForms.py:147
+#: intervention/forms/modalForms.py:153
 msgid "Date"
 msgstr "Datum"
 
@@ -1000,14 +1000,14 @@ msgstr "Zuletzt bearbeitet"
 
 #: compensation/templates/compensation/detail/compensation/view.html:100
 #: compensation/templates/compensation/detail/eco_account/view.html:83
-#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:70
+#: ema/templates/ema/detail/view.html:76
 #: intervention/templates/intervention/detail/view.html:116
 msgid "Shared with"
 msgstr "Freigegeben für"
 
 #: compensation/templates/compensation/detail/eco_account/includes/controls.html:15
 #: ema/templates/ema/detail/includes/controls.html:15
-#: intervention/forms/modalForms.py:84
+#: intervention/forms/modalForms.py:71
 #: intervention/templates/intervention/detail/includes/controls.html:15
 msgid "Share"
 msgstr "Freigabe"
@@ -1348,46 +1348,48 @@ msgstr ""
 "Mehrfachauswahl möglich - Sie können nur Nutzer wählen, für die der Eintrag "
 "noch nicht freigegeben wurde. Geben Sie den ganzen Nutzernamen an."
 
-#: intervention/forms/modalForms.py:73
-msgid "Remove check to remove access for this user"
-msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen"
-
-#: intervention/forms/modalForms.py:85
+#: intervention/forms/modalForms.py:72
 msgid "Share settings for {}"
 msgstr "Freigabe Einstellungen für {}"
 
-#: intervention/forms/modalForms.py:149
+#: intervention/forms/modalForms.py:105 intervention/forms/modalForms.py:111
+msgid ""
+"Only conservation or registration office users are allowed to remove entries."
+msgstr ""
+"Nur Mitarbeiter der Naturschutz- oder Zulassungsbehördengruppe dürfen Einträge entfernen"
+
+#: intervention/forms/modalForms.py:155
 msgid "Date of revocation"
 msgstr "Datum des Widerspruchs"
 
-#: intervention/forms/modalForms.py:160
+#: intervention/forms/modalForms.py:166
 #: intervention/templates/intervention/detail/includes/revocation.html:35
 msgid "Document"
 msgstr "Dokument"
 
-#: intervention/forms/modalForms.py:163
+#: intervention/forms/modalForms.py:169
 msgid "Must be smaller than 15 Mb"
 msgstr "Muss kleiner als 15 Mb sein"
 
-#: intervention/forms/modalForms.py:188
+#: intervention/forms/modalForms.py:194
 #: intervention/templates/intervention/detail/includes/revocation.html:18
 msgid "Add revocation"
 msgstr "Widerspruch hinzufügen"
 
-#: intervention/forms/modalForms.py:245
+#: intervention/forms/modalForms.py:251
 msgid "Checked intervention data"
 msgstr "Eingriffsdaten geprüft"
 
-#: intervention/forms/modalForms.py:251
+#: intervention/forms/modalForms.py:257
 msgid "Checked compensations data and payments"
 msgstr "Kompensationen und Zahlungen geprüft"
 
-#: intervention/forms/modalForms.py:260
+#: intervention/forms/modalForms.py:266
 #: intervention/templates/intervention/detail/includes/controls.html:19
 msgid "Run check"
 msgstr "Prüfung vornehmen"
 
-#: intervention/forms/modalForms.py:261 konova/forms.py:514
+#: intervention/forms/modalForms.py:267 konova/forms.py:514
 msgid ""
 "I, {} {}, confirm that all necessary control steps have been performed by "
 "myself."
@@ -1395,23 +1397,23 @@ msgstr ""
 "Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt "
 "wurden:"
 
-#: intervention/forms/modalForms.py:345
+#: intervention/forms/modalForms.py:351
 msgid "Only recorded accounts can be selected for deductions"
 msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
 
-#: intervention/forms/modalForms.py:372
+#: intervention/forms/modalForms.py:378
 msgid "Only shared interventions can be selected"
 msgstr "Nur freigegebene Eingriffe können gewählt werden"
 
-#: intervention/forms/modalForms.py:385
+#: intervention/forms/modalForms.py:391
 msgid "New Deduction"
 msgstr "Neue Abbuchung"
 
-#: intervention/forms/modalForms.py:386
+#: intervention/forms/modalForms.py:392
 msgid "Enter the information for a new deduction from a chosen eco-account"
 msgstr "Geben Sie die Informationen für eine neue Abbuchung ein."
 
-#: intervention/forms/modalForms.py:429
+#: intervention/forms/modalForms.py:435
 msgid ""
 "Eco-account {} is not recorded yet. You can only deduct from recorded "
 "accounts."
@@ -1419,7 +1421,7 @@ msgstr ""
 "Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
 "verzeichneten Ökokonten erfolgen."
 
-#: intervention/forms/modalForms.py:439
+#: intervention/forms/modalForms.py:445
 msgid ""
 "The account {} has not enough surface for a deduction of {} m². There are "
 "only {} m² left"
@@ -4107,6 +4109,9 @@ msgstr ""
 msgid "Unable to connect to qpid with SASL mechanism %s"
 msgstr ""
 
+#~ msgid "Remove check to remove access for this user"
+#~ msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen"
+
 #~ msgid "Select the action type"
 #~ msgstr "Maßnahmentyp wählen"
 

From 87a93b9a7fd7ca00437a2a0d44cf584c74dabdd2 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 18 Feb 2022 14:06:51 +0100
Subject: [PATCH 24/26] #101 Team data view

* adds overview of shared teams on object detail view
* adds team data view if button is clicked
---
 .../detail/compensation/view.html             |   4 +
 .../compensation/detail/eco_account/view.html |   4 +
 ema/templates/ema/detail/view.html            |   4 +
 .../templates/intervention/detail/view.html   |   4 +
 locale/de/LC_MESSAGES/django.mo               | Bin 39816 -> 39892 bytes
 locale/de/LC_MESSAGES/django.po               | 191 +++++++++---------
 user/forms.py                                 |  43 ++++
 .../user/includes/contact_modal_button.html   |   2 +-
 .../user/includes/team_data_modal_button.html |   6 +
 user/urls.py                                  |   1 +
 user/views.py                                 |  27 ++-
 11 files changed, 193 insertions(+), 93 deletions(-)
 create mode 100644 user/templates/user/includes/team_data_modal_button.html

diff --git a/compensation/templates/compensation/detail/compensation/view.html b/compensation/templates/compensation/detail/compensation/view.html
index c5ff41d6..e3871510 100644
--- a/compensation/templates/compensation/detail/compensation/view.html
+++ b/compensation/templates/compensation/detail/compensation/view.html
@@ -98,6 +98,10 @@
                     <tr>
                         <th scope="row">{% trans 'Shared with' %}</th>
                         <td class="align-middle">
+                            {% for team in obj.intervention.teams.all %}
+                                {% include 'user/includes/team_data_modal_button.html' %}
+                            {% endfor %}
+                            <hr>
                             {% for user in obj.intervention.users.all %}
                                 {% include 'user/includes/contact_modal_button.html' %}
                             {% endfor %}
diff --git a/compensation/templates/compensation/detail/eco_account/view.html b/compensation/templates/compensation/detail/eco_account/view.html
index 288b971d..ee4a0f73 100644
--- a/compensation/templates/compensation/detail/eco_account/view.html
+++ b/compensation/templates/compensation/detail/eco_account/view.html
@@ -81,6 +81,10 @@
                     <tr>
                         <th scope="row">{% trans 'Shared with' %}</th>
                         <td class="align-middle">
+                            {% for team in obj.teams.all %}
+                                {% include 'user/includes/team_data_modal_button.html' %}
+                            {% endfor %}
+                            <hr>
                             {% for user in obj.users.all %}
                                 {% include 'user/includes/contact_modal_button.html' %}
                             {% endfor %}
diff --git a/ema/templates/ema/detail/view.html b/ema/templates/ema/detail/view.html
index 32ddd66b..7b567038 100644
--- a/ema/templates/ema/detail/view.html
+++ b/ema/templates/ema/detail/view.html
@@ -74,6 +74,10 @@
                     <tr>
                         <th scope="row">{% trans 'Shared with' %}</th>
                         <td class="align-middle">
+                            {% for team in obj.teams.all %}
+                                {% include 'user/includes/team_data_modal_button.html' %}
+                            {% endfor %}
+                            <hr>
                             {% for user in obj.users.all %}
                                 {% include 'user/includes/contact_modal_button.html' %}
                             {% endfor %}
diff --git a/intervention/templates/intervention/detail/view.html b/intervention/templates/intervention/detail/view.html
index 8e7fc6ca..f5680cc3 100644
--- a/intervention/templates/intervention/detail/view.html
+++ b/intervention/templates/intervention/detail/view.html
@@ -114,6 +114,10 @@
                     <tr>
                         <th scope="row">{% trans 'Shared with' %}</th>
                         <td class="align-middle">
+                            {% for team in obj.teams.all %}
+                                {% include 'user/includes/team_data_modal_button.html' %}
+                            {% endfor %}
+                            <hr>
                             {% for user in obj.users.all %}
                                 {% include 'user/includes/contact_modal_button.html' %}
                             {% endfor %}
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index cbd6f0b09ac2c43691e3e31e27cb6e98f171d3df..ced4ab1ce70235e9c2f809480b12816984ba7a18 100644
GIT binary patch
delta 9721
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

delta 9658
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
CBmFi2

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index bb96bab4..94efbd7b 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -3,21 +3,21 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
-#: compensation/filters.py:122 compensation/forms/modalForms.py:36
+#: compensation/filters.py:123 compensation/forms/modalForms.py:36
 #: compensation/forms/modalForms.py:47 compensation/forms/modalForms.py:63
 #: compensation/forms/modalForms.py:356 compensation/forms/modalForms.py:463
 #: intervention/forms/forms.py:54 intervention/forms/forms.py:156
-#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:154
-#: intervention/forms/modalForms.py:167 intervention/forms/modalForms.py:180
+#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:150
+#: intervention/forms/modalForms.py:163 intervention/forms/modalForms.py:176
 #: konova/filters/mixins.py:53 konova/filters/mixins.py:54
 #: konova/filters/mixins.py:81 konova/filters/mixins.py:82
 #: konova/filters/mixins.py:94 konova/filters/mixins.py:95
 #: konova/filters/mixins.py:107 konova/filters/mixins.py:108
 #: konova/filters/mixins.py:120 konova/filters/mixins.py:121
 #: konova/filters/mixins.py:134 konova/filters/mixins.py:135
-#: konova/filters/mixins.py:270 konova/filters/mixins.py:315
-#: konova/filters/mixins.py:353 konova/filters/mixins.py:354
-#: konova/filters/mixins.py:385 konova/filters/mixins.py:386
+#: konova/filters/mixins.py:270 konova/filters/mixins.py:316
+#: konova/filters/mixins.py:354 konova/filters/mixins.py:355
+#: konova/filters/mixins.py:386 konova/filters/mixins.py:387
 #: konova/forms.py:143 konova/forms.py:244 konova/forms.py:315
 #: konova/forms.py:359 konova/forms.py:369 konova/forms.py:382
 #: konova/forms.py:394 konova/forms.py:412 user/forms.py:42
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-18 12:35+0100\n"
+"POT-Creation-Date: 2022-02-18 14:01+0100\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"
@@ -52,7 +52,7 @@ msgstr "Bis"
 #: intervention/forms/forms.py:102
 #: intervention/templates/intervention/detail/view.html:56
 #: intervention/templates/intervention/report/report.html:37
-#: intervention/utils/quality.py:49 konova/filters/mixins.py:395
+#: intervention/utils/quality.py:49 konova/filters/mixins.py:396
 msgid "Conservation office"
 msgstr "Eintragungsstelle"
 
@@ -221,7 +221,7 @@ msgstr "Abbuchungen"
 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:36
 #: ema/templates/ema/detail/includes/states-after.html:36
 #: ema/templates/ema/detail/includes/states-before.html:36
-#: intervention/forms/modalForms.py:365
+#: intervention/forms/modalForms.py:361
 msgid "Surface"
 msgstr "Fläche"
 
@@ -284,8 +284,8 @@ msgid "Type"
 msgstr "Typ"
 
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:24
-#: compensation/tables.py:89 intervention/forms/modalForms.py:376
-#: intervention/forms/modalForms.py:383 intervention/tables.py:88
+#: compensation/tables.py:89 intervention/forms/modalForms.py:372
+#: intervention/forms/modalForms.py:379 intervention/tables.py:88
 #: intervention/templates/intervention/detail/view.html:19
 #: konova/templates/konova/includes/quickstart/interventions.html:4
 #: templates/navbars/navbar.html:22
@@ -295,7 +295,7 @@ msgstr "Eingriff"
 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
 #: compensation/tables.py:266
 #: compensation/templates/compensation/detail/eco_account/view.html:20
-#: intervention/forms/modalForms.py:349 intervention/forms/modalForms.py:356
+#: intervention/forms/modalForms.py:345 intervention/forms/modalForms.py:352
 #: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
 #: templates/navbars/navbar.html:34
 msgid "Eco-account"
@@ -309,7 +309,7 @@ msgstr "Altfälle"
 msgid "Before"
 msgstr "Vor"
 
-#: compensation/filters.py:121
+#: compensation/filters.py:122
 msgid "Show only unrecorded"
 msgstr "Nur unverzeichnete anzeigen"
 
@@ -364,7 +364,7 @@ msgstr "Kompensation XY; Flur ABC"
 #: ema/templates/ema/detail/includes/actions.html:34
 #: ema/templates/ema/detail/includes/deadlines.html:34
 #: ema/templates/ema/detail/includes/documents.html:34
-#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:179
+#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:175
 #: intervention/templates/intervention/detail/includes/documents.html:34
 #: intervention/templates/intervention/detail/includes/payments.html:34
 #: intervention/templates/intervention/detail/includes/revocation.html:38
@@ -484,7 +484,7 @@ msgid "Due on which date"
 msgstr "Zahlung wird an diesem Datum erwartet"
 
 #: compensation/forms/modalForms.py:64 compensation/forms/modalForms.py:357
-#: intervention/forms/modalForms.py:181 konova/forms.py:395
+#: intervention/forms/modalForms.py:177 konova/forms.py:395
 msgid "Additional comment, maximum {} letters"
 msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
 
@@ -512,7 +512,7 @@ msgstr "Zusatzbezeichnung"
 msgid "Select an additional biotope type"
 msgstr "Zusatzbezeichnung wählen"
 
-#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:367
+#: compensation/forms/modalForms.py:197 intervention/forms/modalForms.py:363
 msgid "in m²"
 msgstr ""
 
@@ -540,7 +540,7 @@ msgstr "Fristart wählen"
 #: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
 #: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
 #: ema/templates/ema/detail/includes/deadlines.html:31
-#: intervention/forms/modalForms.py:153
+#: intervention/forms/modalForms.py:149
 msgid "Date"
 msgstr "Datum"
 
@@ -1142,7 +1142,7 @@ msgstr "Daten zu den verantwortlichen Stellen"
 msgid "Compensations - Overview"
 msgstr "Kompensationen - Übersicht"
 
-#: compensation/views/compensation.py:151 konova/utils/message_templates.py:31
+#: compensation/views/compensation.py:151 konova/utils/message_templates.py:33
 msgid "Compensation {} edited"
 msgstr "Kompensation {} bearbeitet"
 
@@ -1269,7 +1269,7 @@ msgstr "Mehrfachauswahl möglich"
 #: intervention/forms/forms.py:86
 #: intervention/templates/intervention/detail/view.html:48
 #: intervention/templates/intervention/report/report.html:29
-#: intervention/utils/quality.py:46 konova/filters/mixins.py:363
+#: intervention/utils/quality.py:46 konova/filters/mixins.py:364
 msgid "Registration office"
 msgstr "Zulassungsbehörde"
 
@@ -1322,7 +1322,7 @@ msgstr "Freigabelink"
 
 #: intervention/forms/modalForms.py:31
 msgid "Send this link to users who you want to have writing access on the data"
-msgstr "Andere Nutzer erhalten über diesen Link Zugriff auf die Daten"
+msgstr "Einzelne Nutzer erhalten über diesen Link Zugriff auf die Daten"
 
 #: intervention/forms/modalForms.py:41
 msgid "Add team to share with"
@@ -1338,7 +1338,7 @@ msgstr ""
 
 #: intervention/forms/modalForms.py:55
 msgid "Add user to share with"
-msgstr "Nutzer direkt hinzufügen"
+msgstr "Nutzer einzeln hinzufügen"
 
 #: intervention/forms/modalForms.py:57
 msgid ""
@@ -1352,44 +1352,38 @@ msgstr ""
 msgid "Share settings for {}"
 msgstr "Freigabe Einstellungen für {}"
 
-#: intervention/forms/modalForms.py:105 intervention/forms/modalForms.py:111
-msgid ""
-"Only conservation or registration office users are allowed to remove entries."
-msgstr ""
-"Nur Mitarbeiter der Naturschutz- oder Zulassungsbehördengruppe dürfen Einträge entfernen"
-
-#: intervention/forms/modalForms.py:155
+#: intervention/forms/modalForms.py:151
 msgid "Date of revocation"
 msgstr "Datum des Widerspruchs"
 
-#: intervention/forms/modalForms.py:166
+#: intervention/forms/modalForms.py:162
 #: intervention/templates/intervention/detail/includes/revocation.html:35
 msgid "Document"
 msgstr "Dokument"
 
-#: intervention/forms/modalForms.py:169
+#: intervention/forms/modalForms.py:165
 msgid "Must be smaller than 15 Mb"
 msgstr "Muss kleiner als 15 Mb sein"
 
-#: intervention/forms/modalForms.py:194
+#: intervention/forms/modalForms.py:190
 #: intervention/templates/intervention/detail/includes/revocation.html:18
 msgid "Add revocation"
 msgstr "Widerspruch hinzufügen"
 
-#: intervention/forms/modalForms.py:251
+#: intervention/forms/modalForms.py:247
 msgid "Checked intervention data"
 msgstr "Eingriffsdaten geprüft"
 
-#: intervention/forms/modalForms.py:257
+#: intervention/forms/modalForms.py:253
 msgid "Checked compensations data and payments"
 msgstr "Kompensationen und Zahlungen geprüft"
 
-#: intervention/forms/modalForms.py:266
+#: intervention/forms/modalForms.py:262
 #: intervention/templates/intervention/detail/includes/controls.html:19
 msgid "Run check"
 msgstr "Prüfung vornehmen"
 
-#: intervention/forms/modalForms.py:267 konova/forms.py:514
+#: intervention/forms/modalForms.py:263 konova/forms.py:514
 msgid ""
 "I, {} {}, confirm that all necessary control steps have been performed by "
 "myself."
@@ -1397,23 +1391,23 @@ msgstr ""
 "Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt "
 "wurden:"
 
-#: intervention/forms/modalForms.py:351
+#: intervention/forms/modalForms.py:347
 msgid "Only recorded accounts can be selected for deductions"
 msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
 
-#: intervention/forms/modalForms.py:378
+#: intervention/forms/modalForms.py:374
 msgid "Only shared interventions can be selected"
 msgstr "Nur freigegebene Eingriffe können gewählt werden"
 
-#: intervention/forms/modalForms.py:391
+#: intervention/forms/modalForms.py:387
 msgid "New Deduction"
 msgstr "Neue Abbuchung"
 
-#: intervention/forms/modalForms.py:392
+#: intervention/forms/modalForms.py:388
 msgid "Enter the information for a new deduction from a chosen eco-account"
 msgstr "Geben Sie die Informationen für eine neue Abbuchung ein."
 
-#: intervention/forms/modalForms.py:435
+#: intervention/forms/modalForms.py:431
 msgid ""
 "Eco-account {} is not recorded yet. You can only deduct from recorded "
 "accounts."
@@ -1421,7 +1415,7 @@ msgstr ""
 "Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
 "verzeichneten Ökokonten erfolgen."
 
-#: intervention/forms/modalForms.py:445
+#: intervention/forms/modalForms.py:441
 msgid ""
 "The account {} has not enough surface for a deduction of {} m². There are "
 "only {} m² left"
@@ -1616,15 +1610,15 @@ msgstr "Nach Flurstücknenner suchen"
 msgid "Show unshared"
 msgstr "Nicht freigegebene anzeigen"
 
-#: konova/filters/mixins.py:314
+#: konova/filters/mixins.py:315
 msgid "Show recorded"
 msgstr "Verzeichnete anzeigen"
 
-#: konova/filters/mixins.py:364
+#: konova/filters/mixins.py:365
 msgid "Search for registration office"
 msgstr "Nach Zulassungsbehörde suchen"
 
-#: konova/filters/mixins.py:396
+#: konova/filters/mixins.py:397
 msgid "Search for conservation office"
 msgstr "Nch Eintragungsstelle suchen"
 
@@ -1851,10 +1845,25 @@ msgstr ""
 "der Zwischenzeit angelegt wurde, welcher diese Kennung nun bereits verwendet"
 
 #: konova/utils/message_templates.py:15
+msgid ""
+"Only conservation or registration office users are allowed to remove entries."
+msgstr ""
+"Nur Mitarbeiter der Naturschutz- oder Zulassungsbehördengruppe dürfen "
+"Einträge entfernen"
+
+#: konova/utils/message_templates.py:16
+msgid "You need to be part of another user group."
+msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
+
+#: konova/utils/message_templates.py:17
+msgid "Status of Checked and Recorded reseted"
+msgstr "'Geprüft'/'Verzeichnet' wurde zurückgesetzt"
+
+#: konova/utils/message_templates.py:20
 msgid "This data is not shared with you"
 msgstr "Diese Daten sind für Sie nicht freigegeben"
 
-#: konova/utils/message_templates.py:16
+#: konova/utils/message_templates.py:21
 msgid ""
 "Remember: This data has not been shared with you, yet. This means you can "
 "only read but can not edit or perform any actions like running a check or "
@@ -1864,23 +1873,15 @@ msgstr ""
 "bedeutet, dass Sie nur lesenden Zugriff hierauf haben und weder bearbeiten, "
 "noch Prüfungen durchführen oder verzeichnen können."
 
-#: konova/utils/message_templates.py:17
-msgid "You need to be part of another user group."
-msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
-
-#: konova/utils/message_templates.py:19
-msgid "Status of Checked and Recorded reseted"
-msgstr "'Geprüft'/'Verzeichnet' wurde zurückgesetzt"
-
-#: konova/utils/message_templates.py:22
+#: konova/utils/message_templates.py:24
 msgid "Unsupported file type"
 msgstr "Dateiformat nicht unterstützt"
 
-#: konova/utils/message_templates.py:23
+#: konova/utils/message_templates.py:25
 msgid "File too large"
 msgstr "Datei zu groß"
 
-#: konova/utils/message_templates.py:26
+#: konova/utils/message_templates.py:28
 msgid ""
 "Action canceled. Eco account is recorded or deductions exist. Only "
 "conservation office member can perform this action."
@@ -1888,119 +1889,119 @@ msgstr ""
 "Aktion abgebrochen. Ökokonto ist bereits verzeichnet oder Abbuchungen liegen "
 "vor. Nur Eintragungsstellennutzer können diese Aktion jetzt durchführen."
 
-#: konova/utils/message_templates.py:29
+#: konova/utils/message_templates.py:31
 msgid "Compensation {} added"
 msgstr "Kompensation {} hinzugefügt"
 
-#: konova/utils/message_templates.py:30
+#: konova/utils/message_templates.py:32
 msgid "Compensation {} removed"
 msgstr "Kompensation {} entfernt"
 
-#: konova/utils/message_templates.py:32
+#: konova/utils/message_templates.py:34
 msgid "Added compensation action"
 msgstr "Maßnahme hinzugefügt"
 
-#: konova/utils/message_templates.py:33
+#: konova/utils/message_templates.py:35
 msgid "Added compensation state"
 msgstr "Zustand hinzugefügt"
 
-#: konova/utils/message_templates.py:36
+#: konova/utils/message_templates.py:38
 msgid "State removed"
 msgstr "Zustand gelöscht"
 
-#: konova/utils/message_templates.py:37
+#: konova/utils/message_templates.py:39
 msgid "State edited"
 msgstr "Zustand bearbeitet"
 
-#: konova/utils/message_templates.py:38
+#: konova/utils/message_templates.py:40
 msgid "State added"
 msgstr "Zustand hinzugefügt"
 
-#: konova/utils/message_templates.py:41
+#: konova/utils/message_templates.py:43
 msgid "Action added"
 msgstr "Maßnahme hinzugefügt"
 
-#: konova/utils/message_templates.py:42
+#: konova/utils/message_templates.py:44
 msgid "Action edited"
 msgstr "Maßnahme bearbeitet"
 
-#: konova/utils/message_templates.py:43
+#: konova/utils/message_templates.py:45
 msgid "Action removed"
 msgstr "Maßnahme entfernt"
 
-#: konova/utils/message_templates.py:46
+#: konova/utils/message_templates.py:48
 msgid "Deduction added"
 msgstr "Abbuchung hinzugefügt"
 
-#: konova/utils/message_templates.py:47
+#: konova/utils/message_templates.py:49
 msgid "Deduction edited"
 msgstr "Abbuchung bearbeitet"
 
-#: konova/utils/message_templates.py:48
+#: konova/utils/message_templates.py:50
 msgid "Deduction removed"
 msgstr "Abbuchung entfernt"
 
-#: konova/utils/message_templates.py:51
+#: konova/utils/message_templates.py:53
 msgid "Deadline added"
 msgstr "Frist/Termin hinzugefügt"
 
-#: konova/utils/message_templates.py:52
+#: konova/utils/message_templates.py:54
 msgid "Deadline edited"
 msgstr "Frist/Termin bearbeitet"
 
-#: konova/utils/message_templates.py:53
+#: konova/utils/message_templates.py:55
 msgid "Deadline removed"
 msgstr "Frist/Termin gelöscht"
 
-#: konova/utils/message_templates.py:56
+#: konova/utils/message_templates.py:58
 msgid "Payment added"
 msgstr "Zahlung hinzugefügt"
 
-#: konova/utils/message_templates.py:57
+#: konova/utils/message_templates.py:59
 msgid "Payment edited"
 msgstr "Zahlung bearbeitet"
 
-#: konova/utils/message_templates.py:58
+#: konova/utils/message_templates.py:60
 msgid "Payment removed"
 msgstr "Zahlung gelöscht"
 
-#: konova/utils/message_templates.py:61
+#: konova/utils/message_templates.py:63
 msgid "Revocation added"
 msgstr "Widerspruch hinzugefügt"
 
-#: konova/utils/message_templates.py:62
+#: konova/utils/message_templates.py:64
 msgid "Revocation edited"
 msgstr "Widerspruch bearbeitet"
 
-#: konova/utils/message_templates.py:63
+#: konova/utils/message_templates.py:65
 msgid "Revocation removed"
 msgstr "Widerspruch entfernt"
 
-#: konova/utils/message_templates.py:66
+#: konova/utils/message_templates.py:68
 msgid "Document '{}' deleted"
 msgstr "Dokument '{}' gelöscht"
 
-#: konova/utils/message_templates.py:67
+#: konova/utils/message_templates.py:69
 msgid "Document added"
 msgstr "Dokument hinzugefügt"
 
-#: konova/utils/message_templates.py:68
+#: konova/utils/message_templates.py:70
 msgid "Document edited"
 msgstr "Dokument bearbeitet"
 
-#: konova/utils/message_templates.py:71
+#: konova/utils/message_templates.py:73
 msgid "Edited general data"
 msgstr "Allgemeine Daten bearbeitet"
 
-#: konova/utils/message_templates.py:72
+#: konova/utils/message_templates.py:74
 msgid "Added deadline"
 msgstr "Frist/Termin hinzugefügt"
 
-#: konova/utils/message_templates.py:75
+#: konova/utils/message_templates.py:77
 msgid "Geometry conflict detected with {}"
 msgstr "Geometriekonflikt mit folgenden Einträgen erkannt: {}"
 
-#: konova/utils/message_templates.py:78
+#: konova/utils/message_templates.py:80
 msgid "This intervention has {} revocations"
 msgstr "Dem Eingriff liegen {} Widersprüche vor"
 
@@ -2416,11 +2417,11 @@ msgstr "Neuen Token generieren"
 msgid "A new token needs to be validated by an administrator!"
 msgstr "Neue Tokens müssen durch Administratoren freigeschaltet werden!"
 
-#: user/forms.py:168 user/forms.py:172
+#: user/forms.py:168 user/forms.py:172 user/forms.py:323 user/forms.py:328
 msgid "Team name"
 msgstr "Team Name"
 
-#: user/forms.py:179 user/templates/user/team/index.html:30
+#: user/forms.py:179 user/forms.py:336 user/templates/user/team/index.html:30
 msgid "Description"
 msgstr "Beschreibung"
 
@@ -2468,6 +2469,10 @@ msgstr "Gewählter Administrator ({}) muss ein Mitglied des Teams sein."
 msgid "Edit team"
 msgstr "Team bearbeiten"
 
+#: user/forms.py:347
+msgid "Team"
+msgstr "Team"
+
 #: user/models/user_action.py:22
 msgid "Unrecorded"
 msgstr "Entzeichnet"
@@ -2484,6 +2489,10 @@ msgstr "Gelöscht"
 msgid "Show contact data"
 msgstr "Zeige Kontaktdaten"
 
+#: user/templates/user/includes/team_data_modal_button.html:3
+msgid "Show team data"
+msgstr "Zeige Teamdaten"
+
 #: user/templates/user/index.html:13 user/templates/user/team/index.html:29
 msgid "Name"
 msgstr ""
@@ -2534,7 +2543,7 @@ msgid "Manage teams"
 msgstr ""
 
 #: user/templates/user/index.html:69 user/templates/user/team/index.html:18
-#: user/views.py:142
+#: user/views.py:167
 msgid "Teams"
 msgstr ""
 
@@ -2594,15 +2603,15 @@ msgstr "Neuer Token generiert. Administratoren sind informiert."
 msgid "User API token"
 msgstr "API Nutzer Token"
 
-#: user/views.py:153
+#: user/views.py:178
 msgid "New team added"
 msgstr "Neues Team hinzugefügt"
 
-#: user/views.py:166
+#: user/views.py:191
 msgid "Team edited"
 msgstr "Team bearbeitet"
 
-#: user/views.py:179
+#: user/views.py:204
 msgid "Team removed"
 msgstr "Team gelöscht"
 
diff --git a/user/forms.py b/user/forms.py
index 01ec54b6..34c8fab9 100644
--- a/user/forms.py
+++ b/user/forms.py
@@ -315,3 +315,46 @@ class EditTeamModalForm(NewTeamModalForm):
 
 class RemoveTeamModalForm(RemoveModalForm):
     pass
+
+
+class TeamDataForm(BaseModalForm):
+    name = forms.CharField(
+        label_suffix="",
+        label=_("Team name"),
+        max_length=500,
+        required=False,
+        widget=forms.TextInput(
+            attrs={
+                "placeholder": _("Team name"),
+                "class": "form-control",
+            }
+        )
+    )
+    description = forms.CharField(
+        label_suffix="",
+        required=False,
+        label=_("Description"),
+        widget=forms.Textarea(
+            attrs={
+                "rows": 5,
+                "class": "form-control"
+            }
+        )
+    )
+
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.form_title = _("Team")
+        self.form_caption = ""
+        self.render_submit = False
+        form_data = {
+            "name": self.instance.name,
+            "description": self.instance.description,
+        }
+        self.load_initial_data(
+            form_data,
+            [
+                "name",
+                "description"
+            ]
+        )
\ No newline at end of file
diff --git a/user/templates/user/includes/contact_modal_button.html b/user/templates/user/includes/contact_modal_button.html
index 68ae53a5..5cbd87f0 100644
--- a/user/templates/user/includes/contact_modal_button.html
+++ b/user/templates/user/includes/contact_modal_button.html
@@ -1,6 +1,6 @@
 {% load fontawesome_5 i18n %}
 
 <button class="btn btn-default btn-modal" data-form-url="{% url 'user:contact' user.id %}" title="{% trans 'Show contact data' %}">
-    {% fa5_icon 'id-card' %}
+    {% fa5_icon 'user' %}
     <span>{{user.username}}</span>
 </button>
\ No newline at end of file
diff --git a/user/templates/user/includes/team_data_modal_button.html b/user/templates/user/includes/team_data_modal_button.html
new file mode 100644
index 00000000..b41e63ae
--- /dev/null
+++ b/user/templates/user/includes/team_data_modal_button.html
@@ -0,0 +1,6 @@
+{% load fontawesome_5 i18n %}
+
+<button class="btn btn-default btn-modal" data-form-url="{% url 'user:team-data' team.id %}" title="{% trans 'Show team data' %}">
+    {% fa5_icon 'users' %}
+    <span>{{team.name}}</span>
+</button>
\ No newline at end of file
diff --git a/user/urls.py b/user/urls.py
index 76a86623..5c33427a 100644
--- a/user/urls.py
+++ b/user/urls.py
@@ -16,6 +16,7 @@ urlpatterns = [
     path("token/api", api_token_view, name="api-token"),
     path("contact/<id>", contact_view, name="contact"),
     path("team/", index_team_view, name="team-index"),
+    path("team/<id>", data_team_view, name="team-data"),
     path("team/new", new_team_view, name="team-new"),
     path("team/<id>/edit", edit_team_view, name="team-edit"),
     path("team/<id>/remove", remove_team_view, name="team-remove"),
diff --git a/user/views.py b/user/views.py
index afed5726..9afede1f 100644
--- a/user/views.py
+++ b/user/views.py
@@ -13,7 +13,7 @@ from django.utils.translation import gettext_lazy as _
 from konova.contexts import BaseContext
 from konova.decorators import any_group_check, default_group_required
 from user.forms import UserNotificationForm, UserContactForm, UserAPITokenForm, NewTeamModalForm, EditTeamModalForm, \
-    RemoveTeamModalForm
+    RemoveTeamModalForm, TeamDataForm
 
 
 @login_required
@@ -133,6 +133,31 @@ def contact_view(request: HttpRequest, id: str):
     )
 
 
+@login_required
+def data_team_view(request: HttpRequest, id: str):
+    """ Renders team data
+
+    Args:
+        request (HttpRequest): The incoming request
+        id (str): The team's id
+
+    Returns:
+
+    """
+    team = get_object_or_404(Team, id=id)
+    form = TeamDataForm(request.POST or None, instance=team, request=request)
+    template = "modal/modal_form.html"
+    context = {
+        "form": form,
+    }
+    context = BaseContext(request, context).context
+    return render(
+        request,
+        template,
+        context
+    )
+
+
 @login_required
 def index_team_view(request: HttpRequest):
     template = "user/team/index.html"

From 50def040f2e0f8cc0213bbfb708594c36795d064 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 18 Feb 2022 14:09:45 +0100
Subject: [PATCH 25/26] #101 Datatype team migrations

* adds migration files for ShareableObject data models
---
 .../migrations/0006_ecoaccount_teams.py       | 19 +++++++++++++++++++
 ema/migrations/0003_ema_teams.py              | 19 +++++++++++++++++++
 .../migrations/0003_intervention_teams.py     | 19 +++++++++++++++++++
 3 files changed, 57 insertions(+)
 create mode 100644 compensation/migrations/0006_ecoaccount_teams.py
 create mode 100644 ema/migrations/0003_ema_teams.py
 create mode 100644 intervention/migrations/0003_intervention_teams.py

diff --git a/compensation/migrations/0006_ecoaccount_teams.py b/compensation/migrations/0006_ecoaccount_teams.py
new file mode 100644
index 00000000..14cf5099
--- /dev/null
+++ b/compensation/migrations/0006_ecoaccount_teams.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.3 on 2022-02-18 09:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('user', '0003_team'),
+        ('compensation', '0005_auto_20220218_0917'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='ecoaccount',
+            name='teams',
+            field=models.ManyToManyField(help_text='Teams having access (data shared with)', to='user.Team'),
+        ),
+    ]
diff --git a/ema/migrations/0003_ema_teams.py b/ema/migrations/0003_ema_teams.py
new file mode 100644
index 00000000..606781dd
--- /dev/null
+++ b/ema/migrations/0003_ema_teams.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.3 on 2022-02-18 09:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('user', '0003_team'),
+        ('ema', '0002_auto_20220114_0936'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='ema',
+            name='teams',
+            field=models.ManyToManyField(help_text='Teams having access (data shared with)', to='user.Team'),
+        ),
+    ]
diff --git a/intervention/migrations/0003_intervention_teams.py b/intervention/migrations/0003_intervention_teams.py
new file mode 100644
index 00000000..8dd76241
--- /dev/null
+++ b/intervention/migrations/0003_intervention_teams.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.1.3 on 2022-02-18 09:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('user', '0003_team'),
+        ('intervention', '0002_auto_20220114_0936'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='intervention',
+            name='teams',
+            field=models.ManyToManyField(help_text='Teams having access (data shared with)', to='user.Team'),
+        ),
+    ]

From 963854652ef9d6df09be8eeedfde9b07be7b9259 Mon Sep 17 00:00:00 2001
From: mpeltriaux <michel.peltriaux@sgdnord.rlp.de>
Date: Fri, 18 Feb 2022 15:19:37 +0100
Subject: [PATCH 26/26] #101 Team mails

* adds mail templates for shared data actions
* fixes bug where deleted compensations would be used for checking
---
 intervention/forms/modalForms.py              |   6 +-
 konova/models/object.py                       |  87 ++++++++---
 konova/tasks.py                               |  42 ++++++
 konova/utils/mailer.py                        | 138 ++++++++++++++++++
 locale/de/LC_MESSAGES/django.mo               | Bin 39892 -> 40282 bytes
 locale/de/LC_MESSAGES/django.po               |  43 +++++-
 .../checking/shared_data_checked_team.html    |  28 ++++
 .../deleting/shared_data_deleted_team.html    |  28 ++++
 .../recording/shared_data_recorded_team.html  |  33 +++++
 .../shared_data_unrecorded_team.html          |  33 +++++
 .../sharing/shared_access_given_team.html     |  34 +++++
 .../sharing/shared_access_removed_team.html   |  29 ++++
 user/models/team.py                           |  79 ++++++++++
 13 files changed, 551 insertions(+), 29 deletions(-)
 create mode 100644 templates/email/checking/shared_data_checked_team.html
 create mode 100644 templates/email/deleting/shared_data_deleted_team.html
 create mode 100644 templates/email/recording/shared_data_recorded_team.html
 create mode 100644 templates/email/recording/shared_data_unrecorded_team.html
 create mode 100644 templates/email/sharing/shared_access_given_team.html
 create mode 100644 templates/email/sharing/shared_access_removed_team.html

diff --git a/intervention/forms/modalForms.py b/intervention/forms/modalForms.py
index 39479388..1e5febf8 100644
--- a/intervention/forms/modalForms.py
+++ b/intervention/forms/modalForms.py
@@ -141,7 +141,7 @@ class ShareModalForm(BaseModalForm):
         self.load_initial_data(form_data)
 
     def save(self):
-        self.instance.update_sharing_user(self)
+        self.instance.update_shared_access(self)
 
 
 class NewRevocationModalForm(BaseModalForm):
@@ -290,7 +290,9 @@ class CheckModalForm(BaseModalForm):
         Returns:
 
         """
-        comps = self.instance.compensations.all()
+        comps = self.instance.compensations.filter(
+            deleted=None,
+        )
         comps_valid = True
         for comp in comps:
             checker = comp.quality_check()
diff --git a/konova/models/object.py b/konova/models/object.py
index 92b3ccae..f224b68c 100644
--- a/konova/models/object.py
+++ b/konova/models/object.py
@@ -15,7 +15,10 @@ from django.db.models import QuerySet
 from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP, LANIS_ZOOM_LUT, LANIS_LINK_TEMPLATE
 from konova.tasks import celery_send_mail_shared_access_removed, celery_send_mail_shared_access_given, \
     celery_send_mail_shared_data_recorded, celery_send_mail_shared_data_unrecorded, \
-    celery_send_mail_shared_data_deleted, celery_send_mail_shared_data_checked
+    celery_send_mail_shared_data_deleted, celery_send_mail_shared_data_checked, \
+    celery_send_mail_shared_access_given_team, celery_send_mail_shared_access_removed_team, \
+    celery_send_mail_shared_data_checked_team, celery_send_mail_shared_data_deleted_team, \
+    celery_send_mail_shared_data_unrecorded_team, celery_send_mail_shared_data_recorded_team
 from django.core.exceptions import ObjectDoesNotExist
 from django.http import HttpRequest
 from django.utils.timezone import now
@@ -130,6 +133,11 @@ class BaseObject(BaseResource):
                 for user_id in shared_users:
                     celery_send_mail_shared_data_deleted.delay(self.identifier, self.title, user_id)
 
+                # Send mail
+                shared_teams = self.shared_teams.values_list("id", flat=True)
+                for team_id in shared_teams:
+                    celery_send_mail_shared_data_deleted_team.delay(self.identifier, self.title, team_id)
+
             self.save()
 
     def mark_as_edited(self, performing_user, request: HttpRequest = None, edit_comment: str = None):
@@ -258,10 +266,15 @@ class RecordableObjectMixin(models.Model):
         self.save()
         self.log.add(action)
 
-        shared_users = self.users.all().values_list("id", flat=True)
+        shared_users = self.shared_users.values_list("id", flat=True)
+        shared_teams = self.shared_teams.values_list("id", flat=True)
+
         for user_id in shared_users:
             celery_send_mail_shared_data_unrecorded.delay(self.identifier, self.title, user_id)
 
+        for team_id in shared_teams:
+            celery_send_mail_shared_data_unrecorded_team.delay(self.identifier, self.title, team_id)
+
         return action
 
     def set_recorded(self, user):
@@ -281,10 +294,15 @@ class RecordableObjectMixin(models.Model):
         self.save()
         self.log.add(action)
 
-        shared_users = self.users.all().values_list("id", flat=True)
+        shared_users = self.shared_users.values_list("id", flat=True)
+        shared_teams = self.shared_teams.values_list("id", flat=True)
+
         for user_id in shared_users:
             celery_send_mail_shared_data_recorded.delay(self.identifier, self.title, user_id)
 
+        for team_id in shared_teams:
+            celery_send_mail_shared_data_recorded_team.delay(self.identifier, self.title, team_id)
+
         return action
 
     def unrecord(self, performing_user, request: HttpRequest = None):
@@ -367,10 +385,15 @@ class CheckableObjectMixin(models.Model):
         self.save()
 
         # Send mail
-        shared_users = self.users.all().values_list("id", flat=True)
+        shared_users = self.shared_users.values_list("id", flat=True)
         for user_id in shared_users:
             celery_send_mail_shared_data_checked.delay(self.identifier, self.title, user_id)
 
+        # Send mail
+        shared_teams = self.shared_teams.values_list("id", flat=True)
+        for team_id in shared_teams:
+            celery_send_mail_shared_data_checked_team.delay(self.identifier, self.title, team_id)
+
         self.log.add(action)
         return action
 
@@ -488,8 +511,8 @@ class ShareableObjectMixin(models.Model):
         """
         self.users.set(user_list)
 
-    def update_sharing_user(self, form):
-        """ Adds a new user with shared access to the object
+    def _update_shared_teams(self, form):
+        """ Updates shared access on the object for teams
 
         Args:
             form (ShareModalForm): The form holding the data
@@ -497,33 +520,46 @@ class ShareableObjectMixin(models.Model):
         Returns:
 
         """
-        from user.models import User
         form_data = form.cleaned_data
+        shared_teams = self.shared_teams
 
         # Fetch selected teams and find out which user IDs are in removed teams -> mails need to be sent
         accessing_teams = form_data["teams"]
-        removed_team_users = self.teams.all().exclude(
+        removed_teams = shared_teams.exclude(
             id__in=accessing_teams
-        ).values_list("users__id", flat=True)
-        accessing_team_users = User.objects.filter(
-            id__in=accessing_teams.values_list("users", flat=True)
-        )
-        new_team_users = accessing_team_users.exclude(
-            id__in=self.shared_users
         ).values_list("id", flat=True)
+        new_teams = accessing_teams.exclude(
+            id__in=shared_teams
+        ).values_list("id", flat=True)
+
+        for team_id in new_teams:
+            celery_send_mail_shared_access_given_team.delay(self.identifier, self.title,  team_id)
+        for team_id in removed_teams:
+            celery_send_mail_shared_access_removed_team.delay(self.identifier, self.title, team_id)
+
+        self.share_with_team_list(accessing_teams)
+
+    def _update_shared_users(self, form):
+        """ Updates shared access on the object for single users
+
+        Args:
+            form (ShareModalForm): The form holding the data
+
+        Returns:
+
+        """
+        form_data = form.cleaned_data
+        shared_users = self.shared_users
 
         # Fetch selected users
         accessing_users = form_data["users"]
-        removed_users = self.users.all().exclude(
+        removed_users = shared_users.exclude(
             id__in=accessing_users
         ).values_list("id", flat=True)
         new_users = accessing_users.exclude(
-            id__in=self.shared_users
+            id__in=shared_users
         ).values_list("id", flat=True)
 
-        new_users = new_users.union(new_team_users)
-        removed_users = removed_users.union(removed_team_users)
-
         # Send mails
         for user_id in removed_users:
             celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user_id)
@@ -532,7 +568,18 @@ class ShareableObjectMixin(models.Model):
 
         # Set new shared users
         self.share_with_user_list(accessing_users)
-        self.share_with_team_list(accessing_teams)
+
+    def update_shared_access(self, form):
+        """ Updates shared access on the object
+
+        Args:
+            form (ShareModalForm): The form holding the data
+
+        Returns:
+
+        """
+        self._update_shared_teams(form)
+        self._update_shared_users(form)
 
     @property
     def shared_users(self) -> QuerySet:
diff --git a/konova/tasks.py b/konova/tasks.py
index c74a2bd7..798effb4 100644
--- a/konova/tasks.py
+++ b/konova/tasks.py
@@ -38,6 +38,20 @@ def celery_send_mail_shared_access_given(obj_identifier, obj_title=None, user_id
     user.send_mail_shared_access_given(obj_identifier, obj_title)
 
 
+@shared_task
+def celery_send_mail_shared_access_removed_team(obj_identifier, obj_title=None, team_id=None):
+    from user.models import Team
+    team = Team.objects.get(id=team_id)
+    team.send_mail_shared_access_removed(obj_identifier, obj_title)
+
+
+@shared_task
+def celery_send_mail_shared_access_given_team(obj_identifier, obj_title=None, team_id=None):
+    from user.models import Team
+    team = Team.objects.get(id=team_id)
+    team.send_mail_shared_access_given_team(obj_identifier, obj_title)
+
+
 @shared_task
 def celery_send_mail_shared_data_recorded(obj_identifier, obj_title=None, user_id=None):
     from user.models import User
@@ -52,6 +66,20 @@ def celery_send_mail_shared_data_unrecorded(obj_identifier, obj_title=None, user
     user.send_mail_shared_data_unrecorded(obj_identifier, obj_title)
 
 
+@shared_task
+def celery_send_mail_shared_data_recorded_team(obj_identifier, obj_title=None, team_id=None):
+    from user.models import Team
+    team = Team.objects.get(id=team_id)
+    team.send_mail_shared_data_recorded(obj_identifier, obj_title)
+
+
+@shared_task
+def celery_send_mail_shared_data_unrecorded_team(obj_identifier, obj_title=None, team_id=None):
+    from user.models import Team
+    team = Team.objects.get(id=team_id)
+    team.send_mail_shared_data_unrecorded(obj_identifier, obj_title)
+
+
 @shared_task
 def celery_send_mail_shared_data_deleted(obj_identifier, obj_title=None, user_id=None):
     from user.models import User
@@ -64,3 +92,17 @@ def celery_send_mail_shared_data_checked(obj_identifier, obj_title=None, user_id
     from user.models import User
     user = User.objects.get(id=user_id)
     user.send_mail_shared_data_checked(obj_identifier, obj_title)
+
+
+@shared_task
+def celery_send_mail_shared_data_deleted_team(obj_identifier, obj_title=None, team_id=None):
+    from user.models import Team
+    team = Team.objects.get(id=team_id)
+    team.send_mail_shared_data_deleted(obj_identifier, obj_title)
+
+
+@shared_task
+def celery_send_mail_shared_data_checked_team(obj_identifier, obj_title=None, team_id=None):
+    from user.models import Team
+    team = Team.objects.get(id=team_id)
+    team.send_mail_shared_data_checked(obj_identifier, obj_title)
diff --git a/konova/utils/mailer.py b/konova/utils/mailer.py
index 33907f3c..dd8eef1f 100644
--- a/konova/utils/mailer.py
+++ b/konova/utils/mailer.py
@@ -92,6 +92,144 @@ class Mailer:
             msg
         )
 
+    def send_mail_shared_access_given_team(self, obj_identifier, obj_title, team):
+        """ Send a mail if a team just got access to the object
+
+        Args:
+            obj_identifier (str): The object identifier
+
+        Returns:
+
+        """
+        context = {
+            "team": team,
+            "obj_identifier": obj_identifier,
+            "obj_title": obj_title,
+            "EMAIL_REPLY_TO": EMAIL_REPLY_TO,
+        }
+        msg = render_to_string("email/sharing/shared_access_given_team.html", context)
+        user_mail_address = team.users.values_list("email", flat=True)
+        self.send(
+            user_mail_address,
+            _("{} - Shared access given").format(obj_identifier),
+            msg
+        )
+
+    def send_mail_shared_access_removed_team(self, obj_identifier, obj_title, team):
+        """ Send a mail if a team just lost access to the object
+
+        Args:
+            obj_identifier (str): The object identifier
+
+        Returns:
+
+        """
+        context = {
+            "team": team,
+            "obj_identifier": obj_identifier,
+            "obj_title": obj_title,
+            "EMAIL_REPLY_TO": EMAIL_REPLY_TO,
+        }
+        msg = render_to_string("email/sharing/shared_access_removed_team.html", context)
+        user_mail_address = team.users.values_list("email", flat=True)
+        self.send(
+            user_mail_address,
+            _("{} - Shared access removed").format(obj_identifier),
+            msg
+        )
+
+    def send_mail_shared_data_unrecorded_team(self, obj_identifier, obj_title, team):
+        """ Send a mail if data has just been unrecorded
+
+        Args:
+            obj_identifier (str): The object identifier
+
+        Returns:
+
+        """
+        context = {
+            "team": team,
+            "obj_identifier": obj_identifier,
+            "obj_title": obj_title,
+            "EMAIL_REPLY_TO": EMAIL_REPLY_TO,
+        }
+        msg = render_to_string("email/recording/shared_data_unrecorded_team.html", context)
+        user_mail_address = team.users.values_list("email", flat=True)
+        self.send(
+            user_mail_address,
+            _("{} - Shared data unrecorded").format(obj_identifier),
+            msg
+        )
+
+    def send_mail_shared_data_recorded_team(self, obj_identifier, obj_title, team):
+        """ Send a mail if data has just been recorded
+
+        Args:
+            obj_identifier (str): The object identifier
+
+        Returns:
+
+        """
+        context = {
+            "team": team,
+            "obj_identifier": obj_identifier,
+            "obj_title": obj_title,
+            "EMAIL_REPLY_TO": EMAIL_REPLY_TO,
+        }
+        msg = render_to_string("email/recording/shared_data_recorded_team.html", context)
+        user_mail_address = team.users.values_list("email", flat=True)
+        self.send(
+            user_mail_address,
+            _("{} - Shared data recorded").format(obj_identifier),
+            msg
+        )
+
+    def send_mail_shared_data_checked_team(self, obj_identifier, obj_title, team):
+        """ Send a mail if data has just been checked
+
+        Args:
+            obj_identifier (str): The object identifier
+
+        Returns:
+
+        """
+        context = {
+            "team": team,
+            "obj_identifier": obj_identifier,
+            "obj_title": obj_title,
+            "EMAIL_REPLY_TO": EMAIL_REPLY_TO,
+        }
+        msg = render_to_string("email/checking/shared_data_checked_team.html", context)
+        user_mail_address = team.users.values_list("email", flat=True)
+        self.send(
+            user_mail_address,
+            _("{} - Shared data checked").format(obj_identifier),
+            msg
+        )
+
+    def send_mail_shared_data_deleted_team(self, obj_identifier, obj_title, team):
+        """ Send a mail if data has just been deleted
+
+        Args:
+            obj_identifier (str): The object identifier
+
+        Returns:
+
+        """
+        context = {
+            "team": team,
+            "obj_identifier": obj_identifier,
+            "obj_title": obj_title,
+            "EMAIL_REPLY_TO": EMAIL_REPLY_TO,
+        }
+        msg = render_to_string("email/deleting/shared_data_deleted_team.html", context)
+        user_mail_address = team.users.values_list("email", flat=True)
+        self.send(
+            user_mail_address,
+            _("{} - Shared data deleted").format(obj_identifier),
+            msg
+        )
+
     def send_mail_shared_data_recorded(self, obj_identifier, obj_title, user):
         """ Send a mail if the user's shared data has just been unrecorded
 
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index ced4ab1ce70235e9c2f809480b12816984ba7a18..9437cb993a50c84e2c397c3f30f0e5d7cf7ba041 100644
GIT binary patch
delta 11524
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
Zr47vWROJ^Gobsp8FUQ;wwRDTue*k7fY3cv~

delta 11374
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
Its3a{e>B)xF#rGn

diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index 94efbd7b..051894c4 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -26,7 +26,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-18 14:01+0100\n"
+"POT-Creation-Date: 2022-02-18 14:50+0100\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"
@@ -1796,27 +1796,27 @@ msgstr "In Zwischenablage kopiert"
 msgid "{} - Shared access removed"
 msgstr "{} - Zugriff entzogen"
 
-#: konova/utils/mailer.py:91
+#: konova/utils/mailer.py:91 konova/utils/mailer.py:114
 msgid "{} - Shared access given"
 msgstr "{} - Zugriff freigegeben"
 
-#: konova/utils/mailer.py:114
+#: konova/utils/mailer.py:137
 msgid "{} - Shared data recorded"
 msgstr "{} - Freigegebene Daten verzeichnet"
 
-#: konova/utils/mailer.py:137
+#: konova/utils/mailer.py:160
 msgid "{} - Shared data unrecorded"
 msgstr "{} - Freigegebene Daten entzeichnet"
 
-#: konova/utils/mailer.py:160
+#: konova/utils/mailer.py:183
 msgid "{} - Shared data deleted"
 msgstr "{} - Freigegebene Daten gelöscht"
 
-#: konova/utils/mailer.py:183
+#: konova/utils/mailer.py:206
 msgid "{} - Shared data checked"
 msgstr "{} - Freigegebene Daten geprüft"
 
-#: konova/utils/mailer.py:204 templates/email/api/verify_token.html:4
+#: konova/utils/mailer.py:227 templates/email/api/verify_token.html:4
 msgid "Request for new API token"
 msgstr "Anfrage für neuen API Token"
 
@@ -2092,7 +2092,9 @@ msgstr ""
 #: templates/email/recording/shared_data_recorded.html:19
 #: templates/email/recording/shared_data_unrecorded.html:19
 #: templates/email/sharing/shared_access_given.html:20
+#: templates/email/sharing/shared_access_given_team.html:20
 #: templates/email/sharing/shared_access_removed.html:20
+#: templates/email/sharing/shared_access_removed_team.html:20
 msgid "Best regards"
 msgstr "Beste Grüße"
 
@@ -2179,6 +2181,7 @@ msgstr ""
 "zugehörigen Kompensationen automatisch entzeichnet worden sind."
 
 #: templates/email/sharing/shared_access_given.html:4
+#: templates/email/sharing/shared_access_given_team.html:4
 msgid "Access shared"
 msgstr "Zugriff freigegeben"
 
@@ -2187,10 +2190,12 @@ msgid "the following dataset has just been shared with you"
 msgstr "der folgende Datensatz wurde soeben für Sie freigegeben "
 
 #: templates/email/sharing/shared_access_given.html:16
+#: templates/email/sharing/shared_access_given_team.html:16
 msgid "This means you can now edit this dataset."
 msgstr "Das bedeutet, dass Sie diesen Datensatz nun auch bearbeiten können."
 
 #: templates/email/sharing/shared_access_given.html:17
+#: templates/email/sharing/shared_access_given_team.html:17
 msgid ""
 "The shared dataset appears now by default on your overview for this dataset "
 "type."
@@ -2199,6 +2204,7 @@ msgstr ""
 "Datensatztyp im KSP gelistet."
 
 #: templates/email/sharing/shared_access_given.html:27
+#: templates/email/sharing/shared_access_given_team.html:27
 msgid ""
 "Please note: Shared access on an intervention means you automatically have "
 "editing access to related compensations."
@@ -2207,7 +2213,17 @@ msgstr ""
 "Sie automatisch auch Zugriff auf die zugehörigen Kompensationen erhalten "
 "haben."
 
+#: templates/email/sharing/shared_access_given_team.html:8
+#: templates/email/sharing/shared_access_removed_team.html:8
+msgid "Hello team"
+msgstr "Hallo Team"
+
+#: templates/email/sharing/shared_access_given_team.html:10
+msgid "the following dataset has just been shared with your team"
+msgstr "der folgende Datensatz wurde soeben für Ihr Team freigegeben "
+
 #: templates/email/sharing/shared_access_removed.html:4
+#: templates/email/sharing/shared_access_removed_team.html:4
 msgid "Shared access removed"
 msgstr "Freigegebener Zugriff entzogen"
 
@@ -2219,10 +2235,12 @@ msgstr ""
 "entzogen: "
 
 #: templates/email/sharing/shared_access_removed.html:16
+#: templates/email/sharing/shared_access_removed_team.html:16
 msgid "However, you are still able to view the dataset content."
 msgstr "Sie können den Datensatz aber immer noch im KSP einsehen."
 
 #: templates/email/sharing/shared_access_removed.html:17
+#: templates/email/sharing/shared_access_removed_team.html:17
 msgid ""
 "Please use the provided search filter on the dataset`s overview pages to "
 "find them."
@@ -2230,6 +2248,14 @@ msgstr ""
 "Nutzen Sie hierzu einfach die entsprechenden Suchfilter auf den "
 "Übersichtsseiten"
 
+#: templates/email/sharing/shared_access_removed_team.html:10
+msgid ""
+"your teams shared access, including editing, has been revoked for the "
+"dataset "
+msgstr ""
+"Ihrem Team wurde soeben der bearbeitende Zugriff auf den folgenden Datensatz "
+"entzogen: "
+
 #: templates/email/signature.html:6
 msgid "Please do not reply on this mail."
 msgstr "Bitte antworten Sie nicht auf diese Mail."
@@ -4118,6 +4144,9 @@ msgstr ""
 msgid "Unable to connect to qpid with SASL mechanism %s"
 msgstr ""
 
+#~ msgid "your teams"
+#~ msgstr "Team entfernen"
+
 #~ msgid "Remove check to remove access for this user"
 #~ msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen"
 
diff --git a/templates/email/checking/shared_data_checked_team.html b/templates/email/checking/shared_data_checked_team.html
new file mode 100644
index 00000000..ee813811
--- /dev/null
+++ b/templates/email/checking/shared_data_checked_team.html
@@ -0,0 +1,28 @@
+{% load i18n %}
+
+<div>
+    <h2>{% trans 'Shared data checked' %}</h2>
+    <h4>{{obj_identifier}}</h4>
+    <hr>
+    <article>
+        {% trans 'Hello team' %} {{team.name}},
+        <br>
+        {% trans 'the following dataset has just been checked' %}
+        <br>
+        <strong>{{obj_identifier}}</strong>
+        <br>
+        <strong>{{obj_title}}</strong>
+        <br>
+        {% trans 'This means, the responsible registration office just confirmed the correctness of this dataset.' %}
+        <br>
+        <br>
+        {% trans 'Best regards' %}
+        <br>
+        KSP
+        <br>
+        <br>
+        <br>
+        {% include 'email/signature.html' %}
+    </article>
+</div>
+
diff --git a/templates/email/deleting/shared_data_deleted_team.html b/templates/email/deleting/shared_data_deleted_team.html
new file mode 100644
index 00000000..cedb2a45
--- /dev/null
+++ b/templates/email/deleting/shared_data_deleted_team.html
@@ -0,0 +1,28 @@
+{% load i18n %}
+
+<div>
+    <h2>{% trans 'Shared data deleted' %}</h2>
+    <h4>{{obj_identifier}}</h4>
+    <hr>
+    <article>
+        {% trans 'Hello team' %} {{team.name}},
+        <br>
+        {% trans 'the following dataset has just been deleted' %}
+        <br>
+        <strong>{{obj_identifier}}</strong>
+        <br>
+        <strong>"{{obj_title}}"</strong>
+        <br>
+        {% trans 'If this should not have been happened, please contact us. See the signature for details.' %}
+        <br>
+        <br>
+        {% trans 'Best regards' %}
+        <br>
+        KSP
+        <br>
+        <br>
+        <br>
+        {% include 'email/signature.html' %}
+    </article>
+</div>
+
diff --git a/templates/email/recording/shared_data_recorded_team.html b/templates/email/recording/shared_data_recorded_team.html
new file mode 100644
index 00000000..12efa8f6
--- /dev/null
+++ b/templates/email/recording/shared_data_recorded_team.html
@@ -0,0 +1,33 @@
+{% load i18n %}
+
+<div>
+    <h2>{% trans 'Shared data recorded' %}</h2>
+    <h4>{{obj_identifier}}</h4>
+    <hr>
+    <article>
+        {% trans 'Hello team' %} {{team.name}},
+        <br>
+        {% trans 'the following dataset has just been recorded' %}
+        <br>
+        <strong>{{obj_identifier}}</strong>
+        <br>
+        <strong>"{{obj_title}}"</strong>
+        <br>
+        {% trans 'This means the data is now publicly available, e.g. in LANIS' %}
+        <br>
+        <br>
+        {% trans 'Best regards' %}
+        <br>
+        KSP
+        <br>
+        <br>
+        <br>
+        <small>
+            {% trans 'Please note: Recorded intervention means the compensations are recorded as well.' %}
+        </small>
+        <br>
+        <br>
+        {% include 'email/signature.html' %}
+    </article>
+</div>
+
diff --git a/templates/email/recording/shared_data_unrecorded_team.html b/templates/email/recording/shared_data_unrecorded_team.html
new file mode 100644
index 00000000..64141555
--- /dev/null
+++ b/templates/email/recording/shared_data_unrecorded_team.html
@@ -0,0 +1,33 @@
+{% load i18n %}
+
+<div>
+    <h2>{% trans 'Shared data unrecorded' %}</h2>
+    <h4>{{obj_identifier}}</h4>
+    <hr>
+    <article>
+        {% trans 'Hello team' %} {{team.name}},
+        <br>
+        {% trans 'the following dataset has just been unrecorded' %}
+        <br>
+        <strong>{{obj_identifier}}</strong>
+        <br>
+        <strong>"{{obj_title}}"</strong>
+        <br>
+        {% trans 'This means the data is no longer publicly available.' %}
+        <br>
+        <br>
+        {% trans 'Best regards' %}
+        <br>
+        KSP
+        <br>
+        <br>
+        <br>
+        <small>
+            {% trans 'Please note: Unrecorded intervention means the compensations are unrecorded as well.' %}
+        </small>
+        <br>
+        <br>
+        {% include 'email/signature.html' %}
+    </article>
+</div>
+
diff --git a/templates/email/sharing/shared_access_given_team.html b/templates/email/sharing/shared_access_given_team.html
new file mode 100644
index 00000000..990ba2de
--- /dev/null
+++ b/templates/email/sharing/shared_access_given_team.html
@@ -0,0 +1,34 @@
+{% load i18n %}
+
+<div>
+    <h2>{% trans 'Access shared' %}</h2>
+    <h4>{{obj_identifier}}</h4>
+    <hr>
+    <article>
+        {% trans 'Hello team' %} {{team.name}},
+        <br>
+        {% trans 'the following dataset has just been shared with your team' %}
+        <br>
+        <strong>{{obj_identifier}}</strong>
+        <br>
+        <strong>"{{obj_title}}"</strong>
+        <br>
+        {% trans 'This means you can now edit this dataset.' %}
+        {% trans 'The shared dataset appears now by default on your overview for this dataset type.' %}
+        <br>
+        <br>
+        {% trans 'Best regards' %}
+        <br>
+        KSP
+        <br>
+        <br>
+        <br>
+        <small>
+            {% trans 'Please note: Shared access on an intervention means you automatically have editing access to related compensations.' %}
+        </small>
+        <br>
+        <br>
+        {% include 'email/signature.html' %}
+    </article>
+</div>
+
diff --git a/templates/email/sharing/shared_access_removed_team.html b/templates/email/sharing/shared_access_removed_team.html
new file mode 100644
index 00000000..5472ef73
--- /dev/null
+++ b/templates/email/sharing/shared_access_removed_team.html
@@ -0,0 +1,29 @@
+{% load i18n %}
+
+<div>
+    <h2>{% trans 'Shared access removed' %}</h2>
+    <h4>{{obj_identifier}}</h4>
+    <hr>
+    <article>
+        {% trans 'Hello team' %} {{team.name}},
+        <br>
+        {% trans 'your teams shared access, including editing, has been revoked for the dataset ' %}
+        <br>
+        <strong>{{obj_identifier}}</strong>
+        <br>
+        <strong>"{{obj_title}}"</strong>
+        <br>
+        {% trans 'However, you are still able to view the dataset content.' %}
+        {% trans 'Please use the provided search filter on the dataset`s overview pages to find them.' %}
+        <br>
+        <br>
+        {% trans 'Best regards' %}
+        <br>
+        KSP
+        <br>
+        <br>
+        <br>
+        {% include 'email/signature.html' %}
+    </article>
+</div>
+
diff --git a/user/models/team.py b/user/models/team.py
index c26af3c6..e36c95b4 100644
--- a/user/models/team.py
+++ b/user/models/team.py
@@ -1,6 +1,7 @@
 from django.db import models
 
 from konova.models import UuidModel
+from konova.utils.mailer import Mailer
 
 
 class Team(UuidModel):
@@ -14,3 +15,81 @@ class Team(UuidModel):
 
     def __str__(self):
         return self.name
+
+    def send_mail_shared_access_given_team(self, obj_identifier, obj_title):
+        """ Sends a mail to the team members in case of given shared access
+
+        Args:
+            obj_identifier ():
+            obj_title ():
+
+        Returns:
+
+        """
+        mailer = Mailer()
+        mailer.send_mail_shared_access_given_team(obj_identifier, obj_title, self)
+
+    def send_mail_shared_access_removed(self, obj_identifier, obj_title):
+        """ Sends a mail to the team members in case of removed shared access
+
+        Args:
+            obj_identifier ():
+            obj_title ():
+
+        Returns:
+
+        """
+        mailer = Mailer()
+        mailer.send_mail_shared_access_removed_team(obj_identifier, obj_title, self)
+
+    def send_mail_shared_data_unrecorded(self, obj_identifier, obj_title):
+        """ Sends a mail to the team members in case of unrecorded data
+
+        Args:
+            obj_identifier ():
+            obj_title ():
+
+        Returns:
+
+        """
+        mailer = Mailer()
+        mailer.send_mail_shared_data_unrecorded_team(obj_identifier, obj_title, self)
+
+    def send_mail_shared_data_recorded(self, obj_identifier, obj_title):
+        """ Sends a mail to the team members in case of unrecorded data
+
+        Args:
+            obj_identifier ():
+            obj_title ():
+
+        Returns:
+
+        """
+        mailer = Mailer()
+        mailer.send_mail_shared_data_recorded_team(obj_identifier, obj_title, self)
+
+    def send_mail_shared_data_checked(self, obj_identifier, obj_title):
+        """ Sends a mail to the team members in case of checked data
+
+        Args:
+            obj_identifier ():
+            obj_title ():
+
+        Returns:
+
+        """
+        mailer = Mailer()
+        mailer.send_mail_shared_data_checked_team(obj_identifier, obj_title, self)
+
+    def send_mail_shared_data_deleted(self, obj_identifier, obj_title):
+        """ Sends a mail to the team members in case of deleted data
+
+        Args:
+            obj_identifier ():
+            obj_title ():
+
+        Returns:
+
+        """
+        mailer = Mailer()
+        mailer.send_mail_shared_data_deleted_team(obj_identifier, obj_title, self)