Merge pull request '25_Public_Reports' (#30) from 25_Public_Reports into master
Reviewed-on: SGD-Nord/konova#30
This commit is contained in:
		
						commit
						2b06a439cf
					
				@ -12,9 +12,10 @@ urlpatterns = [
 | 
			
		||||
    path("", index_view, name="acc-index"),
 | 
			
		||||
    path('new/', new_view, name='acc-new'),
 | 
			
		||||
    path('new/id', new_id_view, name='acc-new-id'),
 | 
			
		||||
    path('<id>', open_view, name='acc-open'),
 | 
			
		||||
    path('<id>', detail_view, name='acc-detail'),
 | 
			
		||||
    path('<id>/log', log_view, name='acc-log'),
 | 
			
		||||
    path('<id>/record', record_view, name='acc-record'),
 | 
			
		||||
    path('<id>/report', report_view, name='acc-report'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='acc-edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='acc-remove'),
 | 
			
		||||
    path('<id>/state/new', state_new_view, name='acc-new-state'),
 | 
			
		||||
 | 
			
		||||
@ -14,13 +14,14 @@ urlpatterns = [
 | 
			
		||||
    path('new/id', new_id_view, name='new-id'),
 | 
			
		||||
    path('new/<intervention_id>', new_view, name='new'),
 | 
			
		||||
    path('new', new_view, name='new'),
 | 
			
		||||
    path('<id>', open_view, name='open'),
 | 
			
		||||
    path('<id>', detail_view, name='detail'),
 | 
			
		||||
    path('<id>/log', log_view, name='log'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
    path('<id>/state/new', state_new_view, name='new-state'),
 | 
			
		||||
    path('<id>/action/new', action_new_view, name='new-action'),
 | 
			
		||||
    path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
 | 
			
		||||
    # Documents
 | 
			
		||||
    path('<id>/document/new/', new_document_view, name='new-doc'),
 | 
			
		||||
 | 
			
		||||
@ -179,7 +179,7 @@ class NewCompensationForm(AbstractCompensationForm):
 | 
			
		||||
            self.initialize_form_field("intervention", intervention_id)
 | 
			
		||||
            self.disable_form_field("intervention")
 | 
			
		||||
            self.action_url = reverse("compensation:new", args=(intervention_id,))
 | 
			
		||||
            self.cancel_redirect = reverse("intervention:open", args=(intervention_id,))
 | 
			
		||||
            self.cancel_redirect = reverse("intervention:detail", args=(intervention_id,))
 | 
			
		||||
        else:
 | 
			
		||||
            self.action_url = reverse("compensation:new")
 | 
			
		||||
            self.cancel_redirect = reverse("compensation:index")
 | 
			
		||||
@ -230,7 +230,7 @@ class EditCompensationForm(NewCompensationForm):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("Edit compensation")
 | 
			
		||||
        self.action_url = reverse("compensation:edit", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("compensation:open", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("compensation:detail", args=(self.instance.id,))
 | 
			
		||||
 | 
			
		||||
        # Initialize form data
 | 
			
		||||
        form_data = {
 | 
			
		||||
@ -384,7 +384,7 @@ class EditEcoAccountForm(NewEcoAccountForm):
 | 
			
		||||
        self.form_title = _("Edit Eco-Account")
 | 
			
		||||
 | 
			
		||||
        self.action_url = reverse("compensation:acc-edit", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("compensation:acc-open", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("compensation:acc-detail", args=(self.instance.id,))
 | 
			
		||||
 | 
			
		||||
        # Initialize form data
 | 
			
		||||
        form_data = {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										73
									
								
								compensation/managers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								compensation/managers.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,73 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
 | 
			
		||||
Contact: michel.peltriaux@sgdnord.rlp.de
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().select_related(
 | 
			
		||||
            "biotope_type",
 | 
			
		||||
            "biotope_type__parent"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompensationManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().select_related(
 | 
			
		||||
            "modified",
 | 
			
		||||
            "intervention",
 | 
			
		||||
            "intervention__recorded",
 | 
			
		||||
            "intervention__recorded__user",
 | 
			
		||||
            "intervention__modified",
 | 
			
		||||
            "intervention__checked",
 | 
			
		||||
            "intervention__checked__user",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().select_related(
 | 
			
		||||
            "recorded",
 | 
			
		||||
            "recorded__user",
 | 
			
		||||
            "modified",
 | 
			
		||||
            "modified__user",
 | 
			
		||||
        ).prefetch_related(
 | 
			
		||||
            "users",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountDeductionManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().select_related(
 | 
			
		||||
            "intervention",
 | 
			
		||||
            "intervention__recorded",
 | 
			
		||||
            "created",
 | 
			
		||||
        )
 | 
			
		||||
@ -17,6 +17,8 @@ from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from codelist.models import KonovaCode
 | 
			
		||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID, \
 | 
			
		||||
    CODELIST_COMPENSATION_FUNDING_ID
 | 
			
		||||
from compensation.managers import CompensationStateManager, EcoAccountDeductionManager, CompensationActionManager, \
 | 
			
		||||
    EcoAccountManager, CompensationManager
 | 
			
		||||
from intervention.models import Intervention, ResponsibilityData
 | 
			
		||||
from konova.models import BaseObject, BaseResource, Geometry, UuidModel, AbstractDocument, \
 | 
			
		||||
    generate_document_file_upload_path
 | 
			
		||||
@ -67,6 +69,8 @@ class CompensationState(UuidModel):
 | 
			
		||||
    )
 | 
			
		||||
    surface = models.FloatField()
 | 
			
		||||
 | 
			
		||||
    objects = CompensationStateManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "{} | {} m²".format(self.biotope_type, self.surface)
 | 
			
		||||
 | 
			
		||||
@ -102,6 +106,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 "{} | {} {}".format(self.action_type, self.amount, self.unit)
 | 
			
		||||
 | 
			
		||||
@ -178,6 +184,8 @@ class Compensation(AbstractCompensation):
 | 
			
		||||
        related_name='compensations'
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = CompensationManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "{}".format(self.identifier)
 | 
			
		||||
 | 
			
		||||
@ -301,6 +309,8 @@ class EcoAccount(AbstractCompensation):
 | 
			
		||||
        default=0,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = EcoAccountManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "{}".format(self.identifier)
 | 
			
		||||
 | 
			
		||||
@ -500,5 +510,7 @@ class EcoAccountDeduction(BaseResource):
 | 
			
		||||
        related_name="deductions",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = EcoAccountDeductionManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "{} of {}".format(self.surface, self.account)
 | 
			
		||||
 | 
			
		||||
@ -82,7 +82,7 @@ class CompensationTable(BaseTable):
 | 
			
		||||
        html = ""
 | 
			
		||||
        html += self.render_link(
 | 
			
		||||
            tooltip=_("Open {}").format(_("Compensation")),
 | 
			
		||||
            href=reverse("compensation:open", args=(record.id,)),
 | 
			
		||||
            href=reverse("compensation:detail", args=(record.id,)),
 | 
			
		||||
            txt=value,
 | 
			
		||||
            new_tab=False,
 | 
			
		||||
        )
 | 
			
		||||
@ -148,14 +148,13 @@ class CompensationTable(BaseTable):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        html = ""
 | 
			
		||||
        if value is None:
 | 
			
		||||
            value = User.objects.none()
 | 
			
		||||
        has_access = value.filter(
 | 
			
		||||
            username=self.user.username
 | 
			
		||||
            id=self.user.id
 | 
			
		||||
        ).exists()
 | 
			
		||||
 | 
			
		||||
        html += self.render_icn(
 | 
			
		||||
        html = self.render_icn(
 | 
			
		||||
            tooltip=_("Full access granted") if has_access else _("Access not granted"),
 | 
			
		||||
            icn_class="fas fa-edit rlp-r-inv" if has_access else "far fa-edit",
 | 
			
		||||
        )
 | 
			
		||||
@ -223,7 +222,7 @@ class EcoAccountTable(BaseTable):
 | 
			
		||||
        html = ""
 | 
			
		||||
        html += self.render_link(
 | 
			
		||||
            tooltip=_("Open {}").format(_("Eco-account")),
 | 
			
		||||
            href=reverse("compensation:acc-open", args=(record.id,)),
 | 
			
		||||
            href=reverse("compensation:acc-detail", args=(record.id,)),
 | 
			
		||||
            txt=value,
 | 
			
		||||
            new_tab=False,
 | 
			
		||||
        )
 | 
			
		||||
@ -244,7 +243,7 @@ class EcoAccountTable(BaseTable):
 | 
			
		||||
        return format_html(html)
 | 
			
		||||
 | 
			
		||||
    def render_r(self, value, record: EcoAccount):
 | 
			
		||||
        """ Renders the registered column for an eco account
 | 
			
		||||
        """ Renders the recorded column for an eco account
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            value (str): The identifier value
 | 
			
		||||
@ -268,7 +267,7 @@ class EcoAccountTable(BaseTable):
 | 
			
		||||
        return format_html(html)
 | 
			
		||||
 | 
			
		||||
    def render_e(self, value, record: EcoAccount):
 | 
			
		||||
        """ Renders the registered column for an eco account
 | 
			
		||||
        """ Renders the editable column for an eco account
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            value (str): The identifier value
 | 
			
		||||
@ -278,10 +277,9 @@ class EcoAccountTable(BaseTable):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        html = ""
 | 
			
		||||
        has_access = value.filter(
 | 
			
		||||
            username=self.user.username
 | 
			
		||||
        ).exists()
 | 
			
		||||
 | 
			
		||||
        # Do not use value in here, since value does use unprefetched 'users' manager, where record has already
 | 
			
		||||
        # prefetched users data
 | 
			
		||||
        has_access = self.user in record.users.all()
 | 
			
		||||
        html += self.render_icn(
 | 
			
		||||
            tooltip=_("Full access granted") if has_access else _("Access not granted"),
 | 
			
		||||
            icn_class="fas fa-edit rlp-r-inv" if has_access else "far fa-edit",
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.actions.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{actions.count}}</span>
 | 
			
		||||
                    {% trans 'Actions' context 'Compensation' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -33,13 +33,15 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% for action in obj.actions.all %}
 | 
			
		||||
            {% for action in actions %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    {{ action.action_type }}
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
            LANIS
 | 
			
		||||
        </button>
 | 
			
		||||
    </a>
 | 
			
		||||
    <a href="{% url 'home' %}" class="mr-2">
 | 
			
		||||
    <a href="{% url 'compensation:report' obj.id %}" target="_blank"  class="mr-2">
 | 
			
		||||
        <button class="btn btn-default" title="{% trans 'Public report' %}">
 | 
			
		||||
            {% fa5_icon 'file-alt' %}
 | 
			
		||||
        </button>
 | 
			
		||||
 | 
			
		||||
@ -33,9 +33,11 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
@ -30,9 +30,11 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
@ -35,9 +35,11 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Surface' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.before_states.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{before_states.count}}</span>
 | 
			
		||||
                    {% trans 'States before' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -35,9 +35,11 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Surface' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'compensates intervention' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            <a href="{% url 'intervention:open' obj.intervention.id %}">
 | 
			
		||||
                            <a href="{% url 'intervention:detail' obj.intervention.id %}">
 | 
			
		||||
                                {{obj.intervention.identifier}}
 | 
			
		||||
                            </a>
 | 
			
		||||
                        </td>
 | 
			
		||||
@ -103,7 +103,7 @@
 | 
			
		||||
                {% include 'map/geom_form.html' %}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                {% include 'compensation/detail/compensation/includes/comment.html' %}
 | 
			
		||||
                {% include 'konova/comment_card.html' %}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.actions.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{actions.count}}</span>
 | 
			
		||||
                    {% trans 'Actions' context 'Compensation' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -33,13 +33,15 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% for action in obj.actions.all %}
 | 
			
		||||
            {% for action in actions %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    {{ action.action_type }}
 | 
			
		||||
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
{% load i18n fontawesome_5 %}
 | 
			
		||||
 | 
			
		||||
{% if obj.comment %}
 | 
			
		||||
<div class="w-100">
 | 
			
		||||
    <div class="card mt-3">
 | 
			
		||||
        <div class="card-header rlp-gd">
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-sm-12 col-md-12 col-lg-12">
 | 
			
		||||
                    <h5 class="card-title">
 | 
			
		||||
                        {% fa5_icon 'info-circle' %}
 | 
			
		||||
                        {% trans 'Comment' %}
 | 
			
		||||
                    </h5>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="card-body">
 | 
			
		||||
            <div class="card-text font-italic">
 | 
			
		||||
                {{obj.comment}}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
            LANIS
 | 
			
		||||
        </button>
 | 
			
		||||
    </a>
 | 
			
		||||
    <a href="{% url 'home' %}" class="mr-2">
 | 
			
		||||
    <a href="{% url 'compensation:acc-report' obj.id %}" target="_blank" class="mr-2">
 | 
			
		||||
        <button class="btn btn-default" title="{% trans 'Public report' %}">
 | 
			
		||||
            {% fa5_icon 'file-alt' %}
 | 
			
		||||
        </button>
 | 
			
		||||
 | 
			
		||||
@ -45,15 +45,15 @@
 | 
			
		||||
            {% for deduction in deductions %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    <a href="{% url 'intervention:open' deduction.intervention.id %}">
 | 
			
		||||
                    <a href="{% url 'intervention:detail' deduction.intervention.id %}">
 | 
			
		||||
                        {{ deduction.intervention.identifier }}
 | 
			
		||||
                    </a>
 | 
			
		||||
                </td>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    {% if deduction.intervention.recorded %}
 | 
			
		||||
                        <em title='{{ deduction.intervention.recorded_tooltip }}' class='fas fa-bookmark registered-bookmark'></em>
 | 
			
		||||
                        <em title="{% trans 'Recorded on' %} {{obj.recorded.timestamp}} {% trans 'by' %} {{obj.recorded.user}}" class='fas fa-bookmark registered-bookmark'></em>
 | 
			
		||||
                    {% else %}
 | 
			
		||||
                        <em title='{{ deduction.intervention.recorded_tooltip }}' class='far fa-bookmark'></em>
 | 
			
		||||
                        <em title="{% trans 'Not recorded yet' %}" class='far fa-bookmark'></em>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                </td>
 | 
			
		||||
                <td class="align-middle">{{ deduction.surface|floatformat:2|intcomma }} m²</td>
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.after_states.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{after_states.count}}</span>
 | 
			
		||||
                    {% trans 'States after' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -35,9 +35,11 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Surface' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.before_states.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{before_states.count}}</span>
 | 
			
		||||
                    {% trans 'States before' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -35,9 +35,11 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Surface' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,7 @@
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not obj.responsible.handler %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Intervention handler' %}</th>
 | 
			
		||||
                        <th scope="row">{% trans 'Action handler' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
@ -102,7 +102,7 @@
 | 
			
		||||
                {% include 'map/geom_form.html' %}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                {% include 'compensation/detail/compensation/includes/comment.html' %}
 | 
			
		||||
                {% include 'konova/comment_card.html' %}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,67 @@
 | 
			
		||||
{% extends 'public_base.html' %}
 | 
			
		||||
{% load i18n fontawesome_5 humanize %}
 | 
			
		||||
 | 
			
		||||
{% block body %}
 | 
			
		||||
<div class="row">
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <h3>{% trans 'Report' %}</h3>
 | 
			
		||||
        <h4>{{obj.identifier}}</h4>
 | 
			
		||||
        <div class="table-container">
 | 
			
		||||
            <table class="table table-hover">
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th class="w-25" scope="row">{% trans 'Title' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.title|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'compensates intervention' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            <a href="{% url 'intervention:report' obj.intervention.id %}">
 | 
			
		||||
                                {{obj.intervention.identifier}}
 | 
			
		||||
                            </a>
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Funded by' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% with obj.fundings.all as fundings %}
 | 
			
		||||
                            {% for funding in fundings %}
 | 
			
		||||
                                <div class="badge pill-badge rlp-r-outline">{{funding.short_name}}</div>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% empty %}
 | 
			
		||||
                                {% trans 'None' %}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                            {% endwith %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Last modified' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {{obj.modified.timestamp|default_if_none:""|naturalday}}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
            </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/states-before.html' %}
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/states-after.html' %}
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/actions.html' %}
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            {% include 'map/geom_form.html' %}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'Open in browser' %}</h4>
 | 
			
		||||
                {{ qrcode|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'View in LANIS' %}</h4>
 | 
			
		||||
                {{ qrcode_lanis|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@ -0,0 +1,84 @@
 | 
			
		||||
{% extends 'public_base.html' %}
 | 
			
		||||
{% load i18n fontawesome_5 humanize %}
 | 
			
		||||
 | 
			
		||||
{% block body %}
 | 
			
		||||
<div class="row">
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <h3>{% trans 'Report' %}</h3>
 | 
			
		||||
        <h4>{{obj.identifier}}</h4>
 | 
			
		||||
        <div class="table-container">
 | 
			
		||||
            <table class="table table-hover">
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th class="w-25" scope="row">{% trans 'Title' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.title|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office file number' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Action handler' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Funded by' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% with obj.fundings.all as fundings %}
 | 
			
		||||
                            {% for funding in fundings %}
 | 
			
		||||
                                <div class="badge pill-badge rlp-r-outline">{{funding.short_name}}</div>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% empty %}
 | 
			
		||||
                                {% trans 'None' %}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                            {% endwith %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Deductions for' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% for deduction in deductions %}
 | 
			
		||||
                                <a href="{% url 'intervention:report' deduction.intervention__id %}">
 | 
			
		||||
                                    {{deduction.intervention__identifier}}
 | 
			
		||||
                                </a>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% empty %}
 | 
			
		||||
                                {% trans 'None' %}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Last modified' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {{obj.modified.timestamp|default_if_none:""|naturalday}}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
            </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/states-before.html' %}
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/states-after.html' %}
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/actions.html' %}
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            {% include 'map/geom_form.html' %}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'Open in browser' %}</h4>
 | 
			
		||||
                {{ qrcode|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'View in LANIS' %}</h4>
 | 
			
		||||
                {{ qrcode_lanis|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@ -13,6 +13,7 @@ from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import *
 | 
			
		||||
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm
 | 
			
		||||
from konova.utils.documents import get_document, remove_document
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED
 | 
			
		||||
from konova.utils.user_checks import in_group
 | 
			
		||||
 | 
			
		||||
@ -74,7 +75,7 @@ def new_view(request: HttpRequest, intervention_id: str = None):
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("Compensation {} added").format(comp.identifier))
 | 
			
		||||
            return redirect("compensation:open", id=comp.id)
 | 
			
		||||
            return redirect("compensation:detail", id=comp.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -129,7 +130,7 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
            # The data form takes the geom form for processing, as well as the performing user
 | 
			
		||||
            comp = data_form.save(request.user, geom_form)
 | 
			
		||||
            messages.success(request, _("Compensation {} edited").format(comp.identifier))
 | 
			
		||||
            return redirect("compensation:open", id=comp.id)
 | 
			
		||||
            return redirect("compensation:detail", id=comp.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -145,7 +146,7 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def open_view(request: HttpRequest, id: str):
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a detail view for a compensation
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
@ -162,8 +163,9 @@ def open_view(request: HttpRequest, id: str):
 | 
			
		||||
    is_data_shared = comp.intervention.is_shared_with(_user)
 | 
			
		||||
 | 
			
		||||
    # Order states according to surface
 | 
			
		||||
    before_states = comp.before_states.all().order_by("-surface")
 | 
			
		||||
    after_states = comp.after_states.all().order_by("-surface")
 | 
			
		||||
    before_states = comp.before_states.all().prefetch_related("biotope_type").order_by("-surface")
 | 
			
		||||
    after_states = comp.after_states.all().prefetch_related("biotope_type").order_by("-surface")
 | 
			
		||||
    actions = comp.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
    # Precalculate logical errors between before- and after-states
 | 
			
		||||
    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
@ -175,6 +177,7 @@ def open_view(request: HttpRequest, id: str):
 | 
			
		||||
        "obj": comp,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "has_access": is_data_shared,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "sum_before_states": sum_before_states,
 | 
			
		||||
@ -381,3 +384,53 @@ def action_remove_view(request: HttpRequest, id: str):
 | 
			
		||||
        request,
 | 
			
		||||
        msg_success=_("Action removed")
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def report_view(request:HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # Reuse the compensation report template since compensations are structurally identical
 | 
			
		||||
    template = "compensation/report/compensation/report.html"
 | 
			
		||||
    comp = get_object_or_404(Compensation, id=id)
 | 
			
		||||
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not comp.intervention.recorded:
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        return render(request, template, {})
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=comp
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img = generate_qr_code(
 | 
			
		||||
        request.build_absolute_uri(reverse("compensation:report", args=(id,))),
 | 
			
		||||
        10
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(
 | 
			
		||||
        comp.get_LANIS_link(),
 | 
			
		||||
        7
 | 
			
		||||
    )
 | 
			
		||||
    # Order states by surface
 | 
			
		||||
    before_states = comp.before_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    after_states = comp.after_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    actions = comp.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": comp,
 | 
			
		||||
        "qrcode": qrcode_img,
 | 
			
		||||
        "qrcode_lanis": qrcode_img_lanis,
 | 
			
		||||
        "has_access": False,  # disables action buttons during rendering
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,7 @@ from konova.decorators import any_group_check, default_group_required, conservat
 | 
			
		||||
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm
 | 
			
		||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
 | 
			
		||||
from konova.utils.documents import get_document, remove_document
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID
 | 
			
		||||
from konova.utils.user_checks import in_group
 | 
			
		||||
 | 
			
		||||
@ -41,7 +42,6 @@ def index_view(request: HttpRequest):
 | 
			
		||||
        A rendered view
 | 
			
		||||
    """
 | 
			
		||||
    template = "generic_index.html"
 | 
			
		||||
    user = request.user
 | 
			
		||||
    eco_accounts = EcoAccount.objects.filter(
 | 
			
		||||
        deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
@ -84,7 +84,7 @@ def new_view(request: HttpRequest):
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("Eco-Account {} added").format(acc.identifier))
 | 
			
		||||
            return redirect("compensation:acc-open", id=acc.id)
 | 
			
		||||
            return redirect("compensation:acc-detail", id=acc.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -139,7 +139,7 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
            # The data form takes the geom form for processing, as well as the performing user
 | 
			
		||||
            acc = data_form.save(request.user, geom_form)
 | 
			
		||||
            messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
 | 
			
		||||
            return redirect("compensation:acc-open", id=acc.id)
 | 
			
		||||
            return redirect("compensation:acc-detail", id=acc.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -155,7 +155,7 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def open_view(request: HttpRequest, id: str):
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a detail view for a compensation
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
@ -166,27 +166,36 @@ def open_view(request: HttpRequest, id: str):
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "compensation/detail/eco_account/view.html"
 | 
			
		||||
    acc = get_object_or_404(EcoAccount, id=id)
 | 
			
		||||
    acc = get_object_or_404(
 | 
			
		||||
        EcoAccount.objects.prefetch_related(
 | 
			
		||||
            "deadlines",
 | 
			
		||||
        ).select_related(
 | 
			
		||||
            'geometry',
 | 
			
		||||
            'responsible',
 | 
			
		||||
        ),
 | 
			
		||||
        id=id
 | 
			
		||||
    )
 | 
			
		||||
    geom_form = SimpleGeomForm(instance=acc)
 | 
			
		||||
    _user = request.user
 | 
			
		||||
    is_data_shared = acc.is_shared_with(_user)
 | 
			
		||||
 | 
			
		||||
    # Order states according to surface
 | 
			
		||||
    before_states = acc.before_states.all().order_by("-surface")
 | 
			
		||||
    after_states = acc.after_states.all().order_by("-surface")
 | 
			
		||||
    before_states = acc.before_states.order_by("-surface")
 | 
			
		||||
    after_states = acc.after_states.order_by("-surface")
 | 
			
		||||
 | 
			
		||||
    # Precalculate logical errors between before- and after-states
 | 
			
		||||
    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
    sum_before_states = before_states.aggregate(Sum("surface"))["surface__sum"] or 0
 | 
			
		||||
    sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
 | 
			
		||||
    diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
 | 
			
		||||
    # Calculate rest of available surface for deductions
 | 
			
		||||
    available_total, available_relative = acc.get_available_rest()
 | 
			
		||||
 | 
			
		||||
    # Prefetch related data to decrease the amount of db connections
 | 
			
		||||
    deductions = acc.deductions.filter(
 | 
			
		||||
        intervention__deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
    actions = acc.actions.all()
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": acc,
 | 
			
		||||
@ -204,6 +213,7 @@ def open_view(request: HttpRequest, id: str):
 | 
			
		||||
        "is_ets_member": in_group(_user, ETS_GROUP),
 | 
			
		||||
        "LANIS_LINK": acc.get_LANIS_link(),
 | 
			
		||||
        "deductions": deductions,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
@ -432,3 +442,60 @@ def new_deduction_view(request: HttpRequest, id: str):
 | 
			
		||||
        request,
 | 
			
		||||
        msg_success=_("Deduction added")
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def report_view(request:HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # Reuse the compensation report template since EcoAccounts are structurally identical
 | 
			
		||||
    template = "compensation/report/eco_account/report.html"
 | 
			
		||||
    acc = get_object_or_404(EcoAccount, id=id)
 | 
			
		||||
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not acc.recorded:
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        return render(request, template, {})
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=acc
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img = generate_qr_code(
 | 
			
		||||
        request.build_absolute_uri(reverse("ema:report", args=(id,))),
 | 
			
		||||
        10
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(
 | 
			
		||||
        acc.get_LANIS_link(),
 | 
			
		||||
        7
 | 
			
		||||
    )
 | 
			
		||||
    # Order states by surface
 | 
			
		||||
    before_states = acc.before_states.all().order_by("-surface").select_related("biotope_type__parent")
 | 
			
		||||
    after_states = acc.after_states.all().order_by("-surface").select_related("biotope_type__parent")
 | 
			
		||||
    actions = acc.actions.all().select_related("action_type__parent")
 | 
			
		||||
 | 
			
		||||
    # Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
 | 
			
		||||
    deductions = acc.deductions.all()\
 | 
			
		||||
        .distinct("intervention")\
 | 
			
		||||
        .select_related("intervention")\
 | 
			
		||||
        .values_list("intervention__id", "intervention__identifier", named=True)
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": acc,
 | 
			
		||||
        "qrcode": qrcode_img,
 | 
			
		||||
        "qrcode_lanis": qrcode_img_lanis,
 | 
			
		||||
        "has_access": False,  # disables action buttons during rendering
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        "deductions": deductions,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
@ -99,7 +99,7 @@ class EditEmaForm(NewEmaForm):
 | 
			
		||||
        self.form_title = _("Edit EMA")
 | 
			
		||||
 | 
			
		||||
        self.action_url = reverse("ema:edit", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("ema:open", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("ema:detail", args=(self.instance.id,))
 | 
			
		||||
 | 
			
		||||
        self.fields["identifier"].widget.attrs["url"] = reverse_lazy("ema:new-id")
 | 
			
		||||
        self.fields["title"].widget.attrs["placeholder"] = _("Compensation XY; Location ABC")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										21
									
								
								ema/managers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ema/managers.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,21 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
 | 
			
		||||
Contact: michel.peltriaux@sgdnord.rlp.de
 | 
			
		||||
Created on: 14.10.21
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.db import models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmaManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().select_related(
 | 
			
		||||
            "modified",
 | 
			
		||||
            "modified__user",
 | 
			
		||||
            "recorded",
 | 
			
		||||
            "recorded__user",
 | 
			
		||||
        )
 | 
			
		||||
@ -5,6 +5,7 @@ from django.db import models
 | 
			
		||||
from django.db.models import QuerySet
 | 
			
		||||
 | 
			
		||||
from compensation.models import AbstractCompensation
 | 
			
		||||
from ema.managers import EmaManager
 | 
			
		||||
from konova.models import AbstractDocument, generate_document_file_upload_path
 | 
			
		||||
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE, EMA_DOC_PATH
 | 
			
		||||
from user.models import UserActionLogEntry
 | 
			
		||||
@ -43,6 +44,8 @@ class Ema(AbstractCompensation):
 | 
			
		||||
        related_name="+"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = EmaManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "{}".format(self.identifier)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,7 @@ class EmaTable(BaseTable):
 | 
			
		||||
    lm = tables.Column(
 | 
			
		||||
        verbose_name=_("Last edit"),
 | 
			
		||||
        orderable=True,
 | 
			
		||||
        accessor="created__timestamp",
 | 
			
		||||
        accessor="modified__timestamp",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    class Meta(BaseTable.Meta):
 | 
			
		||||
@ -80,7 +80,7 @@ class EmaTable(BaseTable):
 | 
			
		||||
        html = ""
 | 
			
		||||
        html += self.render_link(
 | 
			
		||||
            tooltip=_("Open {}").format(_("EMA")),
 | 
			
		||||
            href=reverse("ema:open", args=(record.id,)),
 | 
			
		||||
            href=reverse("ema:detail", args=(record.id,)),
 | 
			
		||||
            txt=value,
 | 
			
		||||
            new_tab=False,
 | 
			
		||||
        )
 | 
			
		||||
@ -122,7 +122,7 @@ class EmaTable(BaseTable):
 | 
			
		||||
        """
 | 
			
		||||
        html = ""
 | 
			
		||||
        has_access = value.filter(
 | 
			
		||||
            username=self.user.username
 | 
			
		||||
            id=self.user.id
 | 
			
		||||
        ).exists()
 | 
			
		||||
 | 
			
		||||
        html += self.render_icn(
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
            LANIS
 | 
			
		||||
        </button>
 | 
			
		||||
    </a>
 | 
			
		||||
    <a href="{% url 'home' %}" class="mr-2">
 | 
			
		||||
    <a href="{% url 'ema:report' obj.id %}" target="_blank"  class="mr-2">
 | 
			
		||||
        <button class="btn btn-default" title="{% trans 'Public report' %}">
 | 
			
		||||
            {% fa5_icon 'file-alt' %}
 | 
			
		||||
        </button>
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not obj.responsible.handler %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Intervention handler' %}</th>
 | 
			
		||||
                        <th scope="row">{% trans 'Action handler' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										71
									
								
								ema/templates/ema/report/report.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								ema/templates/ema/report/report.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
{% extends 'public_base.html' %}
 | 
			
		||||
{% load i18n fontawesome_5 humanize %}
 | 
			
		||||
 | 
			
		||||
{% block body %}
 | 
			
		||||
<div class="row">
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <h3>{% trans 'Report' %}</h3>
 | 
			
		||||
        <h4>{{obj.identifier}}</h4>
 | 
			
		||||
        <div class="table-container">
 | 
			
		||||
            <table class="table table-hover">
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th class="w-25" scope="row">{% trans 'Title' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.title|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office file number' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Action handler' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Funded by' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% with obj.fundings.all as fundings %}
 | 
			
		||||
                            {% for funding in fundings %}
 | 
			
		||||
                                <div class="badge pill-badge rlp-r-outline">{{funding.short_name}}</div>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% empty %}
 | 
			
		||||
                                {% trans 'None' %}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                            {% endwith %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Last modified' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {{obj.modified.timestamp|default_if_none:""|naturalday}}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
            </table>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/states-before.html' %}
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/states-after.html' %}
 | 
			
		||||
        {% include 'compensation/detail/compensation/includes/actions.html' %}
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            {% include 'map/geom_form.html' %}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'Open in browser' %}</h4>
 | 
			
		||||
                {{ qrcode|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'View in LANIS' %}</h4>
 | 
			
		||||
                {{ qrcode_lanis|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@ -13,11 +13,12 @@ urlpatterns = [
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path("new/", new_view, name="new"),
 | 
			
		||||
    path("new/id", new_id_view, name="new-id"),
 | 
			
		||||
    path("<id>", open_view, name="open"),
 | 
			
		||||
    path("<id>", detail_view, name="detail"),
 | 
			
		||||
    path('<id>/log', log_view, name='log'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
    path('<id>/record', record_view, name='record'),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
    path('<id>/state/new', state_new_view, name='new-state'),
 | 
			
		||||
    path('<id>/action/new', action_new_view, name='new-action'),
 | 
			
		||||
    path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								ema/views.py
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								ema/views.py
									
									
									
									
									
								
							@ -16,6 +16,7 @@ from ema.models import Ema, EmaDocument
 | 
			
		||||
from konova.forms import RemoveModalForm, NewDocumentForm, SimpleGeomForm, RecordModalForm
 | 
			
		||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
 | 
			
		||||
from konova.utils.documents import get_document, remove_document
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID
 | 
			
		||||
from konova.utils.user_checks import in_group
 | 
			
		||||
 | 
			
		||||
@ -75,7 +76,7 @@ def new_view(request: HttpRequest):
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("EMA {} added").format(ema.identifier))
 | 
			
		||||
            return redirect("ema:open", id=ema.id)
 | 
			
		||||
            return redirect("ema:detail", id=ema.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -108,7 +109,7 @@ def new_id_view(request: HttpRequest):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
def open_view(request: HttpRequest, id: str):
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders the detail view of an EMA
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
@ -199,7 +200,7 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
            # The data form takes the geom form for processing, as well as the performing user
 | 
			
		||||
            ema = data_form.save(request.user, geom_form)
 | 
			
		||||
            messages.success(request, _("EMA {} edited").format(ema.identifier))
 | 
			
		||||
            return redirect("ema:open", id=ema.id)
 | 
			
		||||
            return redirect("ema:detail", id=ema.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -399,3 +400,52 @@ def action_remove_view(request: HttpRequest, id: str):
 | 
			
		||||
        id
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def report_view(request:HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # Reuse the compensation report template since EMAs are structurally identical
 | 
			
		||||
    template = "ema/report/report.html"
 | 
			
		||||
    ema = get_object_or_404(Ema, id=id)
 | 
			
		||||
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not ema.recorded:
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        return render(request, template, {})
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=ema
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img = generate_qr_code(
 | 
			
		||||
        request.build_absolute_uri(reverse("ema:report", args=(id,))),
 | 
			
		||||
        10
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(
 | 
			
		||||
        ema.get_LANIS_link(),
 | 
			
		||||
        7
 | 
			
		||||
    )
 | 
			
		||||
    # Order states by surface
 | 
			
		||||
    before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    actions = ema.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": ema,
 | 
			
		||||
        "qrcode": qrcode_img,
 | 
			
		||||
        "qrcode_lanis": qrcode_img_lanis,
 | 
			
		||||
        "has_access": False,  # disables action buttons during rendering
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
@ -269,7 +269,7 @@ class EditInterventionForm(NewInterventionForm):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        if self.instance is not None:
 | 
			
		||||
            self.action_url = reverse("intervention:edit", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("intervention:open", args=(self.instance.id,))
 | 
			
		||||
        self.cancel_redirect = reverse("intervention:detail", args=(self.instance.id,))
 | 
			
		||||
        self.form_title = _("Edit intervention")
 | 
			
		||||
        self.form_caption = ""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										48
									
								
								intervention/managers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								intervention/managers.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
 | 
			
		||||
Contact: michel.peltriaux@sgdnord.rlp.de
 | 
			
		||||
Created on: 14.10.21
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.db import models
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_queryset().select_related(
 | 
			
		||||
            "recorded",
 | 
			
		||||
            "recorded__user",
 | 
			
		||||
            "modified",
 | 
			
		||||
            "modified__user",
 | 
			
		||||
            "checked",
 | 
			
		||||
            "checked__user",
 | 
			
		||||
        ).prefetch_related(
 | 
			
		||||
            "users",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LegalDataManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_querset().select_related(
 | 
			
		||||
            "process_type",
 | 
			
		||||
        ).prefetch_related(
 | 
			
		||||
            "laws"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ResponsibilityDataManager(models.Manager):
 | 
			
		||||
    """ Holds default db fetch setting for this model type
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    def get_queryset(self):
 | 
			
		||||
        return super().get_querset().select_related(
 | 
			
		||||
            "registration_office",
 | 
			
		||||
            "conservation_office",
 | 
			
		||||
        )
 | 
			
		||||
@ -10,16 +10,15 @@ import shutil
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from django.contrib.gis.db import models
 | 
			
		||||
from django.db.models import QuerySet
 | 
			
		||||
from django.utils.timezone import localtime
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from codelist.models import KonovaCode
 | 
			
		||||
from codelist.settings import CODELIST_REGISTRATION_OFFICE_ID, CODELIST_CONSERVATION_OFFICE_ID, CODELIST_LAW_ID, \
 | 
			
		||||
    CODELIST_PROCESS_TYPE_ID
 | 
			
		||||
from intervention.managers import InterventionManager, LegalDataManager, ResponsibilityDataManager
 | 
			
		||||
from konova.models import BaseObject, Geometry, UuidModel, BaseResource, AbstractDocument, \
 | 
			
		||||
    generate_document_file_upload_path
 | 
			
		||||
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
 | 
			
		||||
from konova.sub_settings.django_settings import DEFAULT_DATE_TIME_FORMAT
 | 
			
		||||
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE, LANIS_ZOOM_LUT
 | 
			
		||||
from konova.utils import generators
 | 
			
		||||
from user.models import UserActionLogEntry
 | 
			
		||||
 | 
			
		||||
@ -57,6 +56,8 @@ class ResponsibilityData(UuidModel):
 | 
			
		||||
    conservation_file_number = models.CharField(max_length=1000, blank=True, null=True)
 | 
			
		||||
    handler = models.CharField(max_length=500, null=True, blank=True, help_text="Refers to 'Eingriffsverursacher' or 'Maßnahmenträger'")
 | 
			
		||||
 | 
			
		||||
    objects = ResponsibilityDataManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "ZB: {} | ETS: {} | Handler: {}".format(
 | 
			
		||||
            self.registration_office,
 | 
			
		||||
@ -171,6 +172,8 @@ class LegalData(UuidModel):
 | 
			
		||||
 | 
			
		||||
    revocation = models.OneToOneField(Revocation, null=True, blank=True, help_text="Refers to 'Widerspruch am'", on_delete=models.SET_NULL)
 | 
			
		||||
 | 
			
		||||
    objects = LegalDataManager()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Intervention(BaseObject):
 | 
			
		||||
    """
 | 
			
		||||
@ -221,6 +224,8 @@ class Intervention(BaseObject):
 | 
			
		||||
        help_text="Used for sharing access",
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    objects = InterventionManager()
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return "{} ({})".format(self.identifier, self.title)
 | 
			
		||||
 | 
			
		||||
@ -361,7 +366,13 @@ class Intervention(BaseObject):
 | 
			
		||||
            geom = self.geometry.geom.transform(DEFAULT_SRID_RLP, clone=True)
 | 
			
		||||
            x = geom.centroid.x
 | 
			
		||||
            y = geom.centroid.y
 | 
			
		||||
            zoom_lvl = 16
 | 
			
		||||
            area = int(geom.envelope.area)
 | 
			
		||||
            z_l = 16
 | 
			
		||||
            for k_area, v_zoom in LANIS_ZOOM_LUT.items():
 | 
			
		||||
                if k_area < area:
 | 
			
		||||
                    z_l = v_zoom
 | 
			
		||||
                    break
 | 
			
		||||
            zoom_lvl = z_l
 | 
			
		||||
        except AttributeError:
 | 
			
		||||
            # If no geometry has been added, yet.
 | 
			
		||||
            x = 1
 | 
			
		||||
@ -373,16 +384,6 @@ class Intervention(BaseObject):
 | 
			
		||||
            y,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    @property
 | 
			
		||||
    def recorded_tooltip(self):
 | 
			
		||||
        tooltip = _("Not recorded yet")
 | 
			
		||||
        if self.recorded:
 | 
			
		||||
            value = self.recorded.timestamp
 | 
			
		||||
            value = localtime(value)
 | 
			
		||||
            on = value.strftime(DEFAULT_DATE_TIME_FORMAT)
 | 
			
		||||
            tooltip = _("Recorded on {} by {}").format(on, self.recorded.user)
 | 
			
		||||
        return tooltip
 | 
			
		||||
 | 
			
		||||
    def get_documents(self) -> (QuerySet, QuerySet):
 | 
			
		||||
        """ Getter for all documents of an intervention
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -86,7 +86,7 @@ class InterventionTable(BaseTable):
 | 
			
		||||
        html = ""
 | 
			
		||||
        html += self.render_link(
 | 
			
		||||
            tooltip=_("Open {}").format(_("Intervention")),
 | 
			
		||||
            href=reverse("intervention:open", args=(record.id,)),
 | 
			
		||||
            href=reverse("intervention:detail", args=(record.id,)),
 | 
			
		||||
            txt=value,
 | 
			
		||||
            new_tab=False,
 | 
			
		||||
        )
 | 
			
		||||
@ -117,7 +117,7 @@ class InterventionTable(BaseTable):
 | 
			
		||||
        return format_html(html)
 | 
			
		||||
 | 
			
		||||
    def render_r(self, value, record: Intervention):
 | 
			
		||||
        """ Renders the registered column for an intervention
 | 
			
		||||
        """ Renders the recorded column for an intervention
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            value (str): The identifier value
 | 
			
		||||
@ -141,7 +141,7 @@ class InterventionTable(BaseTable):
 | 
			
		||||
        return format_html(html)
 | 
			
		||||
 | 
			
		||||
    def render_e(self, value, record: Intervention):
 | 
			
		||||
        """ Renders the registered column for an intervention
 | 
			
		||||
        """ Renders the editable column for an intervention
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            value (str): The identifier value
 | 
			
		||||
@ -152,7 +152,7 @@ class InterventionTable(BaseTable):
 | 
			
		||||
        """
 | 
			
		||||
        html = ""
 | 
			
		||||
        has_access = value.filter(
 | 
			
		||||
            username=self.user.username
 | 
			
		||||
            id=self.user.id
 | 
			
		||||
        ).exists()
 | 
			
		||||
 | 
			
		||||
        html += self.render_icn(
 | 
			
		||||
 | 
			
		||||
@ -1,23 +0,0 @@
 | 
			
		||||
{% load i18n fontawesome_5 %}
 | 
			
		||||
 | 
			
		||||
{% if intervention.comment %}
 | 
			
		||||
<div class="w-100">
 | 
			
		||||
    <div class="card mt-3">
 | 
			
		||||
        <div class="card-header rlp-gd">
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-sm-12 col-md-12 col-lg-12">
 | 
			
		||||
                    <h5 class="card-title">
 | 
			
		||||
                        {% fa5_icon 'info-circle' %}
 | 
			
		||||
                        {% trans 'Comment' %}
 | 
			
		||||
                    </h5>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="card-body">
 | 
			
		||||
            <div class="card-text font-italic">
 | 
			
		||||
                {{intervention.comment}}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
{% endif %}
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <div class="d-flex justify-content-end">
 | 
			
		||||
                    {% if is_default_member and has_access  %}
 | 
			
		||||
                    <a href="{% url 'compensation:new' intervention.id %}" title="{% trans 'Add new compensation' %}">
 | 
			
		||||
                    <a href="{% url 'compensation:new' obj.id %}" title="{% trans 'Add new compensation' %}">
 | 
			
		||||
                        <button class="btn btn-outline-default">
 | 
			
		||||
                            {% fa5_icon 'plus' %}
 | 
			
		||||
                            {% fa5_icon 'leaf' %}
 | 
			
		||||
@ -32,16 +32,18 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Title' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% for comp in compensations %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    <a href="{% url 'compensation:open' comp.id %}">
 | 
			
		||||
                    <a href="{% url 'compensation:detail' comp.id %}">
 | 
			
		||||
                        {{ comp.identifier }}
 | 
			
		||||
                    </a>
 | 
			
		||||
                </td>
 | 
			
		||||
 | 
			
		||||
@ -6,41 +6,41 @@
 | 
			
		||||
            LANIS
 | 
			
		||||
        </button>
 | 
			
		||||
    </a>
 | 
			
		||||
    <a href="{% url 'home' %}" class="mr-2">
 | 
			
		||||
    <a href="{% url 'intervention:report' obj.id %}" target="_blank"  class="mr-2" target="_blank">
 | 
			
		||||
        <button class="btn btn-default" title="{% trans 'Public report' %}">
 | 
			
		||||
            {% fa5_icon 'file-alt' %}
 | 
			
		||||
        </button>
 | 
			
		||||
    </a>
 | 
			
		||||
    {% if has_access %}
 | 
			
		||||
        <button class="btn btn-default btn-modal mr-2" title="{% trans 'Share' %}" data-form-url="{% url 'intervention:share-create' intervention.id %}">
 | 
			
		||||
        <button class="btn btn-default btn-modal mr-2" title="{% trans 'Share' %}" data-form-url="{% url 'intervention:share-create' obj.id %}">
 | 
			
		||||
            {% fa5_icon 'share-alt' %}
 | 
			
		||||
        </button>
 | 
			
		||||
        {% if is_zb_member %}
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" title="{% trans 'Run check' %}" data-form-url="{% url 'intervention:run-check' intervention.id %}">
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" title="{% trans 'Run check' %}" data-form-url="{% url 'intervention:run-check' obj.id %}">
 | 
			
		||||
                {% fa5_icon 'star' %}
 | 
			
		||||
            </button>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% if is_ets_member %}
 | 
			
		||||
            {% if intervention.recorded %}
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" title="{% trans 'Unrecord' %}" data-form-url="{% url 'intervention:record' intervention.id %}">
 | 
			
		||||
            {% if obj.recorded %}
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" title="{% trans 'Unrecord' %}" data-form-url="{% url 'intervention:record' obj.id %}">
 | 
			
		||||
                {% fa5_icon 'bookmark' 'far' %}
 | 
			
		||||
            </button>
 | 
			
		||||
            {% else %}
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" title="{% trans 'Record' %}" data-form-url="{% url 'intervention:record' intervention.id %}">
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" title="{% trans 'Record' %}" data-form-url="{% url 'intervention:record' obj.id %}">
 | 
			
		||||
                {% fa5_icon 'bookmark' %}
 | 
			
		||||
            </button>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        {% endif %}
 | 
			
		||||
        {% if is_default_member %}
 | 
			
		||||
            <a href="{% url 'intervention:edit' intervention.id %}" class="mr-2">
 | 
			
		||||
            <a href="{% url 'intervention:edit' obj.id %}" class="mr-2">
 | 
			
		||||
                <button class="btn btn-default" title="{% trans 'Edit' %}">
 | 
			
		||||
                    {% fa5_icon 'edit' %}
 | 
			
		||||
                </button>
 | 
			
		||||
            </a>
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" data-form-url="{% url 'intervention:log' intervention.id %}" title="{% trans 'Show log' %}">
 | 
			
		||||
            <button class="btn btn-default btn-modal mr-2" data-form-url="{% url 'intervention:log' obj.id %}" title="{% trans 'Show log' %}">
 | 
			
		||||
                {% fa5_icon 'history' %}
 | 
			
		||||
            </button>
 | 
			
		||||
            <button class="btn btn-default btn-modal" data-form-url="{% url 'intervention:remove' intervention.id %}" title="{% trans 'Delete' %}">
 | 
			
		||||
            <button class="btn btn-default btn-modal" data-form-url="{% url 'intervention:remove' obj.id %}" title="{% trans 'Delete' %}">
 | 
			
		||||
                {% fa5_icon 'trash' %}
 | 
			
		||||
            </button>
 | 
			
		||||
        {% endif %}
 | 
			
		||||
 | 
			
		||||
@ -4,14 +4,14 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{intervention.deductions.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.deductions.count}}</span>
 | 
			
		||||
                    {% trans 'Eco Account Deductions' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <div class="d-flex justify-content-end">
 | 
			
		||||
                    {% if is_default_member and has_access  %}
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:acc-new-deduction' intervention.id %}" title="{% trans 'Add new deduction' %}">
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:acc-new-deduction' obj.id %}" title="{% trans 'Add new deduction' %}">
 | 
			
		||||
                        {% fa5_icon 'plus' %}
 | 
			
		||||
                        {% fa5_icon 'tree' %}
 | 
			
		||||
                    </button>
 | 
			
		||||
@ -33,16 +33,18 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Created' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% for deduction in intervention.deductions.all %}
 | 
			
		||||
            {% for deduction in obj.deductions.all %}
 | 
			
		||||
            <tr {% if deduction.account.deleted %}class="align-middle alert-danger" title="{% trans 'Eco-account deleted! Deduction invalid!' %}" {% elif not deduction.account.recorded %}class="align-middle alert-danger" title="{% trans 'Eco-account not recorded! Deduction invalid!' %}"  {% endif %}>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    <a href="{% url 'compensation:acc-open' deduction.account.id %}">
 | 
			
		||||
                    <a href="{% url 'compensation:acc-detail' deduction.account.id %}">
 | 
			
		||||
                        {% if deduction.account.deleted or not deduction.account.recorded %}
 | 
			
		||||
                        {% fa5_icon 'exclamation-triangle' %}
 | 
			
		||||
                        {% endif %}
 | 
			
		||||
 | 
			
		||||
@ -4,14 +4,14 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{intervention.documents.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.documents.count}}</span>
 | 
			
		||||
                    {% trans 'Documents' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <div class="d-flex justify-content-end">
 | 
			
		||||
                    {% if is_default_member and has_access  %}
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-doc' intervention.id %}" title="{% trans 'Add new document' %}">
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-doc' obj.id %}" title="{% trans 'Add new document' %}">
 | 
			
		||||
                        {% fa5_icon 'plus' %}
 | 
			
		||||
                        {% fa5_icon 'file' %}
 | 
			
		||||
                    </button>
 | 
			
		||||
@ -30,13 +30,15 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% for doc in intervention.documents.all %}
 | 
			
		||||
            {% for doc in obj.documents.all %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    <a href="{% url 'intervention:get-doc' doc.id %}">
 | 
			
		||||
 | 
			
		||||
@ -4,14 +4,14 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{{intervention.payments.count}}</span>
 | 
			
		||||
                    <span class="badge badge-light">{{obj.payments.count}}</span>
 | 
			
		||||
                    {% trans 'Payments' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <div class="d-flex justify-content-end">
 | 
			
		||||
                    {% if is_default_member and has_access  %}
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:pay-new' intervention.id %}" title="{% trans 'Add new payment' %}">
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:pay-new' obj.id %}" title="{% trans 'Add new payment' %}">
 | 
			
		||||
                        {% fa5_icon 'plus' %}
 | 
			
		||||
                        {% fa5_icon 'money-bill-wave' %}
 | 
			
		||||
                    </button>
 | 
			
		||||
@ -33,13 +33,15 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% for pay in intervention.payments.all %}
 | 
			
		||||
            {% for pay in obj.payments.all %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    {{ pay.amount|floatformat:2 }} €
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6">
 | 
			
		||||
                <h5>
 | 
			
		||||
                    <span class="badge badge-light">{% if intervention.legal.revocation %}1{% else %}0{% endif %}</span>
 | 
			
		||||
                    <span class="badge badge-light">{% if obj.legal.revocation %}1{% else %}0{% endif %}</span>
 | 
			
		||||
                    {% trans 'Revocation' %}
 | 
			
		||||
                </h5>
 | 
			
		||||
            </div>
 | 
			
		||||
@ -13,8 +13,8 @@
 | 
			
		||||
                    {% comment %}
 | 
			
		||||
                        Only show add-button if no revocation exists, yet.
 | 
			
		||||
                    {% endcomment %}
 | 
			
		||||
                    {% if is_default_member and has_access and not intervention.legal.revocation %}
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-revocation' intervention.id %}" title="{% trans 'Add revocation' %}">
 | 
			
		||||
                    {% if is_default_member and has_access and not obj.legal.revocation %}
 | 
			
		||||
                    <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-revocation' obj.id %}" title="{% trans 'Add revocation' %}">
 | 
			
		||||
                        {% fa5_icon 'plus' %}
 | 
			
		||||
                        {% fa5_icon 'ban' %}
 | 
			
		||||
                    </button>
 | 
			
		||||
@ -36,14 +36,16 @@
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Comment' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                <th scope="col">
 | 
			
		||||
                    {% trans 'Action' %}
 | 
			
		||||
                </th>
 | 
			
		||||
                {% if is_default_member and has_access %}
 | 
			
		||||
                    <th scope="col">
 | 
			
		||||
                        {% trans 'Action' %}
 | 
			
		||||
                    </th>
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            </tr>
 | 
			
		||||
            </thead>
 | 
			
		||||
            <tbody>
 | 
			
		||||
            {% if intervention.legal.revocation %}
 | 
			
		||||
            {% with intervention.legal.revocation as rev %}
 | 
			
		||||
            {% if obj.legal.revocation %}
 | 
			
		||||
            {% with obj.legal.revocation as rev %}
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td class="align-middle">
 | 
			
		||||
                    {{ rev.date }}
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
 | 
			
		||||
    <div id="detail-header" class="row">
 | 
			
		||||
        <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
            <h3>{% trans 'Intervention' %}<br> {{intervention.identifier}}</h3>
 | 
			
		||||
            <h3>{% trans 'Intervention' %}<br> {{obj.identifier}}</h3>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
            {% include 'intervention/detail/includes/controls.html' %}
 | 
			
		||||
@ -26,52 +26,52 @@
 | 
			
		||||
        <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
            <div class="table-container">
 | 
			
		||||
                <table class="table table-hover">
 | 
			
		||||
                    <tr {% if not intervention.title %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.title %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th class="w-25" scope="row">{% trans 'Title' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.title|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.title|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.legal.process_type %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.legal.process_type %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Process type' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.legal.process_type|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.process_type|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if intervention.legal.laws.count == 0 %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if obj.legal.laws.count == 0 %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Law' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% for law in intervention.legal.laws.all %}
 | 
			
		||||
                            {% for law in obj.legal.laws.all %}
 | 
			
		||||
                                <div class="badge pill-badge rlp-r-outline">{{law.short_name}} - {{law.long_name}}</div>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.responsible.registration_office %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.responsible.registration_office %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Registration office' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.responsible.registration_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.registration_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.responsible.registration_file_number %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.responsible.registration_file_number %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Registration office file number' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.responsible.registration_file_number|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.registration_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.responsible.conservation_office %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.responsible.conservation_office %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.responsible.conservation_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.responsible.conservation_file_number %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.responsible.conservation_file_number %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office file number' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.responsible.handler %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.responsible.handler %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Intervention handler' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Checked' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% if intervention.checked is None %}
 | 
			
		||||
                            {% if obj.checked is None %}
 | 
			
		||||
                                <span>
 | 
			
		||||
                                    {% fa5_icon 'star' 'far' %}
 | 
			
		||||
                                </span>
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                                <span class="check-star" title="{% trans 'Checked on '%} {{intervention.checked.timestamp}} {% trans 'by' %} {{intervention.checked.user}}">
 | 
			
		||||
                                <span class="check-star" title="{% trans 'Checked on '%} {{obj.checked.timestamp}} {% trans 'by' %} {{obj.checked.user}}">
 | 
			
		||||
                                    {% fa5_icon 'star' %}
 | 
			
		||||
                                </span>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
@ -80,41 +80,41 @@
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Recorded' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% if intervention.recorded is None %}
 | 
			
		||||
                            {% if obj.recorded is None %}
 | 
			
		||||
                                <span title="{% trans 'Not recorded yet' %}">
 | 
			
		||||
                                    {% fa5_icon 'bookmark' 'far' %}
 | 
			
		||||
                                </span>
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                                <span class="registered-bookmark" title="{% trans 'Recorded on '%} {{intervention.recorded.timestamp}} {% trans 'by' %} {{intervention.recorded.user}}">
 | 
			
		||||
                                <span class="registered-bookmark" title="{% trans 'Recorded on '%} {{obj.recorded.timestamp}} {% trans 'by' %} {{obj.recorded.user}}">
 | 
			
		||||
                                    {% fa5_icon 'bookmark' %}
 | 
			
		||||
                                </span>
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.legal.registration_date %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.legal.registration_date %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Registration date' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.legal.registration_date|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.registration_date|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if not intervention.legal.binding_date %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if not obj.legal.binding_date %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Binding on' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.legal.binding_date|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.binding_date|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr {% if intervention.legal.revocation %}class="alert alert-danger" title="{% trans 'Exists' %}" {% endif %}>
 | 
			
		||||
                    <tr {% if obj.legal.revocation %}class="alert alert-danger" title="{% trans 'Exists' %}" {% endif %}>
 | 
			
		||||
                        <th scope="row">{% trans 'Revocation' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{intervention.legal.revocation.date|naturalday|default_if_none:""}}</td>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.revocation.date|naturalday|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Last modified' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {{intervention.created.timestamp|default_if_none:""|naturalday}}
 | 
			
		||||
                            {{obj.created.timestamp|default_if_none:""|naturalday}}
 | 
			
		||||
                            <br>
 | 
			
		||||
                            {{intervention.created.user.username}}
 | 
			
		||||
                            {{obj.created.user.username}}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Shared with' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% for user in intervention.users.all %}
 | 
			
		||||
                            {% for user in obj.users.all %}
 | 
			
		||||
                                {% include 'user/includes/contact_modal_button.html' %}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </td>
 | 
			
		||||
@ -127,7 +127,7 @@
 | 
			
		||||
                {% include 'map/geom_form.html' %}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                {% include 'intervention/detail/includes/comment.html' %}
 | 
			
		||||
                {% include 'konova/comment_card.html' %}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										117
									
								
								intervention/templates/intervention/report/report.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								intervention/templates/intervention/report/report.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,117 @@
 | 
			
		||||
{% extends 'public_base.html' %}
 | 
			
		||||
{% load i18n fontawesome_5 humanize %}
 | 
			
		||||
 | 
			
		||||
{% block body %}
 | 
			
		||||
<div class="row">
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <h3>{% trans 'Report' %}</h3>
 | 
			
		||||
        <h4>{{obj.identifier}}</h4>
 | 
			
		||||
        <div class="table-container">
 | 
			
		||||
            <table class="table table-hover">
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th class="w-25" scope="row">{% trans 'Title' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.title|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Process type' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.process_type|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Law' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% for law in obj.legal.laws.all %}
 | 
			
		||||
                                <div class="badge pill-badge rlp-r-outline">{{law.short_name}} - {{law.long_name}}</div>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Registration office' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.registration_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Registration office file number' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.registration_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_office.str_as_office|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Conservation office file number' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.conservation_file_number|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Intervention handler' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.responsible.handler|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Compensations' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% for comp in obj.compensations.all %}
 | 
			
		||||
                                <a href="{% url 'compensation:report' comp.id %}">
 | 
			
		||||
                                    {{comp.identifier}}
 | 
			
		||||
                                </a>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% empty %}
 | 
			
		||||
                            {% trans 'None' %}
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Deductions of eco-accounts' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% for deduction in deductions %}
 | 
			
		||||
                                <a href="{% url 'compensation:acc-report' deduction.account.id %}">
 | 
			
		||||
                                    {{deduction.account.identifier}}
 | 
			
		||||
                                </a>
 | 
			
		||||
                                <br>
 | 
			
		||||
                            {% endfor %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Payments' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {% if obj.payments.all %}
 | 
			
		||||
                                {% trans 'Exist' %}
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                                {% trans 'None' %}
 | 
			
		||||
                            {% endif %}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Registration date' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.registration_date|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Binding on' %}</th>
 | 
			
		||||
                        <td class="align-middle">{{obj.legal.binding_date|default_if_none:""}}</td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                        <th scope="row">{% trans 'Last modified' %}</th>
 | 
			
		||||
                        <td class="align-middle">
 | 
			
		||||
                            {{obj.created.timestamp|default_if_none:""|naturalday}}
 | 
			
		||||
                        </td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
            </table>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="col-sm-12 col-md-12 col-lg-6">
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            {% include 'map/geom_form.html' %}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="row">
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'Open in browser' %}</h4>
 | 
			
		||||
                {{ qrcode|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="col-sm-6 col-md-6 col-lg-6">
 | 
			
		||||
                <h4>{% trans 'View in LANIS' %}</h4>
 | 
			
		||||
                {{ qrcode_lanis|safe }}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@ -7,16 +7,16 @@ Created on: 30.11.20
 | 
			
		||||
"""
 | 
			
		||||
from django.urls import path
 | 
			
		||||
 | 
			
		||||
from intervention.views import index_view, new_view, open_view, edit_view, remove_view, new_document_view, share_view, \
 | 
			
		||||
from intervention.views import index_view, new_view, detail_view, edit_view, remove_view, new_document_view, share_view, \
 | 
			
		||||
    create_share_view, remove_revocation_view, new_revocation_view, run_check_view, log_view, new_deduction_view, \
 | 
			
		||||
    record_view, remove_document_view, get_document_view, get_revocation_view, new_id_view
 | 
			
		||||
    record_view, remove_document_view, get_document_view, get_revocation_view, new_id_view, report_view
 | 
			
		||||
 | 
			
		||||
app_name = "intervention"
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path('new/', new_view, name='new'),
 | 
			
		||||
    path('new/id', new_id_view, name='new-id'),
 | 
			
		||||
    path('<id>', open_view, name='open'),
 | 
			
		||||
    path('<id>', detail_view, name='detail'),
 | 
			
		||||
    path('<id>/log', log_view, name='log'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
@ -24,6 +24,7 @@ urlpatterns = [
 | 
			
		||||
    path('<id>/share', create_share_view, name='share-create'),
 | 
			
		||||
    path('<id>/check', run_check_view, name='run-check'),
 | 
			
		||||
    path('<id>/record', record_view, name='record'),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
 | 
			
		||||
    # Documents
 | 
			
		||||
    path('<id>/document/new/', new_document_view, name='new-doc'),
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django.http import HttpRequest, JsonResponse
 | 
			
		||||
from django.shortcuts import render, get_object_or_404
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
 | 
			
		||||
from intervention.forms.forms import NewInterventionForm, EditInterventionForm
 | 
			
		||||
from intervention.forms.modalForms import ShareInterventionModalForm, NewRevocationModalForm, \
 | 
			
		||||
@ -13,6 +13,7 @@ from konova.decorators import *
 | 
			
		||||
from konova.forms import SimpleGeomForm, NewDocumentForm, RemoveModalForm, RecordModalForm
 | 
			
		||||
from konova.sub_settings.django_settings import DEFAULT_DATE_FORMAT
 | 
			
		||||
from konova.utils.documents import remove_document, get_document
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.utils.message_templates import INTERVENTION_INVALID, FORM_INVALID, IDENTIFIER_REPLACED
 | 
			
		||||
from konova.utils.user_checks import in_group
 | 
			
		||||
 | 
			
		||||
@ -34,6 +35,8 @@ def index_view(request: HttpRequest):
 | 
			
		||||
    # Filtering by user access is performed in table filter inside of InterventionTableFilter class
 | 
			
		||||
    interventions = Intervention.objects.filter(
 | 
			
		||||
        deleted=None,  # not deleted
 | 
			
		||||
    ).select_related(
 | 
			
		||||
        "legal"
 | 
			
		||||
    )
 | 
			
		||||
    table = InterventionTable(
 | 
			
		||||
        request=request,
 | 
			
		||||
@ -74,7 +77,7 @@ def new_view(request: HttpRequest):
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("Intervention {} added").format(intervention.identifier))
 | 
			
		||||
            return redirect("intervention:open", id=intervention.id)
 | 
			
		||||
            return redirect("intervention:detail", id=intervention.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -180,7 +183,7 @@ def remove_document_view(request: HttpRequest, doc_id: str):
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def open_view(request: HttpRequest, id: str):
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a detail view for viewing an intervention's data
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
@ -193,7 +196,14 @@ def open_view(request: HttpRequest, id: str):
 | 
			
		||||
    template = "intervention/detail/view.html"
 | 
			
		||||
 | 
			
		||||
    # Fetch data, filter out deleted related data
 | 
			
		||||
    intervention = get_object_or_404(Intervention, id=id)
 | 
			
		||||
    intervention = get_object_or_404(
 | 
			
		||||
        Intervention.objects.select_related(
 | 
			
		||||
            "geometry",
 | 
			
		||||
            "legal",
 | 
			
		||||
            "responsible",
 | 
			
		||||
        ),
 | 
			
		||||
        id=id
 | 
			
		||||
    )
 | 
			
		||||
    compensations = intervention.compensations.filter(
 | 
			
		||||
        deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
@ -213,7 +223,7 @@ def open_view(request: HttpRequest, id: str):
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "intervention": intervention,
 | 
			
		||||
        "obj": intervention,
 | 
			
		||||
        "compensations": compensations,
 | 
			
		||||
        "has_access": is_data_shared,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
@ -252,7 +262,7 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
            # The data form takes the geom form for processing, as well as the performing user
 | 
			
		||||
            intervention = data_form.save(request.user, geom_form)
 | 
			
		||||
            messages.success(request, _("Intervention {} edited").format(intervention.identifier))
 | 
			
		||||
            return redirect("intervention:open", id=intervention.id)
 | 
			
		||||
            return redirect("intervention:detail", id=intervention.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID)
 | 
			
		||||
    else:
 | 
			
		||||
@ -338,7 +348,7 @@ def share_view(request: HttpRequest, id: str, token: str):
 | 
			
		||||
                _("{} has been shared with you").format(intervention.identifier)
 | 
			
		||||
            )
 | 
			
		||||
            intervention.users.add(user)
 | 
			
		||||
        return redirect("intervention:open", id=id)
 | 
			
		||||
        return redirect("intervention:detail", id=id)
 | 
			
		||||
    else:
 | 
			
		||||
        messages.error(
 | 
			
		||||
            request,
 | 
			
		||||
@ -470,4 +480,49 @@ def record_view(request: HttpRequest, id: str):
 | 
			
		||||
        request,
 | 
			
		||||
        msg_succ,
 | 
			
		||||
        msg_error=_("There are errors on this intervention:")
 | 
			
		||||
    )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def report_view(request:HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "intervention/report/report.html"
 | 
			
		||||
    intervention = get_object_or_404(Intervention, id=id)
 | 
			
		||||
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not intervention.recorded:
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        return render(request, template, {})
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=intervention
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    distinct_deductions = intervention.deductions.all().distinct(
 | 
			
		||||
        "account"
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img = generate_qr_code(
 | 
			
		||||
        request.build_absolute_uri(reverse("intervention:report", args=(id,))),
 | 
			
		||||
        10
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(
 | 
			
		||||
        intervention.get_LANIS_link(),
 | 
			
		||||
        7
 | 
			
		||||
    )
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": intervention,
 | 
			
		||||
        "deductions": distinct_deductions,
 | 
			
		||||
        "qrcode": qrcode_img,
 | 
			
		||||
        "qrcode_lanis": qrcode_img_lanis,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@ Created on: 16.11.20
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
 | 
			
		||||
from konova.sub_settings.context_settings import BASE_TITLE, HELP_LINK, BASE_FRONTEND_TITLE
 | 
			
		||||
from konova.sub_settings.django_settings import LANGUAGE_CODE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseContext:
 | 
			
		||||
@ -17,7 +18,7 @@ class BaseContext:
 | 
			
		||||
    context = {
 | 
			
		||||
        "base_title": BASE_TITLE,
 | 
			
		||||
        "base_frontend_title": BASE_FRONTEND_TITLE,
 | 
			
		||||
        "language": "en",
 | 
			
		||||
        "language": LANGUAGE_CODE,
 | 
			
		||||
        "user": None,
 | 
			
		||||
        "current_role": None,
 | 
			
		||||
        "help_link": HELP_LINK,
 | 
			
		||||
 | 
			
		||||
@ -149,7 +149,7 @@ class BaseObject(BaseResource):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        if hasattr(self, "users"):
 | 
			
		||||
            return self.users.filter(username=user.username).exists()
 | 
			
		||||
            return self.users.filter(id=user.id)
 | 
			
		||||
        else:
 | 
			
		||||
            return User.objects.none()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -69,3 +69,14 @@ ETS_GROUP = "Conservation office"
 | 
			
		||||
# Needed to redirect to LANIS
 | 
			
		||||
## Values to be inserted are [zoom_level, x_coord, y_coord]
 | 
			
		||||
LANIS_LINK_TEMPLATE = "https://geodaten.naturschutz.rlp.de/kartendienste_naturschutz/index.php?lang=de&zl={}&x={}&y={}&bl=tk_rlp_tms_grau&bo=1&lo=0.8,0.8,0.8,0.6,0.8,0.8,0.8,0.8,0.8&layers=eiv_f,eiv_l,eiv_p,kom_f,kom_l,kom_p,oek_f,ema_f,mae&service=kartendienste_naturschutz"
 | 
			
		||||
## This look up table (LUT) defines different zoom levels on the size of the calculate area of a geometry.
 | 
			
		||||
LANIS_ZOOM_LUT = {
 | 
			
		||||
    1000000000: 6,
 | 
			
		||||
    100000000: 10,
 | 
			
		||||
    10000000: 17,
 | 
			
		||||
    1000000: 20,
 | 
			
		||||
    100000: 25,
 | 
			
		||||
    10000: 28,
 | 
			
		||||
    1000: 30,
 | 
			
		||||
    500: 31,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@ For the full list of settings and their values, see
 | 
			
		||||
https://docs.djangoproject.com/en/3.1/ref/settings/
 | 
			
		||||
"""
 | 
			
		||||
import os
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
 | 
			
		||||
BASE_DIR = os.path.dirname(
 | 
			
		||||
@ -78,12 +78,12 @@ if DEBUG:
 | 
			
		||||
MIDDLEWARE = [
 | 
			
		||||
    'django.middleware.security.SecurityMiddleware',
 | 
			
		||||
    'django.contrib.sessions.middleware.SessionMiddleware',
 | 
			
		||||
    "django.middleware.locale.LocaleMiddleware",
 | 
			
		||||
    'django.middleware.common.CommonMiddleware',
 | 
			
		||||
    'django.middleware.csrf.CsrfViewMiddleware',
 | 
			
		||||
    'django.contrib.auth.middleware.AuthenticationMiddleware',
 | 
			
		||||
    'django.contrib.messages.middleware.MessageMiddleware',
 | 
			
		||||
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
 | 
			
		||||
    "django.middleware.locale.LocaleMiddleware",
 | 
			
		||||
]
 | 
			
		||||
if DEBUG:
 | 
			
		||||
    MIDDLEWARE += [
 | 
			
		||||
@ -149,6 +149,10 @@ AUTH_PASSWORD_VALIDATORS = [
 | 
			
		||||
# https://docs.djangoproject.com/en/3.1/topics/i18n/
 | 
			
		||||
 | 
			
		||||
LANGUAGE_CODE = 'de'
 | 
			
		||||
LANGUAGES = [
 | 
			
		||||
    ('de', _('German')),
 | 
			
		||||
    ('en', _('English')),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
USE_THOUSAND_SEPARATOR = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,10 @@
 | 
			
		||||
{% load i18n fontawesome_5 %}
 | 
			
		||||
 | 
			
		||||
{% comment %}
 | 
			
		||||
    Used in e.g. reports and detail views for every model which supports comment field (BaseObject derived)
 | 
			
		||||
{% endcomment %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% if obj.comment %}
 | 
			
		||||
<div class="w-100">
 | 
			
		||||
    <div class="card mt-3">
 | 
			
		||||
@ -7,6 +7,10 @@ Created on: 09.11.20
 | 
			
		||||
"""
 | 
			
		||||
import random
 | 
			
		||||
import string
 | 
			
		||||
import qrcode
 | 
			
		||||
import qrcode.image.svg
 | 
			
		||||
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_random_string(length: int, use_numbers: bool = False, use_letters_lc: bool = False, use_letters_uc: bool = False) -> str:
 | 
			
		||||
@ -24,3 +28,24 @@ def generate_random_string(length: int, use_numbers: bool = False, use_letters_l
 | 
			
		||||
    elements = "".join(elements)
 | 
			
		||||
    ret_val = "".join(random.choice(elements) for i in range(length))
 | 
			
		||||
    return ret_val
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_qr_code(content: str, size: int = 20) -> str:
 | 
			
		||||
    """ Generates a qr code from given content
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        content (str): The content for the qr code
 | 
			
		||||
        size (int): The image size
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        qrcode_svg (str): The qr code as svg
 | 
			
		||||
    """
 | 
			
		||||
    qrcode_factory = qrcode.image.svg.SvgImage
 | 
			
		||||
    qrcode_img = qrcode.make(
 | 
			
		||||
        content,
 | 
			
		||||
        image_factory=qrcode_factory,
 | 
			
		||||
        box_size=size
 | 
			
		||||
    )
 | 
			
		||||
    stream = BytesIO()
 | 
			
		||||
    qrcode_img.save(stream)
 | 
			
		||||
    return stream.getvalue().decode()
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -20,7 +20,7 @@
 | 
			
		||||
<body>
 | 
			
		||||
    <header>
 | 
			
		||||
        {% block header %}
 | 
			
		||||
            {% include 'navbar.html' %}
 | 
			
		||||
            {% include 'navbars/navbar.html' %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </header>
 | 
			
		||||
    <div class="container-fluid mt-3 px-5">
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8
									
								
								templates/navbars/public_navbar.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								templates/navbars/public_navbar.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
 | 
			
		||||
<nav class="navbar navbar-expand-lg navbar-dark">
 | 
			
		||||
    <a href="{% url 'home' %}">
 | 
			
		||||
        <div class="nav-icon badge">
 | 
			
		||||
            <strong>KSP</strong>
 | 
			
		||||
        </div>
 | 
			
		||||
    </a>
 | 
			
		||||
</nav>
 | 
			
		||||
							
								
								
									
										44
									
								
								templates/public_base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								templates/public_base.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
{% load static i18n l10n fontawesome_5 bootstrap4 %}
 | 
			
		||||
<html lang="{{ language }}">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1">
 | 
			
		||||
    <title>{{ base_frontend_title }}</title>
 | 
			
		||||
    <link rel="icon" type="image/ico" href="{% static 'images/ksp-favicon.ico' %}">
 | 
			
		||||
    {% bootstrap_css %}
 | 
			
		||||
    {% bootstrap_javascript jquery='full' %}
 | 
			
		||||
    {% fontawesome_5_static %}
 | 
			
		||||
    <link rel="stylesheet" href="{% static 'css/konova.css' %}">
 | 
			
		||||
 | 
			
		||||
    {% block head %}
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
    <header>
 | 
			
		||||
        {% block header %}
 | 
			
		||||
            {% include 'navbars/public_navbar.html' %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </header>
 | 
			
		||||
    <div class="container-fluid mt-3 px-5">
 | 
			
		||||
        <div class="">
 | 
			
		||||
        {% for message in messages %}
 | 
			
		||||
            <div class="row alert alert-{{ message.tags }}">
 | 
			
		||||
                {{ message }}
 | 
			
		||||
            </div>
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        {% block body %}
 | 
			
		||||
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    {% block footer %}
 | 
			
		||||
 | 
			
		||||
    {% endblock %}
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										14
									
								
								templates/report/unavailable.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								templates/report/unavailable.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
{% extends 'public_base.html' %}
 | 
			
		||||
{% load i18n %}
 | 
			
		||||
 | 
			
		||||
{% block body %}
 | 
			
		||||
    <div class="jumbotron">
 | 
			
		||||
        <h1 class="display-4">{% trans 'Unrecorded data' %}</h1>
 | 
			
		||||
        <hr>
 | 
			
		||||
        <p class="lead">
 | 
			
		||||
            {% blocktrans %}
 | 
			
		||||
            The data you want to see is not recorded and might still be work in progress. Please come back another time.
 | 
			
		||||
            {% endblocktrans %}
 | 
			
		||||
        </p>
 | 
			
		||||
    </div>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user