Compare commits
154 Commits
1.9.1
...
c4cd40913d
| Author | SHA1 | Date | |
|---|---|---|---|
| c4cd40913d | |||
| a70434e2cc | |||
| 1ac73e4bbb | |||
| a16fc2eb91 | |||
| 644aa2e3cd | |||
| c14aff771e | |||
| e239736a72 | |||
| 21af4f2c57 | |||
| 765356d064 | |||
| 00bf03f58d | |||
| 3de97e2f6a | |||
| 00109b6bfd | |||
| 971e3f20c8 | |||
| efb76278b4 | |||
| e0b8922494 | |||
| bfdf82ac46 | |||
| 0ad0b02f95 | |||
| a407c86dfb | |||
| abfc48d79b | |||
| 43846e8d2f | |||
| 5e01d7ccda | |||
| 5b1af04d66 | |||
| 0d939c9e19 | |||
| 7d80875727 | |||
| 53d5e03a3f | |||
| 34a8ea4aec | |||
| 478d630d76 | |||
| 00e2178f3c | |||
| 8a984d0169 | |||
| f4e97db9ac | |||
| 95510cef36 | |||
| 225d4e8ce1 | |||
| ca7411b6c3 | |||
| 43f313a71e | |||
| 241db2f51d | |||
| dce61c4d7e | |||
| 17d817bbe1 | |||
| aec10ee0af | |||
| 6df47f1615 | |||
| e25d549a97 | |||
| 5e65b8f4dc | |||
| 22cddb9902 | |||
| c986bd0b92 | |||
| 1b6eea2c9e | |||
| 2c60d86177 | |||
| b7792ececc | |||
| cf6f188ef3 | |||
| f122778232 | |||
| bc2e901ca9 | |||
| 4a16727da1 | |||
| 210f3fcafa | |||
| e7d67560f2 | |||
| b5e991fb95 | |||
| d3a555d406 | |||
| d85ebccec8 | |||
| 837c1de938 | |||
| fe2ac3d97d | |||
| 554ade6794 | |||
| 3a9c4e13f6 | |||
| 9a374f50de | |||
| ce63dd30bc | |||
| 1fc1b533cd | |||
| 1175fe3b37 | |||
| d2a57df080 | |||
| d5accb2143 | |||
| 6056a8882d | |||
| c7a4c309bf | |||
| a7b23935a1 | |||
| 97fbe02742 | |||
| ed5d571704 | |||
| a86d86b731 | |||
| 73178b3fd2 | |||
| 278a951e92 | |||
| 9e4a78ec60 | |||
| d03b714fb5 | |||
| a9b402862b | |||
| 61ec9c8c9b | |||
| f2baa054bf | |||
| 242730435e | |||
| afbdf221c3 | |||
| be9f6f1b7e | |||
| 80e8925a63 | |||
| c597e1934b | |||
| a44d8658d4 | |||
| bb71c0fcc8 | |||
| 67acddf701 | |||
| 21bb988d86 | |||
| 1ceffccd40 | |||
| e5db7f6b13 | |||
| 442f3ceb37 | |||
| cd2949fc03 | |||
| 7bcd32fd7a | |||
| 97f1882698 | |||
| 55cc8eb1f3 | |||
| d6cabd5f6c | |||
| 63a824f9d9 | |||
| a12c2fb57e | |||
| 23bc79ee3b | |||
| 07bac26a58 | |||
| d01816cf71 | |||
| f543dfc1cb | |||
| 62fc019127 | |||
| c01518b675 | |||
| f57306eb72 | |||
| c2b12649b0 | |||
| 6fe67a8fbf | |||
| b38a266bea | |||
| 15f86e866b | |||
| c85b136f0a | |||
| faf8aed777 | |||
| 94c498866f | |||
| 616965c890 | |||
| e39c7eb51f | |||
| 19bd408fbd | |||
| 7bfe6a37f8 | |||
| 9b63307f01 | |||
| 123a470006 | |||
| 5a0c5285e7 | |||
| 3a01eaff92 | |||
| 2af91aa178 | |||
| 53d0af89ac | |||
| 7b5c1f0d97 | |||
| ef076c0b3b | |||
| 72a5075f3b | |||
| d677ac6b5a | |||
| 9149e4cbd3 | |||
| 1c24cbea26 | |||
|
|
bc9cc09372 | ||
| 24518465f3 | |||
| 457548da4d | |||
| fa89bbba99 | |||
| 78eb711057 | |||
| 6ff67d12c9 | |||
| 3c1cbcd0bd | |||
| 416ad8478c | |||
| 6b28c4ec15 | |||
| 46a2a4ff46 | |||
| 90e5cf5b36 | |||
| 50f46e319c | |||
| e2ea087c4e | |||
| a6e43b044b | |||
| be0d261e81 | |||
| 62e1b046c3 | |||
| 669a12410f | |||
| dd77e6c16e | |||
| 33774ce557 | |||
| dc3dc99b3d | |||
| 315f9de958 | |||
| 0726c15086 | |||
| 2492a8abe8 | |||
| dbc5cba5d7 | |||
| c8948ddaea | |||
| 5039da28aa | |||
| 4567339570 |
@@ -24,6 +24,7 @@ DEFAULT_FROM_EMAIL=service@ksp.de
|
||||
|
||||
# Proxy
|
||||
PROXY=CHANGE_ME
|
||||
MAP_PROXY_HOST_WHITELIST=CHANGE_ME_1,CHANGE_ME_2
|
||||
GEOPORTAL_RLP_USER=CHANGE_ME
|
||||
GEOPORTAL_RLP_PASSWORD=CHANGE_ME
|
||||
|
||||
@@ -37,6 +38,7 @@ SSO_SERVER_BASE_URL=https://login.naturschutz.rlp.de
|
||||
OAUTH_CODE_VERIFIER=CHANGE_ME
|
||||
OAUTH_CLIENT_ID=CHANGE_ME
|
||||
OAUTH_CLIENT_SECRET=CHANGE_ME
|
||||
PROPAGATION_SECRET=CHANGE_ME
|
||||
|
||||
# RabbitMQ
|
||||
## For connections to EGON
|
||||
|
||||
@@ -51,7 +51,7 @@ class APIUserToken(models.Model):
|
||||
if token_obj.valid_until is not None and token_obj.valid_until < _today:
|
||||
raise PermissionError("Token validity expired")
|
||||
except ObjectDoesNotExist:
|
||||
raise PermissionError("Credentials invalid")
|
||||
raise PermissionError("Token unknown")
|
||||
return token_obj.user
|
||||
|
||||
|
||||
@@ -155,3 +155,25 @@ class OAuthToken(UuidModel):
|
||||
|
||||
return user
|
||||
|
||||
def revoke(self) -> int:
|
||||
""" Revokes the OAuth2 token of the user
|
||||
|
||||
(/o/revoke_token/ indeed removes the corresponding access token on provider side and invalidates the
|
||||
submitted refresh token in one step)
|
||||
|
||||
Returns:
|
||||
revocation_status_code (int): HTTP status code for revocation of refresh_token
|
||||
"""
|
||||
revoke_url = f"{SSO_SERVER_BASE}o/revoke_token/"
|
||||
token = self.refresh_token
|
||||
revocation_status_code = requests.post(
|
||||
revoke_url,
|
||||
data={
|
||||
'token': token,
|
||||
'token_type_hint': "refresh_token",
|
||||
},
|
||||
auth=(OAUTH_CLIENT_ID, OAUTH_CLIENT_SECRET),
|
||||
).status_code
|
||||
|
||||
return revocation_status_code
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ from django.contrib.gis import geos
|
||||
from django.urls import reverse
|
||||
|
||||
from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
|
||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
||||
from konova.models import Geometry
|
||||
|
||||
|
||||
class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
||||
@@ -64,7 +64,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
||||
|
||||
put_props = put_body["properties"]
|
||||
put_geom = geos.fromstr(json.dumps(put_body))
|
||||
put_geom.transform(DEFAULT_SRID_RLP)
|
||||
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||
self.assertEqual(put_geom, self.intervention.geometry.geom)
|
||||
self.assertEqual(put_props["title"], self.intervention.title)
|
||||
self.assertNotEqual(modified_on, self.intervention.modified)
|
||||
@@ -94,7 +94,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
||||
|
||||
put_props = put_body["properties"]
|
||||
put_geom = geos.fromstr(json.dumps(put_body))
|
||||
put_geom.transform(DEFAULT_SRID_RLP)
|
||||
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||
self.assertEqual(put_geom, self.compensation.geometry.geom)
|
||||
self.assertEqual(put_props["title"], self.compensation.title)
|
||||
self.assertNotEqual(modified_on, self.compensation.modified)
|
||||
@@ -124,7 +124,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
||||
|
||||
put_props = put_body["properties"]
|
||||
put_geom = geos.fromstr(json.dumps(put_body))
|
||||
put_geom.transform(DEFAULT_SRID_RLP)
|
||||
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||
self.assertEqual(put_geom, self.eco_account.geometry.geom)
|
||||
self.assertEqual(put_props["title"], self.eco_account.title)
|
||||
self.assertNotEqual(modified_on, self.eco_account.modified)
|
||||
@@ -156,7 +156,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase):
|
||||
|
||||
put_props = put_body["properties"]
|
||||
put_geom = geos.fromstr(json.dumps(put_body))
|
||||
put_geom.transform(DEFAULT_SRID_RLP)
|
||||
put_geom = Geometry.cast_to_rlp_srid(put_geom)
|
||||
self.assertEqual(put_geom, self.ema.geometry.geom)
|
||||
self.assertEqual(put_props["title"], self.ema.title)
|
||||
self.assertNotEqual(modified_on, self.ema.modified)
|
||||
|
||||
@@ -7,11 +7,8 @@ Created on: 21.01.22
|
||||
"""
|
||||
from django.urls import path, include
|
||||
|
||||
from api.views.method_views import generate_new_token_view
|
||||
|
||||
app_name = "api"
|
||||
|
||||
urlpatterns = [
|
||||
path("v1/", include("api.urls.v1.urls", namespace="v1")),
|
||||
path("token/generate", generate_new_token_view, name="generate-new-token"),
|
||||
]
|
||||
@@ -13,7 +13,7 @@ from django.contrib.gis.geos import GEOSGeometry
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Q
|
||||
|
||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
|
||||
from konova.models import Geometry
|
||||
from konova.utils.message_templates import DATA_UNSHARED
|
||||
|
||||
|
||||
@@ -145,8 +145,8 @@ class AbstractModelAPISerializer:
|
||||
if isinstance(geojson, dict):
|
||||
geojson = json.dumps(geojson)
|
||||
geometry = geos.fromstr(geojson)
|
||||
if geometry.srid != DEFAULT_SRID_RLP:
|
||||
geometry.transform(DEFAULT_SRID_RLP)
|
||||
geometry = Geometry.cast_to_rlp_srid(geometry)
|
||||
geometry = Geometry.cast_to_multipolygon(geometry)
|
||||
return geometry
|
||||
|
||||
def _get_obj_from_db(self, id, user):
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 27.01.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
|
||||
from api.models import APIUserToken
|
||||
|
||||
|
||||
@login_required
|
||||
def generate_new_token_view(request: HttpRequest):
|
||||
""" Handles request for fetching
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
|
||||
if request.method == "GET":
|
||||
token = APIUserToken()
|
||||
while APIUserToken.objects.filter(token=token.token).exists():
|
||||
token = APIUserToken()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": token.token
|
||||
}
|
||||
)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
@@ -50,14 +50,19 @@ class AbstractAPIView(View):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
try:
|
||||
# Fetch the proper user from the given request header token
|
||||
ksp_token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
|
||||
token = request.headers.get(KSP_TOKEN_HEADER_IDENTIFIER, None)
|
||||
ksp_user = request.headers.get(KSP_USER_HEADER_IDENTIFIER, None)
|
||||
token_user = APIUserToken.get_user_from_token(ksp_token)
|
||||
|
||||
if ksp_user != token_user.username:
|
||||
if not token and not ksp_user:
|
||||
bearer_token = request.headers.get("authorization", None)
|
||||
if not bearer_token:
|
||||
raise PermissionError("No token provided")
|
||||
token = bearer_token.split(" ")[1]
|
||||
|
||||
token_user = APIUserToken.get_user_from_token(token)
|
||||
if ksp_user and ksp_user != token_user.username:
|
||||
raise PermissionError(f"Invalid token for {ksp_user}")
|
||||
else:
|
||||
self.user = token_user
|
||||
self.user = token_user
|
||||
|
||||
request.user = self.user
|
||||
if not self.user.is_default_user():
|
||||
|
||||
@@ -82,8 +82,8 @@ class Command(BaseKonovaCommand):
|
||||
atom_id = element.find("atomid").text
|
||||
selectable = element.find("selectable").text.lower()
|
||||
selectable = bool_map.get(selectable, False)
|
||||
short_name = element.find("shortname").text
|
||||
long_name = element.find("longname").text
|
||||
short_name = element.find("shortname").text or ""
|
||||
long_name = element.find("longname").text or ""
|
||||
is_archived = bool_map.get((element.find("archive").text.lower()), False)
|
||||
|
||||
code = KonovaCode.objects.get_or_create(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Generated by Django 5.0.7 on 2024-08-06 13:40
|
||||
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db import migrations
|
||||
from django.db.models import Q
|
||||
|
||||
@@ -10,9 +11,12 @@ def migrate_975_to_288(apps, schema_editor):
|
||||
KonovaCodeList = apps.get_model('codelist', 'KonovaCodeList')
|
||||
CompensationState = apps.get_model('compensation', 'CompensationState')
|
||||
|
||||
list_288 = KonovaCodeList.objects.get(
|
||||
id=CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID
|
||||
).codes.all()
|
||||
try:
|
||||
list_288 = KonovaCodeList.objects.get(
|
||||
id=CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID
|
||||
).codes.all()
|
||||
except ObjectDoesNotExist:
|
||||
raise AssertionError("KonovaCodeList 288 does not exist. Did you run 'update_codelist' before migrating?")
|
||||
|
||||
states_with_extra_code = CompensationState.objects.filter(
|
||||
~Q(biotope_type_details=None)
|
||||
@@ -42,8 +46,15 @@ class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('codelist', '0001_initial'),
|
||||
('compensation', '0003_auto_20220202_0846'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_975_to_288)
|
||||
]
|
||||
# If migration of codelist is not necessary, this variable can shut down the logic whilst not disturbing the
|
||||
# migration history
|
||||
EXECUTE_CODELIST_MIGRATION = True
|
||||
|
||||
operations = []
|
||||
|
||||
if EXECUTE_CODELIST_MIGRATION:
|
||||
operations.append(migrations.RunPython(migrate_975_to_288))
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.0.8 on 2024-08-26 16:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('codelist', '0002_migrate_975_to_288'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='konovacode',
|
||||
name='long_name',
|
||||
field=models.CharField(blank=True, default="", max_length=1000),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='konovacode',
|
||||
name='short_name',
|
||||
field=models.CharField(blank=True, default="", help_text='Short version of long name', max_length=500),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
@@ -168,6 +168,17 @@ class NewCompensationForm(AbstractCompensationForm,
|
||||
comp.log.add(action)
|
||||
return comp, action
|
||||
|
||||
def is_valid(self):
|
||||
valid = super().is_valid()
|
||||
intervention = self.cleaned_data.get("intervention", None)
|
||||
if intervention.is_recorded:
|
||||
valid &= False
|
||||
self.add_error(
|
||||
"intervention",
|
||||
_("This intervention is currently recorded. You cannot add further compensations as long as it is recorded.")
|
||||
)
|
||||
return valid
|
||||
|
||||
def save(self, user: User, geom_form: SimpleGeomForm):
|
||||
with transaction.atomic():
|
||||
comp, action = self.__create_comp(user)
|
||||
|
||||
@@ -7,10 +7,12 @@ Created on: 18.08.22
|
||||
"""
|
||||
from dal import autocomplete
|
||||
from django import forms
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_COMPENSATION_ACTION_DETAIL_ID
|
||||
from compensation.models import CompensationAction
|
||||
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple
|
||||
from konova.forms.modals import BaseModalForm, RemoveModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_ACTION_EDITED, ADDED_COMPENSATION_ACTION
|
||||
@@ -114,7 +116,8 @@ class EditCompensationActionModalForm(NewCompensationActionModalForm):
|
||||
action = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.action = kwargs.pop("action", None)
|
||||
action_id = kwargs.pop("action_id", None)
|
||||
self.action = get_object_or_404(CompensationAction, id=action_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit action")
|
||||
form_data = {
|
||||
@@ -147,8 +150,8 @@ class RemoveCompensationActionModalForm(RemoveModalForm):
|
||||
action = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
action = kwargs.pop("action", None)
|
||||
self.action = action
|
||||
action_id = kwargs.pop("action_id", None)
|
||||
self.action = get_object_or_404(CompensationAction, id=action_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self):
|
||||
|
||||
@@ -6,10 +6,11 @@ Created on: 18.08.22
|
||||
|
||||
"""
|
||||
from django import forms
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from konova.forms.modals import BaseModalForm
|
||||
from konova.models import DeadlineType
|
||||
from konova.models import DeadlineType, Deadline
|
||||
from konova.utils import validators
|
||||
from konova.utils.message_templates import DEADLINE_EDITED
|
||||
|
||||
@@ -90,7 +91,8 @@ class EditDeadlineModalForm(NewDeadlineModalForm):
|
||||
deadline = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.deadline = kwargs.pop("deadline", None)
|
||||
deadline_id = kwargs.pop("deadline_id", None)
|
||||
self.deadline = get_object_or_404(Deadline, id=deadline_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit deadline")
|
||||
form_data = {
|
||||
|
||||
@@ -6,12 +6,27 @@ Created on: 18.08.22
|
||||
|
||||
"""
|
||||
from compensation.models import CompensationDocument, EcoAccountDocument
|
||||
from konova.forms.modals import NewDocumentModalForm
|
||||
from konova.forms.modals import NewDocumentModalForm, EditDocumentModalForm, RemoveDocumentModalForm
|
||||
|
||||
|
||||
class NewCompensationDocumentModalForm(NewDocumentModalForm):
|
||||
document_model = CompensationDocument
|
||||
_DOCUMENT_CLS = CompensationDocument
|
||||
|
||||
|
||||
class EditCompensationDocumentModalForm(EditDocumentModalForm):
|
||||
_DOCUMENT_CLS = CompensationDocument
|
||||
|
||||
|
||||
class RemoveCompensationDocumentModalForm(RemoveDocumentModalForm):
|
||||
_DOCUMENT_CLS = CompensationDocument
|
||||
|
||||
|
||||
class NewEcoAccountDocumentModalForm(NewDocumentModalForm):
|
||||
document_model = EcoAccountDocument
|
||||
_DOCUMENT_CLS = EcoAccountDocument
|
||||
|
||||
class EditEcoAccountDocumentModalForm(EditDocumentModalForm):
|
||||
_DOCUMENT_CLS = EcoAccountDocument
|
||||
|
||||
class RemoveEcoAccountDocumentModalForm(RemoveDocumentModalForm):
|
||||
_DOCUMENT_CLS = EcoAccountDocument
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ Created on: 18.08.22
|
||||
|
||||
"""
|
||||
from django import forms
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import pgettext_lazy as _con, gettext_lazy as _
|
||||
|
||||
from compensation.models import Payment
|
||||
from konova.forms.modals import RemoveModalForm, BaseModalForm
|
||||
from konova.utils import validators
|
||||
from konova.utils.message_templates import PAYMENT_EDITED
|
||||
@@ -103,7 +105,8 @@ class EditPaymentModalForm(NewPaymentForm):
|
||||
payment = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.payment = kwargs.pop("payment", None)
|
||||
payment_id = kwargs.pop("payment_id", None)
|
||||
self.payment = get_object_or_404(Payment, id=payment_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit payment")
|
||||
form_date = {
|
||||
@@ -133,8 +136,8 @@ class RemovePaymentModalForm(RemoveModalForm):
|
||||
payment = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
payment = kwargs.pop("payment", None)
|
||||
self.payment = payment
|
||||
payment_id = kwargs.pop("payment_id", None)
|
||||
self.payment = get_object_or_404(Payment, id=payment_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self):
|
||||
|
||||
15
compensation/forms/modals/resubmission.py
Normal file
15
compensation/forms/modals/resubmission.py
Normal file
@@ -0,0 +1,15 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 21.10.25
|
||||
|
||||
"""
|
||||
from compensation.models import Compensation, EcoAccount
|
||||
from konova.forms.modals import ResubmissionModalForm
|
||||
|
||||
|
||||
class CompensationResubmissionModalForm(ResubmissionModalForm):
|
||||
_MODEL_CLS = Compensation
|
||||
|
||||
|
||||
class EcoAccountResubmissionModalForm(ResubmissionModalForm):
|
||||
_MODEL_CLS = EcoAccount
|
||||
@@ -5,21 +5,17 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 18.08.22
|
||||
|
||||
"""
|
||||
from bootstrap_modal_forms.mixins import is_ajax
|
||||
from dal import autocomplete
|
||||
from django import forms
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect, HttpRequest
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from codelist.settings import CODELIST_BIOTOPES_ID, \
|
||||
CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID
|
||||
from compensation.models import CompensationState
|
||||
from intervention.inputs import CompensationStateTreeRadioSelect
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms.modals import RemoveModalForm, BaseModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_STATE_EDITED, FORM_INVALID, ADDED_COMPENSATION_STATE
|
||||
from konova.utils.message_templates import COMPENSATION_STATE_EDITED, ADDED_COMPENSATION_STATE
|
||||
|
||||
|
||||
class NewCompensationStateModalForm(BaseModalForm):
|
||||
@@ -68,10 +64,13 @@ class NewCompensationStateModalForm(BaseModalForm):
|
||||
)
|
||||
)
|
||||
|
||||
_is_before_state: bool = False
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("New state")
|
||||
self.form_caption = _("Insert data for the new state")
|
||||
self._is_before_state = bool(self.request.GET.get("before", False))
|
||||
choices = KonovaCode.objects.filter(
|
||||
code_lists__in=[CODELIST_BIOTOPES_ID],
|
||||
is_archived=False,
|
||||
@@ -83,65 +82,19 @@ class NewCompensationStateModalForm(BaseModalForm):
|
||||
]
|
||||
self.fields["biotope_type"].choices = choices
|
||||
|
||||
def save(self, is_before_state: bool = False):
|
||||
state = self.instance.add_state(self, is_before_state)
|
||||
def save(self):
|
||||
state = self.instance.add_state(self, self._is_before_state)
|
||||
self.instance.mark_as_edited(self.user, self.request, ADDED_COMPENSATION_STATE)
|
||||
return state
|
||||
|
||||
def process_request(self, request: HttpRequest, msg_success: str = _("Object removed"), msg_error: str = FORM_INVALID, redirect_url: str = None):
|
||||
""" Generic processing of request
|
||||
|
||||
Wraps the request processing logic, so we don't need the same code everywhere a RemoveModalForm is being used
|
||||
|
||||
+++
|
||||
The generic method from super class can not be used, since we need to do some request parameter check in here.
|
||||
+++
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
msg_success (str): The message in case of successful removing
|
||||
msg_error (str): The message in case of an error
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
redirect_url = redirect_url if redirect_url is not None else request.META.get("HTTP_REFERER", "home")
|
||||
template = self.template
|
||||
if request.method == "POST":
|
||||
if self.is_valid():
|
||||
# Modal forms send one POST for checking on data validity. This can be used to return possible errors
|
||||
# on the form. A second POST (if no errors occured) is sent afterwards and needs to process the
|
||||
# saving/commiting of the data to the database. is_ajax() performs this check. The first request is
|
||||
# an ajax call, the second is a regular form POST.
|
||||
if not is_ajax(request.META):
|
||||
is_before_state = bool(request.GET.get("before", False))
|
||||
self.save(is_before_state=is_before_state)
|
||||
messages.success(
|
||||
request,
|
||||
msg_success
|
||||
)
|
||||
return HttpResponseRedirect(redirect_url)
|
||||
else:
|
||||
context = {
|
||||
"form": self,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
elif request.method == "GET":
|
||||
context = {
|
||||
"form": self,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class EditCompensationStateModalForm(NewCompensationStateModalForm):
|
||||
state = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.state = kwargs.pop("state", None)
|
||||
state_id = kwargs.pop("state_id", None)
|
||||
self.state = CompensationState.objects.get(id=state_id)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit state")
|
||||
biotope_type_id = self.state.biotope_type.id if self.state.biotope_type else None
|
||||
@@ -172,8 +125,8 @@ class RemoveCompensationStateModalForm(RemoveModalForm):
|
||||
state = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
state = kwargs.pop("state", None)
|
||||
self.state = state
|
||||
state_id = kwargs.pop("state_id", None)
|
||||
self.state = CompensationState.objects.get(id=state_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self):
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.0.8 on 2024-08-26 16:47
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('codelist', '0003_alter_konovacode_long_name_and_more'),
|
||||
('compensation', '0015_alter_compensation_after_states_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='compensationstate',
|
||||
name='biotope_type_details',
|
||||
field=models.ManyToManyField(blank=True, limit_choices_to={'code_lists__in': [288], 'is_archived': False, 'is_selectable': True}, related_name='+', to='codelist.konovacode'),
|
||||
),
|
||||
]
|
||||
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:new-action' obj.id %}" title="{% trans 'Add new action' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'seedling' %}
|
||||
@@ -34,7 +34,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:action-edit' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit action' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{% fa5_icon 'file-alt' %}
|
||||
</button>
|
||||
</a>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Resubmission' %}" data-form-url="{% url 'compensation:resubmission-create' obj.id %}">
|
||||
{% fa5_icon 'bell' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:new-deadline' obj.id %}" title="{% trans 'Add new deadline' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'calendar-check' %}
|
||||
@@ -38,7 +38,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -60,7 +60,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:deadline-edit' obj.id deadline.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit deadline' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:new-doc' obj.id %}" title="{% trans 'Add new document' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'file' %}
|
||||
@@ -33,7 +33,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:edit-doc' obj.id doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit document' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:new-state' obj.id %}" title="{% trans 'Add new state after' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'layer-group' %}
|
||||
@@ -35,7 +35,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Surface' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -58,7 +58,7 @@
|
||||
</td>
|
||||
<td>{{ state.surface|floatformat:2 }} m²</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:state-edit' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit state' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:new-state' obj.id %}?before=true" title="{% trans 'Add new state before' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'layer-group' %}
|
||||
@@ -35,7 +35,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Surface' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -58,7 +58,7 @@
|
||||
</td>
|
||||
<td>{{ state.surface|floatformat:2 }} m²</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:state-edit' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit state' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
{% include 'user/includes/team_data_modal_button.html' %}
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
{% for user in obj.intervention.shared_users %}
|
||||
{% include 'user/includes/contact_modal_button.html' %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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 'seedling' %}
|
||||
@@ -33,7 +33,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -63,7 +63,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:acc:action-edit' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit action' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{% fa5_icon 'file-alt' %}
|
||||
</button>
|
||||
</a>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Resubmission' %}" data-form-url="{% url 'compensation:acc:resubmission-create' obj.id %}">
|
||||
{% fa5_icon 'bell' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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 'calendar-check' %}
|
||||
@@ -58,7 +58,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:acc:deadline-edit' obj.id deadline.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit deadline' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
<td class="align-middle">{{ deduction.surface|floatformat:2|intcomma }} m²</td>
|
||||
<td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access or is_default_member and user in deduction.intervention.shared_users %}
|
||||
{% if is_default_member and is_entry_shared or is_default_member and user in deduction.intervention.shared_users %}
|
||||
<button data-form-url="{% url 'compensation:acc:edit-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit Deduction' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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 'file' %}
|
||||
@@ -57,7 +57,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:acc:edit-doc' obj.id doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit document' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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 'layer-group' %}
|
||||
@@ -35,7 +35,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Surface' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -58,7 +58,7 @@
|
||||
</td>
|
||||
<td>{{ state.surface|floatformat:2 }} m²</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:acc:state-edit' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit state' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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 'layer-group' %}
|
||||
@@ -35,7 +35,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Surface' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -58,7 +58,7 @@
|
||||
</td>
|
||||
<td>{{ state.surface|floatformat:2 }} m²</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:acc:state-edit' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit state' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
{% include 'user/includes/team_data_modal_button.html' %}
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
{% for user in obj.users.all %}
|
||||
{% include 'user/includes/contact_modal_button.html' %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -54,7 +54,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
|
||||
post_data = {
|
||||
"identifier": test_id,
|
||||
"title": test_title,
|
||||
"geom": geom_json,
|
||||
"output": geom_json,
|
||||
"intervention": self.intervention.id,
|
||||
}
|
||||
pre_creation_intervention_log_count = self.intervention.log.count()
|
||||
@@ -94,7 +94,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
|
||||
post_data = {
|
||||
"identifier": test_id,
|
||||
"title": test_title,
|
||||
"geom": geom_json,
|
||||
"output": geom_json,
|
||||
}
|
||||
pre_creation_intervention_log_count = self.intervention.log.count()
|
||||
|
||||
@@ -150,7 +150,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
|
||||
"title": new_title,
|
||||
"intervention": self.intervention.id, # just keep the intervention as it is
|
||||
"comment": new_comment,
|
||||
"geom": geojson,
|
||||
"output": geojson,
|
||||
}
|
||||
self.client_user.post(url, post_data)
|
||||
self.compensation.refresh_from_db()
|
||||
|
||||
@@ -80,7 +80,11 @@ class EditCompensationActionModalFormTestCase(NewCompensationActionModalFormTest
|
||||
self.compensation.actions.add(self.comp_action)
|
||||
|
||||
def test_init(self):
|
||||
form = EditCompensationActionModalForm(request=self.request, instance=self.compensation, action=self.comp_action)
|
||||
form = EditCompensationActionModalForm(
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
action_id=self.comp_action.id
|
||||
)
|
||||
self.assertEqual(form.form_title, str(_("Edit action")))
|
||||
self.assertEqual(len(form.fields["action_type"].initial), self.comp_action.action_type.count())
|
||||
self.assertEqual(len(form.fields["action_type_details"].initial), self.comp_action.action_type_details.count())
|
||||
@@ -101,7 +105,7 @@ class EditCompensationActionModalFormTestCase(NewCompensationActionModalFormTest
|
||||
"comment": comment,
|
||||
}
|
||||
|
||||
form = EditCompensationActionModalForm(data, request=self.request, instance=self.compensation, action=self.comp_action)
|
||||
form = EditCompensationActionModalForm(data, request=self.request, instance=self.compensation, action_id=self.comp_action.id)
|
||||
|
||||
self.assertTrue(form.is_valid())
|
||||
action = form.save()
|
||||
@@ -126,7 +130,7 @@ class RemoveCompensationActionModalFormTestCase(EditCompensationActionModalFormT
|
||||
|
||||
def test_init(self):
|
||||
self.assertIn(self.comp_action, self.compensation.actions.all())
|
||||
form = RemoveCompensationActionModalForm(request=self.request, instance=self.compensation, action=self.comp_action)
|
||||
form = RemoveCompensationActionModalForm(request=self.request, instance=self.compensation, action_id=self.comp_action.id)
|
||||
self.assertEqual(form.action, self.comp_action)
|
||||
|
||||
def test_save(self):
|
||||
@@ -137,7 +141,7 @@ class RemoveCompensationActionModalFormTestCase(EditCompensationActionModalFormT
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
action=self.comp_action
|
||||
action_id=self.comp_action.id
|
||||
)
|
||||
self.assertTrue(form.is_valid())
|
||||
self.assertIn(self.comp_action, self.compensation.actions.all())
|
||||
@@ -186,12 +190,20 @@ class NewCompensationStateModalFormTestCase(BaseTestCase):
|
||||
self.assertEqual(self.compensation.before_states.count(), 0)
|
||||
self.assertEqual(self.compensation.after_states.count(), 0)
|
||||
|
||||
form = NewCompensationStateModalForm(data, request=self.request, instance=self.compensation)
|
||||
|
||||
self.request.GET._mutable = True
|
||||
self.request.GET.update(
|
||||
{
|
||||
"before": True,
|
||||
}
|
||||
)
|
||||
self.request.GET._mutable = False
|
||||
form = NewCompensationStateModalForm(
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
|
||||
is_before_state = True
|
||||
state = form.save(is_before_state)
|
||||
state = form.save()
|
||||
|
||||
self.assertEqual(self.compensation.before_states.count(), 1)
|
||||
self.assertEqual(self.compensation.after_states.count(), 0)
|
||||
@@ -205,8 +217,16 @@ class NewCompensationStateModalFormTestCase(BaseTestCase):
|
||||
self.assertEqual(last_log.action, UserAction.EDITED)
|
||||
self.assertEqual(last_log.comment, ADDED_COMPENSATION_STATE)
|
||||
|
||||
is_before_state = False
|
||||
state = form.save(is_before_state)
|
||||
self.request.GET._mutable = True
|
||||
del self.request.GET["before"]
|
||||
self.request.GET._mutable = False
|
||||
form = NewCompensationStateModalForm(
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
state = form.save()
|
||||
|
||||
self.assertEqual(self.compensation.before_states.count(), 1)
|
||||
self.assertEqual(self.compensation.after_states.count(), 1)
|
||||
@@ -230,7 +250,11 @@ class EditCompensationStateModalFormTestCase(NewCompensationStateModalFormTestCa
|
||||
self.compensation.after_states.add(self.comp_state)
|
||||
|
||||
def test_init(self):
|
||||
form = EditCompensationStateModalForm(request=self.request, instance=self.compensation, state=self.comp_state)
|
||||
form = EditCompensationStateModalForm(
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
state_id=self.comp_state.id
|
||||
)
|
||||
|
||||
self.assertEqual(form.state, self.comp_state)
|
||||
self.assertEqual(form.form_title, str(_("Edit state")))
|
||||
@@ -261,7 +285,7 @@ class EditCompensationStateModalFormTestCase(NewCompensationStateModalFormTestCa
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
state=self.comp_state
|
||||
state_id=self.comp_state.id
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
|
||||
@@ -282,7 +306,11 @@ class RemoveCompensationStateModalFormTestCase(EditCompensationStateModalFormTes
|
||||
super().setUp()
|
||||
|
||||
def test_init(self):
|
||||
form = RemoveCompensationStateModalForm(request=self.request, instance=self.compensation, state=self.comp_state)
|
||||
form = RemoveCompensationStateModalForm(
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
state_id=self.comp_state.id
|
||||
)
|
||||
|
||||
self.assertEqual(form.state, self.comp_state)
|
||||
|
||||
@@ -294,7 +322,7 @@ class RemoveCompensationStateModalFormTestCase(EditCompensationStateModalFormTes
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
state=self.comp_state
|
||||
state_id=self.comp_state.id
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ class AbstractCompensationModelTestCase(BaseTestCase):
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.compensation,
|
||||
deadline=self.finished_deadline,
|
||||
deadline_id=self.finished_deadline.id,
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
self.assertIn(self.finished_deadline, self.compensation.deadlines.all())
|
||||
|
||||
@@ -46,7 +46,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
||||
post_data = {
|
||||
"identifier": test_id,
|
||||
"title": test_title,
|
||||
"geom": geom_json,
|
||||
"output": geom_json,
|
||||
"surface": test_deductable_surface,
|
||||
"conservation_office": test_conservation_office.id
|
||||
}
|
||||
@@ -86,7 +86,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
||||
new_title = self.create_dummy_string()
|
||||
new_identifier = self.create_dummy_string()
|
||||
new_comment = self.create_dummy_string()
|
||||
new_geometry = MultiPolygon(srid=4326) # Create an empty geometry
|
||||
new_geometry = self.create_dummy_geometry()
|
||||
test_conservation_office = self.get_conservation_office_code()
|
||||
test_deductable_surface = self.eco_account.deductable_surface + 100
|
||||
|
||||
@@ -103,7 +103,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
||||
"identifier": new_identifier,
|
||||
"title": new_title,
|
||||
"comment": new_comment,
|
||||
"geom": new_geometry.geojson,
|
||||
"output": self.create_geojson(new_geometry),
|
||||
"surface": test_deductable_surface,
|
||||
"conservation_office": test_conservation_office.id
|
||||
}
|
||||
|
||||
@@ -10,27 +10,28 @@ from django.urls import path
|
||||
from compensation.views.compensation.document import EditCompensationDocumentView, NewCompensationDocumentView, \
|
||||
GetCompensationDocumentView, RemoveCompensationDocumentView
|
||||
from compensation.views.compensation.resubmission import CompensationResubmissionView
|
||||
from compensation.views.compensation.report import report_view
|
||||
from compensation.views.compensation.report import CompensationReportView
|
||||
from compensation.views.compensation.deadline import NewCompensationDeadlineView, EditCompensationDeadlineView, \
|
||||
RemoveCompensationDeadlineView
|
||||
from compensation.views.compensation.action import NewCompensationActionView, EditCompensationActionView, \
|
||||
RemoveCompensationActionView
|
||||
from compensation.views.compensation.state import NewCompensationStateView, EditCompensationStateView, \
|
||||
RemoveCompensationStateView
|
||||
from compensation.views.compensation.compensation import index_view, new_view, new_id_view, detail_view, edit_view, \
|
||||
remove_view
|
||||
from compensation.views.compensation.compensation import \
|
||||
CompensationIndexView, CompensationIdentifierGeneratorView, CompensationDetailView, \
|
||||
NewCompensationFormView, EditCompensationFormView, RemoveCompensationView
|
||||
from compensation.views.compensation.log import CompensationLogView
|
||||
|
||||
urlpatterns = [
|
||||
# Main compensation
|
||||
path("", index_view, name="index"),
|
||||
path('new/id', new_id_view, name='new-id'),
|
||||
path('new/<intervention_id>', new_view, name='new'),
|
||||
path('new', new_view, name='new'),
|
||||
path('<id>', detail_view, name='detail'),
|
||||
path("", CompensationIndexView.as_view(), name="index"),
|
||||
path('new/id', CompensationIdentifierGeneratorView.as_view(), name='new-id'),
|
||||
path('new/<intervention_id>', NewCompensationFormView.as_view(), name='new'),
|
||||
path('new', NewCompensationFormView.as_view(), name='new'),
|
||||
path('<id>', CompensationDetailView.as_view(), name='detail'),
|
||||
path('<id>/log', CompensationLogView.as_view(), name='log'),
|
||||
path('<id>/edit', edit_view, name='edit'),
|
||||
path('<id>/remove', remove_view, name='remove'),
|
||||
path('<id>/edit', EditCompensationFormView.as_view(), name='edit'),
|
||||
path('<id>/remove', RemoveCompensationView.as_view(), name='remove'),
|
||||
|
||||
path('<id>/state/new', NewCompensationStateView.as_view(), name='new-state'),
|
||||
path('<id>/state/<state_id>/edit', EditCompensationStateView.as_view(), name='state-edit'),
|
||||
@@ -43,7 +44,7 @@ urlpatterns = [
|
||||
path('<id>/deadline/new', NewCompensationDeadlineView.as_view(), name="new-deadline"),
|
||||
path('<id>/deadline/<deadline_id>/edit', EditCompensationDeadlineView.as_view(), name='deadline-edit'),
|
||||
path('<id>/deadline/<deadline_id>/remove', RemoveCompensationDeadlineView.as_view(), name='deadline-remove'),
|
||||
path('<id>/report', report_view, name='report'),
|
||||
path('<id>/report', CompensationReportView.as_view(), name='report'),
|
||||
path('<id>/resub', CompensationResubmissionView.as_view(), name='resubmission-create'),
|
||||
|
||||
# Documents
|
||||
|
||||
@@ -8,11 +8,11 @@ Created on: 24.08.21
|
||||
from django.urls import path
|
||||
|
||||
from compensation.autocomplete.eco_account import EcoAccountAutocomplete
|
||||
from compensation.views.eco_account.eco_account import index_view, new_view, new_id_view, edit_view, remove_view, \
|
||||
detail_view
|
||||
from compensation.views.eco_account.eco_account import EcoAccountIndexView, EcoAccountIdentifierGeneratorView, \
|
||||
EcoAccountDetailView, NewEcoAccountFormView, EditEcoAccountFormView, RemoveEcoAccountView
|
||||
from compensation.views.eco_account.log import EcoAccountLogView
|
||||
from compensation.views.eco_account.record import EcoAccountRecordView
|
||||
from compensation.views.eco_account.report import report_view
|
||||
from compensation.views.eco_account.report import EcoAccountReportView
|
||||
from compensation.views.eco_account.resubmission import EcoAccountResubmissionView
|
||||
from compensation.views.eco_account.state import NewEcoAccountStateView, EditEcoAccountStateView, \
|
||||
RemoveEcoAccountStateView
|
||||
@@ -28,15 +28,15 @@ from compensation.views.eco_account.deduction import NewEcoAccountDeductionView,
|
||||
|
||||
app_name = "acc"
|
||||
urlpatterns = [
|
||||
path("", index_view, name="index"),
|
||||
path('new/', new_view, name='new'),
|
||||
path('new/id', new_id_view, name='new-id'),
|
||||
path('<id>', detail_view, name='detail'),
|
||||
path("", EcoAccountIndexView.as_view(), name="index"),
|
||||
path('new/', NewEcoAccountFormView.as_view(), name='new'),
|
||||
path('new/id', EcoAccountIdentifierGeneratorView.as_view(), name='new-id'),
|
||||
path('<id>', EcoAccountDetailView.as_view(), name='detail'),
|
||||
path('<id>/log', EcoAccountLogView.as_view(), name='log'),
|
||||
path('<id>/record', EcoAccountRecordView.as_view(), name='record'),
|
||||
path('<id>/report', report_view, name='report'),
|
||||
path('<id>/edit', edit_view, name='edit'),
|
||||
path('<id>/remove', remove_view, name='remove'),
|
||||
path('<id>/report', EcoAccountReportView.as_view(), name='report'),
|
||||
path('<id>/edit', EditEcoAccountFormView.as_view(), name='edit'),
|
||||
path('<id>/remove', RemoveEcoAccountView.as_view(), name='remove'),
|
||||
path('<id>/resub', EcoAccountResubmissionView.as_view(), name='resubmission-create'),
|
||||
|
||||
path('<id>/state/new', NewEcoAccountStateView.as_view(), name='new-state'),
|
||||
|
||||
@@ -6,11 +6,11 @@ Created on: 24.08.21
|
||||
|
||||
"""
|
||||
from django.urls import path
|
||||
from compensation.views.payment import *
|
||||
from compensation.views.payment import NewPaymentView, RemovePaymentView, EditPaymentView
|
||||
|
||||
app_name = "pay"
|
||||
urlpatterns = [
|
||||
path('<id>/new', new_payment_view, name='new'),
|
||||
path('<id>/remove/<payment_id>', payment_remove_view, name='remove'),
|
||||
path('<id>/edit/<payment_id>', payment_edit_view, name='edit'),
|
||||
path('<id>/new', NewPaymentView.as_view(), name='new'),
|
||||
path('<id>/remove/<payment_id>', RemovePaymentView.as_view(), name='remove'),
|
||||
path('<id>/edit/<payment_id>', EditPaymentView.as_view(), name='edit'),
|
||||
]
|
||||
|
||||
@@ -5,53 +5,23 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.forms.modals.compensation_action import RemoveCompensationActionModalForm, \
|
||||
EditCompensationActionModalForm, NewCompensationActionModalForm
|
||||
from compensation.models import Compensation, CompensationAction
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.utils.message_templates import COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_EDITED, \
|
||||
COMPENSATION_ACTION_ADDED
|
||||
from compensation.models import Compensation
|
||||
from konova.views.action import AbstractNewCompensationActionView, AbstractEditCompensationActionView, \
|
||||
AbstractRemoveCompensationActionView
|
||||
|
||||
_COMPENSATION_DETAIL_URL_NAME = "compensation:detail"
|
||||
|
||||
class NewCompensationActionView(AbstractNewCompensationActionView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class EditCompensationActionView(AbstractEditCompensationActionView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class RemoveCompensationActionView(AbstractRemoveCompensationActionView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
|
||||
|
||||
@@ -7,8 +7,8 @@ Created on: 19.08.22
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Sum
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.urls import reverse
|
||||
@@ -18,284 +18,157 @@ from compensation.forms.compensation import EditCompensationForm, NewCompensatio
|
||||
from compensation.models import Compensation
|
||||
from compensation.tables.compensation import CompensationTable
|
||||
from intervention.models import Intervention
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import shared_access_required, default_group_required, any_group_check, login_required_modal, \
|
||||
uuid_required
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE, \
|
||||
RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, IDENTIFIER_REPLACED, \
|
||||
COMPENSATION_ADDED_TEMPLATE, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
||||
RECORDED_BLOCKS_EDIT, PARAMS_INVALID
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
@login_required
|
||||
@any_group_check
|
||||
def index_view(request: HttpRequest):
|
||||
"""
|
||||
Renders the index view for compensation
|
||||
class CompensationIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
_TAB_TITLE = _("Compensations - Overview")
|
||||
_INDEX_TABLE_CLS = CompensationTable
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
A rendered view
|
||||
"""
|
||||
template = "generic_index.html"
|
||||
compensations = Compensation.objects.filter(
|
||||
deleted=None, # only show those which are not deleted individually
|
||||
intervention__deleted=None, # and don't show the ones whose intervention has been deleted
|
||||
).order_by(
|
||||
"-modified__timestamp"
|
||||
)
|
||||
table = CompensationTable(
|
||||
request=request,
|
||||
queryset=compensations
|
||||
)
|
||||
context = {
|
||||
"table": table,
|
||||
TAB_TITLE_IDENTIFIER: _("Compensations - Overview"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
def _get_queryset(self):
|
||||
qs = Compensation.objects.filter(
|
||||
deleted=None, # only show those which are not deleted individually
|
||||
intervention__deleted=None, # and don't show the ones whose intervention has been deleted
|
||||
).order_by(
|
||||
"-modified__timestamp"
|
||||
)
|
||||
return qs
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "intervention_id")
|
||||
def new_view(request: HttpRequest, intervention_id: str = None):
|
||||
"""
|
||||
Renders a view for a new compensation creation
|
||||
class NewCompensationFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
_FORM_CLS = NewCompensationForm
|
||||
_MODEL_CLS = Compensation
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_TAB_TITLE = _("New Compensation")
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
# On a new compensation make sure the intervention (if call came directly through an intervention's detail
|
||||
# view) is shared with the user
|
||||
intervention_id = kwargs.get("intervention_id", None)
|
||||
if not intervention_id:
|
||||
return True
|
||||
else:
|
||||
intervention = get_object_or_404(Intervention, id=intervention_id)
|
||||
return intervention.is_shared_with(user)
|
||||
|
||||
Returns:
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be an ets user
|
||||
return user.is_default_user()
|
||||
|
||||
"""
|
||||
template = "compensation/form/view.html"
|
||||
if intervention_id is not None:
|
||||
try:
|
||||
intervention = Intervention.objects.get(id=intervention_id)
|
||||
except ObjectDoesNotExist:
|
||||
messages.error(request, PARAMS_INVALID)
|
||||
return redirect("home")
|
||||
if intervention.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect("intervention:detail", id=intervention_id)
|
||||
|
||||
data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||
if request.method == "POST":
|
||||
if data_form.is_valid() and geom_form.is_valid():
|
||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||
comp = data_form.save(request.user, geom_form)
|
||||
if generated_identifier != comp.identifier:
|
||||
messages.info(
|
||||
request,
|
||||
IDENTIFIER_REPLACED.format(
|
||||
generated_identifier,
|
||||
comp.identifier
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
# Make sure there is an existing intervention based on the given id
|
||||
# Compensations can not exist without an intervention
|
||||
intervention_id = kwargs.get("intervention_id", None)
|
||||
if intervention_id:
|
||||
try:
|
||||
intervention = Intervention.objects.get(id=intervention_id)
|
||||
if intervention.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
)
|
||||
messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
|
||||
if geom_form.geometry_simplified:
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
return redirect("compensation:detail", id=comp.id)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("New compensation"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
return redirect("intervention:detail", id=intervention_id)
|
||||
except ObjectDoesNotExist:
|
||||
messages.error(request, PARAMS_INVALID, extra_tags="danger")
|
||||
return redirect("home")
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
def new_id_view(request: HttpRequest):
|
||||
""" JSON endpoint
|
||||
class EditCompensationFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
_MODEL_CLS = Compensation
|
||||
_FORM_CLS = EditCompensationForm
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
Provides fetching of free identifiers for e.g. AJAX calls
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be a default user
|
||||
return user.is_default_user()
|
||||
|
||||
"""
|
||||
tmp = Compensation()
|
||||
identifier = tmp.generate_new_identifier()
|
||||
while Compensation.objects.filter(identifier=identifier).exists():
|
||||
identifier = tmp.generate_new_identifier()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": identifier
|
||||
|
||||
class CompensationIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = "compensation:index"
|
||||
|
||||
|
||||
class CompensationDetailView(BaseDetailView):
|
||||
_MODEL_CLS = Compensation
|
||||
_TEMPLATE = "compensation/detail/compensation/view.html"
|
||||
|
||||
def _get_object(self, id: str):
|
||||
""" Returns the compensation
|
||||
|
||||
Args:
|
||||
id (str): The compensation's id
|
||||
|
||||
Returns:
|
||||
obj (Compensation): The compensation
|
||||
"""
|
||||
comp = get_object_or_404(
|
||||
Compensation.objects.select_related(
|
||||
"modified",
|
||||
"created",
|
||||
"geometry"
|
||||
),
|
||||
id=id,
|
||||
deleted=None,
|
||||
intervention__deleted=None,
|
||||
)
|
||||
return comp
|
||||
|
||||
def _get_detail_context(self, obj: Compensation):
|
||||
""" Generate object specific detail context for view
|
||||
|
||||
Args:
|
||||
obj (): The record
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# Order states according to surface
|
||||
before_states = obj.before_states.all().prefetch_related("biotope_type").order_by("-surface")
|
||||
after_states = obj.after_states.all().prefetch_related("biotope_type").order_by("-surface")
|
||||
actions = obj.actions.all().prefetch_related("action_type")
|
||||
|
||||
# Precalculate logical errors between before- and after-states
|
||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||
sum_before_states = obj.get_surface_before_states()
|
||||
sum_after_states = obj.get_surface_after_states()
|
||||
diff_states = abs(sum_before_states - sum_after_states)
|
||||
|
||||
last_checked = obj.intervention.get_last_checked_action()
|
||||
last_checked_tooltip = ""
|
||||
if last_checked:
|
||||
last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
|
||||
last_checked.get_timestamp_str_formatted(),
|
||||
last_checked.user
|
||||
)
|
||||
|
||||
context = {
|
||||
"last_checked": last_checked,
|
||||
"last_checked_tooltip": last_checked_tooltip,
|
||||
"actions": actions,
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"sum_before_states": sum_before_states,
|
||||
"sum_after_states": sum_after_states,
|
||||
"diff_states": diff_states,
|
||||
"has_finished_deadlines": obj.get_finished_deadlines().exists(),
|
||||
}
|
||||
)
|
||||
return context
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Compensation, "id")
|
||||
def edit_view(request: HttpRequest, id: str):
|
||||
"""
|
||||
Renders a view for editing compensations
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "compensation/form/view.html"
|
||||
# Get object from db
|
||||
comp = get_object_or_404(Compensation, id=id)
|
||||
if comp.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect("compensation:detail", id=id)
|
||||
|
||||
# Create forms, initialize with values from db/from POST request
|
||||
data_form = EditCompensationForm(request.POST or None, instance=comp)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
||||
if request.method == "POST":
|
||||
if data_form.is_valid() and geom_form.is_valid():
|
||||
# Preserve state of intervention checked to determine whether the user must be informed or not
|
||||
# about a change of the check state
|
||||
intervention_is_checked = comp.intervention.checked is not None
|
||||
|
||||
# The data form takes the geom form for processing, as well as the performing user
|
||||
comp = data_form.save(request.user, geom_form)
|
||||
if intervention_is_checked:
|
||||
messages.info(request, CHECK_STATE_RESET)
|
||||
messages.success(request, _("Compensation {} edited").format(comp.identifier))
|
||||
if geom_form.geometry_simplified:
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
return redirect("compensation:detail", id=comp.id)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
@any_group_check
|
||||
@uuid_required
|
||||
def detail_view(request: HttpRequest, id: str):
|
||||
""" Renders a detail view for a compensation
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The compensation's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "compensation/detail/compensation/view.html"
|
||||
comp = get_object_or_404(
|
||||
Compensation.objects.select_related(
|
||||
"modified",
|
||||
"created",
|
||||
"geometry"
|
||||
),
|
||||
id=id,
|
||||
deleted=None,
|
||||
intervention__deleted=None,
|
||||
)
|
||||
geom_form = SimpleGeomForm(instance=comp)
|
||||
parcels = comp.get_underlying_parcels()
|
||||
_user = request.user
|
||||
is_data_shared = comp.intervention.is_shared_with(_user)
|
||||
|
||||
# Order states according to surface
|
||||
before_states = comp.before_states.all().prefetch_related("biotope_type").order_by("-surface")
|
||||
after_states = comp.after_states.all().prefetch_related("biotope_type").order_by("-surface")
|
||||
actions = comp.actions.all().prefetch_related("action_type")
|
||||
|
||||
# Precalculate logical errors between before- and after-states
|
||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||
sum_before_states = comp.get_surface_before_states()
|
||||
sum_after_states = comp.get_surface_after_states()
|
||||
diff_states = abs(sum_before_states - sum_after_states)
|
||||
|
||||
request = comp.set_status_messages(request)
|
||||
|
||||
last_checked = comp.intervention.get_last_checked_action()
|
||||
last_checked_tooltip = ""
|
||||
if last_checked:
|
||||
last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(last_checked.get_timestamp_str_formatted(), last_checked.user)
|
||||
|
||||
requesting_user_is_only_shared_user = comp.is_only_shared_with(_user)
|
||||
if requesting_user_is_only_shared_user:
|
||||
messages.info(
|
||||
request,
|
||||
DO_NOT_FORGET_TO_SHARE
|
||||
)
|
||||
|
||||
context = {
|
||||
"obj": comp,
|
||||
"last_checked": last_checked,
|
||||
"last_checked_tooltip": last_checked_tooltip,
|
||||
"geom_form": geom_form,
|
||||
"parcels": parcels,
|
||||
"has_access": is_data_shared,
|
||||
"actions": actions,
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"sum_before_states": sum_before_states,
|
||||
"sum_after_states": sum_after_states,
|
||||
"diff_states": diff_states,
|
||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||
"LANIS_LINK": comp.get_LANIS_link(),
|
||||
TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}",
|
||||
"has_finished_deadlines": comp.get_finished_deadlines().exists(),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Compensation, "id")
|
||||
def remove_view(request: HttpRequest, id: str):
|
||||
""" Renders a modal view for removing the compensation
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The compensation's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
comp = get_object_or_404(Compensation, id=id)
|
||||
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("compensation:index"),
|
||||
)
|
||||
class RemoveCompensationView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = Compensation
|
||||
_FORM_CLS = RemoveModalForm
|
||||
_REDIRECT_URL = "compensation:index"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -5,45 +5,21 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import Compensation
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.deadline import AbstractRemoveDeadlineView, AbstractEditDeadlineView, AbstractNewDeadlineView
|
||||
|
||||
_COMPENSATION_DETAIL_URL_NAME = "compensation:detail"
|
||||
|
||||
class NewCompensationDeadlineView(AbstractNewDeadlineView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class EditCompensationDeadlineView(AbstractEditDeadlineView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class RemoveCompensationDeadlineView(AbstractRemoveDeadlineView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
|
||||
|
||||
@@ -5,62 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.forms.modals.document import NewCompensationDocumentModalForm
|
||||
from compensation.forms.modals.document import NewCompensationDocumentModalForm, EditCompensationDocumentModalForm, \
|
||||
RemoveCompensationDocumentModalForm
|
||||
from compensation.models import Compensation, CompensationDocument
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.forms.modals import EditDocumentModalForm
|
||||
from konova.views.document import AbstractNewDocumentView, AbstractGetDocumentView, AbstractRemoveDocumentView, \
|
||||
AbstractEditDocumentView
|
||||
|
||||
|
||||
class NewCompensationDocumentView(AbstractNewDocumentView):
|
||||
model = Compensation
|
||||
form = NewCompensationDocumentModalForm
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_FORM_CLS = NewCompensationDocumentModalForm
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
|
||||
class GetCompensationDocumentView(AbstractGetDocumentView):
|
||||
model = Compensation
|
||||
document_model = CompensationDocument
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_DOCUMENT_CLS = CompensationDocument
|
||||
|
||||
|
||||
class RemoveCompensationDocumentView(AbstractRemoveDocumentView):
|
||||
model = Compensation
|
||||
document_model = CompensationDocument
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_DOCUMENT_CLS = CompensationDocument
|
||||
_FORM_CLS = RemoveCompensationDocumentModalForm
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
|
||||
class EditCompensationDocumentView(AbstractEditDocumentView):
|
||||
model = Compensation
|
||||
document_model = CompensationDocument
|
||||
form = EditDocumentModalForm
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_DOCUMENT_CLS = CompensationDocument
|
||||
_FORM_CLS = EditCompensationDocumentModalForm
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
@@ -5,20 +5,11 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from compensation.models import Compensation
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.log import AbstractLogView
|
||||
|
||||
|
||||
class CompensationLogView(AbstractLogView):
|
||||
model = Compensation
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class CompensationLogView(LoginRequiredMixin, AbstractLogView):
|
||||
_MODEL_CLS = Compensation
|
||||
|
||||
@@ -5,76 +5,48 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from compensation.models import Compensation
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.generators import generate_qr_code
|
||||
from konova.sub_settings.django_settings import BASE_URL
|
||||
from konova.utils.qrcode import QrCode
|
||||
from konova.views.report import BaseReportView
|
||||
|
||||
|
||||
def report_view(request: HttpRequest, id: str):
|
||||
""" Renders the public report view
|
||||
class BaseCompensationReportView(BaseReportView):
|
||||
def _get_compensation_report_context(self, obj):
|
||||
# Order states by surface
|
||||
before_states = obj.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
after_states = obj.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
actions = obj.actions.all().prefetch_related("action_type")
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The id of the intervention
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# Reuse the compensation report template since compensations are structurally identical
|
||||
template = "compensation/report/compensation/report.html"
|
||||
comp = get_object_or_404(Compensation, id=id)
|
||||
|
||||
tab_title = _("Report {}").format(comp.identifier)
|
||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||
if not comp.is_ready_for_publish():
|
||||
template = "report/unavailable.html"
|
||||
context = {
|
||||
TAB_TITLE_IDENTIFIER: tab_title,
|
||||
return {
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"actions": actions,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
# Prepare data for map viewer
|
||||
geom_form = SimpleGeomForm(
|
||||
instance=comp
|
||||
)
|
||||
parcels = comp.get_underlying_parcels()
|
||||
|
||||
qrcode_url = request.build_absolute_uri(reverse("compensation:report", args=(id,)))
|
||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
||||
qrcode_lanis_url = comp.get_LANIS_link()
|
||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
||||
class CompensationReportView(BaseCompensationReportView):
|
||||
_MODEL = Compensation
|
||||
_TEMPLATE = "compensation/report/compensation/report.html"
|
||||
|
||||
# Order states by surface
|
||||
before_states = comp.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
after_states = comp.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
actions = comp.actions.all().prefetch_related("action_type")
|
||||
def _get_report_context(self, obj):
|
||||
report_url = BASE_URL + reverse("compensation:report", args=(obj.id,))
|
||||
qrcode_report = QrCode(report_url, 10)
|
||||
qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
|
||||
|
||||
context = {
|
||||
"obj": comp,
|
||||
"qrcode": {
|
||||
"img": qrcode_img,
|
||||
"url": qrcode_url,
|
||||
},
|
||||
"qrcode_lanis": {
|
||||
"img": qrcode_img_lanis,
|
||||
"url": qrcode_lanis_url,
|
||||
},
|
||||
"has_access": False, # disables action buttons during rendering
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"geom_form": geom_form,
|
||||
"parcels": parcels,
|
||||
"actions": actions,
|
||||
"tables_scrollable": False,
|
||||
TAB_TITLE_IDENTIFIER: tab_title,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
report_context = {
|
||||
"qrcode": {
|
||||
"img": qrcode_report.get_img(),
|
||||
"url": qrcode_report.get_content(),
|
||||
},
|
||||
"qrcode_lanis": {
|
||||
"img": qrcode_lanis.get_img(),
|
||||
"url": qrcode_lanis.get_content(),
|
||||
},
|
||||
"is_entry_shared": False, # disables action buttons during rendering
|
||||
"tables_scrollable": False,
|
||||
}
|
||||
report_context.update(self._get_compensation_report_context(obj))
|
||||
return report_context
|
||||
@@ -5,22 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.forms.modals.resubmission import CompensationResubmissionModalForm
|
||||
from compensation.models import Compensation
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.resubmission import AbstractResubmissionView
|
||||
|
||||
|
||||
class CompensationResubmissionView(AbstractResubmissionView):
|
||||
model = Compensation
|
||||
redirect_url_base = "compensation:detail"
|
||||
form_action_url_base = "compensation:resubmission-create"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_FORM_CLS = CompensationResubmissionModalForm
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
@@ -5,46 +5,21 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import Compensation
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.state import AbstractNewCompensationStateView, AbstractEditCompensationStateView, \
|
||||
AbstractRemoveCompensationStateView
|
||||
|
||||
|
||||
class NewCompensationStateView(AbstractNewCompensationStateView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
|
||||
class EditCompensationStateView(AbstractEditCompensationStateView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
|
||||
class RemoveCompensationStateView(AbstractRemoveCompensationStateView):
|
||||
model = Compensation
|
||||
redirect_url = "compensation:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Compensation, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Compensation
|
||||
_REDIRECT_URL = "compensation:detail"
|
||||
|
||||
@@ -5,46 +5,22 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.action import AbstractNewCompensationActionView, AbstractEditCompensationActionView, \
|
||||
AbstractRemoveCompensationActionView
|
||||
|
||||
_ECO_ACCOUNT_DETAIL_URL_NAME = "compensation:acc:detail"
|
||||
|
||||
class NewEcoAccountActionView(AbstractNewCompensationActionView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class EditEcoAccountActionView(AbstractEditCompensationActionView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class RemoveEcoAccountActionView(AbstractRemoveCompensationActionView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
@@ -5,45 +5,22 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.deadline import AbstractNewDeadlineView, AbstractEditDeadlineView, AbstractRemoveDeadlineView
|
||||
|
||||
_ECO_ACCOUNT_DETAIL_URL_NAME = "compensation:acc:detail"
|
||||
|
||||
class NewEcoAccountDeadlineView(AbstractNewDeadlineView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class EditEcoAccountDeadlineView(AbstractEditDeadlineView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class RemoveEcoAccountDeadlineView(AbstractRemoveDeadlineView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@@ -5,54 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import Http404
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import default_group_required, login_required_modal
|
||||
from konova.views.deduction import AbstractNewDeductionView, AbstractEditDeductionView, AbstractRemoveDeductionView
|
||||
|
||||
_ECO_ACCOUNT_DETAIl_URL_NAME = "compensation:acc:detail"
|
||||
|
||||
class NewEcoAccountDeductionView(AbstractNewDeductionView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class NewEcoAccountDeductionView(LoginRequiredMixin, AbstractNewDeductionView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIl_URL_NAME
|
||||
|
||||
def _custom_check(self, obj):
|
||||
# New deductions can only be created if the eco account has been recorded
|
||||
if not obj.recorded:
|
||||
raise Http404()
|
||||
|
||||
|
||||
class EditEcoAccountDeductionView(AbstractEditDeductionView):
|
||||
def _custom_check(self, obj):
|
||||
pass
|
||||
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _check_for_recorded_instance(self, obj):
|
||||
# Deductions can be created on recorded as well as on non-recorded entries
|
||||
return None
|
||||
|
||||
|
||||
class RemoveEcoAccountDeductionView(AbstractRemoveDeductionView):
|
||||
def _custom_check(self, obj):
|
||||
pass
|
||||
class EditEcoAccountDeductionView(LoginRequiredMixin, AbstractEditDeductionView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIl_URL_NAME
|
||||
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
class RemoveEcoAccountDeductionView(LoginRequiredMixin, AbstractRemoveDeductionView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = _ECO_ACCOUNT_DETAIl_URL_NAME
|
||||
|
||||
@@ -5,65 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.forms.modals.document import NewEcoAccountDocumentModalForm
|
||||
from compensation.forms.modals.document import NewEcoAccountDocumentModalForm, RemoveEcoAccountDocumentModalForm, \
|
||||
EditEcoAccountDocumentModalForm
|
||||
from compensation.models import EcoAccount, EcoAccountDocument
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.forms.modals import EditDocumentModalForm
|
||||
from konova.views.document import AbstractNewDocumentView, AbstractGetDocumentView, AbstractRemoveDocumentView, \
|
||||
AbstractEditDocumentView
|
||||
|
||||
|
||||
class NewEcoAccountDocumentView(AbstractNewDocumentView):
|
||||
model = EcoAccount
|
||||
form = NewEcoAccountDocumentModalForm
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_FORM_CLS = NewEcoAccountDocumentModalForm
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
|
||||
class GetEcoAccountDocumentView(AbstractGetDocumentView):
|
||||
model = EcoAccount
|
||||
document_model = EcoAccountDocument
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_DOCUMENT_CLS = EcoAccountDocument
|
||||
|
||||
|
||||
class RemoveEcoAccountDocumentView(AbstractRemoveDocumentView):
|
||||
model = EcoAccount
|
||||
document_model = EcoAccountDocument
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_DOCUMENT_CLS = EcoAccountDocument
|
||||
_FORM_CLS = RemoveEcoAccountDocumentModalForm
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
|
||||
class EditEcoAccountDocumentView(AbstractEditDocumentView):
|
||||
model = EcoAccount
|
||||
document_model = EcoAccountDocument
|
||||
form = EditDocumentModalForm
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_DOCUMENT_CLS = EcoAccountDocument
|
||||
_FORM_CLS = EditEcoAccountDocumentModalForm
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
@@ -7,8 +7,8 @@ Created on: 19.08.22
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db.models import Sum
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -17,43 +17,52 @@ from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm
|
||||
from compensation.models import EcoAccount
|
||||
from compensation.tables.eco_account import EcoAccountTable
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import shared_access_required, default_group_required, any_group_check, login_required_modal, \
|
||||
uuid_required
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.settings import ETS_GROUP, DEFAULT_GROUP, ZB_GROUP
|
||||
from konova.settings import ETS_GROUP
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import CANCEL_ACC_RECORDED_OR_DEDUCTED, RECORDED_BLOCKS_EDIT, FORM_INVALID, \
|
||||
IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
||||
IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
@login_required
|
||||
@any_group_check
|
||||
def index_view(request: HttpRequest):
|
||||
"""
|
||||
Renders the index view for eco accounts
|
||||
class EcoAccountIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
_INDEX_TABLE_CLS = EcoAccountTable
|
||||
_TAB_TITLE = _("Eco-account - Overview")
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
def _get_queryset(self):
|
||||
qs = EcoAccount.objects.filter(
|
||||
deleted=None,
|
||||
).order_by(
|
||||
"-modified__timestamp"
|
||||
)
|
||||
return qs
|
||||
|
||||
Returns:
|
||||
A rendered view
|
||||
"""
|
||||
template = "generic_index.html"
|
||||
eco_accounts = EcoAccount.objects.filter(
|
||||
deleted=None,
|
||||
).order_by(
|
||||
"-modified__timestamp"
|
||||
)
|
||||
table = EcoAccountTable(
|
||||
request=request,
|
||||
queryset=eco_accounts
|
||||
)
|
||||
context = {
|
||||
"table": table,
|
||||
TAB_TITLE_IDENTIFIER: _("Eco-account - Overview"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
class NewEcoAccountFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
_FORM_CLS = NewEcoAccountForm
|
||||
_MODEL_CLS = EcoAccount
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_TAB_TITLE = _("New Eco-Account")
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be a default user
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
class EditEcoAccountFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
_FORM_CLS = EditEcoAccountForm
|
||||
_MODEL_CLS = EcoAccount
|
||||
_TEMPLATE = "compensation/form/view.html"
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be a default user
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -84,11 +93,19 @@ def new_view(request: HttpRequest):
|
||||
)
|
||||
)
|
||||
messages.success(request, _("Eco-Account {} added").format(acc.identifier))
|
||||
if geom_form.geometry_simplified:
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
|
||||
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||
if num_ignored_geometries > 0:
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||
)
|
||||
|
||||
return redirect("compensation:acc:detail", id=acc.id)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
@@ -104,23 +121,9 @@ def new_view(request: HttpRequest):
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
def new_id_view(request: HttpRequest):
|
||||
""" JSON endpoint
|
||||
|
||||
Provides fetching of free identifiers for e.g. AJAX calls
|
||||
|
||||
"""
|
||||
tmp = EcoAccount()
|
||||
identifier = tmp.generate_new_identifier()
|
||||
while EcoAccount.objects.filter(identifier=identifier).exists():
|
||||
identifier = tmp.generate_new_identifier()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": identifier
|
||||
}
|
||||
)
|
||||
class EcoAccountIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:index"
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -156,11 +159,19 @@ def edit_view(request: HttpRequest, id: str):
|
||||
# The data form takes the geom form for processing, as well as the performing user
|
||||
acc = data_form.save(request.user, geom_form)
|
||||
messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
|
||||
if geom_form.geometry_simplified:
|
||||
if geom_form.has_geometry_simplified():
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
|
||||
num_ignored_geometries = geom_form.get_num_geometries_ignored()
|
||||
if num_ignored_geometries > 0:
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
|
||||
)
|
||||
|
||||
return redirect("compensation:acc:detail", id=acc.id)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
@@ -176,116 +187,78 @@ def edit_view(request: HttpRequest, id: str):
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
@any_group_check
|
||||
@uuid_required
|
||||
def detail_view(request: HttpRequest, id: str):
|
||||
""" Renders a detail view for a compensation
|
||||
class EcoAccountDetailView(BaseDetailView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_TEMPLATE = "compensation/detail/eco_account/view.html"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The compensation's id
|
||||
def _get_object(self, id: str):
|
||||
""" Fetch object for detail view
|
||||
|
||||
Returns:
|
||||
Args:
|
||||
id (str): The record's id'
|
||||
|
||||
"""
|
||||
template = "compensation/detail/eco_account/view.html"
|
||||
acc = get_object_or_404(
|
||||
EcoAccount.objects.prefetch_related(
|
||||
"deadlines",
|
||||
).select_related(
|
||||
'geometry',
|
||||
'responsible',
|
||||
),
|
||||
id=id,
|
||||
deleted=None,
|
||||
)
|
||||
geom_form = SimpleGeomForm(instance=acc)
|
||||
parcels = acc.get_underlying_parcels()
|
||||
_user = request.user
|
||||
is_data_shared = acc.is_shared_with(_user)
|
||||
Returns:
|
||||
|
||||
# Order states according to surface
|
||||
before_states = acc.before_states.order_by("-surface")
|
||||
after_states = acc.after_states.order_by("-surface")
|
||||
|
||||
# Precalculate logical errors between before- and after-states
|
||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||
sum_before_states = acc.get_surface_before_states()
|
||||
sum_after_states = acc.get_surface_after_states()
|
||||
diff_states = abs(sum_before_states - sum_after_states)
|
||||
# Calculate rest of available surface for deductions
|
||||
available_total = acc.deductable_rest
|
||||
available_relative = acc.get_deductable_rest_relative()
|
||||
|
||||
# Prefetch related data to decrease the amount of db connections
|
||||
deductions = acc.deductions.filter(
|
||||
intervention__deleted=None,
|
||||
)
|
||||
actions = acc.actions.all()
|
||||
|
||||
request = acc.set_status_messages(request)
|
||||
|
||||
requesting_user_is_only_shared_user = acc.is_only_shared_with(_user)
|
||||
if requesting_user_is_only_shared_user:
|
||||
messages.info(
|
||||
request,
|
||||
DO_NOT_FORGET_TO_SHARE
|
||||
"""
|
||||
acc = get_object_or_404(
|
||||
EcoAccount.objects.prefetch_related(
|
||||
"deadlines",
|
||||
).select_related(
|
||||
'geometry',
|
||||
'responsible',
|
||||
),
|
||||
id=id,
|
||||
deleted=None,
|
||||
)
|
||||
return acc
|
||||
|
||||
context = {
|
||||
"obj": acc,
|
||||
"geom_form": geom_form,
|
||||
"parcels": parcels,
|
||||
"has_access": is_data_shared,
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"sum_before_states": sum_before_states,
|
||||
"sum_after_states": sum_after_states,
|
||||
"diff_states": diff_states,
|
||||
"available": available_relative,
|
||||
"available_total": available_total,
|
||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||
"LANIS_LINK": acc.get_LANIS_link(),
|
||||
"deductions": deductions,
|
||||
"actions": actions,
|
||||
TAB_TITLE_IDENTIFIER: f"{acc.identifier} - {acc.title}",
|
||||
"has_finished_deadlines": acc.get_finished_deadlines().exists(),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
def _get_detail_context(self, obj: EcoAccount):
|
||||
""" Generate object specific detail context for view
|
||||
|
||||
Args:
|
||||
obj (): The record
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# Order states according to surface
|
||||
before_states = obj.before_states.order_by("-surface")
|
||||
after_states = obj.after_states.order_by("-surface")
|
||||
|
||||
# Precalculate logical errors between before- and after-states
|
||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||
sum_before_states = obj.get_surface_before_states()
|
||||
sum_after_states = obj.get_surface_after_states()
|
||||
diff_states = abs(sum_before_states - sum_after_states)
|
||||
# Calculate rest of available surface for deductions
|
||||
available_total = obj.deductable_rest
|
||||
available_relative = obj.get_deductable_rest_relative()
|
||||
|
||||
# Prefetch related data to decrease the amount of db connections
|
||||
deductions = obj.deductions.filter(
|
||||
intervention__deleted=None,
|
||||
)
|
||||
actions = obj.actions.all()
|
||||
|
||||
context = {
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"sum_before_states": sum_before_states,
|
||||
"sum_after_states": sum_after_states,
|
||||
"diff_states": diff_states,
|
||||
"available": available_relative,
|
||||
"available_total": available_total,
|
||||
"deductions": deductions,
|
||||
"actions": actions,
|
||||
"has_finished_deadlines": obj.get_finished_deadlines().exists(),
|
||||
}
|
||||
return context
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(EcoAccount, "id")
|
||||
def remove_view(request: HttpRequest, id: str):
|
||||
""" Renders a modal view for removing the eco account
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The account's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
acc = get_object_or_404(EcoAccount, id=id)
|
||||
|
||||
# If the eco account has already been recorded OR there are already deductions, it can not be deleted by a regular
|
||||
# default group user
|
||||
if acc.recorded is not None or acc.deductions.exists():
|
||||
user = request.user
|
||||
if not user.in_group(ETS_GROUP):
|
||||
messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED)
|
||||
return redirect("compensation:acc:detail", id=id)
|
||||
|
||||
form = RemoveEcoAccountModalForm(request.POST or None, instance=acc, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=_("Eco-account removed"),
|
||||
redirect_url=reverse("compensation:acc:index"),
|
||||
)
|
||||
class RemoveEcoAccountView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_FORM_CLS = RemoveEcoAccountModalForm
|
||||
_REDIRECT_URL = "compensation:acc:index"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
@@ -5,20 +5,11 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.log import AbstractLogView
|
||||
|
||||
|
||||
class EcoAccountLogView(AbstractLogView):
|
||||
model = EcoAccount
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class EcoAccountLogView(LoginRequiredMixin, AbstractLogView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
|
||||
@@ -5,20 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.views.record import AbstractRecordView
|
||||
|
||||
|
||||
class EcoAccountRecordView(AbstractRecordView):
|
||||
model = EcoAccount
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class EcoAccountRecordView(LoginRequiredMixin, AbstractRecordView):
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
@@ -5,83 +5,41 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.generators import generate_qr_code
|
||||
from compensation.views.compensation.report import BaseCompensationReportView
|
||||
from konova.sub_settings.django_settings import BASE_URL
|
||||
from konova.utils.qrcode import QrCode
|
||||
|
||||
|
||||
def report_view(request: HttpRequest, id: str):
|
||||
""" Renders the public report view
|
||||
class EcoAccountReportView(BaseCompensationReportView):
|
||||
_MODEL = EcoAccount
|
||||
_TEMPLATE = "compensation/report/eco_account/report.html"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The id of the intervention
|
||||
def _get_report_context(self, obj):
|
||||
report_url = BASE_URL + reverse("compensation:acc:report", args=(obj.id,))
|
||||
qrcode_report = QrCode(report_url, 10)
|
||||
qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
|
||||
|
||||
Returns:
|
||||
# Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
|
||||
deductions = obj.deductions.all() \
|
||||
.distinct("intervention") \
|
||||
.select_related("intervention") \
|
||||
.values_list("intervention__id", "intervention__identifier", "intervention__title", named=True)
|
||||
|
||||
"""
|
||||
# Reuse the compensation report template since EcoAccounts are structurally identical
|
||||
template = "compensation/report/eco_account/report.html"
|
||||
acc = get_object_or_404(EcoAccount, id=id)
|
||||
|
||||
tab_title = _("Report {}").format(acc.identifier)
|
||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||
if not acc.is_ready_for_publish():
|
||||
template = "report/unavailable.html"
|
||||
context = {
|
||||
TAB_TITLE_IDENTIFIER: tab_title,
|
||||
report_context = {
|
||||
"qrcode": {
|
||||
"img": qrcode_report.get_img(),
|
||||
"url": qrcode_report.get_content(),
|
||||
},
|
||||
"qrcode_lanis": {
|
||||
"img": qrcode_lanis.get_img(),
|
||||
"url": qrcode_lanis.get_content(),
|
||||
},
|
||||
"is_entry_shared": False, # disables action buttons during rendering
|
||||
"deductions": deductions,
|
||||
"tables_scrollable": False,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
# Prepare data for map viewer
|
||||
geom_form = SimpleGeomForm(
|
||||
instance=acc
|
||||
)
|
||||
parcels = acc.get_underlying_parcels()
|
||||
|
||||
qrcode_url = request.build_absolute_uri(reverse("compensation:acc:report", args=(id,)))
|
||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
||||
qrcode_lanis_url = acc.get_LANIS_link()
|
||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
||||
|
||||
# Order states by surface
|
||||
before_states = acc.before_states.all().order_by("-surface").select_related("biotope_type__parent")
|
||||
after_states = acc.after_states.all().order_by("-surface").select_related("biotope_type__parent")
|
||||
actions = acc.actions.all().prefetch_related("action_type__parent")
|
||||
|
||||
# Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
|
||||
deductions = acc.deductions.all()\
|
||||
.distinct("intervention")\
|
||||
.select_related("intervention")\
|
||||
.values_list("intervention__id", "intervention__identifier", "intervention__title", named=True)
|
||||
|
||||
context = {
|
||||
"obj": acc,
|
||||
"qrcode": {
|
||||
"img": qrcode_img,
|
||||
"url": qrcode_url,
|
||||
},
|
||||
"qrcode_lanis": {
|
||||
"img": qrcode_img_lanis,
|
||||
"url": qrcode_lanis_url,
|
||||
},
|
||||
"has_access": False, # disables action buttons during rendering
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"geom_form": geom_form,
|
||||
"parcels": parcels,
|
||||
"actions": actions,
|
||||
"deductions": deductions,
|
||||
"tables_scrollable": False,
|
||||
TAB_TITLE_IDENTIFIER: tab_title,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
report_context.update(self._get_compensation_report_context(obj))
|
||||
return report_context
|
||||
|
||||
@@ -5,22 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.forms.modals.resubmission import EcoAccountResubmissionModalForm
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.resubmission import AbstractResubmissionView
|
||||
|
||||
|
||||
class EcoAccountResubmissionView(AbstractResubmissionView):
|
||||
model = EcoAccount
|
||||
redirect_url_base = "compensation:acc:detail"
|
||||
form_action_url_base = "compensation:acc:resubmission-create"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_FORM_CLS = EcoAccountResubmissionModalForm
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
@@ -5,29 +5,15 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.share import AbstractShareByTokenView, AbstractShareFormView
|
||||
|
||||
|
||||
class EcoAccountShareByTokenView(AbstractShareByTokenView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
|
||||
class EcoAccountShareFormView(AbstractShareFormView):
|
||||
model = EcoAccount
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
@@ -5,46 +5,21 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from compensation.models import EcoAccount
|
||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
|
||||
from konova.views.state import AbstractNewCompensationStateView, AbstractEditCompensationStateView, \
|
||||
AbstractRemoveCompensationStateView
|
||||
|
||||
|
||||
class NewEcoAccountStateView(AbstractNewCompensationStateView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
|
||||
class EditEcoAccountStateView(AbstractEditCompensationStateView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
|
||||
class RemoveEcoAccountStateView(AbstractRemoveCompensationStateView):
|
||||
model = EcoAccount
|
||||
redirect_url = "compensation:acc:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(EcoAccount, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = EcoAccount
|
||||
_REDIRECT_URL = "compensation:acc:detail"
|
||||
|
||||
@@ -5,84 +5,38 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 09.08.21
|
||||
|
||||
"""
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from compensation.forms.modals.payment import NewPaymentForm, RemovePaymentModalForm, EditPaymentModalForm
|
||||
from compensation.models import Payment
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import default_group_required, shared_access_required
|
||||
from konova.utils.message_templates import PAYMENT_ADDED, PAYMENT_REMOVED, PAYMENT_EDITED
|
||||
from konova.views.base import BaseModalFormView
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def new_payment_view(request: HttpRequest, id: str):
|
||||
""" Renders a modal view for adding new payments
|
||||
class BasePaymentView(LoginRequiredMixin, BaseModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The intervention's id for which a new payment shall be added
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
Returns:
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
url = super()._get_redirect_url(*args, **kwargs)
|
||||
return f"{url}#related_data"
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
form = NewPaymentForm(request.POST or None, instance=intervention, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
msg_success=PAYMENT_ADDED,
|
||||
redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
|
||||
)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def payment_remove_view(request: HttpRequest, id: str, payment_id: str):
|
||||
""" Renders a modal view for removing payments
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The intervention's id
|
||||
payment_id (str): The payment's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
payment = get_object_or_404(Payment, id=payment_id)
|
||||
form = RemovePaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=PAYMENT_REMOVED,
|
||||
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
||||
)
|
||||
class NewPaymentView(BasePaymentView):
|
||||
_FORM_CLS = NewPaymentForm
|
||||
_MSG_SUCCESS = PAYMENT_ADDED
|
||||
|
||||
|
||||
@login_required
|
||||
@default_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def payment_edit_view(request: HttpRequest, id: str, payment_id: str):
|
||||
""" Renders a modal view for editing payments
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The intervention's id
|
||||
payment_id (str): The payment's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
payment = get_object_or_404(Payment, id=payment_id)
|
||||
form = EditPaymentModalForm(request.POST or None, instance=intervention, payment=payment, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=PAYMENT_EDITED,
|
||||
redirect_url=reverse("intervention:detail", args=(payment.intervention_id,)) + "#related_data"
|
||||
)
|
||||
class EditPaymentView(BasePaymentView):
|
||||
_MSG_SUCCESS = PAYMENT_EDITED
|
||||
_FORM_CLS = EditPaymentModalForm
|
||||
|
||||
class RemovePaymentView(BasePaymentView):
|
||||
_MSG_SUCCESS = PAYMENT_REMOVED
|
||||
_FORM_CLS = RemovePaymentModalForm
|
||||
|
||||
14
ema/forms.py
14
ema/forms.py
@@ -15,7 +15,8 @@ from compensation.forms.compensation import AbstractCompensationForm
|
||||
from ema.models import Ema, EmaDocument
|
||||
from intervention.models import Responsibility, Handler
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.forms.modals import NewDocumentModalForm
|
||||
from konova.forms.modals import NewDocumentModalForm, EditDocumentModalForm, RemoveDocumentModalForm, \
|
||||
ResubmissionModalForm
|
||||
from user.models import UserActionLogEntry
|
||||
|
||||
|
||||
@@ -170,4 +171,13 @@ class EditEmaForm(NewEmaForm):
|
||||
|
||||
|
||||
class NewEmaDocumentModalForm(NewDocumentModalForm):
|
||||
document_model = EmaDocument
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
|
||||
class EditEmaDocumentModalForm(EditDocumentModalForm):
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
|
||||
class RemoveEmaDocumentModalForm(RemoveDocumentModalForm):
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
|
||||
class EmaResubmissionModalForm(ResubmissionModalForm):
|
||||
_MODEL_CLS = Ema
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'ema:new-action' obj.id %}" title="{% trans 'Add new action' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'seedling' %}
|
||||
@@ -61,7 +61,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'ema:action-edit' obj.id action.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit action' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{% fa5_icon 'file-alt' %}
|
||||
</button>
|
||||
</a>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Resubmission' %}" data-form-url="{% url 'ema:resubmission-create' obj.id %}">
|
||||
{% fa5_icon 'bell' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'ema:new-deadline' obj.id %}" title="{% trans 'Add new deadline' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'calendar-check' %}
|
||||
@@ -58,7 +58,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'ema:deadline-edit' obj.id deadline.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit deadline' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'ema:new-doc' obj.id %}" title="{% trans 'Add new document' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'file' %}
|
||||
@@ -57,7 +57,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'ema:edit-doc' obj.id doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit document' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'ema:new-state' obj.id %}" title="{% trans 'Add new state after' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'layer-group' %}
|
||||
@@ -56,7 +56,7 @@
|
||||
</td>
|
||||
<td>{{ state.surface|floatformat:2 }} m²</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'ema:state-edit' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit state' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'ema:new-state' obj.id %}?before=true" title="{% trans 'Add new state before' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'layer-group' %}
|
||||
@@ -56,7 +56,7 @@
|
||||
</td>
|
||||
<td>{{ state.surface|floatformat:2 }} m²</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'ema:state-edit' obj.id state.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit state' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
{% include 'user/includes/team_data_modal_button.html' %}
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
{% for user in obj.users.all %}
|
||||
{% include 'user/includes/contact_modal_button.html' %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -46,7 +46,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
||||
post_data = {
|
||||
"identifier": test_id,
|
||||
"title": test_title,
|
||||
"geom": geom_json,
|
||||
"output": geom_json,
|
||||
"conservation_office": test_conservation_office.id
|
||||
}
|
||||
self.client_user.post(new_url, post_data)
|
||||
@@ -84,7 +84,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
||||
new_title = self.create_dummy_string()
|
||||
new_identifier = self.create_dummy_string()
|
||||
new_comment = self.create_dummy_string()
|
||||
new_geometry = MultiPolygon(srid=4326) # Create an empty geometry
|
||||
new_geometry = self.create_dummy_geometry() # Create an empty geometry
|
||||
test_conservation_office = self.get_conservation_office_code()
|
||||
|
||||
check_on_elements = {
|
||||
@@ -99,7 +99,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
|
||||
"identifier": new_identifier,
|
||||
"title": new_title,
|
||||
"comment": new_comment,
|
||||
"geom": new_geometry.geojson,
|
||||
"output": self.create_geojson(new_geometry),
|
||||
"conservation_office": test_conservation_office.id
|
||||
}
|
||||
self.client_user.post(url, post_data)
|
||||
|
||||
@@ -48,7 +48,7 @@ class NewEmaFormTestCase(BaseTestCase):
|
||||
)
|
||||
geom_form_data = json.loads(geom_form_data)
|
||||
geom_form_data = {
|
||||
"geom": json.dumps(geom_form_data)
|
||||
"output": json.dumps(geom_form_data)
|
||||
}
|
||||
|
||||
geom_form = SimpleGeomForm(geom_form_data)
|
||||
@@ -116,7 +116,7 @@ class EditEmaFormTestCase(BaseTestCase):
|
||||
)
|
||||
geom_form_data = json.loads(geom_form_data)
|
||||
geom_form_data = {
|
||||
"geom": json.dumps(geom_form_data)
|
||||
"output": json.dumps(geom_form_data)
|
||||
}
|
||||
|
||||
geom_form = SimpleGeomForm(geom_form_data)
|
||||
|
||||
19
ema/urls.py
19
ema/urls.py
@@ -10,25 +10,26 @@ from django.urls import path
|
||||
from ema.views.action import NewEmaActionView, EditEmaActionView, RemoveEmaActionView
|
||||
from ema.views.deadline import NewEmaDeadlineView, EditEmaDeadlineView, RemoveEmaDeadlineView
|
||||
from ema.views.document import NewEmaDocumentView, EditEmaDocumentView, RemoveEmaDocumentView, GetEmaDocumentView
|
||||
from ema.views.ema import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
|
||||
from ema.views.ema import EmaIndexView, EmaIdentifierGeneratorView, EmaDetailView, EditEmaFormView, NewEmaFormView, \
|
||||
RemoveEmaView
|
||||
from ema.views.log import EmaLogView
|
||||
from ema.views.record import EmaRecordView
|
||||
from ema.views.report import report_view
|
||||
from ema.views.report import EmaReportView
|
||||
from ema.views.resubmission import EmaResubmissionView
|
||||
from ema.views.share import EmaShareFormView, EmaShareByTokenView
|
||||
from ema.views.state import NewEmaStateView, EditEmaStateView, RemoveEmaStateView
|
||||
|
||||
app_name = "ema"
|
||||
urlpatterns = [
|
||||
path("", index_view, name="index"),
|
||||
path("new/", new_view, name="new"),
|
||||
path("new/id", new_id_view, name="new-id"),
|
||||
path("<id>", detail_view, name="detail"),
|
||||
path("", EmaIndexView.as_view(), name="index"),
|
||||
path("new/", NewEmaFormView.as_view(), name="new"),
|
||||
path("new/id", EmaIdentifierGeneratorView.as_view(), name="new-id"),
|
||||
path("<id>", EmaDetailView.as_view(), name="detail"),
|
||||
path('<id>/log', EmaLogView.as_view(), name='log'),
|
||||
path('<id>/edit', edit_view, name='edit'),
|
||||
path('<id>/remove', remove_view, name='remove'),
|
||||
path('<id>/edit', EditEmaFormView.as_view(), name='edit'),
|
||||
path('<id>/remove', RemoveEmaView.as_view(), name='remove'),
|
||||
path('<id>/record', EmaRecordView.as_view(), name='record'),
|
||||
path('<id>/report', report_view, name='report'),
|
||||
path('<id>/report', EmaReportView.as_view(), name='report'),
|
||||
path('<id>/resub', EmaResubmissionView.as_view(), name='resubmission-create'),
|
||||
|
||||
path('<id>/state/new', NewEmaStateView.as_view(), name='new-state'),
|
||||
|
||||
@@ -5,46 +5,31 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from ema.models import Ema
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.views.action import AbstractNewCompensationActionView, AbstractEditCompensationActionView, \
|
||||
AbstractRemoveCompensationActionView
|
||||
|
||||
_EMA_ACCOUNT_DETAIL_URL_NAME = "ema:detail"
|
||||
|
||||
class NewEmaActionView(AbstractNewCompensationActionView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class EditEmaActionView(AbstractEditCompensationActionView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class RemoveEmaActionView(AbstractRemoveCompensationActionView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -5,46 +5,30 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from ema.models import Ema
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.views.deadline import AbstractNewDeadlineView, AbstractRemoveDeadlineView, AbstractEditDeadlineView
|
||||
|
||||
_EMA_DETAIL_URL_NAME = "ema:detail"
|
||||
|
||||
class NewEmaDeadlineView(AbstractNewDeadlineView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_DETAIL_URL_NAME
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class EditEmaDeadlineView(AbstractEditDeadlineView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_DETAIL_URL_NAME
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class RemoveEmaDeadlineView(AbstractRemoveDeadlineView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = _EMA_DETAIL_URL_NAME
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -5,62 +5,41 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from ema.forms import NewEmaDocumentModalForm
|
||||
from ema.forms import NewEmaDocumentModalForm, RemoveEmaDocumentModalForm, EditEmaDocumentModalForm
|
||||
from ema.models import Ema, EmaDocument
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.forms.modals import EditDocumentModalForm
|
||||
from konova.views.document import AbstractEditDocumentView, AbstractRemoveDocumentView, AbstractGetDocumentView, \
|
||||
AbstractNewDocumentView
|
||||
|
||||
|
||||
class NewEmaDocumentView(AbstractNewDocumentView):
|
||||
model = Ema
|
||||
form = NewEmaDocumentModalForm
|
||||
redirect_url = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Ema
|
||||
_FORM_CLS = NewEmaDocumentModalForm
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class GetEmaDocumentView(AbstractGetDocumentView):
|
||||
model = Ema
|
||||
document_model = EmaDocument
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Ema
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class RemoveEmaDocumentView(AbstractRemoveDocumentView):
|
||||
model = Ema
|
||||
document_model = EmaDocument
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
_MODEL_CLS = Ema
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
_FORM_CLS = RemoveEmaDocumentModalForm
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
class EditEmaDocumentView(AbstractEditDocumentView):
|
||||
model = Ema
|
||||
document_model = EmaDocument
|
||||
form = EditDocumentModalForm
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_FORM_CLS = EditEmaDocumentModalForm
|
||||
_DOCUMENT_CLS = EmaDocument
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
325
ema/views/ema.py
325
ema/views/ema.py
@@ -5,255 +5,112 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db.models import Sum
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ema.forms import NewEmaForm, EditEmaForm
|
||||
from ema.models import Ema
|
||||
from ema.tables import EmaTable
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal, \
|
||||
uuid_required
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID, \
|
||||
DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED
|
||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
|
||||
BaseEditSpatialLocatedObjectFormView
|
||||
from konova.views.detail import BaseDetailView
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
@login_required
|
||||
def index_view(request: HttpRequest):
|
||||
""" Renders the index view for EMAs
|
||||
class EmaIndexView(LoginRequiredMixin, BaseIndexView):
|
||||
_TAB_TITLE = _("EMAs - Overview")
|
||||
_INDEX_TABLE_CLS = EmaTable
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "generic_index.html"
|
||||
emas = Ema.objects.filter(
|
||||
deleted=None,
|
||||
).order_by(
|
||||
"-modified__timestamp"
|
||||
)
|
||||
|
||||
table = EmaTable(
|
||||
request,
|
||||
queryset=emas
|
||||
)
|
||||
context = {
|
||||
"table": table,
|
||||
TAB_TITLE_IDENTIFIER: _("EMAs - Overview"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
def _get_queryset(self):
|
||||
qs = Ema.objects.filter(
|
||||
deleted=None,
|
||||
).order_by(
|
||||
"-modified__timestamp"
|
||||
)
|
||||
return qs
|
||||
|
||||
|
||||
@login_required
|
||||
@conservation_office_group_required
|
||||
def new_view(request: HttpRequest):
|
||||
"""
|
||||
Renders a view for a new eco account creation
|
||||
class NewEmaFormView(BaseNewSpatialLocatedObjectFormView):
|
||||
_FORM_CLS = NewEmaForm
|
||||
_MODEL_CLS = Ema
|
||||
_TEMPLATE = "ema/form/view.html"
|
||||
_TAB_TITLE = _("New EMA")
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "ema/form/view.html"
|
||||
data_form = NewEmaForm(request.POST or None)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
|
||||
if request.method == "POST":
|
||||
if data_form.is_valid() and geom_form.is_valid():
|
||||
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
||||
ema = data_form.save(request.user, geom_form)
|
||||
if generated_identifier != ema.identifier:
|
||||
messages.info(
|
||||
request,
|
||||
IDENTIFIER_REPLACED.format(
|
||||
generated_identifier,
|
||||
ema.identifier
|
||||
)
|
||||
)
|
||||
messages.success(request, _("EMA {} added").format(ema.identifier))
|
||||
if geom_form.geometry_simplified:
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
|
||||
return redirect("ema:detail", id=ema.id)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("New EMA"),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be an ets user
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
@login_required
|
||||
@conservation_office_group_required
|
||||
def new_id_view(request: HttpRequest):
|
||||
""" JSON endpoint
|
||||
class EditEmaFormView(BaseEditSpatialLocatedObjectFormView):
|
||||
_MODEL_CLS = Ema
|
||||
_FORM_CLS = EditEmaForm
|
||||
_TEMPLATE = "ema/form/view.html"
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
_TAB_TITLE = _("Edit {}")
|
||||
|
||||
Provides fetching of free identifiers for e.g. AJAX calls
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
# User has to be an ets user
|
||||
return user.is_ets_user()
|
||||
|
||||
"""
|
||||
tmp = Ema()
|
||||
identifier = tmp.generate_new_identifier()
|
||||
while Ema.objects.filter(identifier=identifier).exists():
|
||||
identifier = tmp.generate_new_identifier()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"gen_data": identifier
|
||||
|
||||
class EmaIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:index"
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class EmaDetailView(BaseDetailView):
|
||||
_MODEL_CLS = Ema
|
||||
_TEMPLATE = "ema/detail/view.html"
|
||||
|
||||
def _get_object(self, id: str):
|
||||
""" Fetch object for detail view
|
||||
|
||||
Args:
|
||||
id (str): The record's id'
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
ema = get_object_or_404(Ema, id=id, deleted=None)
|
||||
return ema
|
||||
|
||||
def _get_detail_context(self, obj: Ema):
|
||||
""" Generate object specific detail context for view
|
||||
|
||||
Args:
|
||||
obj (): The record
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
# Order states according to surface
|
||||
before_states = obj.before_states.all().order_by("-surface")
|
||||
after_states = obj.after_states.all().order_by("-surface")
|
||||
|
||||
# Precalculate logical errors between before- and after-states
|
||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||
sum_before_states = obj.get_surface_before_states()
|
||||
sum_after_states = obj.get_surface_after_states()
|
||||
diff_states = abs(sum_before_states - sum_after_states)
|
||||
|
||||
context = {
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"sum_before_states": sum_before_states,
|
||||
"sum_after_states": sum_after_states,
|
||||
"diff_states": diff_states,
|
||||
"has_finished_deadlines": obj.get_finished_deadlines().exists(),
|
||||
}
|
||||
)
|
||||
return context
|
||||
|
||||
class RemoveEmaView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:index"
|
||||
|
||||
@login_required
|
||||
@uuid_required
|
||||
def detail_view(request: HttpRequest, id: str):
|
||||
""" Renders the detail view of an EMA
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The EMA id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "ema/detail/view.html"
|
||||
ema = get_object_or_404(Ema, id=id, deleted=None)
|
||||
|
||||
geom_form = SimpleGeomForm(instance=ema)
|
||||
parcels = ema.get_underlying_parcels()
|
||||
_user = request.user
|
||||
is_data_shared = ema.is_shared_with(_user)
|
||||
|
||||
# Order states according to surface
|
||||
before_states = ema.before_states.all().order_by("-surface")
|
||||
after_states = ema.after_states.all().order_by("-surface")
|
||||
|
||||
# Precalculate logical errors between before- and after-states
|
||||
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
||||
sum_before_states = ema.get_surface_before_states()
|
||||
sum_after_states = ema.get_surface_after_states()
|
||||
diff_states = abs(sum_before_states - sum_after_states)
|
||||
|
||||
ema.set_status_messages(request)
|
||||
|
||||
requesting_user_is_only_shared_user = ema.is_only_shared_with(_user)
|
||||
if requesting_user_is_only_shared_user:
|
||||
messages.info(
|
||||
request,
|
||||
DO_NOT_FORGET_TO_SHARE
|
||||
)
|
||||
|
||||
context = {
|
||||
"obj": ema,
|
||||
"geom_form": geom_form,
|
||||
"parcels": parcels,
|
||||
"has_access": is_data_shared,
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"sum_before_states": sum_before_states,
|
||||
"sum_after_states": sum_after_states,
|
||||
"diff_states": diff_states,
|
||||
"is_default_member": _user.in_group(DEFAULT_GROUP),
|
||||
"is_zb_member": _user.in_group(ZB_GROUP),
|
||||
"is_ets_member": _user.in_group(ETS_GROUP),
|
||||
"LANIS_LINK": ema.get_LANIS_link(),
|
||||
TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}",
|
||||
"has_finished_deadlines": ema.get_finished_deadlines().exists(),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required
|
||||
@conservation_office_group_required
|
||||
@shared_access_required(Ema, "id")
|
||||
def edit_view(request: HttpRequest, id: str):
|
||||
"""
|
||||
Renders a view for editing compensations
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "compensation/form/view.html"
|
||||
# Get object from db
|
||||
ema = get_object_or_404(Ema, id=id)
|
||||
if ema.is_recorded:
|
||||
messages.info(
|
||||
request,
|
||||
RECORDED_BLOCKS_EDIT
|
||||
)
|
||||
return redirect("ema:detail", id=id)
|
||||
|
||||
# Create forms, initialize with values from db/from POST request
|
||||
data_form = EditEmaForm(request.POST or None, instance=ema)
|
||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
|
||||
if request.method == "POST":
|
||||
if data_form.is_valid() and geom_form.is_valid():
|
||||
# The data form takes the geom form for processing, as well as the performing user
|
||||
ema = data_form.save(request.user, geom_form)
|
||||
messages.success(request, _("EMA {} edited").format(ema.identifier))
|
||||
if geom_form.geometry_simplified:
|
||||
messages.info(
|
||||
request,
|
||||
GEOMETRY_SIMPLIFIED
|
||||
)
|
||||
return redirect("ema:detail", id=ema.id)
|
||||
else:
|
||||
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
||||
else:
|
||||
# For clarification: nothing in this case
|
||||
pass
|
||||
context = {
|
||||
"form": data_form,
|
||||
"geom_form": geom_form,
|
||||
TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
@conservation_office_group_required
|
||||
@shared_access_required(Ema, "id")
|
||||
def remove_view(request: HttpRequest, id: str):
|
||||
""" Renders a modal view for removing the EMA
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The EMA's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
ema = get_object_or_404(Ema, id=id)
|
||||
form = RemoveModalForm(request.POST or None, instance=ema, request=request)
|
||||
return form.process_request(
|
||||
request=request,
|
||||
msg_success=_("EMA removed"),
|
||||
redirect_url=reverse("ema:index"),
|
||||
)
|
||||
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -5,20 +5,14 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from ema.models import Ema
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.views.log import AbstractLogView
|
||||
|
||||
|
||||
class EmaLogView(AbstractLogView):
|
||||
model = Ema
|
||||
class EmaLogView(LoginRequiredMixin, AbstractLogView):
|
||||
_MODEL_CLS = Ema
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -5,20 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from ema.models import Ema
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.views.record import AbstractRecordView
|
||||
|
||||
|
||||
class EmaRecordView(AbstractRecordView):
|
||||
model = Ema
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class EmaRecordView(LoginRequiredMixin, AbstractRecordView):
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
@@ -5,76 +5,36 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from compensation.views.compensation.report import BaseCompensationReportView
|
||||
from ema.models import Ema
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import SimpleGeomForm
|
||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||
from konova.utils.generators import generate_qr_code
|
||||
from konova.sub_settings.django_settings import BASE_URL
|
||||
from konova.utils.qrcode import QrCode
|
||||
|
||||
|
||||
def report_view(request:HttpRequest, id: str):
|
||||
""" Renders the public report view
|
||||
class EmaReportView(BaseCompensationReportView):
|
||||
_TEMPLATE = "ema/report/report.html"
|
||||
_MODEL = Ema
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The id of the intervention
|
||||
def _get_report_context(self, obj):
|
||||
report_url = BASE_URL + reverse("ema:report", args=(obj.id,))
|
||||
qrcode_report = QrCode(report_url, 10)
|
||||
qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
|
||||
|
||||
Returns:
|
||||
generic_compensation_report_context = self._get_compensation_report_context(obj)
|
||||
|
||||
"""
|
||||
# Reuse the compensation report template since EMAs are structurally identical
|
||||
template = "ema/report/report.html"
|
||||
ema = get_object_or_404(Ema, id=id)
|
||||
|
||||
tab_title = _("Report {}").format(ema.identifier)
|
||||
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
||||
if not ema.is_ready_for_publish():
|
||||
template = "report/unavailable.html"
|
||||
context = {
|
||||
TAB_TITLE_IDENTIFIER: tab_title,
|
||||
report_context = {
|
||||
"qrcode": {
|
||||
"img": qrcode_report.get_img(),
|
||||
"url": qrcode_report.get_content(),
|
||||
},
|
||||
"qrcode_lanis": {
|
||||
"img": qrcode_lanis.get_img(),
|
||||
"url": qrcode_lanis.get_content(),
|
||||
},
|
||||
"is_entry_shared": False, # disables action buttons during rendering
|
||||
"tables_scrollable": False,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
|
||||
# Prepare data for map viewer
|
||||
geom_form = SimpleGeomForm(
|
||||
instance=ema,
|
||||
)
|
||||
parcels = ema.get_underlying_parcels()
|
||||
|
||||
qrcode_url = request.build_absolute_uri(reverse("ema:report", args=(id,)))
|
||||
qrcode_img = generate_qr_code(qrcode_url, 10)
|
||||
qrcode_lanis_url = ema.get_LANIS_link()
|
||||
qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
|
||||
|
||||
# Order states by surface
|
||||
before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
||||
actions = ema.actions.all().prefetch_related("action_type")
|
||||
|
||||
context = {
|
||||
"obj": ema,
|
||||
"qrcode": {
|
||||
"img": qrcode_img,
|
||||
"url": qrcode_url
|
||||
},
|
||||
"qrcode_lanis": {
|
||||
"img": qrcode_img_lanis,
|
||||
"url": qrcode_lanis_url
|
||||
},
|
||||
"has_access": False, # disables action buttons during rendering
|
||||
"before_states": before_states,
|
||||
"after_states": after_states,
|
||||
"geom_form": geom_form,
|
||||
"parcels": parcels,
|
||||
"actions": actions,
|
||||
"tables_scrollable": False,
|
||||
TAB_TITLE_IDENTIFIER: tab_title,
|
||||
}
|
||||
context = BaseContext(request, context).context
|
||||
return render(request, template, context)
|
||||
report_context.update(generic_compensation_report_context)
|
||||
return report_context
|
||||
@@ -5,22 +5,16 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from ema.forms import EmaResubmissionModalForm
|
||||
from ema.models import Ema
|
||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
|
||||
from konova.views.resubmission import AbstractResubmissionView
|
||||
|
||||
|
||||
class EmaResubmissionView(AbstractResubmissionView):
|
||||
model = Ema
|
||||
redirect_url_base = "ema:detail"
|
||||
form_action_url_base = "ema:resubmission-create"
|
||||
_MODEL_CLS = Ema
|
||||
_FORM_CLS = EmaResubmissionModalForm
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
action_url = "ema:resubmission-create"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -5,29 +5,17 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from ema.models import Ema
|
||||
from konova.decorators import conservation_office_group_required, shared_access_required, login_required_modal
|
||||
from konova.views.share import AbstractShareByTokenView, AbstractShareFormView
|
||||
|
||||
|
||||
class EmaShareByTokenView(AbstractShareByTokenView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
|
||||
@method_decorator(login_required)
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
class EmaShareFormView(AbstractShareFormView):
|
||||
model = Ema
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
@@ -5,46 +5,30 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
|
||||
from ema.models import Ema
|
||||
from konova.decorators import conservation_office_group_required, shared_access_required, login_required_modal
|
||||
from konova.views.state import AbstractNewCompensationStateView, AbstractEditCompensationStateView, \
|
||||
AbstractRemoveCompensationStateView
|
||||
|
||||
|
||||
class NewEmaStateView(AbstractNewCompensationStateView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class EditEmaStateView(AbstractEditCompensationStateView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
|
||||
class RemoveEmaStateView(AbstractRemoveCompensationStateView):
|
||||
model = Ema
|
||||
redirect_url = "ema:detail"
|
||||
_MODEL_CLS = Ema
|
||||
_REDIRECT_URL = "ema:detail"
|
||||
|
||||
@method_decorator(login_required_modal)
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(conservation_office_group_required)
|
||||
@method_decorator(shared_access_required(Ema, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_ets_user()
|
||||
|
||||
@@ -172,7 +172,8 @@ class EditEcoAccountDeductionModalForm(NewEcoAccountDeductionModalForm):
|
||||
deduction = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.deduction = kwargs.pop("deduction", None)
|
||||
deduction_id = kwargs.pop("deduction_id", None)
|
||||
self.deduction = EcoAccountDeduction.objects.get(id=deduction_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit Deduction")
|
||||
form_data = {
|
||||
@@ -252,19 +253,20 @@ class RemoveEcoAccountDeductionModalForm(RemoveModalForm):
|
||||
Can be used for anything, where removing shall be confirmed by the user a second time.
|
||||
|
||||
"""
|
||||
deduction = None
|
||||
_DEDUCTION_OBJ = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
deduction = kwargs.pop("deduction", None)
|
||||
self.deduction = deduction
|
||||
deduction_id = kwargs.pop("deduction_id", None)
|
||||
deduction = EcoAccountDeduction.objects.get(id=deduction_id)
|
||||
self._DEDUCTION_OBJ = deduction
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self):
|
||||
with transaction.atomic():
|
||||
self.deduction.intervention.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
|
||||
self.deduction.account.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
|
||||
self.deduction.delete()
|
||||
self._DEDUCTION_OBJ.intervention.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
|
||||
self._DEDUCTION_OBJ.account.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
|
||||
self._DEDUCTION_OBJ.delete()
|
||||
|
||||
def check_for_recorded_instance(self):
|
||||
if self.deduction.intervention.is_recorded:
|
||||
if self._DEDUCTION_OBJ.intervention.is_recorded:
|
||||
self.block_form()
|
||||
|
||||
@@ -6,11 +6,11 @@ Created on: 18.08.22
|
||||
|
||||
"""
|
||||
from intervention.models import InterventionDocument
|
||||
from konova.forms.modals import NewDocumentModalForm
|
||||
from konova.forms.modals import NewDocumentModalForm, EditDocumentModalForm, RemoveDocumentModalForm
|
||||
|
||||
|
||||
class NewInterventionDocumentModalForm(NewDocumentModalForm):
|
||||
document_model = InterventionDocument
|
||||
_DOCUMENT_CLS = InterventionDocument
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
""" Extension of regular NewDocumentModalForm
|
||||
@@ -28,3 +28,31 @@ class NewInterventionDocumentModalForm(NewDocumentModalForm):
|
||||
self.instance.send_data_to_egon()
|
||||
|
||||
return doc
|
||||
|
||||
class EditInterventionDocumentModalForm(EditDocumentModalForm):
|
||||
_DOCUMENT_CLS = InterventionDocument
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
""" Extension of regular EditDocumentModalForm
|
||||
|
||||
Checks whether payments exist on the intervention and sends the data to EGON
|
||||
|
||||
Args:
|
||||
*args ():
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
doc = super().save(*args, **kwargs)
|
||||
self.instance.send_data_to_egon()
|
||||
|
||||
return doc
|
||||
|
||||
|
||||
class RemoveInterventionDocumentModalForm(RemoveDocumentModalForm):
|
||||
_DOCUMENT_CLS = InterventionDocument
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
super().save(*args, **kwargs)
|
||||
self.instance.send_data_to_egon()
|
||||
|
||||
22
intervention/forms/modals/remove.py
Normal file
22
intervention/forms/modals/remove.py
Normal file
@@ -0,0 +1,22 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 08.11.25
|
||||
|
||||
"""
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from compensation.models import Compensation
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
|
||||
|
||||
class RemoveCompensationFromInterventionModalForm(RemoveModalForm):
|
||||
""" Specific form for removing a compensation from an intervention
|
||||
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
# The 'instance' that is pushed into the constructor by the generic base class points to the
|
||||
# intervention instead of the compensation, which shall be deleted. Therefore we need to fetch the compensation
|
||||
# and replace the instance parameter with that object
|
||||
instance = get_object_or_404(Compensation, id=kwargs.pop("comp_id"))
|
||||
kwargs["instance"] = instance
|
||||
super().__init__(*args, **kwargs)
|
||||
11
intervention/forms/modals/resubmission.py
Normal file
11
intervention/forms/modals/resubmission.py
Normal file
@@ -0,0 +1,11 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Created on: 21.10.25
|
||||
|
||||
"""
|
||||
from intervention.models import Intervention
|
||||
from konova.forms.modals import ResubmissionModalForm
|
||||
|
||||
|
||||
class InterventionResubmissionModalForm(ResubmissionModalForm):
|
||||
_MODEL_CLS = Intervention
|
||||
@@ -7,9 +7,10 @@ Created on: 18.08.22
|
||||
"""
|
||||
from django import forms
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from intervention.models import RevocationDocument
|
||||
from intervention.models import RevocationDocument, Revocation
|
||||
from konova.forms.modals import BaseModalForm, RemoveModalForm
|
||||
from konova.utils import validators
|
||||
from konova.utils.message_templates import REVOCATION_ADDED, REVOCATION_EDITED
|
||||
@@ -75,7 +76,8 @@ class EditRevocationModalForm(NewRevocationModalForm):
|
||||
revocation = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.revocation = kwargs.pop("revocation", None)
|
||||
revocation_id = kwargs.pop("revocation_id", None)
|
||||
self.revocation = get_object_or_404(Revocation, id=revocation_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("Edit revocation")
|
||||
try:
|
||||
@@ -104,8 +106,8 @@ class RemoveRevocationModalForm(RemoveModalForm):
|
||||
revocation = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
revocation = kwargs.pop("revocation", None)
|
||||
self.revocation = revocation
|
||||
revocation_id = kwargs.pop("revocation_id", None)
|
||||
self.revocation = get_object_or_404(Revocation, id=revocation_id)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self):
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<a href="{% url 'compensation:new' obj.id %}" title="{% trans 'Add new compensation' %}">
|
||||
<button class="btn btn-outline-default">
|
||||
{% fa5_icon 'plus' %}
|
||||
@@ -32,7 +32,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Title' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -51,7 +51,7 @@
|
||||
</td>
|
||||
<td class="align-middle">{{ comp.title }}</td>
|
||||
<td>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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' %}
|
||||
</button>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{% fa5_icon 'file-alt' %}
|
||||
</button>
|
||||
</a>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
<button class="btn btn-default btn-modal mr-2" title="{% trans 'Resubmission' %}" data-form-url="{% url 'intervention:resubmission-create' obj.id %}">
|
||||
{% fa5_icon 'bell' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<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 'tree' %}
|
||||
@@ -33,7 +33,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Created' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -56,7 +56,7 @@
|
||||
<td class="align-middle">{{ deduction.surface|floatformat:2|intcomma }} m²</td>
|
||||
<td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'intervention:edit-deduction' obj.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit Deduction' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-doc' obj.id %}" title="{% trans 'Add new document' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'file' %}
|
||||
@@ -38,7 +38,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -66,7 +66,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'intervention:edit-doc' obj.id doc.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit document' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="d-flex justify-content-end">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'compensation:pay:new' obj.id %}" title="{% trans 'Add new payment' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'money-bill-wave' %}
|
||||
@@ -33,7 +33,7 @@
|
||||
<th class="w-50" scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -46,16 +46,24 @@
|
||||
{% for pay in obj.payments.all %}
|
||||
<tr>
|
||||
<td class="align-middle">
|
||||
{{ pay.amount|floatformat:2 }} €
|
||||
{% if is_entry_shared %}
|
||||
{{ pay.amount|floatformat:2 }} €
|
||||
{% else %}
|
||||
***
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="align-middle">{{ pay.due_on|default_if_none:"---" }}</td>
|
||||
<td class="align-middle">
|
||||
<div class="scroll-150">
|
||||
{{ pay.comment }}
|
||||
{% if is_entry_shared %}
|
||||
{{ pay.comment }}
|
||||
{% else %}
|
||||
{% trans 'This data is not shared with you' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'compensation:pay:edit' obj.id pay.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit payment' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
{% comment %}
|
||||
Only show add-button if no revocation exists, yet.
|
||||
{% endcomment %}
|
||||
{% if is_default_member and has_access and not obj.legal.revocation %}
|
||||
{% if is_default_member and is_entry_shared and not obj.legal.revocation %}
|
||||
<button class="btn btn-outline-default btn-modal" data-form-url="{% url 'intervention:new-revocation' obj.id %}" title="{% trans 'Add revocation' %}">
|
||||
{% fa5_icon 'plus' %}
|
||||
{% fa5_icon 'ban' %}
|
||||
@@ -36,7 +36,7 @@
|
||||
<th scope="col">
|
||||
{% trans 'Comment' %}
|
||||
</th>
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<th class="w-10" scope="col">
|
||||
<span class="float-right">
|
||||
{% trans 'Action' %}
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle float-right">
|
||||
{% if is_default_member and has_access %}
|
||||
{% if is_default_member and is_entry_shared %}
|
||||
<button data-form-url="{% url 'intervention:edit-revocation' obj.id rev.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit revocation' %}">
|
||||
{% fa5_icon 'edit' %}
|
||||
</button>
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
{% include 'user/includes/team_data_modal_button.html' %}
|
||||
{% endfor %}
|
||||
<hr>
|
||||
{% if has_access %}
|
||||
{% if is_entry_shared %}
|
||||
{% for user in obj.users.all %}
|
||||
{% include 'user/includes/contact_modal_button.html' %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -60,7 +60,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
|
||||
post_data = {
|
||||
"identifier": test_id,
|
||||
"title": test_title,
|
||||
"geom": geom_json,
|
||||
"output": geom_json,
|
||||
}
|
||||
response = self.client_user.post(
|
||||
new_url,
|
||||
|
||||
@@ -62,7 +62,7 @@ class NewInterventionFormTestCase(BaseTestCase):
|
||||
)
|
||||
geom_form_data = json.loads(geom_form_data)
|
||||
geom_form_data = {
|
||||
"geom": json.dumps(geom_form_data)
|
||||
"output": json.dumps(geom_form_data)
|
||||
}
|
||||
geom_form = SimpleGeomForm(geom_form_data)
|
||||
|
||||
@@ -104,7 +104,7 @@ class EditInterventionFormTestCase(NewInterventionFormTestCase):
|
||||
)
|
||||
geom_form_data = json.loads(geom_form_data)
|
||||
geom_form_data = {
|
||||
"geom": json.dumps(geom_form_data)
|
||||
"output": json.dumps(geom_form_data)
|
||||
}
|
||||
|
||||
geom_form = SimpleGeomForm(geom_form_data)
|
||||
@@ -124,7 +124,7 @@ class EditInterventionFormTestCase(NewInterventionFormTestCase):
|
||||
self.assertIsNotNone(obj.responsible.handler)
|
||||
self.assertEqual(obj.title, data["title"])
|
||||
self.assertEqual(obj.comment, data["comment"])
|
||||
self.assertTrue(test_geom.equals_exact(obj.geometry.geom, 0.000001))
|
||||
self.assert_equal_geometries(test_geom, obj.geometry.geom)
|
||||
|
||||
self.assertEqual(obj.legal.binding_date, today)
|
||||
self.assertEqual(obj.legal.registration_date, today)
|
||||
@@ -280,7 +280,7 @@ class EditRevocationModalFormTestCase(NewRevocationModalFormTestCase):
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.intervention,
|
||||
revocation=self.revoc
|
||||
revocation_id=self.revoc.id
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
obj = form.save()
|
||||
@@ -302,7 +302,7 @@ class RemoveRevocationModalFormTestCase(EditRevocationModalFormTestCase):
|
||||
form = RemoveRevocationModalForm(
|
||||
request=self.request,
|
||||
instance=self.intervention,
|
||||
revocation=self.revoc,
|
||||
revocation_id=self.revoc.id,
|
||||
)
|
||||
self.assertEqual(form.instance, self.intervention)
|
||||
self.assertEqual(form.revocation, self.revoc)
|
||||
@@ -317,7 +317,7 @@ class RemoveRevocationModalFormTestCase(EditRevocationModalFormTestCase):
|
||||
data,
|
||||
request=self.request,
|
||||
instance=self.intervention,
|
||||
revocation=self.revoc
|
||||
revocation_id=self.revoc.id
|
||||
)
|
||||
self.assertTrue(form.is_valid(), msg=form.errors)
|
||||
form.save()
|
||||
|
||||
@@ -8,39 +8,40 @@ Created on: 30.11.20
|
||||
from django.urls import path
|
||||
|
||||
from intervention.autocomplete.intervention import InterventionAutocomplete
|
||||
from intervention.views.check import check_view
|
||||
from intervention.views.compensation import remove_compensation_view
|
||||
from intervention.views.check import InterventionCheckView
|
||||
from intervention.views.compensation import RemoveCompensationFromInterventionView
|
||||
from intervention.views.deduction import NewInterventionDeductionView, EditInterventionDeductionView, \
|
||||
RemoveInterventionDeductionView
|
||||
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
|
||||
RemoveInterventionDocumentView, EditInterventionDocumentView
|
||||
from intervention.views.intervention import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
|
||||
from intervention.views.intervention import InterventionIndexView, InterventionIdentifierGeneratorView, \
|
||||
InterventionDetailView, NewInterventionFormView, EditInterventionFormView, RemoveInterventionView
|
||||
from intervention.views.log import InterventionLogView
|
||||
from intervention.views.record import InterventionRecordView
|
||||
from intervention.views.report import report_view
|
||||
from intervention.views.report import InterventionReportView
|
||||
from intervention.views.resubmission import InterventionResubmissionView
|
||||
from intervention.views.revocation import new_revocation_view, edit_revocation_view, remove_revocation_view, \
|
||||
get_revocation_view
|
||||
from intervention.views.revocation import NewRevocationView, GetRevocationDocumentView, EditRevocationView, \
|
||||
RemoveRevocationView
|
||||
from intervention.views.share import InterventionShareFormView, InterventionShareByTokenView
|
||||
|
||||
app_name = "intervention"
|
||||
urlpatterns = [
|
||||
path("", index_view, name="index"),
|
||||
path('new/', new_view, name='new'),
|
||||
path('new/id', new_id_view, name='new-id'),
|
||||
path('<id>', detail_view, name='detail'),
|
||||
path("", InterventionIndexView.as_view(), name="index"),
|
||||
path('new/', NewInterventionFormView.as_view(), name='new'),
|
||||
path('new/id', InterventionIdentifierGeneratorView.as_view(), name='new-id'),
|
||||
path('<id>', InterventionDetailView.as_view(), name='detail'),
|
||||
path('<id>/log', InterventionLogView.as_view(), name='log'),
|
||||
path('<id>/edit', edit_view, name='edit'),
|
||||
path('<id>/remove', remove_view, name='remove'),
|
||||
path('<id>/edit', EditInterventionFormView.as_view(), name='edit'),
|
||||
path('<id>/remove', RemoveInterventionView.as_view(), name='remove'),
|
||||
path('<id>/share/<token>', InterventionShareByTokenView.as_view(), name='share-token'),
|
||||
path('<id>/share', InterventionShareFormView.as_view(), name='share-form'),
|
||||
path('<id>/check', check_view, name='check'),
|
||||
path('<id>/check', InterventionCheckView.as_view(), name='check'),
|
||||
path('<id>/record', InterventionRecordView.as_view(), name='record'),
|
||||
path('<id>/report', report_view, name='report'),
|
||||
path('<id>/report', InterventionReportView.as_view(), name='report'),
|
||||
path('<id>/resub', InterventionResubmissionView.as_view(), name='resubmission-create'),
|
||||
|
||||
# Compensations
|
||||
path('<id>/compensation/<comp_id>/remove', remove_compensation_view, name='remove-compensation'),
|
||||
path('<id>/compensation/<comp_id>/remove', RemoveCompensationFromInterventionView.as_view(), name='remove-compensation'),
|
||||
|
||||
# Documents
|
||||
path('<id>/document/new/', NewInterventionDocumentView.as_view(), name='new-doc'),
|
||||
@@ -54,10 +55,10 @@ urlpatterns = [
|
||||
path('<id>/deduction/<deduction_id>/remove', RemoveInterventionDeductionView.as_view(), name='remove-deduction'),
|
||||
|
||||
# Revocation routes
|
||||
path('<id>/revocation/new', new_revocation_view, name='new-revocation'),
|
||||
path('<id>/revocation/<revocation_id>/edit', edit_revocation_view, name='edit-revocation'),
|
||||
path('<id>/revocation/<revocation_id>/remove', remove_revocation_view, name='remove-revocation'),
|
||||
path('revocation/<doc_id>', get_revocation_view, name='get-doc-revocation'),
|
||||
path('<id>/revocation/new', NewRevocationView.as_view(), name='new-revocation'),
|
||||
path('<id>/revocation/<revocation_id>/edit', EditRevocationView.as_view(), name='edit-revocation'),
|
||||
path('<id>/revocation/<revocation_id>/remove', RemoveRevocationView.as_view(), name='remove-revocation'),
|
||||
path('revocation/<doc_id>', GetRevocationDocumentView.as_view(), name='get-doc-revocation'),
|
||||
|
||||
# Autocomplete
|
||||
path("atcmplt/interventions", InterventionAutocomplete.as_view(), name="autocomplete"),
|
||||
|
||||
@@ -5,35 +5,24 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from intervention.forms.modals.check import CheckModalForm
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import registration_office_group_required, shared_access_required
|
||||
from konova.utils.message_templates import INTERVENTION_INVALID
|
||||
from konova.views.base import BaseModalFormView
|
||||
|
||||
|
||||
@login_required
|
||||
@registration_office_group_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def check_view(request: HttpRequest, id: str):
|
||||
""" Renders check form for an intervention
|
||||
class InterventionCheckView(LoginRequiredMixin, BaseModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_FORM_CLS = CheckModalForm
|
||||
_MSG_SUCCESS = _("Check performed")
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): Intervention's id
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
intervention = get_object_or_404(Intervention, id=id)
|
||||
form = CheckModalForm(request.POST or None, instance=intervention, request=request)
|
||||
return form.process_request(
|
||||
request,
|
||||
msg_success=_("Check performed"),
|
||||
msg_error=INTERVENTION_INVALID
|
||||
)
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_zb_user()
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
redirect_url = super()._get_redirect_url(*args, **kwargs)
|
||||
redirect_url += "#related_data"
|
||||
return redirect_url
|
||||
|
||||
@@ -5,42 +5,36 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.urls import reverse
|
||||
|
||||
from compensation.models import Compensation
|
||||
from intervention.forms.modals.remove import RemoveCompensationFromInterventionModalForm
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import shared_access_required, login_required_modal
|
||||
from konova.forms.modals import RemoveModalForm
|
||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE
|
||||
from konova.views.remove import BaseRemoveModalFormView
|
||||
|
||||
|
||||
@login_required_modal
|
||||
@login_required
|
||||
@shared_access_required(Intervention, "id")
|
||||
def remove_compensation_view(request: HttpRequest, id: str, comp_id: str):
|
||||
""" Renders a modal view for removing the compensation
|
||||
class RemoveCompensationFromInterventionView(LoginRequiredMixin, BaseRemoveModalFormView):
|
||||
_MODEL_CLS = Intervention
|
||||
_FORM_CLS = RemoveCompensationFromInterventionModalForm
|
||||
_MSG_SUCCESS = COMPENSATION_REMOVED_TEMPLATE
|
||||
_REDIRECT_URL = "intervention:detail"
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
id (str): The compensation's id
|
||||
def _user_has_shared_access(self, user, **kwargs):
|
||||
compensation_id = kwargs.get("comp_id", None)
|
||||
compensation = get_object_or_404(Compensation, id=compensation_id)
|
||||
return compensation.is_shared_with(user)
|
||||
|
||||
Returns:
|
||||
def _user_has_permission(self, user, **kwargs):
|
||||
return user.is_default_user()
|
||||
|
||||
"""
|
||||
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 _get_msg_success(self, *args, **kwargs):
|
||||
compensation_id = kwargs.get("comp_id", None)
|
||||
compensation = get_object_or_404(Compensation, id=compensation_id)
|
||||
return self._MSG_SUCCESS.format(compensation.identifier)
|
||||
|
||||
def _get_redirect_url(self, *args, **kwargs):
|
||||
obj = kwargs.get("obj")
|
||||
return reverse(self._REDIRECT_URL, args=(obj.id,)) + "#related_data"
|
||||
|
||||
@@ -5,51 +5,27 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||
Created on: 19.08.22
|
||||
|
||||
"""
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import default_group_required, shared_access_required
|
||||
from konova.utils.message_templates import DEDUCTION_ADDED, DEDUCTION_EDITED, DEDUCTION_REMOVED
|
||||
from konova.views.deduction import AbstractNewDeductionView, AbstractEditDeductionView, AbstractRemoveDeductionView
|
||||
|
||||
_INTERVENTION_DETAIL_URL_NAME = "intervention:detail"
|
||||
|
||||
class NewInterventionDeductionView(AbstractNewDeductionView):
|
||||
def _custom_check(self, obj):
|
||||
pass
|
||||
|
||||
model = Intervention
|
||||
redirect_url = "intervention:detail"
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Intervention, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class NewInterventionDeductionView(LoginRequiredMixin, AbstractNewDeductionView):
|
||||
_MODEL_CLS = Intervention
|
||||
_MSG_SUCCESS = DEDUCTION_ADDED
|
||||
_REDIRECT_URL = _INTERVENTION_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class EditInterventionDeductionView(AbstractEditDeductionView):
|
||||
def _custom_check(self, obj):
|
||||
pass
|
||||
|
||||
model = Intervention
|
||||
redirect_url = "intervention:detail"
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Intervention, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class EditInterventionDeductionView(LoginRequiredMixin, AbstractEditDeductionView):
|
||||
_MODEL_CLS = Intervention
|
||||
_MSG_SUCCESS = DEDUCTION_EDITED
|
||||
_REDIRECT_URL = _INTERVENTION_DETAIL_URL_NAME
|
||||
|
||||
|
||||
class RemoveInterventionDeductionView(AbstractRemoveDeductionView):
|
||||
def _custom_check(self, obj):
|
||||
pass
|
||||
|
||||
model = Intervention
|
||||
redirect_url = "intervention:detail"
|
||||
|
||||
@method_decorator(login_required)
|
||||
@method_decorator(default_group_required)
|
||||
@method_decorator(shared_access_required(Intervention, "id"))
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
class RemoveInterventionDeductionView(LoginRequiredMixin, AbstractRemoveDeductionView):
|
||||
_MODEL_CLS = Intervention
|
||||
_MSG_SUCCESS = DEDUCTION_REMOVED
|
||||
_REDIRECT_URL = _INTERVENTION_DETAIL_URL_NAME
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user