diff --git a/api/utils/serializer/v1/compensation.py b/api/utils/serializer/v1/compensation.py index 81ea46c3..e78ff7f8 100644 --- a/api/utils/serializer/v1/compensation.py +++ b/api/utils/serializer/v1/compensation.py @@ -113,7 +113,9 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa obj = self._initialize_objects(json_model, user) # Fill in data to objects - properties = json_model["properties"] + properties = json_model.get("properties", None) + if not properties: + raise AssertionError("No 'properties' found in payload!") obj.identifier = obj.generate_new_identifier() obj.title = properties["title"] obj.is_cef = properties["is_cef"] @@ -129,6 +131,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_deadlines(obj, properties["deadlines"]) + self._set_external_identifier(obj, properties.get("external_identifier", None)) obj.log.add(obj.created) celery_update_parcels.delay(obj.geometry.id) @@ -153,6 +156,10 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa # Fill in data to objects properties = json_model["properties"] + + external_identifier = properties.get("external_identifier", None) + self._check_external_identifier_on_entry_creation(external_identifier) + obj.title = properties["title"] obj.is_cef = properties["is_cef"] obj.is_coherence_keeping = properties["is_coherence_keeping"] @@ -170,6 +177,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_deadlines(obj, properties["deadlines"]) + self._set_external_identifier(obj, properties.get("external_identifier", None)) obj.log.add(update_action) celery_update_parcels.delay(obj.geometry.id) diff --git a/api/utils/serializer/v1/ecoaccount.py b/api/utils/serializer/v1/ecoaccount.py index f2def5ce..e930b0dc 100644 --- a/api/utils/serializer/v1/ecoaccount.py +++ b/api/utils/serializer/v1/ecoaccount.py @@ -121,7 +121,9 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1, obj = self._initialize_objects(json_model, user) # Fill in data to objects - properties = json_model["properties"] + properties = json_model.get("properties", None) + if not properties: + raise AssertionError("No 'properties' found in payload!") obj.identifier = obj.generate_new_identifier() obj.title = properties["title"] obj.is_pik = properties.get("is_pik", False) @@ -147,6 +149,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1, obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_deadlines(obj, properties["deadlines"]) + self._set_external_identifier(obj, properties.get("external_identifier", None)) obj.log.add(obj.created) obj.users.add(user) @@ -172,6 +175,10 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1, # Fill in data to objects properties = json_model["properties"] + + external_identifier = properties.get("external_identifier", None) + self._check_external_identifier_on_entry_creation(external_identifier) + obj.title = properties["title"] obj.is_pik = properties.get("is_pik", False) obj.deductable_surface = float(properties["deductable_surface"]) @@ -192,6 +199,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1, obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_deadlines(obj, properties["deadlines"]) + self._set_external_identifier(obj, external_identifier) obj.log.add(update_action) celery_update_parcels.delay(obj.geometry.id) diff --git a/api/utils/serializer/v1/ema.py b/api/utils/serializer/v1/ema.py index 8191597c..2f045919 100644 --- a/api/utils/serializer/v1/ema.py +++ b/api/utils/serializer/v1/ema.py @@ -104,6 +104,10 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe # Fill in data to objects properties = json_model["properties"] + + external_identifier = properties.get("external_identifier", None) + self._check_external_identifier_on_entry_creation(external_identifier) + obj.identifier = obj.generate_new_identifier() obj.title = properties["title"] obj.is_pik = properties.get("is_pik", False) @@ -119,6 +123,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_deadlines(obj, properties["deadlines"]) + self._set_external_identifier(obj, external_identifier) obj.log.add(obj.created) obj.users.add(user) @@ -161,6 +166,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_deadlines(obj, properties["deadlines"]) + self._set_external_identifier(obj, properties.get("external_identifier", None)) obj.log.add(update_action) celery_update_parcels.delay(obj.geometry.id) diff --git a/api/utils/serializer/v1/intervention.py b/api/utils/serializer/v1/intervention.py index cd044ea6..da4ff327 100644 --- a/api/utils/serializer/v1/intervention.py +++ b/api/utils/serializer/v1/intervention.py @@ -150,10 +150,14 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1, # Fill in data to objects properties = json_model["properties"] + + external_identifier = properties.get("external_identifier", None) + self._check_external_identifier_on_entry_creation(external_identifier) + obj.identifier = obj.generate_new_identifier() - obj.title = properties["title"] - self._set_responsibility(obj, properties["responsible"]) - self._set_legal(obj, properties["legal"]) + obj.title = properties.get("title", None) + self._set_responsibility(obj, properties.get("responsible", None)) + self._set_legal(obj, properties.get("legal", None)) obj.responsible.handler.save() obj.responsible.save() @@ -161,6 +165,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1, obj.legal.save() obj.save() + self._set_external_identifier(obj, external_identifier) obj.users.add(user) obj.log.add(obj.created) @@ -186,7 +191,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1, # Fill in data to objects properties = json_model["properties"] - obj.title = properties["title"] + obj.title = properties.get("title") self._set_responsibility(obj, properties.get("responsible", None)) self._set_legal(obj, properties.get("legal", None)) self._set_payments(obj, properties.get("payments", None)) @@ -199,6 +204,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1, obj.legal.save() obj.save() + self._set_external_identifier(obj, properties.get("external_identifier", None)) obj.mark_as_edited(user, edit_comment="API update") obj.send_data_to_egon() diff --git a/api/utils/serializer/v1/serializer.py b/api/utils/serializer/v1/serializer.py index 03ca0e07..adadee93 100644 --- a/api/utils/serializer/v1/serializer.py +++ b/api/utils/serializer/v1/serializer.py @@ -12,6 +12,7 @@ from django.contrib.gis.geos import MultiPolygon from django.core.exceptions import ObjectDoesNotExist from django.db.models import QuerySet +from api.models import ExternalIdentifier from api.utils.serializer.serializer import AbstractModelAPISerializer from codelist.models import KonovaCode from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID, CODELIST_PROCESS_TYPE_ID, \ @@ -137,6 +138,63 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer): success = entry.deleted is not None return success + def _set_external_identifier(self, obj, external_identifier): + """ If an external identifier was provided in the payload, we set it + in the database + + Args: + obj (BaseObject): The already processed konova object (EIV, KOM, ...) + external_identifier (any): The external identifier taken from the payload + + Returns: + + """ + if external_identifier is None: + return None + + ext_id_obj = ExternalIdentifier.objects.get_or_create( + internal_id=obj.id, + external_id=external_identifier + )[0] + if not ext_id_obj.created: + ext_id_obj.created = obj.created + ext_id_obj.save() + + return ext_id_obj + + def _get_external_identifier(self, external_identifier): + """ Checks whether a linkage based on an external identifier already exists and returns it if so. + + Args: + external_identifier (any): The external identifier according to payload + + Returns: + ExternalIdentifier | None + """ + if external_identifier: + try: + obj = ExternalIdentifier.objects.get(external_id=external_identifier) + return obj + except ObjectDoesNotExist: + pass + return None + + def _check_external_identifier_on_entry_creation(self, external_identifier): + """ Special check for POST processing: + Checks whether an external identifier already exists on the database. This hints that + the entry already has been created in the past. Instead of POST, the PUT method shall be used + to avoid creating duplicates. + + Args: + external_identifier (any): The external identifier according to payload + + Returns: + + """ + persisted_external_identifier = self._get_external_identifier(external_identifier) + if persisted_external_identifier: + raise AssertionError(f"{external_identifier} has already been initially created! Use PUT for updates!") + class DeductableAPISerializerV1Mixin: class Meta: