#31 API POST Intervention

* adds support for proper POST of intervention
* makes /<id> optional (required for Post)
This commit is contained in:
mpeltriaux 2022-01-24 12:17:17 +01:00
parent 45ac5b68b9
commit d0f3fb9f61
12 changed files with 171 additions and 41 deletions

View File

@ -12,7 +12,11 @@ from api.views.v1.views import EmaAPIViewV1, EcoAccountAPIViewV1, CompensationAP
app_name = "v1"
urlpatterns = [
path("intervention/<id>", InterventionAPIViewV1.as_view(), name="intervention"),
path("intervention/", InterventionAPIViewV1.as_view(), name="intervention"),
path("compensation/<id>", CompensationAPIViewV1.as_view(), name="compensation"),
path("compensation/", CompensationAPIViewV1.as_view(), name="compensation"),
path("ecoaccount/<id>", EcoAccountAPIViewV1.as_view(), name="ecoaccount"),
path("ecoaccount/", EcoAccountAPIViewV1.as_view(), name="ecoaccount"),
path("ema/<id>", EmaAPIViewV1.as_view(), name="ema"),
path("ema/", EmaAPIViewV1.as_view(), name="ema"),
]

View File

@ -5,12 +5,15 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""
import json
from abc import abstractmethod
from django.contrib.gis import geos
from django.contrib.gis.geos import GEOSGeometry
class AbstractModelAPISerializer:
model = None
user = None
lookup = None
properties_data = None
@ -74,3 +77,30 @@ class AbstractModelAPISerializer:
entry = self.model.objects.get(**self.lookup)
serialized_data = self.model_to_geo_json(entry)
return serialized_data
@abstractmethod
def create_model_from_json(self, json_model, user):
""" Creates a new instance from given json data
Args:
json_model (dict): JSON data
user (User): The performing user
Returns:
"""
raise NotImplementedError("Must be implemented in subclasses")
def create_geometry_from_json(self, geojson) -> GEOSGeometry:
""" Creates a GEOSGeometry object based on the given geojson
Args:
geojson (str|dict): The geojson as str or dict
Returns:
geometry (GEOSGeometry)
"""
if isinstance(geojson, dict):
geojson = json.dumps(geojson)
geometry = geos.fromstr(geojson)
return geometry

View File

@ -0,0 +1,7 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""

View File

@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""
from api.utils.v1.serializer import AbstractModelAPISerializerV1
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1
from compensation.models import Compensation
@ -31,4 +31,4 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1):
self.properties_data["before_states"] = self.compensation_state_to_json(entry.before_states.all())
self.properties_data["after_states"] = self.compensation_state_to_json(entry.after_states.all())
self.properties_data["actions"] = self.compensation_actions_to_json(entry.actions.all())
self.properties_data["deadlines"] = self.deadlines_to_json(entry.deadlines.all())
self.properties_data["deadlines"] = self.deadlines_to_json(entry.deadlines.all())

View File

@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""
from api.utils.v1.serializer import AbstractModelAPISerializerV1
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1
from compensation.models import EcoAccount
from intervention.models import Legal, Responsibility

View File

@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""
from api.utils.v1.serializer import AbstractModelAPISerializerV1
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1
from ema.models import Ema
from intervention.models import Responsibility

View File

@ -0,0 +1,88 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""
from django.db import transaction
from django.db.models import QuerySet
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1
from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_REGISTRATION_OFFICE_ID, \
CODELIST_PROCESS_TYPE_ID, CODELIST_LAW_ID
from intervention.models import Intervention, Responsibility, Legal
from konova.models import Geometry
from konova.tasks import celery_update_parcels
from user.models import UserActionLogEntry
class InterventionAPISerializerV1(AbstractModelAPISerializerV1):
model = Intervention
def compensations_to_json(self, qs: QuerySet):
return list(
qs.values(
"id", "identifier", "title"
)
)
def extend_properties_data(self, entry):
self.properties_data["responsible"] = self.responsible_to_json(entry.responsible)
self.properties_data["legal"] = self.legal_to_json(entry.legal)
self.properties_data["compensations"] = self.compensations_to_json(entry.compensations.all())
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
# 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
# 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)
obj.responsible.save()
obj.geometry.save()
obj.legal.save()
obj.save()
obj.users.add(user)
celery_update_parcels.delay(geometry.id)
return obj.id

View File

@ -10,7 +10,7 @@ import json
from django.db.models import QuerySet
from api.utils.serializer import AbstractModelAPISerializer
from api.utils.serializer.serializer import AbstractModelAPISerializer
from codelist.models import KonovaCode
from intervention.models import Responsibility, Legal
@ -53,6 +53,22 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
"short_name": konova_code.short_name,
}
def konova_code_from_json(self, json_str, code_list_identifier):
""" Returns a konova code instance
Args:
json_str (str): The value for the code (atom id)
code_list_identifier (str): From which konova code list this code is supposed to be from
Returns:
"""
code = KonovaCode.objects.get(
atom_id=json_str,
code_lists__in=[code_list_identifier]
)
return code
def responsible_to_json(self, responsible: Responsibility):
""" Serializes Responsibility model into json

View File

@ -1,30 +0,0 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 24.01.22
"""
from django.db.models import QuerySet
from api.utils.v1.serializer import AbstractModelAPISerializerV1
from intervention.models import Intervention
class InterventionAPISerializerV1(AbstractModelAPISerializerV1):
model = Intervention
def compensations_to_json(self, qs: QuerySet):
return list(
qs.values(
"id", "identifier", "title"
)
)
def extend_properties_data(self, entry):
self.properties_data["responsible"] = self.responsible_to_json(entry.responsible)
self.properties_data["legal"] = self.legal_to_json(entry.legal)
self.properties_data["compensations"] = self.compensations_to_json(entry.compensations.all())
self.properties_data["payments"] = self.payments_to_json(entry.payments.all())
self.properties_data["deductions"] = self.deductions_to_json(entry.deductions.all())

View File

@ -5,12 +5,14 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 21.01.22
"""
import json
from django.http import JsonResponse, HttpRequest
from api.utils.v1.compensation import CompensationAPISerializerV1
from api.utils.v1.ecoaccount import EcoAccountAPISerializerV1
from api.utils.v1.ema import EmaAPISerializerV1
from api.utils.v1.intervention import InterventionAPISerializerV1
from api.utils.serializer.v1.compensation import CompensationAPISerializerV1
from api.utils.serializer.v1.ecoaccount import EcoAccountAPISerializerV1
from api.utils.serializer.v1.ema import EmaAPISerializerV1
from api.utils.serializer.v1.intervention import InterventionAPISerializerV1
from api.views.views import AbstractModelAPIView
@ -19,7 +21,7 @@ class AbstractModelAPIViewV1(AbstractModelAPIView):
"""
def get(self, request: HttpRequest, id):
def get(self, request: HttpRequest, id=None):
""" Handles the GET request
Performs the fetching and serialization of the data
@ -32,12 +34,23 @@ class AbstractModelAPIViewV1(AbstractModelAPIView):
"""
try:
if id is None:
raise AttributeError("No id provided")
self.serializer.prepare_lookup(id, self.user)
data = self.serializer.fetch_and_serialize()
except Exception as e:
return self.return_error_response(e, 500)
return JsonResponse(data)
def post(self, request: HttpRequest, id=None):
try:
body = request.body.decode("utf-8")
body = json.loads(body)
created_id = self.serializer.create_model_from_json(body, self.user)
except Exception as e:
return self.return_error_response(e, 500)
return JsonResponse({"id": created_id})
class InterventionAPIViewV1(AbstractModelAPIViewV1):
serializer = InterventionAPISerializerV1

View File

@ -8,6 +8,7 @@ Created on: 21.01.22
from django.http import JsonResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt
from api.models import APIUserToken
from api.settings import KSP_TOKEN_HEADER_IDENTIFIER
@ -36,6 +37,7 @@ class AbstractModelAPIView(View):
super().__init__(*args, **kwargs)
self.serializer = self.serializer()
@csrf_exempt
def dispatch(self, request, *args, **kwargs):
try:
# Fetch the proper user from the given request header token