From b87389e07b6ed1087d8f43ec4bc9845629e4400e Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Mon, 24 Jan 2022 13:04:39 +0100 Subject: [PATCH] #31 API POST/PUT Intervention * splits code in smaller, reusable methods * adds put method to view * adds update_model_from_json() method --- api/utils/serializer/serializer.py | 14 +++ api/utils/serializer/v1/intervention.py | 121 +++++++++++++++++------- api/views/v1/views.py | 9 ++ 3 files changed, 108 insertions(+), 36 deletions(-) diff --git a/api/utils/serializer/serializer.py b/api/utils/serializer/serializer.py index a2b2b4bb..bbe49279 100644 --- a/api/utils/serializer/serializer.py +++ b/api/utils/serializer/serializer.py @@ -78,6 +78,20 @@ class AbstractModelAPISerializer: serialized_data = self.model_to_geo_json(entry) return serialized_data + @abstractmethod + def update_model_from_json(self, id, json_model, user): + """ Updates an instance from given json data + + Args: + id (str): The instance's to be updated + json_model (dict): JSON data + user (User): The performing user + + Returns: + + """ + raise NotImplementedError("Must be implemented in subclasses") + @abstractmethod def create_model_from_json(self, json_model, user): """ Creates a new instance from given json data diff --git a/api/utils/serializer/v1/intervention.py b/api/utils/serializer/v1/intervention.py index b3ab2072..65be4ea6 100644 --- a/api/utils/serializer/v1/intervention.py +++ b/api/utils/serializer/v1/intervention.py @@ -34,47 +34,96 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1): self.properties_data["payments"] = self.payments_to_json(entry.payments.all()) self.properties_data["deductions"] = self.deductions_to_json(entry.deductions.all()) - def create_model_from_json(self, json_model, user): - with transaction.atomic(): - # Create geometry - json_geom = self.create_geometry_from_json(json_model) - geometry = Geometry() - geometry.geom = json_geom + def initialize_objects(self, json_model, user): + """ Initializes all needed objects from the json_model data - # Create linked objects - obj = Intervention() - resp = Responsibility() - legal = Legal() - created = UserActionLogEntry.get_created_action(user, comment="API Import") - obj.legal = legal - obj.created = created - obj.geometry = geometry - obj.responsible = resp + Does not persist data to the DB! + + Args: + json_model (dict): The json data + user (User): The API user + + Returns: + obj (Intervention) + """ + # Create geometry + json_geom = self.create_geometry_from_json(json_model) + geometry = Geometry() + geometry.geom = json_geom + + # Create linked objects + obj = Intervention() + resp = Responsibility() + legal = Legal() + created = UserActionLogEntry.get_created_action(user, comment="API Import") + obj.legal = legal + obj.created = created + obj.geometry = geometry + obj.responsible = resp + return obj + + def set_legal(self, obj, legal_data): + """ Sets the legal data contents to the provided legal_data dict + + Args: + obj (Intervention): The intervention object + legal_data (dict): The new data + + Returns: + obj + """ + obj.legal.registration_date = legal_data["registration_date"] + obj.legal.binding_date = legal_data["binding_date"] + obj.legal.process_type = self.konova_code_from_json( + legal_data["process_type"], + CODELIST_PROCESS_TYPE_ID, + ) + laws = [self.konova_code_from_json(law, CODELIST_LAW_ID) for law in legal_data["laws"]] + obj.legal.laws.set(laws) + return obj + + def set_responsibility(self, obj, responsibility_data: dict): + """ Sets the responsible data contents to the provided responsibility_data dict + + Args: + obj (Intervention): The intervention object + responsibility_data (dict): The new data + + Returns: + obj + """ + obj.responsible.registration_office = self.konova_code_from_json( + responsibility_data["registration_office"], + CODELIST_REGISTRATION_OFFICE_ID + ) + obj.responsible.registration_file_number = responsibility_data["registration_file_number"] + obj.responsible.conservation_office = self.konova_code_from_json( + responsibility_data["conservation_office"], + CODELIST_CONSERVATION_OFFICE_ID, + ) + obj.responsible.conservation_file_number = responsibility_data["conservation_file_number"] + obj.responsible.handler = responsibility_data["handler"] + return obj + + def create_model_from_json(self, json_model, user): + """ Creates a new entry for the model based on the contents of json_model + + Args: + json_model (dict): The json containing data + user (User): The API user + + Returns: + created_id (str): The id of the newly created Intervention entry + """ + with transaction.atomic(): + obj = self.initialize_objects(json_model, user) # Fill in data to objects properties = json_model["properties"] obj.identifier = obj.generate_new_identifier() obj.title = properties["title"] - obj.responsible.registration_office = self.konova_code_from_json( - properties["responsible"]["registration_office"], - CODELIST_REGISTRATION_OFFICE_ID - ) - obj.responsible.registration_file_number = properties["responsible"]["registration_file_number"] - obj.responsible.conservation_office = self.konova_code_from_json( - properties["responsible"]["conservation_office"], - CODELIST_CONSERVATION_OFFICE_ID, - ) - obj.responsible.conservation_file_number = properties["responsible"]["conservation_file_number"] - obj.responsible.handler = properties["responsible"]["handler"] - - obj.legal.registration_date = properties["legal"]["registration_date"] - obj.legal.binding_date = properties["legal"]["binding_date"] - obj.legal.process_type = self.konova_code_from_json( - properties["legal"]["process_type"], - CODELIST_PROCESS_TYPE_ID, - ) - laws = [self.konova_code_from_json(law, CODELIST_LAW_ID) for law in properties["legal"]["laws"]] - obj.legal.laws.set(laws) + self.set_responsibility(obj, properties["responsible"]) + self.set_legal(obj, properties["legal"]) obj.responsible.save() obj.geometry.save() @@ -83,6 +132,6 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1): obj.users.add(user) - celery_update_parcels.delay(geometry.id) + celery_update_parcels.delay(obj.geometry.id) return obj.id diff --git a/api/views/v1/views.py b/api/views/v1/views.py index f62aa271..7e271dd5 100644 --- a/api/views/v1/views.py +++ b/api/views/v1/views.py @@ -51,6 +51,15 @@ class AbstractModelAPIViewV1(AbstractModelAPIView): return self.return_error_response(e, 500) return JsonResponse({"id": created_id}) + def put(self, request: HttpRequest, id=None): + try: + body = request.body.decode("utf-8") + body = json.loads(body) + updated_id = self.serializer.update_model_from_json(id, body, self.user) + except Exception as e: + return self.return_error_response(e, 500) + return JsonResponse({"id": updated_id}) + class InterventionAPIViewV1(AbstractModelAPIViewV1): serializer = InterventionAPISerializerV1