Merge pull request '86_User_suggestions_and_feedback' (#106) from 86_User_suggestions_and_feedback into master

Reviewed-on: SGD-Nord/konova#106
pull/109/head
mpeltriaux 3 years ago
commit b453256916

@ -3,11 +3,11 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Evaluation report' %} {{office.long_name}}</h3> <h3>{% trans 'Evaluation report' %} {{office.long_name}}</h3>
<h5>{% trans 'From' %} {{report.date_from.date}} {% trans 'to' %} {{report.date_to.date}}</h5> <h5>{% trans 'From' %} {{report.date_from.date}} {% trans 'to' %} {{report.date_to.date}}</h5>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
<div class="dropdown"> <div class="dropdown">
<div class="btn btn" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> <div class="btn btn" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">

@ -3,6 +3,8 @@ from django.contrib import admin
from compensation.models import Compensation, CompensationAction, CompensationState, Payment, \ from compensation.models import Compensation, CompensationAction, CompensationState, Payment, \
EcoAccountDeduction, EcoAccount EcoAccountDeduction, EcoAccount
from konova.admin import BaseObjectAdmin, BaseResourceAdmin from konova.admin import BaseObjectAdmin, BaseResourceAdmin
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE
from user.models import UserAction
class AbstractCompensationAdmin(BaseObjectAdmin): class AbstractCompensationAdmin(BaseObjectAdmin):
@ -42,6 +44,17 @@ class CompensationAdmin(AbstractCompensationAdmin):
"intervention", "intervention",
] ]
def restore_deleted_data(self, request, queryset):
super().restore_deleted_data(request, queryset)
for entry in queryset:
# Remove delete log entry from related intervention log history
logs = entry.intervention.log.filter(
action=UserAction.EDITED,
comment=COMPENSATION_REMOVED_TEMPLATE.format(entry.identifier)
)
logs.delete()
class EcoAccountAdmin(AbstractCompensationAdmin): class EcoAccountAdmin(AbstractCompensationAdmin):
list_display = [ list_display = [

@ -18,7 +18,7 @@ from compensation.models import Compensation, EcoAccount
from intervention.inputs import GenerateInput from intervention.inputs import GenerateInput
from intervention.models import Intervention, Responsibility, Legal from intervention.models import Intervention, Responsibility, Legal
from konova.forms import BaseForm, SimpleGeomForm from konova.forms import BaseForm, SimpleGeomForm
from konova.utils.message_templates import EDITED_GENERAL_DATA from konova.utils.message_templates import EDITED_GENERAL_DATA, COMPENSATION_ADDED_TEMPLATE
from user.models import UserActionLogEntry from user.models import UserActionLogEntry
@ -200,35 +200,49 @@ class NewCompensationForm(AbstractCompensationForm, CEFCompensationFormMixin, Co
self.initialize_form_field("identifier", identifier) self.initialize_form_field("identifier", identifier)
self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:new-id") self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:new-id")
def save(self, user: User, geom_form: SimpleGeomForm): def __create_comp(self, user, geom_form) -> Compensation:
with transaction.atomic(): """ Creates the compensation from form data
# Fetch data from cleaned POST values
identifier = self.cleaned_data.get("identifier", None) Args:
title = self.cleaned_data.get("title", None) user (User): The performing user
intervention = self.cleaned_data.get("intervention", None) geom_form (SimpleGeomForm): The geometry form
is_cef = self.cleaned_data.get("is_cef", None)
is_coherence_keeping = self.cleaned_data.get("is_coherence_keeping", None) Returns:
comment = self.cleaned_data.get("comment", None) comp (Compensation): The compensation object
"""
# Create log entry # Fetch data from cleaned POST values
action = UserActionLogEntry.get_created_action(user) identifier = self.cleaned_data.get("identifier", None)
# Process the geometry form title = self.cleaned_data.get("title", None)
geometry = geom_form.save(action) intervention = self.cleaned_data.get("intervention", None)
is_cef = self.cleaned_data.get("is_cef", None)
is_coherence_keeping = self.cleaned_data.get("is_coherence_keeping", None)
comment = self.cleaned_data.get("comment", None)
# Create log entry
action = UserActionLogEntry.get_created_action(user)
# Process the geometry form
geometry = geom_form.save(action)
# Finally create main object
comp = Compensation.objects.create(
identifier=identifier,
title=title,
intervention=intervention,
created=action,
is_cef=is_cef,
is_coherence_keeping=is_coherence_keeping,
geometry=geometry,
comment=comment,
)
# Finally create main object # Add the log entry to the main objects log list
comp = Compensation.objects.create( comp.log.add(action)
identifier=identifier, return comp
title=title,
intervention=intervention,
created=action,
is_cef=is_cef,
is_coherence_keeping=is_coherence_keeping,
geometry=geometry,
comment=comment,
)
# Add the log entry to the main objects log list def save(self, user: User, geom_form: SimpleGeomForm):
comp.log.add(action) with transaction.atomic():
comp = self.__create_comp(user, geom_form)
comp.intervention.mark_as_edited(user, edit_comment=COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
return comp return comp
@ -339,13 +353,13 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.form_title = _("New Eco-Account") self.form_title = _("New Eco-Account")
self.action_url = reverse("compensation:acc-new") self.action_url = reverse("compensation:acc:new")
self.cancel_redirect = reverse("compensation:acc-index") self.cancel_redirect = reverse("compensation:acc:index")
tmp = EcoAccount() tmp = EcoAccount()
identifier = tmp.generate_new_identifier() identifier = tmp.generate_new_identifier()
self.initialize_form_field("identifier", identifier) self.initialize_form_field("identifier", identifier)
self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:acc-new-id") self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:acc:new-id")
self.fields["title"].widget.attrs["placeholder"] = _("Eco-Account XY; Location ABC") self.fields["title"].widget.attrs["placeholder"] = _("Eco-Account XY; Location ABC")
def save(self, user: User, geom_form: SimpleGeomForm): def save(self, user: User, geom_form: SimpleGeomForm):
@ -402,8 +416,8 @@ class EditEcoAccountForm(NewEcoAccountForm):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.form_title = _("Edit Eco-Account") self.form_title = _("Edit Eco-Account")
self.action_url = reverse("compensation:acc-edit", args=(self.instance.id,)) self.action_url = reverse("compensation:acc:edit", args=(self.instance.id,))
self.cancel_redirect = reverse("compensation:acc-detail", args=(self.instance.id,)) self.cancel_redirect = reverse("compensation:acc:detail", args=(self.instance.id,))
# Initialize form data # Initialize form data
reg_date = self.instance.legal.registration_date reg_date = self.instance.legal.registration_date

@ -21,7 +21,7 @@ from konova.contexts import BaseContext
from konova.forms import BaseModalForm, NewDocumentForm from konova.forms import BaseModalForm, NewDocumentForm
from konova.models import DeadlineType from konova.models import DeadlineType
from konova.utils.message_templates import FORM_INVALID, ADDED_COMPENSATION_STATE, ADDED_DEADLINE, \ from konova.utils.message_templates import FORM_INVALID, ADDED_COMPENSATION_STATE, ADDED_DEADLINE, \
ADDED_COMPENSATION_ACTION ADDED_COMPENSATION_ACTION, PAYMENT_ADDED
class NewPaymentForm(BaseModalForm): class NewPaymentForm(BaseModalForm):
@ -100,7 +100,7 @@ class NewPaymentForm(BaseModalForm):
def save(self): def save(self):
pay = self.instance.add_payment(self) pay = self.instance.add_payment(self)
self.instance.mark_as_edited(self.user, self.request) self.instance.mark_as_edited(self.user, self.request, edit_comment=PAYMENT_ADDED)
return pay return pay
@ -346,10 +346,9 @@ class NewActionModalForm(BaseModalForm):
) )
comment = forms.CharField( comment = forms.CharField(
required=False, required=False,
max_length=200,
label=_("Comment"), label=_("Comment"),
label_suffix=_(""), label_suffix=_(""),
help_text=_("Additional comment, maximum {} letters").format(200), help_text=_("Additional comment"),
widget=forms.Textarea( widget=forms.Textarea(
attrs={ attrs={
"rows": 5, "rows": 5,

@ -20,7 +20,8 @@ from compensation.utils.quality import CompensationQualityChecker
from konova.models import BaseObject, AbstractDocument, Deadline, generate_document_file_upload_path, \ from konova.models import BaseObject, AbstractDocument, Deadline, generate_document_file_upload_path, \
GeoReferencedMixin GeoReferencedMixin
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION, COMPENSATION_REMOVED_TEMPLATE, \
DOCUMENT_REMOVED_TEMPLATE
from user.models import UserActionLogEntry from user.models import UserActionLogEntry
@ -235,6 +236,11 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
self.identifier = self.generate_new_identifier() self.identifier = self.generate_new_identifier()
super().save(*args, **kwargs) super().save(*args, **kwargs)
def mark_as_deleted(self, user, send_mail: bool = True):
super().mark_as_deleted(user, send_mail)
if user is not None:
self.intervention.mark_as_edited(user, edit_comment=COMPENSATION_REMOVED_TEMPLATE.format(self.identifier))
def is_shared_with(self, user: User): def is_shared_with(self, user: User):
""" Access check """ Access check
@ -326,7 +332,7 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
Returns: Returns:
""" """
self.intervention.mark_as_edited(user, request, edit_comment, reset_recorded) return self.intervention.mark_as_edited(user, request, edit_comment, reset_recorded)
def is_ready_for_publish(self) -> bool: def is_ready_for_publish(self) -> bool:
""" Not inherited by RecordableObjectMixin """ Not inherited by RecordableObjectMixin
@ -353,7 +359,7 @@ class CompensationDocument(AbstractDocument):
max_length=1000, max_length=1000,
) )
def delete(self, *args, **kwargs): def delete(self, user=None, *args, **kwargs):
""" """
Custom delete functionality for CompensationDocuments. Custom delete functionality for CompensationDocuments.
Removes the folder from the file system if there are no further documents for this entry. Removes the folder from the file system if there are no further documents for this entry.
@ -375,6 +381,9 @@ class CompensationDocument(AbstractDocument):
folder_path = self.file.path.split("/")[:-1] folder_path = self.file.path.split("/")[:-1]
folder_path = "/".join(folder_path) folder_path = "/".join(folder_path)
if user:
self.instance.mark_as_edited(user, edit_comment=DOCUMENT_REMOVED_TEMPLATE.format(self.title))
# Remove the file itself # Remove the file itself
super().delete(*args, **kwargs) super().delete(*args, **kwargs)

@ -7,10 +7,12 @@ Created on: 16.11.21
""" """
import shutil import shutil
from user.models import User from django.urls import reverse
from konova.utils.message_templates import DEDUCTION_REMOVED, DOCUMENT_REMOVED_TEMPLATE
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from django.db import models, transaction from django.db import models
from django.db.models import Sum, QuerySet from django.db.models import Sum, QuerySet
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -20,7 +22,6 @@ from compensation.utils.quality import EcoAccountQualityChecker
from konova.models import ShareableObjectMixin, RecordableObjectMixin, AbstractDocument, BaseResource, \ from konova.models import ShareableObjectMixin, RecordableObjectMixin, AbstractDocument, BaseResource, \
generate_document_file_upload_path generate_document_file_upload_path
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
from user.models import UserActionLogEntry
class EcoAccount(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin): class EcoAccount(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin):
@ -165,34 +166,6 @@ class EcoAccount(AbstractCompensation, ShareableObjectMixin, RecordableObjectMix
) )
return docs return docs
def add_deduction(self, form):
""" Adds a new deduction to the intervention
Args:
form (NewDeductionModalForm): The form holding the data
Returns:
"""
form_data = form.cleaned_data
user = form.user
with transaction.atomic():
# Create log entry
user_action_create = UserActionLogEntry.get_created_action(user)
user_action_edit = UserActionLogEntry.get_edited_action(user)
self.log.add(user_action_edit)
self.modified = user_action_edit
self.save()
deduction = EcoAccountDeduction.objects.create(
intervention=form_data["intervention"],
account=self,
surface=form_data["surface"],
created=user_action_create,
)
return deduction
def is_ready_for_publish(self) -> bool: def is_ready_for_publish(self) -> bool:
""" Checks whether the data passes all constraints for being publishable """ Checks whether the data passes all constraints for being publishable
@ -203,6 +176,14 @@ class EcoAccount(AbstractCompensation, ShareableObjectMixin, RecordableObjectMix
is_ready = is_recorded is_ready = is_recorded
return is_ready return is_ready
def get_share_link(self):
""" Returns the share url for the object
Returns:
"""
return reverse("compensation:acc:share", args=(self.id, self.access_token))
class EcoAccountDocument(AbstractDocument): class EcoAccountDocument(AbstractDocument):
""" """
@ -218,7 +199,7 @@ class EcoAccountDocument(AbstractDocument):
max_length=1000, max_length=1000,
) )
def delete(self, *args, **kwargs): def delete(self, user=None, *args, **kwargs):
""" """
Custom delete functionality for EcoAccountDocuments. Custom delete functionality for EcoAccountDocuments.
Removes the folder from the file system if there are no further documents for this entry. Removes the folder from the file system if there are no further documents for this entry.
@ -240,6 +221,9 @@ class EcoAccountDocument(AbstractDocument):
folder_path = self.file.path.split("/")[:-1] folder_path = self.file.path.split("/")[:-1]
folder_path = "/".join(folder_path) folder_path = "/".join(folder_path)
if user:
self.instance.mark_as_edited(user, edit_comment=DOCUMENT_REMOVED_TEMPLATE.format(self.title))
# Remove the file itself # Remove the file itself
super().delete(*args, **kwargs) super().delete(*args, **kwargs)
@ -285,3 +269,9 @@ class EcoAccountDeduction(BaseResource):
def __str__(self): def __str__(self):
return "{} of {}".format(self.surface, self.account) return "{} of {}".format(self.surface, self.account)
def delete(self, user=None, *args, **kwargs):
if user is not None:
self.intervention.mark_as_edited(user, edit_comment=DEDUCTION_REMOVED)
self.account.mark_as_edited(user, edit_comment=DEDUCTION_REMOVED, reset_recorded=False)
super().delete(*args, **kwargs)

@ -10,6 +10,8 @@ from django.db import models
from intervention.models import Intervention from intervention.models import Intervention
from konova.models import BaseResource from konova.models import BaseResource
from konova.utils.message_templates import PAYMENT_REMOVED
from user.models import UserActionLogEntry
class Payment(BaseResource): class Payment(BaseResource):
@ -35,3 +37,8 @@ class Payment(BaseResource):
ordering = [ ordering = [
"-amount", "-amount",
] ]
def delete(self, user=None, *args, **kwargs):
if user is not None:
self.intervention.mark_as_edited(user, edit_comment=PAYMENT_REMOVED)
super().delete(*args, **kwargs)

@ -201,7 +201,7 @@ class EcoAccountTable(BaseTable, TableRenderMixin):
def __init__(self, request: HttpRequest, *args, **kwargs): def __init__(self, request: HttpRequest, *args, **kwargs):
self.title = _("Eco Accounts") self.title = _("Eco Accounts")
self.add_new_url = reverse("compensation:acc-new") self.add_new_url = reverse("compensation:acc:new")
qs = kwargs.get("queryset", None) qs = kwargs.get("queryset", None)
self.filter = EcoAccountTableFilter( self.filter = EcoAccountTableFilter(
user=request.user, user=request.user,
@ -224,7 +224,7 @@ class EcoAccountTable(BaseTable, TableRenderMixin):
html = "" html = ""
html += self.render_link( html += self.render_link(
tooltip=_("Open {}").format(_("Eco-account")), tooltip=_("Open {}").format(_("Eco-account")),
href=reverse("compensation:acc-detail", args=(record.id,)), href=reverse("compensation:acc:detail", args=(record.id,)),
txt=value, txt=value,
new_tab=False, new_tab=False,
) )

@ -1,4 +1,5 @@
{% load i18n l10n fontawesome_5 humanize %} {% load i18n l10n fontawesome_5 humanize ksp_filters %}
<div id="actions" class="card"> <div id="actions" class="card">
<div class="card-header rlp-r"> <div class="card-header rlp-r">
<div class="row"> <div class="row">
@ -20,16 +21,13 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="" scope="col">
{% trans 'Action type' %} {% trans 'Action type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Action type details' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Amount' context 'Compensation' %} {% trans 'Amount' context 'Compensation' %}
</th> </th>
@ -38,7 +36,9 @@
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -46,19 +46,24 @@
<tbody> <tbody>
{% for action in actions %} {% for action in actions %}
<tr> <tr>
<td class="align-middle"> <td class="">
{{ action.action_type }} <span>{{ action.action_type }}</span>
{% if action.action_type_details.count > 0 %}
<br>
{% for detail in action.action_type_details.all %}
<span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{% endfor %}
{% endif %}
</td> </td>
<td class="align-middle"> <td class="">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td>
{% for detail in action.action_type_details.all %} <td class="">
<div class="mb-2" title="{{detail}}">{{detail.long_name}}</div> <div class="scroll-150">
{% endfor %} {{ action.comment }}
</div>
</td> </td>
<td class="align-middle">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td> <td class="">
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:action-remove' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}"> <button data-form-url="{% url 'compensation:action-remove' obj.id action.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -35,7 +35,9 @@
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -47,10 +49,14 @@
{% trans deadline.type_humanized %} {% trans deadline.type_humanized %}
</td> </td>
<td class="align-middle">{{ deadline.date|default_if_none:"---" }}</td> <td class="align-middle">{{ deadline.date|default_if_none:"---" }}</td>
<td class="align-middle">{{ deadline.comment }}</td> <td class="align-middle">
<div class="scroll-150">
{{ deadline.comment }}
</div>
</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'deadline-remove' deadline.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove deadline' %}"> <button data-form-url="{% url 'compensation:deadline-remove' obj.id deadline.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove deadline' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -32,7 +32,9 @@
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -45,10 +47,14 @@
{{ doc.title }} {{ doc.title }}
</a> </a>
</td> </td>
<td class="align-middle">{{ doc.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ doc.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:remove-doc' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}"> <button data-form-url="{% url 'compensation:remove-doc' doc.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove document' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,27 +20,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> {% if sum_before_states > sum_after_states %}
{% if sum_before_states > sum_after_states %} <div class="alert alert-danger mb-0">
<div class="row alert alert-danger"> {% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m²
{% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m² </div>
</div> {% endif %}
{% endif %} <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-50" scope="col">
{% trans 'Biotope type' %} {% trans 'Biotope type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Biotope additional type' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Surface' %} {% trans 'Surface' %}
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -48,20 +47,19 @@
<tbody> <tbody>
{% for state in after_states %} {% for state in after_states %}
<tr> <tr>
<td class="align-middle"> <td>
{{ state.biotope_type }} <span>{{ state.biotope_type }}</span>
</td> {% if state.biotope_type_details.count > 0 %}
<td class="align-middle"> <br>
{% for biotope_extra in state.biotope_type_details.all %} {% for detail in state.biotope_type_details.all %}
<div class="mb-2" title="{{ biotope_extra }}"> <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{{ biotope_extra.long_name }} {% endfor %}
</div> {% endif %}
{% endfor %}
</td> </td>
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td>{{ state.surface|floatformat:2 }} m²</td>
<td class="align-middle"> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:state-remove' obj.id state.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,27 +20,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> {% if sum_before_states < sum_after_states %}
{% if sum_before_states < sum_after_states %} <div class="alert alert-danger mb-0">
<div class="row alert alert-danger"> {% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m²
{% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m² </div>
</div> {% endif %}
{% endif %} <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-50" scope="col">
{% trans 'Biotope type' %} {% trans 'Biotope type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Biotope additional type' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Surface' %} {% trans 'Surface' %}
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -48,20 +47,19 @@
<tbody> <tbody>
{% for state in before_states %} {% for state in before_states %}
<tr> <tr>
<td class="align-middle"> <td>
{{ state.biotope_type }} <span>{{ state.biotope_type }}</span>
</td> {% if state.biotope_type_details.count > 0 %}
<td class="align-middle"> <br>
{% for biotope_extra in state.biotope_type_details.all %} {% for detail in state.biotope_type_details.all %}
<div class="mb-2" title="{{ biotope_extra }}"> <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{{ biotope_extra.long_name }} {% endfor %}
</div> {% endif %}
{% endfor %}
</td> </td>
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td>{{ state.surface|floatformat:2 }} m²</td>
<td class="align-middle"> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:state-remove' obj.id state.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -14,16 +14,16 @@
{% block body %} {% block body %}
<div id="detail-header" class="row"> <div id="detail-header" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Compensation' %}<br> {{obj.identifier}}</h3> <h3>{% trans 'Compensation' %}<br> {{obj.identifier}}</h3>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/compensation/includes/controls.html' %} {% include 'compensation/detail/compensation/includes/controls.html' %}
</div> </div>
</div> </div>
<hr> <hr>
<div id="data" class="row"> <div id="data" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="table-container"> <div class="table-container">
<table class="table table-hover"> <table class="table table-hover">
<tr> <tr>
@ -105,39 +105,42 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="col">
{% include 'map/geom_form.html' %} <div class="row">
</div> {% include 'map/geom_form.html' %}
<div class="row"> </div>
{% include 'konova/includes/parcels.html' %} <div class="row">
</div> {% include 'konova/includes/parcels.html' %}
<div class="row"> </div>
{% include 'konova/includes/comment_card.html' %} <div class="row">
{% include 'konova/includes/comment_card.html' %}
</div>
</div> </div>
</div> </div>
</div> </div>
<hr> <hr>
<div id="related_data">
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/compensation/includes/states-before.html' %} {% include 'compensation/detail/compensation/includes/states-before.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/compensation/includes/states-after.html' %} {% include 'compensation/detail/compensation/includes/states-after.html' %}
</div> </div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
{% include 'compensation/detail/compensation/includes/actions.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="row">
{% include 'compensation/detail/compensation/includes/deadlines.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/compensation/includes/actions.html' %}
</div>
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/compensation/includes/deadlines.html' %}
</div>
</div> </div>
</div> <div class="row">
<div class="row"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="col-sm-12 col-md-12 col-lg-6"> {% include 'compensation/detail/compensation/includes/documents.html' %}
{% include 'compensation/detail/compensation/includes/documents.html' %} </div>
</div> </div>
</div> </div>

@ -1,4 +1,4 @@
{% load i18n l10n fontawesome_5 humanize %} {% load i18n l10n fontawesome_5 humanize ksp_filters %}
<div id="actions" class="card"> <div id="actions" class="card">
<div class="card-header rlp-r"> <div class="card-header rlp-r">
<div class="row"> <div class="row">
@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc-new-action' obj.id %}" title="{% trans 'Add new action' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-action' obj.id %}" title="{% trans 'Add new action' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'seedling' %} {% fa5_icon 'seedling' %}
</button> </button>
@ -20,25 +20,24 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="" scope="col">
{% trans 'Action type' %} {% trans 'Action type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Action type details' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Amount' context 'Compensation' %} {% trans 'Amount' context 'Compensation' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
{% if default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -46,19 +45,24 @@
<tbody> <tbody>
{% for action in actions %} {% for action in actions %}
<tr> <tr>
<td class="align-middle"> <td class="">
{{ action.action_type }} <span>{{ action.action_type }}</span>
{% if action.action_type_details.count > 0 %}
<br>
{% for detail in action.action_type_details.all %}
<span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{% endfor %}
{% endif %}
</td> </td>
<td class="align-middle"> <td class="">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td>
{% for detail in action.action_type_details.all %} <td class="">
<div class="mb-2" title="{{detail}}">{{detail.long_name}}</div> <div class="scroll-150">
{% endfor %} {{ action.comment }}
</div>
</td> </td>
<td class="align-middle">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td> <td class="">
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc-action-remove' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}"> <button data-form-url="{% url 'compensation:acc:action-remove' obj.id action.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -6,36 +6,36 @@
LANIS LANIS
</button> </button>
</a> </a>
<a href="{% url 'compensation:acc-report' obj.id %}" target="_blank" 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' %}"> <button class="btn btn-default" title="{% trans 'Public report' %}">
{% fa5_icon 'file-alt' %} {% fa5_icon 'file-alt' %}
</button> </button>
</a> </a>
{% if has_access %} {% if has_access %}
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Share' %}" data-form-url="{% url 'compensation:share-create' obj.id %}"> <button class="btn btn-default btn-modal mr-2" title="{% trans 'Share' %}" data-form-url="{% url 'compensation:acc:share-create' obj.id %}">
{% fa5_icon 'share-alt' %} {% fa5_icon 'share-alt' %}
</button> </button>
{% if is_ets_member %} {% if is_ets_member %}
{% if obj.recorded %} {% if obj.recorded %}
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Unrecord' %}" data-form-url="{% url 'compensation:acc-record' obj.id %}"> <button class="btn btn-default btn-modal mr-2" title="{% trans 'Unrecord' %}" data-form-url="{% url 'compensation:acc:record' obj.id %}">
{% fa5_icon 'bookmark' 'far' %} {% fa5_icon 'bookmark' 'far' %}
</button> </button>
{% else %} {% else %}
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Record' %}" data-form-url="{% url 'compensation:acc-record' obj.id %}"> <button class="btn btn-default btn-modal mr-2" title="{% trans 'Record' %}" data-form-url="{% url 'compensation:acc:record' obj.id %}">
{% fa5_icon 'bookmark' %} {% fa5_icon 'bookmark' %}
</button> </button>
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if is_default_member %} {% if is_default_member %}
<a href="{% url 'compensation:acc-edit' obj.id %}" class="mr-2"> <a href="{% url 'compensation:acc:edit' obj.id %}" class="mr-2">
<button class="btn btn-default" title="{% trans 'Edit' %}"> <button class="btn btn-default" title="{% trans 'Edit' %}">
{% fa5_icon 'edit' %} {% fa5_icon 'edit' %}
</button> </button>
</a> </a>
<button class="btn btn-default btn-modal mr-2" data-form-url="{% url 'compensation:acc-log' obj.id %}" title="{% trans 'Show log' %}"> <button class="btn btn-default btn-modal mr-2" data-form-url="{% url 'compensation:acc:log' obj.id %}" title="{% trans 'Show log' %}">
{% fa5_icon 'history' %} {% fa5_icon 'history' %}
</button> </button>
<button class="btn btn-default btn-modal" data-form-url="{% url 'compensation:acc-remove' obj.id %}" title="{% trans 'Delete' %}"> <button class="btn btn-default btn-modal" data-form-url="{% url 'compensation:acc:remove' obj.id %}" title="{% trans 'Delete' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc-new-deadline' obj.id %}" title="{% trans 'Add new deadline' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-deadline' obj.id %}" title="{% trans 'Add new deadline' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'calendar-check' %} {% fa5_icon 'calendar-check' %}
</button> </button>
@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -34,7 +34,9 @@
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
@ -45,10 +47,14 @@
{% trans deadline.type_humanized %} {% trans deadline.type_humanized %}
</td> </td>
<td class="align-middle">{{ deadline.date|default_if_none:"---" }}</td> <td class="align-middle">{{ deadline.date|default_if_none:"---" }}</td>
<td class="align-middle">{{ deadline.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ deadline.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'deadline-remove' deadline.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove deadline' %}"> <button data-form-url="{% url 'compensation:acc:deadline-remove' obj.id deadline.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove deadline' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc-new-deduction' obj.id %}" title="{% trans 'Add new deduction' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-deduction' obj.id %}" title="{% trans 'Add new deduction' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'tree' %} {% fa5_icon 'tree' %}
</button> </button>
@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -37,7 +37,9 @@
{% trans 'Created' %} {% trans 'Created' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
@ -60,7 +62,7 @@
<td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td> <td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc-remove-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove Deduction' %}"> <button data-form-url="{% url 'compensation:acc:remove-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove Deduction' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc-new-doc' obj.id %}" title="{% trans 'Add new document' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-doc' obj.id %}" title="{% trans 'Add new document' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'file' %} {% fa5_icon 'file' %}
</button> </button>
@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -31,7 +31,9 @@
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
@ -39,14 +41,18 @@
{% for doc in obj.documents.all %} {% for doc in obj.documents.all %}
<tr> <tr>
<td class="align-middle"> <td class="align-middle">
<a href="{% url 'compensation:acc-get-doc' doc.id %}"> <a href="{% url 'compensation:acc:get-doc' doc.id %}">
{{ doc.title }} {{ doc.title }}
</a> </a>
</td> </td>
<td class="align-middle">{{ doc.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ doc.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc-remove-doc' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}"> <button data-form-url="{% url 'compensation:acc:remove-doc' doc.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove document' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc-new-state' obj.id %}" title="{% trans 'Add new state after' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-state' obj.id %}" title="{% trans 'Add new state after' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'layer-group' %} {% fa5_icon 'layer-group' %}
</button> </button>
@ -20,27 +20,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> {% if sum_before_states > sum_after_states %}
{% if sum_before_states > sum_after_states %} <div class="alert alert-danger mb-0">
<div class="row alert alert-danger"> {% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m²
{% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m² </div>
</div> {% endif %}
{% endif %} <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-50" scope="col">
{% trans 'Biotope type' %} {% trans 'Biotope type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Biotope additional type' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Surface' %} {% trans 'Surface' %}
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -48,20 +47,19 @@
<tbody> <tbody>
{% for state in after_states %} {% for state in after_states %}
<tr> <tr>
<td class="align-middle"> <td>
{{ state.biotope_type }} <span>{{ state.biotope_type }}</span>
</td> {% if state.biotope_type_details.count > 0 %}
<td class="align-middle"> <br>
{% for biotope_extra in state.biotope_type_details.all %} {% for detail in state.biotope_type_details.all %}
<div class="mb-2" title="{{ biotope_extra }}"> <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{{ biotope_extra.long_name }} {% endfor %}
</div> {% endif %}
{% endfor %}
</td> </td>
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td>{{ state.surface|floatformat:2 }} m²</td>
<td class="align-middle"> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc-state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:acc:state-remove' obj.id state.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc-new-state' obj.id %}?before=true" title="{% trans 'Add new state before' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:acc:new-state' obj.id %}?before=true" title="{% trans 'Add new state before' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'layer-group' %} {% fa5_icon 'layer-group' %}
</button> </button>
@ -20,27 +20,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> {% if sum_before_states < sum_after_states %}
{% if sum_before_states < sum_after_states %} <div class="alert alert-danger mb-0">
<div class="row alert alert-danger"> {% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m²
{% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m² </div>
</div> {% endif %}
{% endif %} <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-50" scope="col">
{% trans 'Biotope type' %} {% trans 'Biotope type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Biotope additional type' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Surface' %} {% trans 'Surface' %}
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -48,20 +47,19 @@
<tbody> <tbody>
{% for state in before_states %} {% for state in before_states %}
<tr> <tr>
<td class="align-middle"> <td>
{{ state.biotope_type }} <span>{{ state.biotope_type }}</span>
</td> {% if state.biotope_type_details.count > 0 %}
<td class="align-middle"> <br>
{% for biotope_extra in state.biotope_type_details.all %} {% for detail in state.biotope_type_details.all %}
<div class="mb-2" title="{{ biotope_extra }}"> <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{{ biotope_extra.long_name }} {% endfor %}
</div> {% endif %}
{% endfor %}
</td> </td>
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td>{{ state.surface|floatformat:2 }} m²</td>
<td class="align-middle"> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc-state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'compensation:acc:state-remove' obj.id state.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -14,16 +14,16 @@
{% block body %} {% block body %}
<div id="detail-header" class="row"> <div id="detail-header" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Eco-account' %}<br> {{obj.identifier}}</h3> <h3>{% trans 'Eco-account' %}<br> {{obj.identifier}}</h3>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/eco_account/includes/controls.html' %} {% include 'compensation/detail/eco_account/includes/controls.html' %}
</div> </div>
</div> </div>
<hr> <hr>
<div id="data" class="row"> <div id="data" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="table-container"> <div class="table-container">
<table class="table table-hover"> <table class="table table-hover">
<tr> <tr>
@ -88,7 +88,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>
@ -102,28 +102,30 @@
</div> </div>
<hr> <hr>
<div class="row"> <div id="related_data">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="row">
{% include 'compensation/detail/eco_account/includes/states-before.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
</div> {% include 'compensation/detail/eco_account/includes/states-before.html' %}
<div class="col-sm-12 col-md-12 col-lg-6"> </div>
{% include 'compensation/detail/eco_account/includes/states-after.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
</div> {% include 'compensation/detail/eco_account/includes/states-after.html' %}
</div> </div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
{% include 'compensation/detail/eco_account/includes/actions.html' %}
</div>
<div class="col-sm-12 col-md-12 col-lg-6">
{% include 'compensation/detail/eco_account/includes/deadlines.html' %}
</div> </div>
</div> <div class="row">
<div class="row"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="col-sm-12 col-md-12 col-lg-6"> {% include 'compensation/detail/eco_account/includes/actions.html' %}
{% include 'compensation/detail/eco_account/includes/documents.html' %} </div>
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/eco_account/includes/deadlines.html' %}
</div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="row">
{% include 'compensation/detail/eco_account/includes/deductions.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/eco_account/includes/documents.html' %}
</div>
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'compensation/detail/eco_account/includes/deductions.html' %}
</div>
</div> </div>
</div> </div>

@ -3,7 +3,7 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Report' %}</h3> <h3>{% trans 'Report' %}</h3>
<h4>{{obj.identifier}}</h4> <h4>{{obj.identifier}}</h4>
<div class="table-container"> <div class="table-container">
@ -33,7 +33,7 @@
{% include 'compensation/detail/compensation/includes/states-after.html' %} {% include 'compensation/detail/compensation/includes/states-after.html' %}
{% include 'compensation/detail/compensation/includes/actions.html' %} {% include 'compensation/detail/compensation/includes/actions.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>

@ -3,7 +3,7 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Report' %}</h3> <h3>{% trans 'Report' %}</h3>
<h4>{{obj.identifier}}</h4> <h4>{{obj.identifier}}</h4>
<div class="table-container"> <div class="table-container">
@ -50,7 +50,7 @@
{% include 'compensation/detail/compensation/includes/states-after.html' %} {% include 'compensation/detail/compensation/includes/states-after.html' %}
{% include 'compensation/detail/compensation/includes/actions.html' %} {% include 'compensation/detail/compensation/includes/actions.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>

@ -245,20 +245,20 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
cls.eco_account.actions.set([action]) cls.eco_account.actions.set([action])
# Prepare urls # Prepare urls
cls.index_url = reverse("compensation:acc-index", args=()) cls.index_url = reverse("compensation:acc:index", args=())
cls.new_url = reverse("compensation:acc-new", args=()) cls.new_url = reverse("compensation:acc:new", args=())
cls.new_id_url = reverse("compensation:acc-new-id", args=()) cls.new_id_url = reverse("compensation:acc:new-id", args=())
cls.detail_url = reverse("compensation:acc-detail", args=(cls.eco_account.id,)) cls.detail_url = reverse("compensation:acc:detail", args=(cls.eco_account.id,))
cls.log_url = reverse("compensation:acc-log", args=(cls.eco_account.id,)) cls.log_url = reverse("compensation:acc:log", args=(cls.eco_account.id,))
cls.edit_url = reverse("compensation:acc-edit", args=(cls.eco_account.id,)) cls.edit_url = reverse("compensation:acc:edit", args=(cls.eco_account.id,))
cls.remove_url = reverse("compensation:acc-remove", args=(cls.eco_account.id,)) cls.remove_url = reverse("compensation:acc:remove", args=(cls.eco_account.id,))
cls.report_url = reverse("compensation:acc-report", args=(cls.eco_account.id,)) cls.report_url = reverse("compensation:acc:report", args=(cls.eco_account.id,))
cls.state_new_url = reverse("compensation:acc-new-state", args=(cls.eco_account.id,)) cls.state_new_url = reverse("compensation:acc:new-state", args=(cls.eco_account.id,))
cls.action_new_url = reverse("compensation:acc-new-action", args=(cls.eco_account.id,)) cls.action_new_url = reverse("compensation:acc:new-action", args=(cls.eco_account.id,))
cls.deadline_new_url = reverse("compensation:acc-new-deadline", args=(cls.eco_account.id,)) cls.deadline_new_url = reverse("compensation:acc:new-deadline", args=(cls.eco_account.id,))
cls.new_doc_url = reverse("compensation:acc-new-doc", args=(cls.eco_account.id,)) cls.new_doc_url = reverse("compensation:acc:new-doc", args=(cls.eco_account.id,))
cls.state_remove_url = reverse("compensation:acc-state-remove", args=(cls.eco_account.id, cls.comp_state.id,)) cls.state_remove_url = reverse("compensation:acc:state-remove", args=(cls.eco_account.id, cls.comp_state.id,))
cls.action_remove_url = reverse("compensation:acc-action-remove", args=(cls.eco_account.id, cls.comp_action.id,)) cls.action_remove_url = reverse("compensation:acc:action-remove", args=(cls.eco_account.id, cls.comp_action.id,))
def test_logged_in_no_groups_shared(self): def test_logged_in_no_groups_shared(self):
""" Check correct status code for all requests """ Check correct status code for all requests

@ -258,7 +258,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
self.intervention.share_with(self.superuser) self.intervention.share_with(self.superuser)
# Prepare data for deduction creation # Prepare data for deduction creation
deduct_url = reverse("compensation:acc-new-deduction", args=(self.eco_account.id,)) deduct_url = reverse("compensation:acc:new-deduction", args=(self.eco_account.id,))
test_surface = 10.00 test_surface = 10.00
post_data = { post_data = {
"surface": test_surface, "surface": test_surface,

@ -23,6 +23,7 @@ urlpatterns = [
path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'), path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'),
path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'), path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'),
path('<id>/deadline/new', deadline_new_view, name="new-deadline"), path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
path('<id>/deadline/<deadline_id>/remove', deadline_remove_view, name='deadline-remove'),
path('<id>/report', report_view, name='report'), path('<id>/report', report_view, name='report'),
# Documents # Documents

@ -8,31 +8,33 @@ Created on: 24.08.21
from django.urls import path from django.urls import path
from compensation.views.eco_account import * from compensation.views.eco_account import *
app_name = "acc"
urlpatterns = [ urlpatterns = [
path("", index_view, name="acc-index"), path("", index_view, name="index"),
path('new/', new_view, name='acc-new'), path('new/', new_view, name='new'),
path('new/id', new_id_view, name='acc-new-id'), path('new/id', new_id_view, name='new-id'),
path('<id>', detail_view, name='acc-detail'), path('<id>', detail_view, name='detail'),
path('<id>/log', log_view, name='acc-log'), path('<id>/log', log_view, name='log'),
path('<id>/record', record_view, name='acc-record'), path('<id>/record', record_view, name='record'),
path('<id>/report', report_view, name='acc-report'), path('<id>/report', report_view, name='report'),
path('<id>/edit', edit_view, name='acc-edit'), path('<id>/edit', edit_view, name='edit'),
path('<id>/remove', remove_view, name='acc-remove'), path('<id>/remove', remove_view, name='remove'),
path('<id>/state/new', state_new_view, name='acc-new-state'), path('<id>/state/new', state_new_view, name='new-state'),
path('<id>/action/new', action_new_view, name='acc-new-action'), path('<id>/action/new', action_new_view, name='new-action'),
path('<id>/state/<state_id>/remove', state_remove_view, name='acc-state-remove'), path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'),
path('<id>/action/<action_id>/remove', action_remove_view, name='acc-action-remove'), path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'),
path('<id>/deadline/new', deadline_new_view, name="acc-new-deadline"), path('<id>/deadline/<deadline_id>/remove', deadline_remove_view, name='deadline-remove'),
path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
path('<id>/share/<token>', share_view, name='share'), path('<id>/share/<token>', share_view, name='share'),
path('<id>/share', create_share_view, name='share-create'), path('<id>/share', create_share_view, name='share-create'),
# Documents # Documents
path('<id>/document/new/', new_document_view, name='acc-new-doc'), path('<id>/document/new/', new_document_view, name='new-doc'),
path('document/<doc_id>', get_document_view, name='acc-get-doc'), path('document/<doc_id>', get_document_view, name='get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='acc-remove-doc'), path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),
# Eco-account deductions # Eco-account deductions
path('<id>/remove/<deduction_id>', deduction_remove_view, name='acc-remove-deduction'), path('<id>/remove/<deduction_id>', deduction_remove_view, name='remove-deduction'),
path('<id>/deduct/new', new_deduction_view, name='acc-new-deduction'), path('<id>/deduct/new', new_deduction_view, name='new-deduction'),
] ]

@ -8,7 +8,8 @@ Created on: 24.08.21
from django.urls import path from django.urls import path
from compensation.views.payment import * from compensation.views.payment import *
app_name = "pay"
urlpatterns = [ urlpatterns = [
path('<intervention_id>/new', new_payment_view, name='pay-new'), path('<intervention_id>/new', new_payment_view, name='new'),
path('<id>/remove', payment_remove_view, name='pay-remove'), path('<id>/remove', payment_remove_view, name='remove'),
] ]

@ -10,6 +10,6 @@ from django.urls import path, include
app_name = "compensation" app_name = "compensation"
urlpatterns = [ urlpatterns = [
path("", include("compensation.urls.compensation")), path("", include("compensation.urls.compensation")),
path("acc/", include("compensation.urls.eco_account")), path("acc/", include("compensation.urls.eco_account", namespace="acc")),
path("pay/", include("compensation.urls.payment")), path("pay/", include("compensation.urls.payment", namespace="pay")),
] ]

@ -13,11 +13,12 @@ from intervention.models import Intervention
from konova.contexts import BaseContext from konova.contexts import BaseContext
from konova.decorators import * from konova.decorators import *
from konova.forms import RemoveModalForm, SimpleGeomForm from konova.forms import RemoveModalForm, SimpleGeomForm
from konova.models import Deadline
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.documents import get_document, remove_document from konova.utils.documents import get_document, remove_document
from konova.utils.generators import generate_qr_code from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DATA_UNSHARED_EXPLANATION, \ from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DATA_UNSHARED_EXPLANATION, \
CHECKED_RECORDED_RESET CHECKED_RECORDED_RESET, COMPENSATION_ADDED_TEMPLATE, COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED
from konova.utils.user_checks import in_group from konova.utils.user_checks import in_group
@ -78,7 +79,7 @@ def new_view(request: HttpRequest, intervention_id: str = None):
comp.identifier comp.identifier
) )
) )
messages.success(request, _("Compensation {} added").format(comp.identifier)) messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
return redirect("compensation:detail", id=comp.id) return redirect("compensation:detail", id=comp.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)
@ -255,7 +256,7 @@ def remove_view(request: HttpRequest, id: str):
form = RemoveModalForm(request.POST or None, instance=comp, request=request) form = RemoveModalForm(request.POST or None, instance=comp, request=request)
return form.process_request( return form.process_request(
request=request, request=request,
msg_success=_("Compensation removed"), msg_success=COMPENSATION_REMOVED_TEMPLATE.format(comp.identifier),
redirect_url=reverse("compensation:index"), redirect_url=reverse("compensation:index"),
) )
@ -276,7 +277,8 @@ def new_document_view(request: HttpRequest, id: str):
form = NewCompensationDocumentForm(request.POST or None, request.FILES or None, instance=comp, request=request) form = NewCompensationDocumentForm(request.POST or None, request.FILES or None, instance=comp, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Document added") msg_success=DOCUMENT_ADDED,
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
) )
@ -345,7 +347,8 @@ def state_new_view(request: HttpRequest, id: str):
form = NewStateModalForm(request.POST or None, instance=comp, request=request) form = NewStateModalForm(request.POST or None, instance=comp, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("State added") msg_success=_("State added"),
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
) )
@ -366,7 +369,8 @@ def action_new_view(request: HttpRequest, id: str):
form = NewActionModalForm(request.POST or None, instance=comp, request=request) form = NewActionModalForm(request.POST or None, instance=comp, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Action added") msg_success=_("Action added"),
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
) )
@ -387,7 +391,31 @@ def deadline_new_view(request: HttpRequest, id: str):
form = NewDeadlineModalForm(request.POST or None, instance=comp, request=request) form = NewDeadlineModalForm(request.POST or None, instance=comp, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Deadline added") msg_success=_("Deadline added"),
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
)
@login_required
@default_group_required
@shared_access_required(Compensation, "id")
def deadline_remove_view(request: HttpRequest, id: str, deadline_id: str):
""" Renders a form for removing deadlines from a compensation
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
deadline_id (str): The deadline's id
Returns:
"""
deadline = get_object_or_404(Deadline, id=deadline_id)
form = RemoveModalForm(request.POST or None, instance=deadline, request=request)
return form.process_request(
request,
msg_success=_("Deadline removed"),
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
) )
@ -409,7 +437,8 @@ def state_remove_view(request: HttpRequest, id: str, state_id: str):
form = RemoveModalForm(request.POST or None, instance=state, request=request) form = RemoveModalForm(request.POST or None, instance=state, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("State removed") msg_success=_("State removed"),
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
) )
@ -431,7 +460,8 @@ def action_remove_view(request: HttpRequest, id: str, action_id: str):
form = RemoveModalForm(request.POST or None, instance=action, request=request) form = RemoveModalForm(request.POST or None, instance=action, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Action removed") msg_success=_("Action removed"),
redirect_url=reverse("compensation:detail", args=(id,)) + "#related_data"
) )

@ -24,12 +24,13 @@ from konova.contexts import BaseContext
from konova.decorators import any_group_check, default_group_required, conservation_office_group_required, \ from konova.decorators import any_group_check, default_group_required, conservation_office_group_required, \
shared_access_required shared_access_required
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm
from konova.models import Deadline
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.documents import get_document, remove_document from konova.utils.documents import get_document, remove_document
from konova.utils.generators import generate_qr_code from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION, \ from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION, \
CANCEL_ACC_RECORDED_OR_DEDUCTED CANCEL_ACC_RECORDED_OR_DEDUCTED, DEDUCTION_REMOVED, DEDUCTION_ADDED, DOCUMENT_ADDED
from konova.utils.user_checks import in_group from konova.utils.user_checks import in_group
@ -89,7 +90,7 @@ def new_view(request: HttpRequest):
) )
) )
messages.success(request, _("Eco-Account {} added").format(acc.identifier)) messages.success(request, _("Eco-Account {} added").format(acc.identifier))
return redirect("compensation:acc-detail", id=acc.id) return redirect("compensation:acc:detail", id=acc.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
@ -147,7 +148,7 @@ def edit_view(request: HttpRequest, id: str):
# The data form takes the geom form for processing, as well as the performing user # The data form takes the geom form for processing, as well as the performing user
acc = data_form.save(request.user, geom_form) acc = data_form.save(request.user, geom_form)
messages.success(request, _("Eco-Account {} edited").format(acc.identifier)) messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
return redirect("compensation:acc-detail", id=acc.id) return redirect("compensation:acc:detail", id=acc.id)
else: else:
messages.error(request, FORM_INVALID, extra_tags="danger",) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
@ -254,13 +255,13 @@ def remove_view(request: HttpRequest, id: str):
user = request.user user = request.user
if not in_group(user, ETS_GROUP): if not in_group(user, ETS_GROUP):
messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED) messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED)
return redirect("compensation:acc-detail", id=id) return redirect("compensation:acc:detail", id=id)
form = RemoveModalForm(request.POST or None, instance=acc, request=request) form = RemoveModalForm(request.POST or None, instance=acc, request=request)
return form.process_request( return form.process_request(
request=request, request=request,
msg_success=_("Eco-account removed"), msg_success=_("Eco-account removed"),
redirect_url=reverse("compensation:acc-index"), redirect_url=reverse("compensation:acc:index"),
) )
@ -287,7 +288,8 @@ def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
form = RemoveModalForm(request.POST or None, instance=eco_deduction, request=request) form = RemoveModalForm(request.POST or None, instance=eco_deduction, request=request)
return form.process_request( return form.process_request(
request=request, request=request,
msg_success=_("Deduction removed") msg_success=DEDUCTION_REMOVED,
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -357,7 +359,8 @@ def state_new_view(request: HttpRequest, id: str):
form = NewStateModalForm(request.POST or None, instance=acc, request=request) form = NewStateModalForm(request.POST or None, instance=acc, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("State added") msg_success=_("State added"),
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -378,7 +381,8 @@ def action_new_view(request: HttpRequest, id: str):
form = NewActionModalForm(request.POST or None, instance=acc, request=request) form = NewActionModalForm(request.POST or None, instance=acc, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Action added") msg_success=_("Action added"),
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -400,7 +404,8 @@ def state_remove_view(request: HttpRequest, id: str, state_id: str):
form = RemoveModalForm(request.POST or None, instance=state, request=request) form = RemoveModalForm(request.POST or None, instance=state, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("State removed") msg_success=_("State removed"),
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -422,7 +427,31 @@ def action_remove_view(request: HttpRequest, id: str, action_id: str):
form = RemoveModalForm(request.POST or None, instance=action, request=request) form = RemoveModalForm(request.POST or None, instance=action, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Action removed") msg_success=_("Action removed"),
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
)
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def deadline_remove_view(request: HttpRequest, id: str, deadline_id: str):
""" Renders a form for removing deadlines from a compensation
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
deadline_id (str): The deadline's id
Returns:
"""
deadline = get_object_or_404(Deadline, id=deadline_id)
form = RemoveModalForm(request.POST or None, instance=deadline, request=request)
return form.process_request(
request,
msg_success=_("Deadline removed"),
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -443,7 +472,8 @@ def deadline_new_view(request: HttpRequest, id: str):
form = NewDeadlineModalForm(request.POST or None, instance=acc, request=request) form = NewDeadlineModalForm(request.POST or None, instance=acc, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Deadline added") msg_success=_("Deadline added"),
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -463,7 +493,8 @@ def new_document_view(request: HttpRequest, id: str):
form = NewEcoAccountDocumentForm(request.POST or None, request.FILES or None, instance=acc, request=request) form = NewEcoAccountDocumentForm(request.POST or None, request.FILES or None, instance=acc, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Document added") msg_success=DOCUMENT_ADDED,
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data",
) )
@ -490,7 +521,7 @@ def get_document_view(request: HttpRequest, doc_id: str):
request, request,
DATA_UNSHARED DATA_UNSHARED
) )
return redirect("compensation:acc-detail", id=instance.id) return redirect("compensation:acc:detail", id=instance.id)
return get_document(doc) return get_document(doc)
@ -533,7 +564,8 @@ def new_deduction_view(request: HttpRequest, id: str):
form = NewDeductionModalForm(request.POST or None, instance=acc, request=request) form = NewDeductionModalForm(request.POST or None, instance=acc, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Deduction added") msg_success=DEDUCTION_ADDED,
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
) )
@ -632,7 +664,7 @@ def share_view(request: HttpRequest, id: str, token: str):
_("{} has been shared with you").format(obj.identifier) _("{} has been shared with you").format(obj.identifier)
) )
obj.share_with(user) obj.share_with(user)
return redirect("compensation:acc-detail", id=id) return redirect("compensation:acc:detail", id=id)
else: else:
messages.error( messages.error(
request, request,

@ -5,6 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 09.08.21 Created on: 09.08.21
""" """
from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import HttpRequest from django.http import HttpRequest
@ -15,6 +16,7 @@ from compensation.models import Payment
from intervention.models import Intervention from intervention.models import Intervention
from konova.decorators import default_group_required from konova.decorators import default_group_required
from konova.forms import RemoveModalForm from konova.forms import RemoveModalForm
from konova.utils.message_templates import PAYMENT_ADDED, PAYMENT_REMOVED
@login_required @login_required
@ -33,7 +35,8 @@ def new_payment_view(request: HttpRequest, intervention_id: str):
form = NewPaymentForm(request.POST or None, instance=intervention, request=request) form = NewPaymentForm(request.POST or None, instance=intervention, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Payment added") msg_success=PAYMENT_ADDED,
redirect_url=reverse("intervention:detail", args=(intervention_id,)) + "#related_data"
) )
@ -53,6 +56,7 @@ def payment_remove_view(request: HttpRequest, id: str):
form = RemoveModalForm(request.POST or None, instance=payment, request=request) form = RemoveModalForm(request.POST or None, instance=payment, request=request)
return form.process_request( return form.process_request(
request=request, request=request,
msg_success=_("Payment removed"), msg_success=PAYMENT_REMOVED,
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
) )

@ -11,13 +11,14 @@ from django.contrib import messages
from django.db import models from django.db import models
from django.db.models import QuerySet from django.db.models import QuerySet
from django.http import HttpRequest from django.http import HttpRequest
from django.urls import reverse
from compensation.models import AbstractCompensation from compensation.models import AbstractCompensation
from ema.managers import EmaManager from ema.managers import EmaManager
from ema.utils.quality import EmaQualityChecker from ema.utils.quality import EmaQualityChecker
from konova.models import AbstractDocument, generate_document_file_upload_path, RecordableObjectMixin, ShareableObjectMixin from konova.models import AbstractDocument, generate_document_file_upload_path, RecordableObjectMixin, ShareableObjectMixin
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION, DOCUMENT_REMOVED_TEMPLATE
class Ema(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin): class Ema(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin):
@ -119,6 +120,14 @@ class Ema(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin):
is_ready = is_recorded is_ready = is_recorded
return is_ready return is_ready
def get_share_link(self):
""" Returns the share url for the object
Returns:
"""
return reverse("ema:share", args=(self.id, self.access_token))
class EmaDocument(AbstractDocument): class EmaDocument(AbstractDocument):
""" """
@ -134,7 +143,7 @@ class EmaDocument(AbstractDocument):
max_length=1000, max_length=1000,
) )
def delete(self, *args, **kwargs): def delete(self, user=None, *args, **kwargs):
""" """
Custom delete functionality for EcoAccountDocuments. Custom delete functionality for EcoAccountDocuments.
Removes the folder from the file system if there are no further documents for this entry. Removes the folder from the file system if there are no further documents for this entry.
@ -156,6 +165,9 @@ class EmaDocument(AbstractDocument):
folder_path = self.file.path.split("/")[:-1] folder_path = self.file.path.split("/")[:-1]
folder_path = "/".join(folder_path) folder_path = "/".join(folder_path)
if user:
self.instance.mark_as_edited(user, edit_comment=DOCUMENT_REMOVED_TEMPLATE.format(self.title))
# Remove the file itself # Remove the file itself
super().delete(*args, **kwargs) super().delete(*args, **kwargs)

@ -1,4 +1,4 @@
{% load i18n l10n fontawesome_5 humanize %} {% load i18n l10n fontawesome_5 humanize ksp_filters %}
<div id="actions" class="card"> <div id="actions" class="card">
<div class="card-header rlp-r"> <div class="card-header rlp-r">
<div class="row"> <div class="row">
@ -20,16 +20,13 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-25" scope="col">
{% trans 'Action type' %} {% trans 'Action type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Action type details' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Amount' context 'Compensation' %} {% trans 'Amount' context 'Compensation' %}
</th> </th>
@ -37,26 +34,33 @@
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for action in obj.actions.all %} {% for action in obj.actions.all %}
<tr> <tr>
<td class="align-middle"> <td class="">
{{ action.action_type }} <span>{{ action.action_type }}</span>
{% if action.action_type_details.count > 0 %}
<br>
{% for detail in action.action_type_details.all %}
<span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{% endfor %}
{% endif %}
</td> </td>
<td class="align-middle"> <td class="">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td>
{% for detail in action.action_type_details.all %} <td class="">
<div class="mb-2" title="{{detail}}">{{detail.long_name}}</div> <div class="scroll-150">
{% endfor %} {{ action.comment }}
</div>
</td> </td>
<td class="align-middle">{{ action.amount|floatformat:2|intcomma }} {{ action.unit_humanize }}</td> <td class="">
<td class="align-middle">{{ action.comment|default_if_none:"" }}</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:action-remove' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove action' %}"> <button data-form-url="{% url 'ema:action-remove' obj.id action.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove action' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -34,7 +34,9 @@
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
@ -45,10 +47,14 @@
{% trans deadline.type_humanized %} {% trans deadline.type_humanized %}
</td> </td>
<td class="align-middle">{{ deadline.date|default_if_none:"---" }}</td> <td class="align-middle">{{ deadline.date|default_if_none:"---" }}</td>
<td class="align-middle">{{ deadline.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ deadline.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'deadline-remove' deadline.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove deadline' %}"> <button data-form-url="{% url 'ema:deadline-remove' obj.id deadline.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove deadline' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -31,7 +31,9 @@
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
@ -43,10 +45,14 @@
{{ doc.title }} {{ doc.title }}
</a> </a>
</td> </td>
<td class="align-middle">{{ doc.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ doc.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:remove-doc' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}"> <button data-form-url="{% url 'ema:remove-doc' doc.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove document' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,46 +20,44 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> {% if sum_before_states > sum_after_states %}
{% if sum_before_states > sum_after_states %} <div class="alert alert-danger mb-0">
<div class="row alert alert-danger"> {% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m²
{% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m² </div>
</div> {% endif %}
{% endif %} <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-50" scope="col">
{% trans 'Biotope type' %} {% trans 'Biotope type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Biotope additional type' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Surface' %} {% trans 'Surface' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for state in after_states %} {% for state in after_states %}
<tr> <tr>
<td class="align-middle"> <td>
{{ state.biotope_type }} <span>{{ state.biotope_type }}</span>
</td> {% if state.biotope_type_details.count > 0 %}
<td class="align-middle"> <br>
{% for biotope_extra in state.biotope_type_details.all %} {% for detail in state.biotope_type_details.all %}
<div class="mb-2" title="{{ biotope_extra }}"> <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{{ biotope_extra.long_name }} {% endfor %}
</div> {% endif %}
{% endfor %}
</td> </td>
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td>{{ state.surface|floatformat:2 }} m²</td>
<td class="align-middle"> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'ema:state-remove' obj.id state.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,46 +20,44 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> {% if sum_before_states < sum_after_states %}
{% if sum_before_states < sum_after_states %} <div class="alert alert-danger mb-0">
<div class="row alert alert-danger"> {% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m²
{% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m² </div>
</div> {% endif %}
{% endif %} <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th class="w-25" scope="col"> <th class="w-50" scope="col">
{% trans 'Biotope type' %} {% trans 'Biotope type' %}
</th> </th>
<th class="w-25" scope="col">
{% trans 'Biotope additional type' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'Surface' %} {% trans 'Surface' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for state in before_states %} {% for state in before_states %}
<tr> <tr>
<td class="align-middle"> <td>
{{ state.biotope_type }} <span>{{ state.biotope_type }}</span>
</td> {% if state.biotope_type_details.count > 0 %}
<td class="align-middle"> <br>
{% for biotope_extra in state.biotope_type_details.all %} {% for detail in state.biotope_type_details.all %}
<div class="mb-2" title="{{ biotope_extra }}"> <span class="badge badge-pill rlp-r" title="{{detail}}">{{detail.long_name}}</span>
{{ biotope_extra.long_name }} {% endfor %}
</div> {% endif %}
{% endfor %}
</td> </td>
<td class="align-middle">{{ state.surface|floatformat:2 }} m²</td> <td>{{ state.surface|floatformat:2 }} m²</td>
<td class="align-middle"> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'ema:state-remove' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove state' %}"> <button data-form-url="{% url 'ema:state-remove' obj.id state.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove state' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -14,16 +14,16 @@
{% block body %} {% block body %}
<div id="detail-header" class="row"> <div id="detail-header" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Payment funded compensation' %} <br> {{obj.identifier}}</h3> <h3>{% trans 'Payment funded compensation' %} <br> {{obj.identifier}}</h3>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'ema/detail/includes/controls.html' %} {% include 'ema/detail/includes/controls.html' %}
</div> </div>
</div> </div>
<hr> <hr>
<div id="data" class="row"> <div id="data" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="table-container"> <div class="table-container">
<table class="table table-hover"> <table class="table table-hover">
<tr> <tr>
@ -82,7 +82,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>
@ -95,26 +95,27 @@
</div> </div>
</div> </div>
<hr> <hr>
<div id="related_data">
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'ema/detail/includes/states-before.html' %} {% include 'ema/detail/includes/states-before.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'ema/detail/includes/states-after.html' %} {% include 'ema/detail/includes/states-after.html' %}
</div> </div>
</div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
{% include 'ema/detail/includes/actions.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="row">
{% include 'ema/detail/includes/deadlines.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'ema/detail/includes/actions.html' %}
</div>
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'ema/detail/includes/deadlines.html' %}
</div>
</div> </div>
</div> <div class="row">
<div class="row"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="col-sm-12 col-md-12 col-lg-6"> {% include 'ema/detail/includes/documents.html' %}
{% include 'ema/detail/includes/documents.html' %} </div>
</div> </div>
</div> </div>

@ -3,7 +3,7 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Report' %}</h3> <h3>{% trans 'Report' %}</h3>
<h4>{{obj.identifier}}</h4> <h4>{{obj.identifier}}</h4>
<div class="table-container"> <div class="table-container">
@ -37,7 +37,7 @@
{% include 'compensation/detail/compensation/includes/states-after.html' %} {% include 'compensation/detail/compensation/includes/states-after.html' %}
{% include 'compensation/detail/compensation/includes/actions.html' %} {% include 'compensation/detail/compensation/includes/actions.html' %}
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>

@ -23,12 +23,12 @@ urlpatterns = [
path('<id>/action/new', action_new_view, name='new-action'), path('<id>/action/new', action_new_view, name='new-action'),
path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'), path('<id>/state/<state_id>/remove', state_remove_view, name='state-remove'),
path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'), path('<id>/action/<action_id>/remove', action_remove_view, name='action-remove'),
path('<id>/deadline/<deadline_id>/remove', deadline_remove_view, name='deadline-remove'),
path('<id>/deadline/new', deadline_new_view, name="new-deadline"), path('<id>/deadline/new', deadline_new_view, name="new-deadline"),
path('<id>/share/<token>', share_view, name='share'), path('<id>/share/<token>', share_view, name='share'),
path('<id>/share', create_share_view, name='share-create'), path('<id>/share', create_share_view, name='share-create'),
# Documents # Documents
# Document remove route can be found in konova/urls.py
path('<id>/document/new/', document_new_view, name='new-doc'), path('<id>/document/new/', document_new_view, name='new-doc'),
path('document/<doc_id>', get_document_view, name='get-doc'), path('document/<doc_id>', get_document_view, name='get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'), path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),

@ -15,11 +15,13 @@ from konova.contexts import BaseContext
from konova.decorators import conservation_office_group_required, shared_access_required from konova.decorators import conservation_office_group_required, shared_access_required
from ema.models import Ema, EmaDocument from ema.models import Ema, EmaDocument
from konova.forms import RemoveModalForm, SimpleGeomForm, RecordModalForm from konova.forms import RemoveModalForm, SimpleGeomForm, RecordModalForm
from konova.models import Deadline
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.documents import get_document, remove_document from konova.utils.documents import get_document, remove_document
from konova.utils.generators import generate_qr_code from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION, \
DOCUMENT_ADDED
from konova.utils.user_checks import in_group from konova.utils.user_checks import in_group
@ -290,7 +292,8 @@ def state_new_view(request: HttpRequest, id: str):
form = NewStateModalForm(request.POST or None, instance=ema, request=request) form = NewStateModalForm(request.POST or None, instance=ema, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("State added") msg_success=_("State added"),
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
) )
@ -311,7 +314,8 @@ def action_new_view(request: HttpRequest, id: str):
form = NewActionModalForm(request.POST or None, instance=ema, request=request) form = NewActionModalForm(request.POST or None, instance=ema, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Action added") msg_success=_("Action added"),
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
) )
@ -332,7 +336,8 @@ def deadline_new_view(request: HttpRequest, id: str):
form = NewDeadlineModalForm(request.POST or None, instance=ema, request=request) form = NewDeadlineModalForm(request.POST or None, instance=ema, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Deadline added") msg_success=_("Deadline added"),
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
) )
@ -352,7 +357,8 @@ def document_new_view(request: HttpRequest, id: str):
form = NewEmaDocumentForm(request.POST or None, request.FILES or None, instance=ema, request=request) form = NewEmaDocumentForm(request.POST or None, request.FILES or None, instance=ema, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Document added") msg_success=DOCUMENT_ADDED,
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
) )
@ -422,7 +428,8 @@ def state_remove_view(request: HttpRequest, id: str, state_id: str):
form = RemoveModalForm(request.POST or None, instance=state, request=request) form = RemoveModalForm(request.POST or None, instance=state, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("State removed") msg_success=_("State removed"),
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
) )
@ -444,7 +451,8 @@ def action_remove_view(request: HttpRequest, id: str, action_id: str):
form = RemoveModalForm(request.POST or None, instance=action, request=request) form = RemoveModalForm(request.POST or None, instance=action, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Action removed") msg_success=_("Action removed"),
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
) )
@ -565,3 +573,26 @@ def create_share_view(request: HttpRequest, id: str):
request, request,
msg_success=_("Share settings updated") msg_success=_("Share settings updated")
) )
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def deadline_remove_view(request: HttpRequest, id: str, deadline_id: str):
""" Renders a form for removing deadlines from a compensation
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
deadline_id (str): The deadline's id
Returns:
"""
deadline = get_object_or_404(Deadline, id=deadline_id)
form = RemoveModalForm(request.POST or None, instance=deadline, request=request)
return form.process_request(
request,
msg_success=_("Deadline removed"),
redirect_url=reverse("ema:detail", args=(id,)) + "#related_data"
)

@ -7,6 +7,8 @@ Created on: 02.12.20
""" """
from dal import autocomplete from dal import autocomplete
from django import forms from django import forms
from konova.utils.message_templates import EDITED_GENERAL_DATA
from user.models import User from user.models import User
from django.db import transaction from django.db import transaction
from django.urls import reverse, reverse_lazy from django.urls import reverse, reverse_lazy
@ -333,7 +335,7 @@ class EditInterventionForm(NewInterventionForm):
self.instance.responsible.conservation_file_number = conservation_file_number self.instance.responsible.conservation_file_number = conservation_file_number
self.instance.responsible.save() self.instance.responsible.save()
user_action = UserActionLogEntry.get_edited_action(user) user_action = self.instance.mark_as_edited(user, edit_comment=EDITED_GENERAL_DATA)
geometry = geom_form.save(user_action) geometry = geom_form.save(user_action)
self.instance.geometry = geometry self.instance.geometry = geometry
@ -347,8 +349,5 @@ class EditInterventionForm(NewInterventionForm):
self.instance.modified = user_action self.instance.modified = user_action
self.instance.save() self.instance.save()
# Uncheck and unrecord intervention due to changed data
self.instance.mark_as_edited(user)
return self.instance return self.instance

@ -6,13 +6,14 @@ Created on: 27.09.21
""" """
from dal import autocomplete from dal import autocomplete
from user.models import User
from konova.utils.message_templates import DEDUCTION_ADDED, REVOCATION_ADDED
from user.models import User, UserActionLogEntry
from django.db import transaction from django.db import transaction
from django import forms from django import forms
from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from compensation.models import EcoAccount from compensation.models import EcoAccount, EcoAccountDeduction
from intervention.inputs import TextToClipboardInput from intervention.inputs import TextToClipboardInput
from intervention.models import Intervention, InterventionDocument from intervention.models import Intervention, InterventionDocument
from konova.forms import BaseModalForm, NewDocumentForm from konova.forms import BaseModalForm, NewDocumentForm
@ -80,10 +81,8 @@ class ShareModalForm(BaseModalForm):
""" """
# Initialize share_link field # Initialize share_link field
url_name = f"{self.instance._meta.app_label}:share" share_link = self.instance.get_share_link()
self.share_link = self.request.build_absolute_uri( self.share_link = self.request.build_absolute_uri(share_link)
reverse(url_name, args=(self.instance.id, self.instance.access_token,))
)
self.initialize_form_field( self.initialize_form_field(
"url", "url",
self.share_link self.share_link
@ -169,7 +168,7 @@ class NewRevocationModalForm(BaseModalForm):
def save(self): def save(self):
revocation = self.instance.add_revocation(self) revocation = self.instance.add_revocation(self)
self.instance.mark_as_edited(self.user, self.request) self.instance.mark_as_edited(self.user, self.request, edit_comment=REVOCATION_ADDED)
return revocation return revocation
@ -368,9 +367,26 @@ class NewDeductionModalForm(BaseModalForm):
) )
return is_valid_surface and super_result return is_valid_surface and super_result
def __create_deduction(self):
""" Creates the deduction
Returns:
"""
with transaction.atomic():
user_action_create = UserActionLogEntry.get_created_action(self.user)
deduction = EcoAccountDeduction.objects.create(
intervention=self.cleaned_data["intervention"],
account=self.cleaned_data["account"],
surface=self.cleaned_data["surface"],
created=user_action_create,
)
return deduction
def save(self): def save(self):
deduction = self.instance.add_deduction(self) deduction = self.__create_deduction()
self.instance.mark_as_edited(self.user, self.request, reset_recorded=False) self.cleaned_data["intervention"].mark_as_edited(self.user, edit_comment=DEDUCTION_ADDED)
self.cleaned_data["account"].mark_as_edited(self.user, edit_comment=DEDUCTION_ADDED, reset_recorded=False)
return deduction return deduction

@ -8,6 +8,7 @@ Created on: 15.11.21
import shutil import shutil
from django.contrib import messages from django.contrib import messages
from django.urls import reverse
from django.utils import timezone from django.utils import timezone
from user.models import User from user.models import User
@ -25,7 +26,7 @@ from konova.models import generate_document_file_upload_path, AbstractDocument,
ShareableObjectMixin, \ ShareableObjectMixin, \
RecordableObjectMixin, CheckableObjectMixin, GeoReferencedMixin RecordableObjectMixin, CheckableObjectMixin, GeoReferencedMixin
from konova.settings import LANIS_LINK_TEMPLATE, LANIS_ZOOM_LUT, DEFAULT_SRID_RLP from konova.settings import LANIS_LINK_TEMPLATE, LANIS_ZOOM_LUT, DEFAULT_SRID_RLP
from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION, DEDUCTION_ADDED, DOCUMENT_REMOVED_TEMPLATE
from user.models import UserActionLogEntry from user.models import UserActionLogEntry
@ -228,28 +229,6 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
) )
return revocation return revocation
def add_deduction(self, form):
""" Adds a new deduction to the intervention
Args:
form (NewDeductionModalForm): The form holding the data
Returns:
"""
form_data = form.cleaned_data
user = form.user
with transaction.atomic():
user_action_create = UserActionLogEntry.get_created_action(user)
deduction = EcoAccountDeduction.objects.create(
intervention=self,
account=form_data["account"],
surface=form_data["surface"],
created=user_action_create,
)
return deduction
def mark_as_edited(self, performing_user: User, request: HttpRequest = None, edit_comment: str = None, reset_recorded: bool = True): def mark_as_edited(self, performing_user: User, request: HttpRequest = None, edit_comment: str = None, reset_recorded: bool = True):
""" In case the object or a related object changed, internal processes need to be started, such as """ In case the object or a related object changed, internal processes need to be started, such as
unrecord and uncheck unrecord and uncheck
@ -263,9 +242,10 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
Returns: Returns:
""" """
super().mark_as_edited(performing_user, request, edit_comment, reset_recorded) action = super().mark_as_edited(performing_user, request, edit_comment, reset_recorded)
if self.checked: if self.checked:
self.set_unchecked() self.set_unchecked()
return action
def set_status_messages(self, request: HttpRequest): def set_status_messages(self, request: HttpRequest):
""" Setter for different information that need to be rendered """ Setter for different information that need to be rendered
@ -299,6 +279,14 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
and is_free_of_revocations and is_free_of_revocations
return is_ready return is_ready
def get_share_link(self):
""" Returns the share url for the object
Returns:
"""
return reverse("intervention:share", args=(self.id, self.access_token))
class InterventionDocument(AbstractDocument): class InterventionDocument(AbstractDocument):
""" """
@ -314,7 +302,7 @@ class InterventionDocument(AbstractDocument):
max_length=1000, max_length=1000,
) )
def delete(self, *args, **kwargs): def delete(self, user=None, *args, **kwargs):
""" """
Custom delete functionality for InterventionDocuments. Custom delete functionality for InterventionDocuments.
Removes the folder from the file system if there are no further documents for this entry. Removes the folder from the file system if there are no further documents for this entry.
@ -336,6 +324,9 @@ class InterventionDocument(AbstractDocument):
folder_path = self.file.path.split("/")[:-1] folder_path = self.file.path.split("/")[:-1]
folder_path = "/".join(folder_path) folder_path = "/".join(folder_path)
if user:
self.instance.mark_as_edited(user, edit_comment=DOCUMENT_REMOVED_TEMPLATE.format(self.title))
# Remove the file itself # Remove the file itself
super().delete(*args, **kwargs) super().delete(*args, **kwargs)

@ -9,7 +9,10 @@ Created on: 15.11.21
import shutil import shutil
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.core.exceptions import ObjectDoesNotExist
from konova.models import BaseResource, AbstractDocument, generate_document_file_upload_path from konova.models import BaseResource, AbstractDocument, generate_document_file_upload_path
from konova.utils.message_templates import REVOCATION_REMOVED
class Revocation(BaseResource): class Revocation(BaseResource):
@ -20,12 +23,23 @@ class Revocation(BaseResource):
legal = models.ForeignKey("Legal", null=False, blank=False, on_delete=models.CASCADE, help_text="Refers to 'Widerspruch am'", related_name="revocations") legal = models.ForeignKey("Legal", null=False, blank=False, on_delete=models.CASCADE, help_text="Refers to 'Widerspruch am'", related_name="revocations")
comment = models.TextField(null=True, blank=True) comment = models.TextField(null=True, blank=True)
def delete(self, *args, **kwargs): def delete(self, user=None, *args, **kwargs):
# Make sure related objects are being removed as well # Make sure related objects are being removed as well
if self.document: try:
self.document.delete(*args, **kwargs) self.document.delete(*args, **kwargs)
except ObjectDoesNotExist:
# No file to delete
pass
if user is not None:
self.legal.intervention.mark_as_edited(user, edit_comment=REVOCATION_REMOVED)
super().delete() super().delete()
@property
def intervention(self):
return self.legal.intervention
class RevocationDocument(AbstractDocument): class RevocationDocument(AbstractDocument):
""" """

@ -22,11 +22,11 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th scope="col"> <th class="w-25" scope="col">
{% trans 'Identifier' %} {% trans 'Identifier' %}
</th> </th>
<th scope="col"> <th scope="col">
@ -34,7 +34,9 @@
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -50,7 +52,7 @@
<td class="align-middle">{{ comp.title }}</td> <td class="align-middle">{{ comp.title }}</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:remove' comp.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove compensation' %}"> <button data-form-url="{% url 'intervention:remove-compensation' obj.id comp.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove compensation' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:acc-new-deduction' obj.id %}" title="{% trans 'Add new deduction' %}"> <button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-deduction' obj.id %}" title="{% trans 'Add new deduction' %}">
{% fa5_icon 'plus' %} {% fa5_icon 'plus' %}
{% fa5_icon 'tree' %} {% fa5_icon 'tree' %}
</button> </button>
@ -20,11 +20,11 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th scope="col"> <th class="w-25" scope="col">
{% trans 'Account Identifier' %} {% trans 'Account Identifier' %}
</th> </th>
<th scope="col"> <th scope="col">
@ -35,7 +35,9 @@
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -44,7 +46,7 @@
{% for deduction in obj.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 %}> <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"> <td class="align-middle">
<a href="{% url 'compensation:acc-detail' deduction.account.id %}"> <a href="{% url 'compensation:acc:detail' deduction.account.id %}">
{% if deduction.account.deleted or not deduction.account.recorded %} {% if deduction.account.deleted or not deduction.account.recorded %}
{% fa5_icon 'exclamation-triangle' %} {% fa5_icon 'exclamation-triangle' %}
{% endif %} {% endif %}
@ -55,7 +57,7 @@
<td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td> <td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc-remove-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove Deduction' %}"> <button data-form-url="{% url 'intervention:remove-deduction' obj.id deduction.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove Deduction' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -20,19 +20,21 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th scope="col"> <th scope="col">
{% trans 'Title' %} {% trans 'Title' %}
</th> </th>
<th scope="col"> <th class="w-50" scope="col">
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -40,15 +42,19 @@
<tbody> <tbody>
{% for doc in obj.documents.all %} {% for doc in obj.documents.all %}
<tr> <tr>
<td class="align-middle"> <td>
<a href="{% url 'intervention:get-doc' doc.id %}"> <a href="{% url 'intervention:get-doc' doc.id %}">
{{ doc.title }} {{ doc.title }}
</a> </a>
</td> </td>
<td class="align-middle">{{ doc.comment }}</td> <td>
<div class="scroll-150">
{{ doc.comment }}
</div>
</td>
<td> <td>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'intervention:remove-doc' doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove document' %}"> <button data-form-url="{% url 'intervention:remove-doc' doc.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove document' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -11,7 +11,7 @@
<div class="col-sm-6"> <div class="col-sm-6">
<div class="d-flex justify-content-end"> <div class="d-flex justify-content-end">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:pay-new' obj.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 'plus' %}
{% fa5_icon 'money-bill-wave' %} {% fa5_icon 'money-bill-wave' %}
</button> </button>
@ -20,7 +20,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -30,12 +30,14 @@
<th scope="col"> <th scope="col">
{% trans 'Due on' %} {% trans 'Due on' %}
</th> </th>
<th scope="col"> <th class="w-50" scope="col">
{% trans 'Comment' %} {% trans 'Comment' %}
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -47,10 +49,14 @@
{{ pay.amount|floatformat:2 }} € {{ pay.amount|floatformat:2 }} €
</td> </td>
<td class="align-middle">{{ pay.due_on|default_if_none:"---" }}</td> <td class="align-middle">{{ pay.due_on|default_if_none:"---" }}</td>
<td class="align-middle">{{ pay.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ pay.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:pay-remove' pay.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove payment' %}"> <button data-form-url="{% url 'compensation:pay:remove' pay.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove payment' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -23,7 +23,7 @@
</div> </div>
</div> </div>
</div> </div>
<div class="card-body scroll-300"> <div class="card-body scroll-300 p-2">
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
@ -38,7 +38,9 @@
</th> </th>
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<th scope="col"> <th scope="col">
{% trans 'Action' %} <span class="float-right">
{% trans 'Action' %}
</span>
</th> </th>
{% endif %} {% endif %}
</tr> </tr>
@ -56,10 +58,14 @@
</a> </a>
{% endif %} {% endif %}
</td> </td>
<td class="align-middle">{{ rev.comment }}</td> <td class="align-middle">
<td> <div class="scroll-150">
{{ rev.comment }}
</div>
</td>
<td class="align-middle">
{% if is_default_member and has_access %} {% if is_default_member and has_access %}
<button data-form-url="{% url 'intervention:remove-revocation' rev.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove revocation' %}"> <button data-form-url="{% url 'intervention:remove-revocation' rev.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove revocation' %}">
{% fa5_icon 'trash' %} {% fa5_icon 'trash' %}
</button> </button>
{% endif %} {% endif %}

@ -14,16 +14,16 @@
{% block body %} {% block body %}
<div id="detail-header" class="row"> <div id="detail-header" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Intervention' %}<br> {{obj.identifier}}</h3> <h3>{% trans 'Intervention' %}<br> {{obj.identifier}}</h3>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'intervention/detail/includes/controls.html' %} {% include 'intervention/detail/includes/controls.html' %}
</div> </div>
</div> </div>
<hr> <hr>
<div id="data" class="row"> <div id="data" class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="table-container"> <div class="table-container">
<table class="table table-hover"> <table class="table table-hover">
<tr {% if not obj.title %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}> <tr {% if not obj.title %}class="alert alert-danger" title="{% trans 'Missing' %}" {% endif %}>
@ -122,7 +122,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>
@ -136,27 +136,29 @@
</div> </div>
<hr> <hr>
<div class="row"> <div id="related_data">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="row">
{% include 'intervention/detail/includes/compensations.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
</div> {% include 'intervention/detail/includes/compensations.html' %}
<div class="col-sm-12 col-md-12 col-lg-6"> </div>
{% include 'intervention/detail/includes/payments.html' %} <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
</div> {% include 'intervention/detail/includes/payments.html' %}
</div> </div>
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6">
{% include 'intervention/detail/includes/deductions.html' %}
</div>
<div class="col-sm-12 col-md-12 col-lg-6">
{% include 'intervention/detail/includes/revocation.html' %}
</div> </div>
</div> <div class="row">
<div class="row"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="col-sm-12 col-md-12 col-lg-6"> {% include 'intervention/detail/includes/deductions.html' %}
{% include 'intervention/detail/includes/documents.html' %} </div>
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'intervention/detail/includes/revocation.html' %}
</div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
{% include 'intervention/detail/includes/documents.html' %}
</div>
<div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
</div>
</div> </div>
</div> </div>

@ -3,7 +3,7 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<h3>{% trans 'Report' %}</h3> <h3>{% trans 'Report' %}</h3>
<h4>{{obj.identifier}}</h4> <h4>{{obj.identifier}}</h4>
<div class="table-container"> <div class="table-container">
@ -62,7 +62,7 @@
<th scope="row">{% trans 'Deductions of eco-accounts' %}</th> <th scope="row">{% trans 'Deductions of eco-accounts' %}</th>
<td class="align-middle"> <td class="align-middle">
{% for deduction in deductions %} {% for deduction in deductions %}
<a href="{% url 'compensation:acc-report' deduction.account.id %}"> <a href="{% url 'compensation:acc:report' deduction.account.id %}">
{{deduction.account.identifier}} - {{deduction.account.title}} {{deduction.account.identifier}} - {{deduction.account.title}}
</a> </a>
<br> <br>
@ -96,7 +96,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="col-sm-12 col-md-12 col-lg-6"> <div class="col-sm-12 col-md-12 col-lg-12 col-xl-6">
<div class="row"> <div class="row">
{% include 'map/geom_form.html' %} {% include 'map/geom_form.html' %}
</div> </div>

@ -210,7 +210,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
# Attention: Despite the fact, this url refers to a compensation app route, we test it here for the interventions. # Attention: Despite the fact, this url refers to a compensation app route, we test it here for the interventions.
# Reason: A payment is some kind of compensation for an intervention. Therefore it lives inside the compensation app. # Reason: A payment is some kind of compensation for an intervention. Therefore it lives inside the compensation app.
# BUT: Payments are added on the intervention detail page. Therefore it's part of a regular intervention workflow. # BUT: Payments are added on the intervention detail page. Therefore it's part of a regular intervention workflow.
new_payment_url = reverse("compensation:pay-new", args=(self.intervention.id,)) new_payment_url = reverse("compensation:pay:new", args=(self.intervention.id,))
# Make sure there are no payments on the intervention, yet # Make sure there are no payments on the intervention, yet
self.assertEqual(0, self.intervention.payments.count()) self.assertEqual(0, self.intervention.payments.count())
@ -251,7 +251,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
""" """
# Create removing url for the payment # Create removing url for the payment
remove_url = reverse("compensation:pay-remove", args=(payment.id,)) remove_url = reverse("compensation:pay:remove", args=(payment.id,))
post_data = { post_data = {
"confirm": True, "confirm": True,
} }
@ -390,7 +390,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
""" """
# Create the url for creating a new deduction # Create the url for creating a new deduction
new_url = reverse("compensation:acc-new-deduction", args=(self.eco_account.id,)) new_url = reverse("compensation:acc:new-deduction", args=(self.eco_account.id,))
# Prepare the form data # Prepare the form data
test_surface = 100.00 test_surface = 100.00
@ -415,7 +415,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
""" """
# Prepare url for deleting of this deduction # Prepare url for deleting of this deduction
delete_url = reverse("compensation:acc-remove-deduction", args=(self.eco_account.id, deduction.id,)) delete_url = reverse("compensation:acc:remove-deduction", args=(self.eco_account.id, deduction.id,))
post_data = { post_data = {
"confirm": True "confirm": True
} }

@ -9,7 +9,8 @@ from django.urls import path
from intervention.views import index_view, new_view, detail_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, check_view, log_view, new_deduction_view, \ create_share_view, remove_revocation_view, new_revocation_view, check_view, log_view, new_deduction_view, \
record_view, remove_document_view, get_document_view, get_revocation_view, new_id_view, report_view record_view, remove_document_view, get_document_view, get_revocation_view, new_id_view, report_view, \
remove_deduction_view, remove_compensation_view
app_name = "intervention" app_name = "intervention"
urlpatterns = [ urlpatterns = [
@ -26,13 +27,17 @@ urlpatterns = [
path('<id>/record', record_view, name='record'), path('<id>/record', record_view, name='record'),
path('<id>/report', report_view, name='report'), path('<id>/report', report_view, name='report'),
# Compensations
path('<id>/remove/<comp_id>', remove_compensation_view, name='remove-compensation'),
# Documents # Documents
path('<id>/document/new/', new_document_view, name='new-doc'), path('<id>/document/new/', new_document_view, name='new-doc'),
path('document/<doc_id>', get_document_view, name='get-doc'), path('document/<doc_id>', get_document_view, name='get-doc'),
path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'), path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),
# Deductions # Deductions
path('<id>/deduction/new', new_deduction_view, name='acc-new-deduction'), path('<id>/deduction/new', new_deduction_view, name='new-deduction'),
path('<id>/remove/<deduction_id>', remove_deduction_view, name='remove-deduction'),
# Revocation routes # Revocation routes
path('<id>/revocation/new', new_revocation_view, name='new-revocation'), path('<id>/revocation/new', new_revocation_view, name='new-revocation'),

@ -1,6 +1,7 @@
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.http import HttpRequest, JsonResponse from django.http import HttpRequest, JsonResponse, Http404
from django.shortcuts import render from django.shortcuts import render
from intervention.forms.forms import NewInterventionForm, EditInterventionForm from intervention.forms.forms import NewInterventionForm, EditInterventionForm
@ -15,7 +16,8 @@ from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.documents import remove_document, get_document from konova.utils.documents import remove_document, get_document
from konova.utils.generators import generate_qr_code from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import INTERVENTION_INVALID, FORM_INVALID, IDENTIFIER_REPLACED, \ from konova.utils.message_templates import INTERVENTION_INVALID, FORM_INVALID, IDENTIFIER_REPLACED, \
CHECKED_RECORDED_RESET CHECKED_RECORDED_RESET, DEDUCTION_REMOVED, DEDUCTION_ADDED, REVOCATION_ADDED, REVOCATION_REMOVED, \
COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED
from konova.utils.user_checks import in_group from konova.utils.user_checks import in_group
@ -129,7 +131,8 @@ def new_document_view(request: HttpRequest, id: str):
form = NewInterventionDocumentForm(request.POST or None, request.FILES or None, instance=intervention, request=request) form = NewInterventionDocumentForm(request.POST or None, request.FILES or None, instance=intervention, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Document added") msg_success=DOCUMENT_ADDED,
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
) )
@ -348,10 +351,12 @@ def remove_revocation_view(request: HttpRequest, id: str):
""" """
obj = Revocation.objects.get(id=id) obj = Revocation.objects.get(id=id)
form = RemoveModalForm(request.POST or None, instance=obj, request=request) form = RemoveModalForm(request.POST or None, instance=obj, request=request)
return form.process_request( return form.process_request(
request, request,
_("Revocation removed"), REVOCATION_REMOVED,
redirect_url=reverse("intervention:detail", args=(obj.intervention.id,)) + "#related_data"
) )
@ -455,7 +460,8 @@ def new_revocation_view(request: HttpRequest, id: str):
form = NewRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention, request=request) form = NewRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Revocation added") msg_success=REVOCATION_ADDED,
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
) )
@ -502,7 +508,36 @@ def new_deduction_view(request: HttpRequest, id: str):
form = NewDeductionModalForm(request.POST or None, instance=intervention, request=request) form = NewDeductionModalForm(request.POST or None, instance=intervention, request=request)
return form.process_request( return form.process_request(
request, request,
msg_success=_("Deduction added") msg_success=DEDUCTION_ADDED,
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data",
)
@login_required
@default_group_required
@shared_access_required(Intervention, "id")
def remove_deduction_view(request: HttpRequest, id: str, deduction_id: str):
""" Renders a modal view for removing deductions
Args:
request (HttpRequest): The incoming request
id (str): The intervention's id
deduction_id (str): The deduction's id
Returns:
"""
intervention = get_object_or_404(Intervention, id=id)
try:
eco_deduction = intervention.deductions.get(id=deduction_id)
except ObjectDoesNotExist:
raise Http404("Unknown deduction")
form = RemoveModalForm(request.POST or None, instance=eco_deduction, request=request)
return form.process_request(
request=request,
msg_success=DEDUCTION_REMOVED,
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
) )
@ -530,6 +565,31 @@ def record_view(request: HttpRequest, id: str):
) )
def remove_compensation_view(request:HttpRequest, id: str, comp_id: str):
""" Renders a modal view for removing the compensation
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
Returns:
"""
intervention = get_object_or_404(Intervention, id=id)
try:
comp = intervention.compensations.get(
id=comp_id
)
except ObjectDoesNotExist:
raise Http404("Unknown compensation")
form = RemoveModalForm(request.POST or None, instance=comp, request=request)
return form.process_request(
request=request,
msg_success=COMPENSATION_REMOVED_TEMPLATE.format(comp.identifier),
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data",
)
def report_view(request:HttpRequest, id: str): def report_view(request:HttpRequest, id: str):
""" Renders the public report view """ Renders the public report view

@ -8,6 +8,8 @@ Created on: 22.07.21
from django.contrib import admin from django.contrib import admin
from konova.models import Geometry, Deadline, GeometryConflict, Parcel, District from konova.models import Geometry, Deadline, GeometryConflict, Parcel, District
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE
from user.models import UserAction
class GeometryAdmin(admin.ModelAdmin): class GeometryAdmin(admin.ModelAdmin):
@ -78,6 +80,9 @@ class BaseObjectAdmin(BaseResourceAdmin):
"identifier", "identifier",
"title", "title",
] ]
actions = [
"restore_deleted_data"
]
def get_fields(self, request, obj=None): def get_fields(self, request, obj=None):
return super().get_fields(request, obj) + ["deleted"] return super().get_fields(request, obj) + ["deleted"]
@ -87,6 +92,14 @@ class BaseObjectAdmin(BaseResourceAdmin):
"deleted", "deleted",
] ]
def restore_deleted_data(self, request, queryset):
queryset = queryset.filter(
deleted__isnull=False
)
for entry in queryset:
entry.deleted.delete()
# Outcommented for a cleaner admin backend on production # Outcommented for a cleaner admin backend on production
#admin.site.register(Geometry, GeometryAdmin) #admin.site.register(Geometry, GeometryAdmin)

@ -327,7 +327,7 @@ class RemoveModalForm(BaseModalForm):
self.instance.mark_as_deleted(self.user) self.instance.mark_as_deleted(self.user)
else: else:
# If the class does not provide restorable delete functionality, we must delete the entry finally # If the class does not provide restorable delete functionality, we must delete the entry finally
self.instance.delete() self.instance.delete(self.user)
class NewDocumentForm(BaseModalForm): class NewDocumentForm(BaseModalForm):

@ -275,9 +275,9 @@ class RecordableObjectMixin(models.Model):
Returns: Returns:
""" """
action = UserActionLogEntry.get_edited_action(performing_user, edit_comment) edit_action = UserActionLogEntry.get_edited_action(performing_user, edit_comment)
self.modified = action self.modified = edit_action
self.log.add(action) self.log.add(edit_action)
self.save() self.save()
if self.recorded and reset_recorded: if self.recorded and reset_recorded:
@ -288,6 +288,7 @@ class RecordableObjectMixin(models.Model):
request, request,
CHECKED_RECORDED_RESET CHECKED_RECORDED_RESET
) )
return edit_action
@abstractmethod @abstractmethod
def is_ready_for_publish(self) -> bool: def is_ready_for_publish(self) -> bool:
@ -479,6 +480,15 @@ class ShareableObjectMixin(models.Model):
""" """
return self.users.all() return self.users.all()
@abstractmethod
def get_share_url(self):
""" Returns the share url for the object
Returns:
"""
raise NotImplementedError("Must be implemented in subclasses!")
class GeoReferencedMixin(models.Model): class GeoReferencedMixin(models.Model):
geometry = models.ForeignKey("konova.Geometry", null=True, blank=True, on_delete=models.SET_NULL) geometry = models.ForeignKey("konova.Geometry", null=True, blank=True, on_delete=models.SET_NULL)

@ -223,12 +223,27 @@ Overwrites bootstrap .btn:focus box shadow color
Extends css for django autocomplete light (dal) Extends css for django autocomplete light (dal)
No other approach worked to get the autocomplete fields to full width of parent containers No other approach worked to get the autocomplete fields to full width of parent containers
*/ */
.select2-container{ .select2{
width: 100% !important; width: 100% !important;
} }
/*
Similar to bootstraps 'shadow-lg'
*/
.select2-results{
box-shadow: 0 1rem 3rem rgba(0,0,0,.2) !important;
}
.select2-results__option--highlighted{ .select2-results__option--highlighted{
background-color: var(--rlp-red) !important; background-color: var(--rlp-red) !important;
} }
.select2-container--default .select2-results__group{
background-color: var(--rlp-gray-light);
}
.select2-container--default .select2-results__option .select2-results__option{
padding-left: 2em !important;
}
.select2-container--default .select2-results > .select2-results__options{ .select2-container--default .select2-results > .select2-results__options{
max-height: 500px !important; max-height: 500px !important;
} }
.select2-container--default .select2-results__option .select2-results__option{
padding-left: 2em;
}

@ -4,7 +4,7 @@
{% trans 'Eco-account' %} {% trans 'Eco-account' %}
</h4> </h4>
<div class="row"> <div class="row">
<a class="text-decoration-none" href="{% url 'compensation:acc-index' %}"> <a class="text-decoration-none" href="{% url 'compensation:acc:index' %}">
<div class="col-sm-5"> <div class="col-sm-5">
<div class="qs-box d-flex justify-content-center align-items-center"> <div class="qs-box d-flex justify-content-center align-items-center">
{% fa5_icon 'tree' %} {% fa5_icon 'tree' %}
@ -26,12 +26,12 @@
<div class="col-sm-12 col-lg"> <div class="col-sm-12 col-lg">
<div class="col-sm"> <div class="col-sm">
<div class="row my-1"> <div class="row my-1">
<a href="{% url 'compensation:acc-new' %}"> <a href="{% url 'compensation:acc:new' %}">
<button class="btn btn-default">{% fa5_icon 'plus' %} {% trans 'Create' %}</button> <button class="btn btn-default">{% fa5_icon 'plus' %} {% trans 'Create' %}</button>
</a> </a>
</div> </div>
<div class="row my-1"> <div class="row my-1">
<a href="{% url 'compensation:acc-index' %}"> <a href="{% url 'compensation:acc:index' %}">
<button class="btn btn-default">{% fa5_icon 'eye' %} {% trans 'Show' %}</button> <button class="btn btn-default">{% fa5_icon 'eye' %} {% trans 'Show' %}</button>
</a> </a>
</div> </div>

@ -52,3 +52,19 @@ def default_if_zero(val1, val2):
""" """
return val1 if val1 > 0 else val2 return val1 if val1 > 0 else val2
@register.filter("shorten")
def shorten(val, length):
""" Returns val shortened to the first number of length character
Args:
val (str): The value
length (int): The number of characters left
Returns:
"""
if val is not None and len(val) > length:
val = f"{val[:length]}..."
return val

@ -23,7 +23,7 @@ from konova.autocompletes import EcoAccountAutocomplete, \
ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete ShareUserAutocomplete, BiotopeExtraCodeAutocomplete, CompensationActionDetailCodeAutocomplete
from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
from konova.sso.sso import KonovaSSOClient from konova.sso.sso import KonovaSSOClient
from konova.views import logout_view, home_view, remove_deadline_view from konova.views import logout_view, home_view
sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY) sso_client = KonovaSSOClient(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
urlpatterns = [ urlpatterns = [
@ -40,9 +40,6 @@ urlpatterns = [
path('analysis/', include("analysis.urls")), path('analysis/', include("analysis.urls")),
path('api/', include("api.urls")), path('api/', include("api.urls")),
# Generic deadline routes
path('deadline/<id>/remove', remove_deadline_view, name="deadline-remove"),
# Autocomplete paths for all apps # Autocomplete paths for all apps
path("atcmplt/eco-accounts", EcoAccountAutocomplete.as_view(), name="accounts-autocomplete"), path("atcmplt/eco-accounts", EcoAccountAutocomplete.as_view(), name="accounts-autocomplete"),
path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="interventions-autocomplete"), path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="interventions-autocomplete"),

@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy as _
from konova.forms import RemoveModalForm from konova.forms import RemoveModalForm
from konova.models import AbstractDocument from konova.models import AbstractDocument
from konova.utils.message_templates import DOCUMENT_REMOVED_TEMPLATE
def get_document(doc: AbstractDocument): def get_document(doc: AbstractDocument):
@ -49,5 +50,5 @@ def remove_document(request: HttpRequest, doc: AbstractDocument):
form = RemoveModalForm(request.POST or None, instance=doc, request=request) form = RemoveModalForm(request.POST or None, instance=doc, request=request)
return form.process_request( return form.process_request(
request=request, request=request,
msg_success=_("Document '{}' deleted").format(title) msg_success=DOCUMENT_REMOVED_TEMPLATE.format(title)
) )

@ -21,6 +21,26 @@ CHECKED_RECORDED_RESET = _("Status of Checked and Recorded reseted")
# ECO ACCOUNT # ECO ACCOUNT
CANCEL_ACC_RECORDED_OR_DEDUCTED = _("Action canceled. Eco account is recorded or deductions exist. Only conservation office member can perform this action.") CANCEL_ACC_RECORDED_OR_DEDUCTED = _("Action canceled. Eco account is recorded or deductions exist. Only conservation office member can perform this action.")
# COMPENSATION
COMPENSATION_ADDED_TEMPLATE = _("Compensation {} added")
COMPENSATION_REMOVED_TEMPLATE = _("Compensation {} removed")
# DEDUCTIONS
DEDUCTION_ADDED = _("Deduction added")
DEDUCTION_REMOVED = _("Deduction removed")
# PAYMENTS
PAYMENT_ADDED = _("Payment added")
PAYMENT_REMOVED = _("Payment removed")
# REVOCATIONS
REVOCATION_ADDED = _("Revocation added")
REVOCATION_REMOVED = _("Revocation removed")
# DOCUMENTS
DOCUMENT_REMOVED_TEMPLATE = _("Document '{}' deleted")
DOCUMENT_ADDED = _("Document added")
# Edited # Edited
EDITED_GENERAL_DATA = _("Edited general data") EDITED_GENERAL_DATA = _("Edited general data")
ADDED_COMPENSATION_STATE = _("Added compensation state") ADDED_COMPENSATION_STATE = _("Added compensation state")

@ -99,25 +99,6 @@ def home_view(request: HttpRequest):
return render(request, template, context) return render(request, template, context)
@login_required
def remove_deadline_view(request: HttpRequest, id:str):
""" Renders a modal form for removing a deadline object
Args:
request (HttpRequest): The incoming request
id (str): The deadline id
Returns:
"""
deadline = get_object_or_404(Deadline, id=id)
form = RemoveModalForm(request.POST or None, instance=deadline, request=request)
return form.process_request(
request,
msg_success=_("Deadline removed")
)
def get_404_view(request: HttpRequest, exception=None): def get_404_view(request: HttpRequest, exception=None):
""" Returns a 404 handling view """ Returns a 404 handling view

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -23,20 +23,19 @@
{% include 'navbars/navbar.html' %} {% include 'navbars/navbar.html' %}
{% endblock %} {% endblock %}
</header> </header>
<div class="container-fluid mt-3 px-5"> <div class="col">
<div class="">
{% for message in messages %} {% for message in messages %}
<div class="row alert alert-{{ message.tags }}"> <div class="row alert alert-{{ message.tags }}">
{{ message }} {{ message }}
</div>
{% endfor %}
</div> </div>
{% endfor %}
</div>
<div class="container-fluid mt-3 px-4">
{% comment %} {% comment %}
The modal wrapper, which can be used on every view can stay on the base.html template The modal wrapper, which can be used on every view can stay on the base.html template
{% endcomment %} {% endcomment %}
<div class="modal fade" tabindex="-1" role="dialog" id="modal"> <div class="modal fade" tabindex="-1" role="dialog" id="modal">
<div class="modal-dialog modal-md modal-lg" role="document"> <div class="modal-dialog modal-md modal-xl" role="document">
<div class="modal-content"></div> <div class="modal-content"></div>
</div> </div>
</div> </div>

@ -3,12 +3,15 @@
<table class="table table-hover"> <table class="table table-hover">
<thead> <thead>
<tr> <tr>
<th scope="col"> <th scope="col" class="w-25">
{% trans 'Timestamp' %} {% trans 'Timestamp' %}
</th> </th>
<th scope="col"> <th scope="col">
{% trans 'Action' %} {% trans 'Action' %}
</th> </th>
<th scope="col">
{% trans 'Details' %}
</th>
<th scope="col"> <th scope="col">
{% trans 'User' %} {% trans 'User' %}
</th> </th>
@ -23,6 +26,9 @@
<td> <td>
{{ entry.action_humanize}} {{ entry.action_humanize}}
</td> </td>
<td>
{{ entry.comment|default_if_none:"-" }}
</td>
<td> <td>
{{entry.user}} {{entry.user}}
</td> </td>

@ -29,7 +29,7 @@
</a> </a>
</li> </li>
<li class=" menu-elem"> <li class=" menu-elem">
<a class="nav-btn nav-link" href="{% url 'compensation:acc-index' %}"> <a class="nav-btn nav-link" href="{% url 'compensation:acc:index' %}">
{% fa5_icon 'tree' %} {% fa5_icon 'tree' %}
{% trans 'Eco-account' %} {% trans 'Eco-account' %}
</a> </a>

Loading…
Cancel
Save