diff --git a/compensation/models.py b/compensation/models.py index 8e0dde35..a8584b31 100644 --- a/compensation/models.py +++ b/compensation/models.py @@ -248,6 +248,10 @@ class EcoAccount(AbstractCompensation): y, ) + def quality_check(self) -> (bool, dict): + # ToDo + pass + class EcoAccountWithdraw(BaseResource): """ diff --git a/compensation/templates/compensation/detail/eco_account/includes/controls.html b/compensation/templates/compensation/detail/eco_account/includes/controls.html index b09e3554..e7543612 100644 --- a/compensation/templates/compensation/detail/eco_account/includes/controls.html +++ b/compensation/templates/compensation/detail/eco_account/includes/controls.html @@ -13,11 +13,15 @@ {% if has_access %} {% if is_ets_member %} - - - + {% if obj.recorded %} + + {% else %} + + {% endif %} {% endif %} {% if is_default_member %} diff --git a/compensation/urls.py b/compensation/urls.py index 7b12765a..c36d45a5 100644 --- a/compensation/urls.py +++ b/compensation/urls.py @@ -24,6 +24,7 @@ urlaptterns_eco_acc = [ path('acc/new/', eco_account_views.new_view, name='acc-new'), path('acc/', eco_account_views.open_view, name='acc-open'), path('acc//log', eco_account_views.log_view, name='acc-log'), + path('acc//record', eco_account_views.record_view, name='acc-record'), path('acc//edit', eco_account_views.edit_view, name='acc-edit'), path('acc//remove', eco_account_views.remove_view, name='acc-remove'), path('acc//state/new', eco_account_views.state_new_view, name='acc-new-state'), diff --git a/compensation/views/eco_account_views.py b/compensation/views/eco_account_views.py index 650a1f78..084c9a9b 100644 --- a/compensation/views/eco_account_views.py +++ b/compensation/views/eco_account_views.py @@ -18,8 +18,8 @@ from compensation.models import EcoAccount from compensation.tables import EcoAccountTable from intervention.forms import NewWithdrawForm from konova.contexts import BaseContext -from konova.decorators import any_group_check, default_group_required -from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm +from konova.decorators import any_group_check, default_group_required, conservation_office_group_required +from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordForm from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.utils.user_checks import in_group @@ -188,6 +188,28 @@ def log_view(request: HttpRequest, id: str): return render(request, template, context) +@login_required +@conservation_office_group_required +def record_view(request: HttpRequest, id:str): + """ Renders a modal form for recording an eco account + + Args: + request (HttpRequest): The incoming request + id (str): The account's id + + Returns: + + """ + acc = get_object_or_404(EcoAccount, id=id) + form = RecordForm(request.POST or None, instance=acc, user=request.user) + msg_succ = _("{} unrecorded") if acc.recorded else _("{} recorded") + msg_succ = msg_succ.format(acc.identifier) + return form.process_request( + request, + msg_succ + ) + + @login_required def state_new_view(request: HttpRequest, id: str): """ Renders a form for adding new states for an eco account diff --git a/intervention/forms.py b/intervention/forms.py index 5e69a755..afdf3341 100644 --- a/intervention/forms.py +++ b/intervention/forms.py @@ -408,9 +408,13 @@ class RunCheckForm(BaseModalForm): def is_valid(self): super_result = super().is_valid() # Perform check - result, msgs = self.instance.check_validity() - self.errors.update(msgs) - return result & super_result + msgs = self.instance.quality_check() + for msg in msgs: + self.add_error( + "checked_intervention", + msg + ) + return super_result and (len(msgs) == 0) def save(self): with transaction.atomic(): diff --git a/intervention/models.py b/intervention/models.py index f5867b26..40f2f672 100644 --- a/intervention/models.py +++ b/intervention/models.py @@ -194,39 +194,62 @@ class Intervention(BaseObject): self.identifier = new_id super().save(*args, **kwargs) - def check_validity(self) -> (bool, dict): - """ Validity check + def quality_check(self) -> list: + """ Quality check + + Returns: + ret_msgs (list): True if quality acceptable, False otherwise + """ + ret_msgs = [] + + self._check_quality_responsible_data(ret_msgs) + self._check_quality_legal_data(ret_msgs) + + # ToDo: Extend for more! + + return ret_msgs + + def _check_quality_responsible_data(self, ret_msgs: list): + """ Checks data quality of related ResponsibilityData + + Args: + ret_msgs (dict): Holds error messages Returns: """ - ret_msgs = {} - missing_str = _("Missing") - not_missing_str = _("Exists") + try: + # Check for file numbers + if not self.responsible.registration_file_number or len(self.responsible.registration_file_number) == 0: + ret_msgs.append(_("Registration office file number missing")) - # Check responsible data - if self.responsible: - if self.responsible.registration_file_number is None or len(self.responsible.registration_file_number) == 0: - ret_msgs["Registration office file number"] = missing_str - if self.responsible.conservation_file_number is None or len(self.responsible.conservation_file_number) == 0: - ret_msgs["Conversation office file number"] = missing_str - else: - ret_msgs["responsible"] = missing_str + if not self.responsible.conservation_file_number or len(self.responsible.conservation_file_number) == 0: + ret_msgs.append(_("Conversation office file number missing")) + except AttributeError: + # responsible data not found + ret_msgs.append(_("Responsible data missing")) - # Check revocation - if self.legal.revocation: - ret_msgs["Revocation"] = not_missing_str + def _check_quality_legal_data(self, ret_msgs: list): + """ Checks data quality of related LegalData + + Args: + ret_msgs (dict): Holds error messages + + Returns: + + """ + try: + # Check for a revocation + if self.legal.revocation: + ret_msgs.append(_("Revocation exists")) - if self.legal: if self.legal.registration_date is None: - ret_msgs["Registration date"] = missing_str - if self.legal.binding_date is None: - ret_msgs["Binding on"] = missing_str - else: - ret_msgs["legal"] = missing_str + ret_msgs.append(_("Registration date missing")) - ret_result = len(ret_msgs) == 0 - return ret_result, ret_msgs + if self.legal.binding_date is None: + ret_msgs.append(_("Binding on missing")) + except AttributeError: + ret_msgs.append(_("Legal data missing")) def get_LANIS_link(self) -> str: """ Generates a link for LANIS depending on the geometry @@ -248,4 +271,4 @@ class Intervention(BaseObject): zoom_lvl, x, y, - ) \ No newline at end of file + ) diff --git a/intervention/templates/intervention/detail/includes/controls.html b/intervention/templates/intervention/detail/includes/controls.html index ef263d93..77a749af 100644 --- a/intervention/templates/intervention/detail/includes/controls.html +++ b/intervention/templates/intervention/detail/includes/controls.html @@ -12,33 +12,37 @@ {% if has_access %} - - {% if is_zb_member %} - - {% endif %} - {% if is_ets_member %} - - - - {% endif %} - {% if is_default_member %} - - + {% endif %} + {% if is_ets_member %} + {% if intervention.recorded %} + + {% else %} + + {% endif %} + {% endif %} + {% if is_default_member %} + + + + + - - - {% endif %} {% endif %} \ No newline at end of file diff --git a/intervention/urls.py b/intervention/urls.py index 05f580b8..97f8241c 100644 --- a/intervention/urls.py +++ b/intervention/urls.py @@ -8,7 +8,8 @@ Created on: 30.11.20 from django.urls import path from intervention.views import index_view, new_view, open_view, edit_view, remove_view, new_document_view, share_view, \ - create_share_view, remove_revocation_view, new_revocation_view, run_check_view, log_view, new_withdraw_view + create_share_view, remove_revocation_view, new_revocation_view, run_check_view, log_view, new_withdraw_view, \ + record_view app_name = "intervention" urlpatterns = [ @@ -22,6 +23,7 @@ urlpatterns = [ path('/share/', share_view, name='share'), path('/share', create_share_view, name='share-create'), path('/check', run_check_view, name='run-check'), + path('/record', record_view, name='record'), # Withdraws path('/withdraw/new', new_withdraw_view, name='acc-new-withdraw'), diff --git a/intervention/views.py b/intervention/views.py index 432fea52..f9df7265 100644 --- a/intervention/views.py +++ b/intervention/views.py @@ -10,9 +10,9 @@ from intervention.models import Intervention, Revocation from intervention.tables import InterventionTable from konova.contexts import BaseContext from konova.decorators import * -from konova.forms import SimpleGeomForm, NewDocumentForm, RemoveModalForm +from konova.forms import SimpleGeomForm, NewDocumentForm, RemoveModalForm, RecordForm from konova.sub_settings.django_settings import DEFAULT_DATE_FORMAT -from konova.utils.message_templates import FORM_INVALID +from konova.utils.message_templates import FORM_INVALID, INTERVENTION_INVALID from konova.utils.user_checks import in_group @@ -304,34 +304,11 @@ def run_check_view(request: HttpRequest, id: str): """ intervention = get_object_or_404(Intervention, id=id) form = RunCheckForm(request.POST or None, instance=intervention, user=request.user) - if request.method == "POST": - if form.is_valid(): - form.save() - messages.info( - request, - _("Check performed") - ) - else: - messages.error( - request, - _("There has been errors on this intervention:"), - extra_tags="danger" - ) - for error_name, error_val in form.errors.items(): - messages.error( - request, - _("{}: {}").format(_(error_name), _(error_val)), - extra_tags="danger" - ) - return redirect(request.META.get("HTTP_REFERER", "home")) - elif request.method == "GET": - context = { - "form": form, - } - context = BaseContext(request, context).context - return render(request, form.template, context) - else: - raise NotImplementedError + return form.process_request( + request, + msg_success=_("Check performed"), + msg_error=INTERVENTION_INVALID + ) @login_required @@ -413,3 +390,26 @@ def new_withdraw_view(request: HttpRequest, id: str): request, msg_success=_("Withdraw added") ) + + +@login_required +@conservation_office_group_required +def record_view(request: HttpRequest, id: str): + """ Renders a modal form for recording an intervention + + Args: + request (HttpRequest): The incoming request + id (str): The intervention's id + + Returns: + + """ + intervention = get_object_or_404(Intervention, id=id) + form = RecordForm(request.POST or None, instance=intervention, user=request.user) + msg_succ = _("{} unrecorded") if intervention.recorded else _("{} recorded") + msg_succ = msg_succ.format(intervention.identifier) + return form.process_request( + request, + msg_succ, + msg_error=_("There are errors on this intervention:") + ) \ No newline at end of file diff --git a/konova/forms.py b/konova/forms.py index 36717d98..86c75b36 100644 --- a/konova/forms.py +++ b/konova/forms.py @@ -20,6 +20,8 @@ from django.shortcuts import redirect, render from django.utils import timezone from django.utils.translation import gettext_lazy as _ +from compensation.models import EcoAccount +from intervention.models import Intervention from konova.contexts import BaseContext from konova.models import Document, BaseObject from konova.utils.message_templates import FORM_INVALID @@ -328,3 +330,71 @@ class NewDocumentForm(BaseModalForm): self.instance.log.add(edited_action) return doc + + +class RecordForm(BaseModalForm): + """ Modal form for recording data + + """ + confirm = forms.BooleanField( + label=_("Confirm record"), + label_suffix="", + widget=forms.CheckboxInput(), + required=True, + ) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.form_title = _("Record data") + self.form_caption = _("I, {} {}, confirm that all necessary control steps have been performed by myself.").format(self.user.first_name, self.user.last_name) + + if self.instance.recorded: + # unrecord! + self.fields["confirm"].label = _("Confirm unrecord") + self.form_title = _("Unrecord data") + self.form_caption = _("I, {} {}, confirm that this data must be unrecorded.").format(self.user.first_name, self.user.last_name) + + implemented_cls_logic = { + Intervention, + EcoAccount + } + instance_name = self.instance.__class__ + if instance_name not in implemented_cls_logic: + raise NotImplementedError + + def is_valid(self): + """ Checks for instance's validity and data quality + + Returns: + + """ + super_val = super().is_valid() + msgs = self.instance.quality_check() + for msg in msgs: + self.add_error( + "confirm", + msg + ) + return super_val and (len(msgs) == 0) + + def save(self): + with transaction.atomic(): + if self.cleaned_data["confirm"]: + if self.instance.recorded: + # unrecord! + unrecord_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.UNRECORDED + ) + # Do not delete the old .recorded attribute, since it shall stay in the .log list! + self.instance.recorded = None + self.instance.log.add(unrecord_action) + else: + record_action = UserActionLogEntry.objects.create( + user=self.user, + action=UserAction.RECORDED + ) + self.instance.recorded = record_action + self.instance.log.add(record_action) + self.instance.save() + return self.instance \ No newline at end of file diff --git a/konova/management/commands/setup_data.py b/konova/management/commands/setup_data.py index 396e5c18..91082bd0 100644 --- a/konova/management/commands/setup_data.py +++ b/konova/management/commands/setup_data.py @@ -8,7 +8,6 @@ Created on: 15.12.20 from django.utils.translation import gettext_lazy as _ from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP -from user.enums import UserNotificationEnum TEST_ORGANISATION_DATA = [ { diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py index ca701dcf..109d7c83 100644 --- a/konova/utils/message_templates.py +++ b/konova/utils/message_templates.py @@ -9,3 +9,4 @@ from django.utils.translation import gettext_lazy as _ FORM_INVALID = _("There was an error on this form.") +INTERVENTION_INVALID = _("There are errors in this intervention.") diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index c1e769b4..189b3213 100644 Binary files a/locale/de/LC_MESSAGES/django.mo and b/locale/de/LC_MESSAGES/django.mo differ diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index d9622951..0059cdea 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -16,7 +16,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-10 14:11+0200\n" +"POT-Creation-Date: 2021-08-10 14:39+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -384,19 +384,19 @@ msgid "Public report" msgstr "Öffentlicher Bericht" #: compensation/templates/compensation/detail/compensation/includes/controls.html:17 -#: compensation/templates/compensation/detail/eco_account/includes/controls.html:17 +#: compensation/templates/compensation/detail/eco_account/includes/controls.html:28 #: intervention/templates/intervention/detail/includes/controls.html:32 msgid "Edit" msgstr "Bearbeiten" #: compensation/templates/compensation/detail/compensation/includes/controls.html:21 -#: compensation/templates/compensation/detail/eco_account/includes/controls.html:21 +#: compensation/templates/compensation/detail/eco_account/includes/controls.html:32 #: intervention/templates/intervention/detail/includes/controls.html:36 msgid "Show log" msgstr "Log anzeigen" #: compensation/templates/compensation/detail/compensation/includes/controls.html:24 -#: compensation/templates/compensation/detail/eco_account/includes/controls.html:24 +#: compensation/templates/compensation/detail/eco_account/includes/controls.html:35 #: intervention/templates/intervention/detail/includes/controls.html:39 #: venv/lib/python3.7/site-packages/django/forms/formsets.py:391 msgid "Delete" @@ -522,6 +522,15 @@ msgstr "Zuletzt bearbeitet" msgid "Shared with" msgstr "Freigegeben für" +#: compensation/templates/compensation/detail/eco_account/includes/controls.html:17 +msgid "Unrecord" +msgstr "Entzeichnen" + +#: compensation/templates/compensation/detail/eco_account/includes/controls.html:21 +#: intervention/templates/intervention/detail/includes/controls.html:25 +msgid "Record" +msgstr "Verzeichnen" + #: compensation/templates/compensation/detail/eco_account/includes/withdraws.html:8 #: intervention/templates/intervention/detail/includes/withdraws.html:8 msgid "Eco Account Withdraws" @@ -538,7 +547,7 @@ msgstr "Eingriffskennung" #: compensation/templates/compensation/detail/eco_account/includes/withdraws.html:34 #: intervention/templates/intervention/detail/includes/withdraws.html:34 -#: user/models.py:50 +#: user/models.py:51 msgid "Created" msgstr "Erstellt" @@ -567,22 +576,22 @@ msgid "Compensation removed" msgstr "Kompensation entfernt" #: compensation/views/compensation_views.py:162 -#: compensation/views/eco_account_views.py:262 intervention/views.py:96 +#: compensation/views/eco_account_views.py:275 intervention/views.py:96 msgid "Document added" msgstr "Dokument hinzugefügt" #: compensation/views/compensation_views.py:181 -#: compensation/views/eco_account_views.py:206 +#: compensation/views/eco_account_views.py:219 msgid "State added" msgstr "Zustand hinzugefügt" #: compensation/views/compensation_views.py:200 -#: compensation/views/eco_account_views.py:225 +#: compensation/views/eco_account_views.py:238 msgid "Action added" msgstr "Maßnahme hinzugefügt" #: compensation/views/compensation_views.py:219 -#: compensation/views/eco_account_views.py:244 +#: compensation/views/eco_account_views.py:257 msgid "Deadline added" msgstr "Frist hinzugefügt" @@ -602,7 +611,15 @@ msgstr "Ökokonto entfernt" msgid "Withdraw removed" msgstr "Abbuchung entfernt" -#: compensation/views/eco_account_views.py:282 intervention/views.py:414 +#: compensation/views/eco_account_views.py:196 +msgid "{} unrecorded" +msgstr "{} entzeichnet" + +#: compensation/views/eco_account_views.py:196 +msgid "{} recorded" +msgstr "{} verzeichnet" + +#: compensation/views/eco_account_views.py:295 intervention/views.py:414 msgid "Withdraw added" msgstr "Abbuchung hinzugefügt" @@ -748,7 +765,7 @@ msgstr "Kompensationen und Zahlungen geprüft" msgid "Run check" msgstr "Prüfung vornehmen" -#: intervention/forms.py:406 +#: intervention/forms.py:406 konova/forms.py:347 msgid "" "I, {} {}, confirm that all necessary control steps have been performed by " "myself." @@ -802,12 +819,12 @@ msgstr "" #: intervention/templates/intervention/detail/view.html:90 #: intervention/templates/intervention/detail/view.html:94 #: intervention/templates/intervention/detail/view.html:98 -msgid "Missing" -msgstr "Fehlt" +msgid "missing" +msgstr "fehlt" #: intervention/models.py:205 -msgid "Exists" -msgstr "Existiert" +msgid "exists" +msgstr "vorhanden" #: intervention/tables.py:70 msgid "Interventions" @@ -829,10 +846,6 @@ msgstr "Neue Kompensation hinzufügen" msgid "Remove compensation" msgstr "Kompensation entfernen" -#: intervention/templates/intervention/detail/includes/controls.html:25 -msgid "Record" -msgstr "Verzeichnen" - #: intervention/templates/intervention/detail/includes/payments.html:8 msgid "Payments" msgstr "Ersatzzahlungen" @@ -1024,27 +1037,47 @@ msgstr "Datei" msgid "Added document" msgstr "Dokument hinzugefügt" -#: konova/management/commands/setup_data.py:42 +#: konova/forms.py:338 +msgid "Confirm record" +msgstr "Verzeichnen bestätigen" + +#: konova/forms.py:346 +msgid "Record data" +msgstr "Daten verzeichnen" + +#: konova/forms.py:351 +msgid "Confirm unrecord" +msgstr "Entzeichnen bestätigen" + +#: konova/forms.py:352 +msgid "Unrecord data" +msgstr "Daten entzeichnen" + +#: konova/forms.py:353 +msgid "I, {} {}, confirm that this data must be unrecorded." +msgstr "Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen." + +#: konova/management/commands/setup_data.py:41 msgid "On new related data" msgstr "Wenn neue Daten für mich angelegt werden" -#: konova/management/commands/setup_data.py:43 +#: konova/management/commands/setup_data.py:42 msgid "On disabled share link" msgstr "Wenn ein Freigabelink deaktiviert wird" -#: konova/management/commands/setup_data.py:44 +#: konova/management/commands/setup_data.py:43 msgid "On shared access removed" msgstr "Wenn mir eine Freigabe zu Daten entzogen wird" -#: konova/management/commands/setup_data.py:45 +#: konova/management/commands/setup_data.py:44 msgid "On shared data recorded" msgstr "Wenn meine freigegebenen Daten verzeichnet wurden" -#: konova/management/commands/setup_data.py:46 +#: konova/management/commands/setup_data.py:45 msgid "On shared data deleted" msgstr "Wenn meine freigegebenen Daten gelöscht wurden" -#: konova/management/commands/setup_data.py:47 +#: konova/management/commands/setup_data.py:46 msgid "On registered data edited" msgstr "Wenn meine freigegebenen Daten bearbeitet wurden" @@ -1276,11 +1309,15 @@ msgstr "" msgid "User contact data" msgstr "Kontaktdaten" -#: user/models.py:51 +#: user/models.py:50 +msgid "Unrecorded" +msgstr "Entzeichnet" + +#: user/models.py:52 msgid "Edited" msgstr "Bearbeitet" -#: user/models.py:52 +#: user/models.py:53 msgid "Deleted" msgstr "Gelöscht" @@ -2552,9 +2589,6 @@ msgstr "" #~ msgid "Delete eco account" #~ msgstr "Ökokonto löschen" -#~ msgid "Confirm check on data" -#~ msgstr "Datenprüfung bestätigen" - #~ msgid "Add new EMA" #~ msgstr "Neue EMA hinzufügen" diff --git a/user/models.py b/user/models.py index ebeb5cff..d8d73206 100644 --- a/user/models.py +++ b/user/models.py @@ -47,6 +47,7 @@ class UserAction(models.TextChoices): """ CHECKED = "checked", _("Checked") RECORDED = "recorded", _("Recorded") + UNRECORDED = "unrecorded", _("Unrecorded") CREATED = "created", _("Created") EDITED = "edited", _("Edited") DELETED = "deleted", _("Deleted")