From 5ef840f172483f113f85cb3df0e1e0c89b3ae18d Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Tue, 21 May 2024 11:54:06 +0200 Subject: [PATCH 1/3] # 404 Extend API * extends API shared record access with team based sharing --- api/utils/serializer/serializer.py | 17 ++++++++++++++--- api/utils/serializer/v1/compensation.py | 7 +++++-- api/utils/serializer/v1/deduction.py | 7 +++++-- api/views/v1/views.py | 5 ----- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/api/utils/serializer/serializer.py b/api/utils/serializer/serializer.py index 04a03123..c3096cc1 100644 --- a/api/utils/serializer/serializer.py +++ b/api/utils/serializer/serializer.py @@ -11,6 +11,7 @@ from abc import abstractmethod from django.contrib.gis import geos from django.contrib.gis.geos import GEOSGeometry from django.core.paginator import Paginator +from django.db.models import Q from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP from konova.utils.message_templates import DATA_UNSHARED @@ -32,8 +33,8 @@ class AbstractModelAPISerializer: self.lookup = { "id": None, # must be set "deleted__isnull": True, - "users__in": [], # must be set } + self.shared_lookup = Q() # must be set, so user or team based share will be used properly super().__init__(*args, **kwargs) @abstractmethod @@ -76,7 +77,11 @@ class AbstractModelAPISerializer: else: # Return certain object self.lookup["id"] = _id - self.lookup["users__in"] = [user] + + self.shared_lookup = Q( + Q(users__in=[user]) | + Q(teams__in=list(user.shared_teams)) + ) def fetch_and_serialize(self): """ Serializes the model entry according to the given lookup data @@ -86,7 +91,13 @@ class AbstractModelAPISerializer: Returns: serialized_data (dict) """ - entries = self.model.objects.filter(**self.lookup).order_by("id") + entries = self.model.objects.filter( + **self.lookup + ).filter( + self.shared_lookup + ).order_by( + "id" + ).distinct() self.paginator = Paginator(entries, self.rpp) requested_entries = self.paginator.page(self.page_number) diff --git a/api/utils/serializer/v1/compensation.py b/api/utils/serializer/v1/compensation.py index 5b38b4cd..81ea46c3 100644 --- a/api/utils/serializer/v1/compensation.py +++ b/api/utils/serializer/v1/compensation.py @@ -6,6 +6,7 @@ Created on: 24.01.22 """ from django.db import transaction +from django.db.models import Q from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, AbstractCompensationAPISerializerV1Mixin from compensation.models import Compensation @@ -21,8 +22,10 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa def prepare_lookup(self, id, user): super().prepare_lookup(id, user) - del self.lookup["users__in"] - self.lookup["intervention__users__in"] = [user] + self.shared_lookup = Q( + Q(intervention__users__in=[user]) | + Q(intervention__teams__in=user.shared_teams) + ) def intervention_to_json(self, entry): return { diff --git a/api/utils/serializer/v1/deduction.py b/api/utils/serializer/v1/deduction.py index c66a2129..708b3775 100644 --- a/api/utils/serializer/v1/deduction.py +++ b/api/utils/serializer/v1/deduction.py @@ -6,6 +6,7 @@ Created on: 28.01.22 """ from django.core.exceptions import ObjectDoesNotExist +from django.db.models import Q from api.utils.serializer.v1.serializer import DeductableAPISerializerV1Mixin, AbstractModelAPISerializerV1 from compensation.models import EcoAccountDeduction, EcoAccount @@ -28,9 +29,11 @@ class DeductionAPISerializerV1(AbstractModelAPISerializerV1, """ super().prepare_lookup(_id, user) - del self.lookup["users__in"] del self.lookup["deleted__isnull"] - self.lookup["intervention__users__in"] = [user] + self.shared_lookup = Q( + Q(intervention__users__in=[user]) | + Q(intervention__teams__in=user.shared_teams) + ) def _model_to_geo_json(self, entry): """ Adds the basic data diff --git a/api/views/v1/views.py b/api/views/v1/views.py index 8da5d49e..5ab9f4b9 100644 --- a/api/views/v1/views.py +++ b/api/views/v1/views.py @@ -23,11 +23,6 @@ class AbstractAPIViewV1(AbstractAPIView): """ def __init__(self, *args, **kwargs): - self.lookup = { - "id": None, # must be set in subclasses - "deleted__isnull": True, - "users__in": [], # must be set in subclasses - } super().__init__(*args, **kwargs) self.serializer = self.serializer() -- 2.45.2 From 898a56db8a6ac6d017bbb451e303e8dedc92950c Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Tue, 21 May 2024 14:42:49 +0200 Subject: [PATCH 2/3] # Comment card * adds proper line break rendering in comment card --- konova/templates/konova/includes/comment_card.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/konova/templates/konova/includes/comment_card.html b/konova/templates/konova/includes/comment_card.html index d9ea59bc..51a5667a 100644 --- a/konova/templates/konova/includes/comment_card.html +++ b/konova/templates/konova/includes/comment_card.html @@ -20,7 +20,7 @@
- {{obj.comment}} + {{obj.comment|linebreaks}}
-- 2.45.2 From eaea0eb5124752eb7b2aeda04ea2f2b18c6ec200 Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Tue, 18 Jun 2024 11:48:56 +0200 Subject: [PATCH 3/3] # Send-to-EGON cmd * adds new custom command send_to_egon for performing EGON sending on a list of intervention ids --- konova/management/commands/send_to_egon.py | 54 ++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 konova/management/commands/send_to_egon.py diff --git a/konova/management/commands/send_to_egon.py b/konova/management/commands/send_to_egon.py new file mode 100644 index 00000000..c2a5b766 --- /dev/null +++ b/konova/management/commands/send_to_egon.py @@ -0,0 +1,54 @@ +""" +Author: Michel Peltriaux +Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany +Contact: ksp-servicestelle@sgdnord.rlp.de +Created on: 18.06.24 + +""" +from django.db.models import QuerySet + +from intervention.models import Intervention +from konova.management.commands.setup import BaseKonovaCommand + + +class Command(BaseKonovaCommand): + help = "Send specific intervention entries to EGON if there are any payments on them" + + def add_arguments(self, parser): + try: + parser.add_argument("--intervention-ids", type=str) + except ValueError as e: + self._write_error(f"Argument error: {e}") + exit(-1) + + def __handle_arguments(self, options): + self.intervention_ids = options["intervention_ids"] or "" + self.intervention_ids = self.intervention_ids.split(",") + self.intervention_ids = [x.strip() for x in self.intervention_ids] + + def handle(self, *args, **options): + try: + self.__handle_arguments(options) + interventions = self.get_interventions() + self.process_egon_sending(interventions) + except KeyboardInterrupt: + self._break_line() + exit(-1) + + def get_interventions(self) -> QuerySet: + """ + Getter for interventions, defined by parameter 'intervention-ids' + + Returns: + interventions (QuerySet): The interventions + """ + interventions = Intervention.objects.filter( + id__in=self.intervention_ids, + ) + self._write_success(f"... Found {interventions.count()} interventions") + return interventions + + def process_egon_sending(self, interventions: QuerySet): + for intervention in interventions: + intervention.send_data_to_egon() + self._write_warning(f"... {intervention.identifier} has been sent to EGON (if it has payments)") -- 2.45.2