Compare commits

...

5 Commits

Author SHA1 Message Date
a22a926199 #31 API PUT Tests
* adds tests for PUT method in api
2022-01-28 13:31:44 +01:00
bfefc43522 #31 API GET Tests
* adds tests for api GET method
* fixes bug where non existing geometry could not be serialized properly
2022-01-28 12:30:09 +01:00
27c1de2c53 #31 API protected visibility
* reworks most internal API methods for de/serializing from public to protected visibility
* moves test_api_sharing.py into /share subfolder of tests
2022-01-28 09:44:16 +01:00
3d446883c6 #31 API DELETE Tests
* adds tests for DELETE method of all major data types
2022-01-28 09:24:14 +01:00
e7dbea49cd #31 API DELETE
* adds support for DELETE method for all relevant objects
* improves get_obj_from_db functionality
* drops custom compensation logic for get_obj_from_db due to improvement of base method
2022-01-28 08:52:11 +01:00
21 changed files with 893 additions and 158 deletions

View File

@ -9,7 +9,7 @@ import json
from django.urls import reverse from django.urls import reverse
from api.tests.v1.test_api_sharing import BaseAPIV1TestCase from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
class APIV1CreateTestCase(BaseAPIV1TestCase): class APIV1CreateTestCase(BaseAPIV1TestCase):

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: 28.01.22
"""

View File

@ -0,0 +1,95 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 28.01.22
"""
import json
from django.urls import reverse
from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
class APIV1DeleteTestCase(BaseAPIV1TestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
def _run_delete_request(self, url):
response = self.client.delete(
url,
**self.header_data
)
return response
def _test_delete_object(self, obj, url):
""" Tests the API DELETE of a data object.
Args:
url (str): The api delete url
Returns:
"""
obj.refresh_from_db()
_id = obj.id
self.assertIsNotNone(_id)
self.assertIsNone(obj.deleted)
response = self._run_delete_request(url)
content = json.loads(response.content)
self.assertEqual(response.status_code, 200, msg=response.content)
self.assertTrue(content.get("success", False), msg=response.content)
obj.refresh_from_db()
self.assertIsNotNone(obj.deleted)
self.assertEqual(obj.deleted.user, self.superuser)
def test_delete_intervention(self):
""" Tests api creation of bare minimum interventions
Returns:
"""
test_intervention = self.create_dummy_intervention()
test_intervention.share_with(self.superuser)
url = reverse("api:v1:intervention", args=(str(test_intervention.id),))
self._test_delete_object(test_intervention, url)
def test_delete_compensation(self):
""" Tests api creation of bare minimum interventions
Returns:
"""
test_comp = self.create_dummy_compensation()
test_comp.share_with(self.superuser)
url = reverse("api:v1:compensation", args=(str(test_comp.id),))
self._test_delete_object(test_comp, url)
def test_delete_eco_account(self):
""" Tests api creation of bare minimum interventions
Returns:
"""
test_acc = self.create_dummy_eco_account()
test_acc.share_with(self.superuser)
url = reverse("api:v1:ecoaccount", args=(str(test_acc.id),))
self._test_delete_object(test_acc, url)
def test_delete_ema(self):
""" Tests api creation of bare minimum interventions
Returns:
"""
test_ema = self.create_dummy_ema()
test_ema.share_with(self.superuser)
url = reverse("api:v1:ema", args=(str(test_ema.id),))
self._test_delete_object(test_ema, url)

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: 28.01.22
"""

View File

@ -0,0 +1,157 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 28.01.22
"""
import json
from django.urls import reverse
from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
class APIV1GetTestCase(BaseAPIV1TestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
def _run_get_request(self, url):
response = self.client.get(
url,
**self.header_data
)
return response
def _test_get_object(self, obj, url):
""" Tests the API GET of a data object.
Args:
url (str): The api get url
Returns:
"""
response = self._run_get_request(url)
content = json.loads(response.content)
geojson = content[str(obj.id)]
self.assertEqual(response.status_code, 200, msg=response.content)
try:
geojson["type"]
geojson["coordinates"]
props = geojson["properties"]
props["id"]
props["identifier"]
props["title"]
props["created_on"]
props["modified_on"]
except KeyError as e:
self.fail(e)
return geojson
def test_get_intervention(self):
""" Tests api GET
Returns:
"""
self.intervention.share_with(self.superuser)
url = reverse("api:v1:intervention", args=(str(self.intervention.id),))
geojson = self._test_get_object(self.intervention, url)
try:
props = geojson["properties"]
props["responsible"]
props["responsible"]["registration_office"]
props["responsible"]["registration_file_number"]
props["responsible"]["conservation_office"]
props["responsible"]["conservation_file_number"]
props["legal"]["registration_date"]
props["legal"]["binding_date"]
props["legal"]["process_type"]
props["legal"]["laws"]
props["compensations"]
props["payments"]
props["deductions"]
except KeyError as e:
self.fail(e)
def test_get_compensation(self):
""" Tests api GET
Returns:
"""
self.intervention.share_with(self.superuser)
self.compensation.intervention = self.intervention
self.compensation.save()
url = reverse("api:v1:compensation", args=(str(self.compensation.id),))
geojson = self._test_get_object(self.compensation, url)
try:
props = geojson["properties"]
props["is_cef"]
props["is_coherence_keeping"]
props["intervention"]
props["intervention"]["id"]
props["intervention"]["identifier"]
props["intervention"]["title"]
props["before_states"]
props["after_states"]
props["actions"]
props["deadlines"]
except KeyError as e:
self.fail(e)
def test_get_eco_account(self):
""" Tests api GET
Returns:
"""
self.eco_account.share_with(self.superuser)
url = reverse("api:v1:ecoaccount", args=(str(self.eco_account.id),))
geojson = self._test_get_object(self.eco_account, url)
try:
props = geojson["properties"]
props["deductable_surface"]
props["deductable_surface_available"]
props["responsible"]
props["responsible"]["conservation_office"]
props["responsible"]["conservation_file_number"]
props["responsible"]["handler"]
props["legal"]
props["legal"]["agreement_date"]
props["before_states"]
props["after_states"]
props["actions"]
props["deadlines"]
props["deductions"]
except KeyError as e:
self.fail(e)
def test_get_ema(self):
""" Tests api GET
Returns:
"""
self.ema.share_with(self.superuser)
url = reverse("api:v1:ema", args=(str(self.ema.id),))
geojson = self._test_get_object(self.ema, url)
try:
props = geojson["properties"]
props["responsible"]
props["responsible"]["conservation_office"]
props["responsible"]["conservation_file_number"]
props["responsible"]["handler"]
props["before_states"]
props["after_states"]
props["actions"]
props["deadlines"]
except KeyError as e:
self.fail(e)

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: 28.01.22
"""

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: 28.01.22
"""

View File

@ -0,0 +1,61 @@
{
"type": "MultiPolygon",
"coordinates": [
[
[
[
7.845568656921382,
50.79829702304368
],
[
7.837371826171871,
50.80155187891526
],
[
7.835698127746578,
50.805267562209806
],
[
7.841062545776364,
50.806623577403386
],
[
7.848916053771969,
50.808359219420474
],
[
7.855696678161618,
50.807057493952975
],
[
7.854666709899899,
50.80423696434001
],
[
7.850461006164548,
50.80217570040005
],
[
7.845568656921382,
50.79829702304368
]
]
]
],
"properties": {
"title": "TEST_compensation_CHANGED",
"is_cef": true,
"is_coherence_keeping": true,
"intervention": "CHANGE_BEFORE_RUN!!!",
"before_states": [],
"after_states": [],
"actions": [],
"deadlines": [
{
"type": "finished",
"date": "2022-01-31",
"comment": "TEST_CHANGED"
}
]
}
}

View File

@ -0,0 +1,70 @@
{
"type": "MultiPolygon",
"coordinates": [
[
[
[
7.845568656921382,
50.79829702304368
],
[
7.837371826171871,
50.80155187891526
],
[
7.835698127746578,
50.805267562209806
],
[
7.841062545776364,
50.806623577403386
],
[
7.848916053771969,
50.808359219420474
],
[
7.855696678161618,
50.807057493952975
],
[
7.854666709899899,
50.80423696434001
],
[
7.850461006164548,
50.80217570040005
],
[
7.845568656921382,
50.79829702304368
]
]
]
],
"properties": {
"title": "TEST_account_CHANGED",
"deductable_surface": "100000.0",
"responsible": {
"conservation_office": null,
"conservation_file_number": "123-TEST",
"handler": "TEST_HANDLER_CHANGED"
},
"legal": {
"agreement_date": "2022-01-11"
},
"before_states": [
],
"after_states": [
],
"actions": [
],
"deadlines": [
{
"type": "finished",
"date": "2022-01-31",
"comment": "TEST_CHANGED"
}
]
}
}

View File

@ -0,0 +1,63 @@
{
"type": "MultiPolygon",
"coordinates": [
[
[
[
7.845568656921382,
50.79829702304368
],
[
7.837371826171871,
50.80155187891526
],
[
7.835698127746578,
50.805267562209806
],
[
7.841062545776364,
50.806623577403386
],
[
7.848916053771969,
50.808359219420474
],
[
7.855696678161618,
50.807057493952975
],
[
7.854666709899899,
50.80423696434001
],
[
7.850461006164548,
50.80217570040005
],
[
7.845568656921382,
50.79829702304368
]
]
]
],
"properties": {
"title": "TEST_EMA_CHANGED",
"responsible": {
"conservation_office": null,
"conservation_file_number": "TEST_CHANGED",
"handler": "TEST_HANDLER_CHANGED"
},
"before_states": [],
"after_states": [],
"actions": [],
"deadlines": [
{
"type": "finished",
"date": "2022-01-31",
"comment": "TEST_CHANGED"
}
]
}
}

View File

@ -0,0 +1,61 @@
{
"type": "MultiPolygon",
"coordinates": [
[
[
[
7.845568656921382,
50.79829702304368
],
[
7.837371826171871,
50.80155187891526
],
[
7.835698127746578,
50.805267562209806
],
[
7.841062545776364,
50.806623577403386
],
[
7.848916053771969,
50.808359219420474
],
[
7.855696678161618,
50.807057493952975
],
[
7.854666709899899,
50.80423696434001
],
[
7.850461006164548,
50.80217570040005
],
[
7.845568656921382,
50.79829702304368
]
]
]
],
"properties": {
"title": "Test_intervention_CHANGED",
"responsible": {
"registration_office": null,
"registration_file_number": "CHANGED",
"conservation_office": null,
"conservation_file_number": "CHANGED",
"handler": null
},
"legal": {
"registration_date": "2022-02-01",
"binding_date": "2022-02-01",
"process_type": null,
"laws": []
}
}
}

View File

@ -0,0 +1,163 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 28.01.22
"""
import json
from django.contrib.gis import geos
from django.urls import reverse
from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase
class APIV1UpdateTestCase(BaseAPIV1TestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
def _run_update_request(self, url, data):
data = json.dumps(data)
response = self.client.put(
url,
data=data,
content_type="application/json",
**self.header_data
)
return response
def _test_update_object(self, url, put_body):
""" Tests the API update of a data object.
Put body data stored in a local json file
Args:
url (str): The api creation url
put_body (dict): The put body content as dict
Returns:
"""
response = self._run_update_request(url, put_body)
self.assertEqual(response.status_code, 200, msg=response.content)
content = json.loads(response.content)
self.assertIsNotNone(content.get("id", None), msg=response.content)
def test_update_intervention(self):
""" Tests api update
Returns:
"""
self.intervention.share_with(self.superuser)
modified_on = self.intervention.modified
url = reverse("api:v1:intervention", args=(str(self.intervention.id),))
json_file_path = "api/tests/v1/update/intervention_update_put_body.json"
with open(json_file_path) as json_file:
put_body = json.load(fp=json_file)
self._test_update_object(url, put_body)
self.intervention.refresh_from_db()
put_props = put_body["properties"]
put_geom = geos.fromstr(json.dumps(put_body))
self.assertEqual(put_geom, self.intervention.geometry.geom)
self.assertEqual(put_props["title"], self.intervention.title)
self.assertNotEqual(modified_on, self.intervention.modified)
self.assertEqual(put_props["responsible"]["registration_file_number"], self.intervention.responsible.registration_file_number)
self.assertEqual(put_props["responsible"]["conservation_file_number"], self.intervention.responsible.conservation_file_number)
self.assertEqual(put_props["legal"]["registration_date"], str(self.intervention.legal.registration_date))
self.assertEqual(put_props["legal"]["binding_date"], str(self.intervention.legal.binding_date))
def test_update_compensation(self):
""" Tests api update
Returns:
"""
self.compensation.intervention = self.intervention
self.compensation.save()
self.intervention.share_with(self.superuser)
modified_on = self.compensation.modified
url = reverse("api:v1:compensation", args=(str(self.compensation.id),))
json_file_path = "api/tests/v1/update/compensation_update_put_body.json"
with open(json_file_path) as json_file:
put_body = json.load(fp=json_file)
put_body["properties"]["intervention"] = str(self.intervention.id)
self._test_update_object(url, put_body)
self.compensation.refresh_from_db()
put_props = put_body["properties"]
put_geom = geos.fromstr(json.dumps(put_body))
self.assertEqual(put_geom, self.compensation.geometry.geom)
self.assertEqual(put_props["title"], self.compensation.title)
self.assertNotEqual(modified_on, self.compensation.modified)
self.assertEqual(put_props["is_cef"], self.compensation.is_cef)
self.assertEqual(put_props["is_coherence_keeping"], self.compensation.is_coherence_keeping)
self.assertEqual(len(put_props["actions"]), self.compensation.actions.count())
self.assertEqual(len(put_props["before_states"]), self.compensation.before_states.count())
self.assertEqual(len(put_props["after_states"]), self.compensation.after_states.count())
self.assertEqual(len(put_props["deadlines"]), self.compensation.deadlines.count())
def test_update_ecoaccount(self):
""" Tests api update
Returns:
"""
self.eco_account.share_with(self.superuser)
modified_on = self.eco_account.modified
url = reverse("api:v1:ecoaccount", args=(str(self.eco_account.id),))
json_file_path = "api/tests/v1/update/ecoaccount_update_put_body.json"
with open(json_file_path) as json_file:
put_body = json.load(fp=json_file)
self._test_update_object(url, put_body)
self.eco_account.refresh_from_db()
put_props = put_body["properties"]
put_geom = geos.fromstr(json.dumps(put_body))
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)
self.assertEqual(put_props["deductable_surface"], str(self.eco_account.deductable_surface))
self.assertEqual(put_props["responsible"]["conservation_office"], self.eco_account.responsible.conservation_office)
self.assertEqual(put_props["responsible"]["conservation_file_number"], self.eco_account.responsible.conservation_file_number)
self.assertEqual(put_props["responsible"]["handler"], self.eco_account.responsible.handler)
self.assertEqual(put_props["legal"]["agreement_date"], str(self.eco_account.legal.registration_date))
self.assertEqual(len(put_props["actions"]), self.eco_account.actions.count())
self.assertEqual(len(put_props["before_states"]), self.eco_account.before_states.count())
self.assertEqual(len(put_props["after_states"]), self.eco_account.after_states.count())
self.assertEqual(len(put_props["deadlines"]), self.eco_account.deadlines.count())
def test_update_ema(self):
""" Tests api update
Returns:
"""
self.ema.share_with(self.superuser)
modified_on = self.ema.modified
url = reverse("api:v1:ema", args=(str(self.ema.id),))
json_file_path = "api/tests/v1/update/ema_update_put_body.json"
with open(json_file_path) as json_file:
put_body = json.load(fp=json_file)
self._test_update_object(url, put_body)
self.ema.refresh_from_db()
put_props = put_body["properties"]
put_geom = geos.fromstr(json.dumps(put_body))
self.assertEqual(put_geom, self.ema.geometry.geom)
self.assertEqual(put_props["title"], self.ema.title)
self.assertNotEqual(modified_on, self.ema.modified)
self.assertEqual(put_props["responsible"]["conservation_office"], self.ema.responsible.conservation_office)
self.assertEqual(put_props["responsible"]["conservation_file_number"], self.ema.responsible.conservation_file_number)
self.assertEqual(put_props["responsible"]["handler"], self.ema.responsible.handler)
self.assertEqual(len(put_props["actions"]), self.ema.actions.count())
self.assertEqual(len(put_props["before_states"]), self.ema.before_states.count())
self.assertEqual(len(put_props["after_states"]), self.ema.after_states.count())
self.assertEqual(len(put_props["deadlines"]), self.ema.deadlines.count())

View File

@ -11,6 +11,8 @@ from abc import abstractmethod
from django.contrib.gis import geos from django.contrib.gis import geos
from django.contrib.gis.geos import GEOSGeometry from django.contrib.gis.geos import GEOSGeometry
from konova.utils.message_templates import DATA_UNSHARED
class AbstractModelAPISerializer: class AbstractModelAPISerializer:
model = None model = None
@ -29,7 +31,7 @@ class AbstractModelAPISerializer:
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@abstractmethod @abstractmethod
def model_to_geo_json(self, entry): def _model_to_geo_json(self, entry):
""" Defines the model as geo json """ Defines the model as geo json
Args: Args:
@ -41,7 +43,7 @@ class AbstractModelAPISerializer:
raise NotImplementedError("Must be implemented in subclasses") raise NotImplementedError("Must be implemented in subclasses")
@abstractmethod @abstractmethod
def extend_properties_data(self, entry): def _extend_properties_data(self, entry):
""" Defines the 'properties' part of geo json """ Defines the 'properties' part of geo json
Args: Args:
@ -66,7 +68,7 @@ class AbstractModelAPISerializer:
# Return all objects # Return all objects
del self.lookup["id"] del self.lookup["id"]
else: else:
# Return certain objects # Return certain object
self.lookup["id"] = _id self.lookup["id"] = _id
self.lookup["users__in"] = [user] self.lookup["users__in"] = [user]
@ -81,7 +83,7 @@ class AbstractModelAPISerializer:
entries = self.model.objects.filter(**self.lookup) entries = self.model.objects.filter(**self.lookup)
serialized_data = {} serialized_data = {}
for entry in entries: for entry in entries:
serialized_data[str(entry.id)] = self.model_to_geo_json(entry) serialized_data[str(entry.id)] = self._model_to_geo_json(entry)
return serialized_data return serialized_data
@abstractmethod @abstractmethod
@ -111,7 +113,7 @@ class AbstractModelAPISerializer:
""" """
raise NotImplementedError("Must be implemented in subclasses") raise NotImplementedError("Must be implemented in subclasses")
def create_geometry_from_json(self, geojson) -> GEOSGeometry: def _create_geometry_from_json(self, geojson) -> GEOSGeometry:
""" Creates a GEOSGeometry object based on the given geojson """ Creates a GEOSGeometry object based on the given geojson
Args: Args:
@ -127,7 +129,7 @@ class AbstractModelAPISerializer:
geometry = None geometry = None
return geometry return geometry
def get_obj_from_db(self, id, user): def _get_obj_from_db(self, id, user):
""" Returns the object from database """ Returns the object from database
Fails if id not found or user does not have shared access Fails if id not found or user does not have shared access
@ -139,13 +141,17 @@ class AbstractModelAPISerializer:
Returns: Returns:
""" """
return self.model.objects.get( obj = self.model.objects.get(
id=id, id=id,
users__in=[user] deleted__isnull=True,
) )
is_shared = obj.is_shared_with(user)
if not is_shared:
raise PermissionError(DATA_UNSHARED)
return obj
@abstractmethod @abstractmethod
def initialize_objects(self, json_model, user): def _initialize_objects(self, json_model, user):
""" Initializes all needed objects from the json_model data """ Initializes all needed objects from the json_model data
Does not persist data to the DB! Does not persist data to the DB!

View File

@ -31,16 +31,16 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
"title": entry.title, "title": entry.title,
} }
def extend_properties_data(self, entry): def _extend_properties_data(self, entry):
self.properties_data["is_cef"] = entry.is_cef self.properties_data["is_cef"] = entry.is_cef
self.properties_data["is_coherence_keeping"] = entry.is_coherence_keeping self.properties_data["is_coherence_keeping"] = entry.is_coherence_keeping
self.properties_data["intervention"] = self.intervention_to_json(entry.intervention) self.properties_data["intervention"] = self.intervention_to_json(entry.intervention)
self.properties_data["before_states"] = self.compensation_state_to_json(entry.before_states.all()) 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["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["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())
def initialize_objects(self, json_model, user): def _initialize_objects(self, json_model, user):
""" Initializes all needed objects from the json_model data """ Initializes all needed objects from the json_model data
Does not persist data to the DB! Does not persist data to the DB!
@ -54,7 +54,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
""" """
create_action = UserActionLogEntry.get_created_action(user, comment="API Import") create_action = UserActionLogEntry.get_created_action(user, comment="API Import")
# Create geometry # Create geometry
json_geom = self.create_geometry_from_json(json_model) json_geom = self._create_geometry_from_json(json_model)
geometry = Geometry() geometry = Geometry()
geometry.geom = json_geom geometry.geom = json_geom
geometry.created = create_action geometry.created = create_action
@ -105,7 +105,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
created_id (str): The id of the newly created Compensation entry created_id (str): The id of the newly created Compensation entry
""" """
with transaction.atomic(): with transaction.atomic():
obj = self.initialize_objects(json_model, user) obj = self._initialize_objects(json_model, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
@ -118,10 +118,10 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
obj.geometry.save() obj.geometry.save()
obj.save() obj.save()
obj = self.set_compensation_actions(obj, properties["actions"]) obj = self._set_compensation_actions(obj, properties["actions"])
obj = self.set_compensation_states(obj, properties["before_states"], obj.before_states) obj = self._set_compensation_states(obj, properties["before_states"], obj.before_states)
obj = self.set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
obj = self.set_deadlines(obj, properties["deadlines"]) obj = self._set_deadlines(obj, properties["deadlines"])
obj.log.add(obj.created) obj.log.add(obj.created)
@ -129,23 +129,6 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
return obj.id return obj.id
def get_obj_from_db(self, id, user):
""" Returns the object from database
Fails if id not found or user does not have shared access
Args:
id (str): The object's id
user (User): The API user
Returns:
"""
return self.model.objects.get(
id=id,
intervention__users__in=[user]
)
def update_model_from_json(self, id, json_model, user): def update_model_from_json(self, id, json_model, user):
""" Updates an entry for the model based on the contents of json_model """ Updates an entry for the model based on the contents of json_model
@ -159,7 +142,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
""" """
with transaction.atomic(): with transaction.atomic():
update_action = UserActionLogEntry.get_edited_action(user, "API update") update_action = UserActionLogEntry.get_edited_action(user, "API update")
obj = self.get_obj_from_db(id, user) obj = self._get_obj_from_db(id, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
@ -167,17 +150,17 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
obj.is_cef = properties["is_cef"] obj.is_cef = properties["is_cef"]
obj.is_coherence_keeping = properties["is_coherence_keeping"] obj.is_coherence_keeping = properties["is_coherence_keeping"]
obj.modified = update_action obj.modified = update_action
obj.geometry.geom = self.create_geometry_from_json(json_model) obj.geometry.geom = self._create_geometry_from_json(json_model)
obj.geometry.modified = update_action obj.geometry.modified = update_action
obj = self.set_intervention(obj, properties["intervention"], user) obj = self.set_intervention(obj, properties["intervention"], user)
obj.geometry.save() obj.geometry.save()
obj.save() obj.save()
obj = self.set_compensation_actions(obj, properties["actions"]) obj = self._set_compensation_actions(obj, properties["actions"])
obj = self.set_compensation_states(obj, properties["before_states"], obj.before_states) obj = self._set_compensation_states(obj, properties["before_states"], obj.before_states)
obj = self.set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
obj = self.set_deadlines(obj, properties["deadlines"]) obj = self._set_deadlines(obj, properties["deadlines"])
obj.log.add(update_action) obj.log.add(update_action)

View File

@ -24,30 +24,30 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
DeductableAPISerializerV1Mixin): DeductableAPISerializerV1Mixin):
model = EcoAccount model = EcoAccount
def extend_properties_data(self, entry): def _extend_properties_data(self, entry):
self.properties_data["deductable_surface"] = entry.deductable_surface self.properties_data["deductable_surface"] = entry.deductable_surface
self.properties_data["deductable_surface_available"] = entry.deductable_surface - entry.get_deductions_surface() self.properties_data["deductable_surface_available"] = entry.deductable_surface - entry.get_deductions_surface()
self.properties_data["responsible"] = self.responsible_to_json(entry.responsible) self.properties_data["responsible"] = self._responsible_to_json(entry.responsible)
self.properties_data["legal"] = self.legal_to_json(entry.legal) self.properties_data["legal"] = self._legal_to_json(entry.legal)
self.properties_data["before_states"] = self.compensation_state_to_json(entry.before_states.all()) 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["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["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())
self.properties_data["deductions"] = self.deductions_to_json(entry.deductions.all()) self.properties_data["deductions"] = self._deductions_to_json(entry.deductions.all())
def legal_to_json(self, legal: Legal): def _legal_to_json(self, legal: Legal):
return { return {
"agreement_date": legal.registration_date, "agreement_date": legal.registration_date,
} }
def responsible_to_json(self, responsible: Responsibility): def _responsible_to_json(self, responsible: Responsibility):
return { return {
"conservation_office": self.konova_code_to_json(responsible.conservation_office), "conservation_office": self._konova_code_to_json(responsible.conservation_office),
"conservation_file_number": responsible.conservation_file_number, "conservation_file_number": responsible.conservation_file_number,
"handler": responsible.handler, "handler": responsible.handler,
} }
def set_responsibility(self, obj, responsibility_data: dict): def _set_responsibility(self, obj, responsibility_data: dict):
""" Sets the responsible data contents to the provided responsibility_data dict """ Sets the responsible data contents to the provided responsibility_data dict
Args: Args:
@ -59,7 +59,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
""" """
if responsibility_data is None: if responsibility_data is None:
return obj return obj
obj.responsible.conservation_office = self.konova_code_from_json( obj.responsible.conservation_office = self._konova_code_from_json(
responsibility_data["conservation_office"], responsibility_data["conservation_office"],
CODELIST_CONSERVATION_OFFICE_ID, CODELIST_CONSERVATION_OFFICE_ID,
) )
@ -67,11 +67,11 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
obj.responsible.handler = responsibility_data["handler"] obj.responsible.handler = responsibility_data["handler"]
return obj return obj
def set_legal(self, obj, legal_data): def _set_legal(self, obj, legal_data):
obj.legal.registration_date = legal_data.get("agreement_date", None) obj.legal.registration_date = legal_data.get("agreement_date", None)
return obj return obj
def initialize_objects(self, json_model, user): def _initialize_objects(self, json_model, user):
""" Initializes all needed objects from the json_model data """ Initializes all needed objects from the json_model data
Does not persist data to the DB! Does not persist data to the DB!
@ -85,7 +85,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
""" """
create_action = UserActionLogEntry.get_created_action(user, comment="API Import") create_action = UserActionLogEntry.get_created_action(user, comment="API Import")
# Create geometry # Create geometry
json_geom = self.create_geometry_from_json(json_model) json_geom = self._create_geometry_from_json(json_model)
geometry = Geometry() geometry = Geometry()
geometry.geom = json_geom geometry.geom = json_geom
geometry.created = create_action geometry.created = create_action
@ -110,7 +110,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
created_id (str): The id of the newly created EcoAccount entry created_id (str): The id of the newly created EcoAccount entry
""" """
with transaction.atomic(): with transaction.atomic():
obj = self.initialize_objects(json_model, user) obj = self._initialize_objects(json_model, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
@ -124,18 +124,18 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
if obj.deductable_surface < 0: if obj.deductable_surface < 0:
raise ValueError("Deductable surface (m²) must be greater or equal 0") raise ValueError("Deductable surface (m²) must be greater or equal 0")
obj = self.set_responsibility(obj, properties["responsible"]) obj = self._set_responsibility(obj, properties["responsible"])
obj = self.set_legal(obj, properties["legal"]) obj = self._set_legal(obj, properties["legal"])
obj.geometry.save() obj.geometry.save()
obj.responsible.save() obj.responsible.save()
obj.legal.save() obj.legal.save()
obj.save() obj.save()
obj = self.set_compensation_actions(obj, properties["actions"]) obj = self._set_compensation_actions(obj, properties["actions"])
obj = self.set_compensation_states(obj, properties["before_states"], obj.before_states) obj = self._set_compensation_states(obj, properties["before_states"], obj.before_states)
obj = self.set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
obj = self.set_deadlines(obj, properties["deadlines"]) obj = self._set_deadlines(obj, properties["deadlines"])
obj.log.add(obj.created) obj.log.add(obj.created)
obj.users.add(user) obj.users.add(user)
@ -157,27 +157,27 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
""" """
with transaction.atomic(): with transaction.atomic():
update_action = UserActionLogEntry.get_edited_action(user, "API update") update_action = UserActionLogEntry.get_edited_action(user, "API update")
obj = self.get_obj_from_db(id, user) obj = self._get_obj_from_db(id, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
obj.title = properties["title"] obj.title = properties["title"]
obj.deductable_surface = float(properties["deductable_surface"]) obj.deductable_surface = float(properties["deductable_surface"])
obj.modified = update_action obj.modified = update_action
obj.geometry.geom = self.create_geometry_from_json(json_model) obj.geometry.geom = self._create_geometry_from_json(json_model)
obj.geometry.modified = update_action obj.geometry.modified = update_action
obj = self.set_responsibility(obj, properties["responsible"]) obj = self._set_responsibility(obj, properties["responsible"])
obj = self.set_legal(obj, properties["legal"]) obj = self._set_legal(obj, properties["legal"])
obj.geometry.save() obj.geometry.save()
obj.responsible.save() obj.responsible.save()
obj.legal.save() obj.legal.save()
obj.save() obj.save()
obj = self.set_compensation_actions(obj, properties["actions"]) obj = self._set_compensation_actions(obj, properties["actions"])
obj = self.set_compensation_states(obj, properties["before_states"], obj.before_states) obj = self._set_compensation_states(obj, properties["before_states"], obj.before_states)
obj = self.set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
obj = self.set_deadlines(obj, properties["deadlines"]) obj = self._set_deadlines(obj, properties["deadlines"])
obj.log.add(update_action) obj.log.add(update_action)

View File

@ -20,21 +20,21 @@ from user.models import UserActionLogEntry
class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISerializerV1Mixin, ResponsibilityAPISerializerV1Mixin): class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISerializerV1Mixin, ResponsibilityAPISerializerV1Mixin):
model = Ema model = Ema
def extend_properties_data(self, entry): def _extend_properties_data(self, entry):
self.properties_data["responsible"] = self.responsible_to_json(entry.responsible) self.properties_data["responsible"] = self._responsible_to_json(entry.responsible)
self.properties_data["before_states"] = self.compensation_state_to_json(entry.before_states.all()) 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["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["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())
def responsible_to_json(self, responsible: Responsibility): def _responsible_to_json(self, responsible: Responsibility):
return { return {
"conservation_office": self.konova_code_to_json(responsible.conservation_office), "conservation_office": self._konova_code_to_json(responsible.conservation_office),
"conservation_file_number": responsible.conservation_file_number, "conservation_file_number": responsible.conservation_file_number,
"handler": responsible.handler, "handler": responsible.handler,
} }
def set_responsibility(self, obj, responsibility_data: dict): def _set_responsibility(self, obj, responsibility_data: dict):
""" Sets the responsible data contents to the provided responsibility_data dict """ Sets the responsible data contents to the provided responsibility_data dict
Args: Args:
@ -46,7 +46,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
""" """
if responsibility_data is None: if responsibility_data is None:
return obj return obj
obj.responsible.conservation_office = self.konova_code_from_json( obj.responsible.conservation_office = self._konova_code_from_json(
responsibility_data["conservation_office"], responsibility_data["conservation_office"],
CODELIST_CONSERVATION_OFFICE_ID, CODELIST_CONSERVATION_OFFICE_ID,
) )
@ -54,7 +54,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
obj.responsible.handler = responsibility_data["handler"] obj.responsible.handler = responsibility_data["handler"]
return obj return obj
def initialize_objects(self, json_model, user): def _initialize_objects(self, json_model, user):
""" Initializes all needed objects from the json_model data """ Initializes all needed objects from the json_model data
Does not persist data to the DB! Does not persist data to the DB!
@ -68,7 +68,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
""" """
create_action = UserActionLogEntry.get_created_action(user, comment="API Import") create_action = UserActionLogEntry.get_created_action(user, comment="API Import")
# Create geometry # Create geometry
json_geom = self.create_geometry_from_json(json_model) json_geom = self._create_geometry_from_json(json_model)
geometry = Geometry() geometry = Geometry()
geometry.geom = json_geom geometry.geom = json_geom
geometry.created = create_action geometry.created = create_action
@ -92,22 +92,22 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
created_id (str): The id of the newly created Ema entry created_id (str): The id of the newly created Ema entry
""" """
with transaction.atomic(): with transaction.atomic():
obj = self.initialize_objects(json_model, user) obj = self._initialize_objects(json_model, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
obj.identifier = obj.generate_new_identifier() obj.identifier = obj.generate_new_identifier()
obj.title = properties["title"] obj.title = properties["title"]
obj = self.set_responsibility(obj, properties["responsible"]) obj = self._set_responsibility(obj, properties["responsible"])
obj.geometry.save() obj.geometry.save()
obj.responsible.save() obj.responsible.save()
obj.save() obj.save()
obj = self.set_compensation_actions(obj, properties["actions"]) obj = self._set_compensation_actions(obj, properties["actions"])
obj = self.set_compensation_states(obj, properties["before_states"], obj.before_states) obj = self._set_compensation_states(obj, properties["before_states"], obj.before_states)
obj = self.set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
obj = self.set_deadlines(obj, properties["deadlines"]) obj = self._set_deadlines(obj, properties["deadlines"])
obj.log.add(obj.created) obj.log.add(obj.created)
obj.users.add(user) obj.users.add(user)
@ -129,24 +129,24 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
""" """
with transaction.atomic(): with transaction.atomic():
update_action = UserActionLogEntry.get_edited_action(user, "API update") update_action = UserActionLogEntry.get_edited_action(user, "API update")
obj = self.get_obj_from_db(id, user) obj = self._get_obj_from_db(id, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
obj.title = properties["title"] obj.title = properties["title"]
obj.modified = update_action obj.modified = update_action
obj.geometry.geom = self.create_geometry_from_json(json_model) obj.geometry.geom = self._create_geometry_from_json(json_model)
obj.geometry.modified = update_action obj.geometry.modified = update_action
obj = self.set_responsibility(obj, properties["responsible"]) obj = self._set_responsibility(obj, properties["responsible"])
obj.geometry.save() obj.geometry.save()
obj.responsible.save() obj.responsible.save()
obj.save() obj.save()
obj = self.set_compensation_actions(obj, properties["actions"]) obj = self._set_compensation_actions(obj, properties["actions"])
obj = self.set_compensation_states(obj, properties["before_states"], obj.before_states) obj = self._set_compensation_states(obj, properties["before_states"], obj.before_states)
obj = self.set_compensation_states(obj, properties["after_states"], obj.after_states) obj = self._set_compensation_states(obj, properties["after_states"], obj.after_states)
obj = self.set_deadlines(obj, properties["deadlines"]) obj = self._set_deadlines(obj, properties["deadlines"])
obj.log.add(update_action) obj.log.add(update_action)

View File

@ -23,14 +23,14 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
DeductableAPISerializerV1Mixin): DeductableAPISerializerV1Mixin):
model = Intervention model = Intervention
def compensations_to_json(self, qs: QuerySet): def _compensations_to_json(self, qs: QuerySet):
return list( return list(
qs.values( qs.values(
"id", "identifier", "title" "id", "identifier", "title"
) )
) )
def payments_to_json(self, qs: QuerySet): def _payments_to_json(self, qs: QuerySet):
""" Serializes payments into json """ Serializes payments into json
Args: Args:
@ -41,14 +41,14 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
""" """
return list(qs.values("amount", "due_on", "comment")) return list(qs.values("amount", "due_on", "comment"))
def extend_properties_data(self, entry): def _extend_properties_data(self, entry):
self.properties_data["responsible"] = self.responsible_to_json(entry.responsible) self.properties_data["responsible"] = self._responsible_to_json(entry.responsible)
self.properties_data["legal"] = self.legal_to_json(entry.legal) self.properties_data["legal"] = self._legal_to_json(entry.legal)
self.properties_data["compensations"] = self.compensations_to_json(entry.compensations.all()) 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["payments"] = self._payments_to_json(entry.payments.all())
self.properties_data["deductions"] = self.deductions_to_json(entry.deductions.all()) self.properties_data["deductions"] = self._deductions_to_json(entry.deductions.all())
def initialize_objects(self, json_model, user): def _initialize_objects(self, json_model, user):
""" Initializes all needed objects from the json_model data """ Initializes all needed objects from the json_model data
Does not persist data to the DB! Does not persist data to the DB!
@ -62,7 +62,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
""" """
create_action = UserActionLogEntry.get_created_action(user, comment="API Import") create_action = UserActionLogEntry.get_created_action(user, comment="API Import")
# Create geometry # Create geometry
json_geom = self.create_geometry_from_json(json_model) json_geom = self._create_geometry_from_json(json_model)
geometry = Geometry() geometry = Geometry()
geometry.geom = json_geom geometry.geom = json_geom
geometry.created = create_action geometry.created = create_action
@ -78,7 +78,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
obj.responsible = resp obj.responsible = resp
return obj return obj
def set_payments(self, obj, payment_data): def _set_payments(self, obj, payment_data):
""" Sets the linked Payment data according to the given payment_data """ Sets the linked Payment data according to the given payment_data
@ -143,14 +143,14 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
created_id (str): The id of the newly created Intervention entry created_id (str): The id of the newly created Intervention entry
""" """
with transaction.atomic(): with transaction.atomic():
obj = self.initialize_objects(json_model, user) obj = self._initialize_objects(json_model, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
obj.identifier = obj.generate_new_identifier() obj.identifier = obj.generate_new_identifier()
obj.title = properties["title"] obj.title = properties["title"]
self.set_responsibility(obj, properties["responsible"]) self._set_responsibility(obj, properties["responsible"])
self.set_legal(obj, properties["legal"]) self._set_legal(obj, properties["legal"])
obj.responsible.save() obj.responsible.save()
obj.geometry.save() obj.geometry.save()
@ -177,15 +177,15 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
""" """
with transaction.atomic(): with transaction.atomic():
update_action = UserActionLogEntry.get_edited_action(user, "API update") update_action = UserActionLogEntry.get_edited_action(user, "API update")
obj = self.get_obj_from_db(id, user) obj = self._get_obj_from_db(id, user)
# Fill in data to objects # Fill in data to objects
properties = json_model["properties"] properties = json_model["properties"]
obj.title = properties["title"] obj.title = properties["title"]
self.set_responsibility(obj, properties.get("responsible", None)) self._set_responsibility(obj, properties.get("responsible", None))
self.set_legal(obj, properties.get("legal", None)) self._set_legal(obj, properties.get("legal", None))
self.set_payments(obj, properties.get("payments", None)) self._set_payments(obj, properties.get("payments", None))
obj.geometry.geom = self.create_geometry_from_json(json_model) obj.geometry.geom = self._create_geometry_from_json(json_model)
obj.geometry.modified = update_action obj.geometry.modified = update_action
obj.responsible.save() obj.responsible.save()

View File

@ -8,6 +8,7 @@ Created on: 24.01.22
import json import json
from django.contrib.gis.geos import MultiPolygon
from django.db.models import QuerySet from django.db.models import QuerySet
from api.utils.serializer.serializer import AbstractModelAPISerializer from api.utils.serializer.serializer import AbstractModelAPISerializer
@ -17,10 +18,11 @@ from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES
from compensation.models import CompensationAction, UnitChoices, CompensationState from compensation.models import CompensationAction, UnitChoices, CompensationState
from intervention.models import Responsibility, Legal from intervention.models import Responsibility, Legal
from konova.models import Deadline, DeadlineType from konova.models import Deadline, DeadlineType
from konova.utils.message_templates import DATA_UNSHARED
class AbstractModelAPISerializerV1(AbstractModelAPISerializer): class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
def model_to_geo_json(self, entry): def _model_to_geo_json(self, entry):
""" Adds the basic data, which all elements hold """ Adds the basic data, which all elements hold
Args: Args:
@ -29,20 +31,23 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
Returns: Returns:
""" """
if entry.geometry.geom is not None:
geom = entry.geometry.geom.geojson geom = entry.geometry.geom.geojson
else:
geom = MultiPolygon().geojson
geo_json = json.loads(geom) geo_json = json.loads(geom)
self.properties_data = { self.properties_data = {
"id": entry.id, "id": entry.id,
"identifier": entry.identifier, "identifier": entry.identifier,
"title": entry.title, "title": entry.title,
"created_on": self.created_on_to_json(entry), "created_on": self._created_on_to_json(entry),
"modified_on": self.modified_on_to_json(entry), "modified_on": self._modified_on_to_json(entry),
} }
self.extend_properties_data(entry) self._extend_properties_data(entry)
geo_json["properties"] = self.properties_data geo_json["properties"] = self.properties_data
return geo_json return geo_json
def konova_code_to_json(self, konova_code: KonovaCode): def _konova_code_to_json(self, konova_code: KonovaCode):
""" Serializes KonovaCode model into json """ Serializes KonovaCode model into json
Args: Args:
@ -59,7 +64,7 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
"short_name": konova_code.short_name, "short_name": konova_code.short_name,
} }
def konova_code_from_json(self, json_str, code_list_identifier): def _konova_code_from_json(self, json_str, code_list_identifier):
""" Returns a konova code instance """ Returns a konova code instance
Args: Args:
@ -77,7 +82,7 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
) )
return code return code
def created_on_to_json(self, entry): def _created_on_to_json(self, entry):
""" Serializes the created_on into json """ Serializes the created_on into json
Args: Args:
@ -88,7 +93,7 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
""" """
return entry.created.timestamp if entry.created is not None else None return entry.created.timestamp if entry.created is not None else None
def modified_on_to_json(self, entry): def _modified_on_to_json(self, entry):
""" Serializes the modified_on into json """ Serializes the modified_on into json
Args: Args:
@ -101,12 +106,33 @@ class AbstractModelAPISerializerV1(AbstractModelAPISerializer):
modified_on = modified_on.timestamp if modified_on is not None else None modified_on = modified_on.timestamp if modified_on is not None else None
return modified_on return modified_on
def delete_entry(self, id, user):
""" Marks an entry as deleted
Args:
id (str): The entry's id
user (User): The API user
Returns:
"""
entry = self._get_obj_from_db(id, user)
is_shared = entry.is_shared_with(user)
if not is_shared:
raise PermissionError(DATA_UNSHARED)
# Do not send mails if entry is deleting using API. THere could be hundreds of deletion resulting in hundreds of
# mails at once.
entry.mark_as_deleted(user, send_mail=False)
entry.refresh_from_db()
success = entry.deleted is not None
return success
class DeductableAPISerializerV1Mixin: class DeductableAPISerializerV1Mixin:
class Meta: class Meta:
abstract = True abstract = True
def deductions_to_json(self, qs: QuerySet): def _deductions_to_json(self, qs: QuerySet):
""" Serializes eco account deductions into json """ Serializes eco account deductions into json
Args: Args:
@ -138,7 +164,7 @@ class ResponsibilityAPISerializerV1Mixin:
class Meta: class Meta:
abstract = True abstract = True
def responsible_to_json(self, responsible: Responsibility): def _responsible_to_json(self, responsible: Responsibility):
""" Serializes Responsibility model into json """ Serializes Responsibility model into json
Args: Args:
@ -148,14 +174,14 @@ class ResponsibilityAPISerializerV1Mixin:
serialized_json (dict) serialized_json (dict)
""" """
return { return {
"registration_office": self.konova_code_to_json(responsible.registration_office), "registration_office": self._konova_code_to_json(responsible.registration_office),
"registration_file_number": responsible.registration_file_number, "registration_file_number": responsible.registration_file_number,
"conservation_office": self.konova_code_to_json(responsible.conservation_office), "conservation_office": self._konova_code_to_json(responsible.conservation_office),
"conservation_file_number": responsible.conservation_file_number, "conservation_file_number": responsible.conservation_file_number,
"handler": responsible.handler, "handler": responsible.handler,
} }
def set_responsibility(self, obj, responsibility_data: dict): def _set_responsibility(self, obj, responsibility_data: dict):
""" Sets the responsible data contents to the provided responsibility_data dict """ Sets the responsible data contents to the provided responsibility_data dict
Args: Args:
@ -167,12 +193,12 @@ class ResponsibilityAPISerializerV1Mixin:
""" """
if responsibility_data is None: if responsibility_data is None:
return obj return obj
obj.responsible.registration_office = self.konova_code_from_json( obj.responsible.registration_office = self._konova_code_from_json(
responsibility_data["registration_office"], responsibility_data["registration_office"],
CODELIST_REGISTRATION_OFFICE_ID CODELIST_REGISTRATION_OFFICE_ID
) )
obj.responsible.registration_file_number = responsibility_data["registration_file_number"] obj.responsible.registration_file_number = responsibility_data["registration_file_number"]
obj.responsible.conservation_office = self.konova_code_from_json( obj.responsible.conservation_office = self._konova_code_from_json(
responsibility_data["conservation_office"], responsibility_data["conservation_office"],
CODELIST_CONSERVATION_OFFICE_ID, CODELIST_CONSERVATION_OFFICE_ID,
) )
@ -185,7 +211,7 @@ class LegalAPISerializerV1Mixin:
class Meta: class Meta:
abstract = True abstract = True
def legal_to_json(self, legal: Legal): def _legal_to_json(self, legal: Legal):
""" Serializes Legal model into json """ Serializes Legal model into json
Args: Args:
@ -197,11 +223,11 @@ class LegalAPISerializerV1Mixin:
return { return {
"registration_date": legal.registration_date, "registration_date": legal.registration_date,
"binding_date": legal.binding_date, "binding_date": legal.binding_date,
"process_type": self.konova_code_to_json(legal.process_type), "process_type": self._konova_code_to_json(legal.process_type),
"laws": [self.konova_code_to_json(law) for law in legal.laws.all()], "laws": [self._konova_code_to_json(law) for law in legal.laws.all()],
} }
def set_legal(self, obj, legal_data): def _set_legal(self, obj, legal_data):
""" Sets the legal data contents to the provided legal_data dict """ Sets the legal data contents to the provided legal_data dict
Args: Args:
@ -215,11 +241,11 @@ class LegalAPISerializerV1Mixin:
return obj return obj
obj.legal.registration_date = legal_data.get("registration_date", None) obj.legal.registration_date = legal_data.get("registration_date", None)
obj.legal.binding_date = legal_data.get("binding_date", None) obj.legal.binding_date = legal_data.get("binding_date", None)
obj.legal.process_type = self.konova_code_from_json( obj.legal.process_type = self._konova_code_from_json(
legal_data.get("process_type", None), legal_data.get("process_type", None),
CODELIST_PROCESS_TYPE_ID, CODELIST_PROCESS_TYPE_ID,
) )
laws = [self.konova_code_from_json(law, CODELIST_LAW_ID) for law in legal_data.get("laws", [])] laws = [self._konova_code_from_json(law, CODELIST_LAW_ID) for law in legal_data.get("laws", [])]
obj.legal.laws.set(laws) obj.legal.laws.set(laws)
return obj return obj
@ -228,7 +254,7 @@ class AbstractCompensationAPISerializerV1Mixin:
class Meta: class Meta:
abstract = True abstract = True
def set_deadlines(self, obj, deadline_data): def _set_deadlines(self, obj, deadline_data):
""" Sets the linked deadline data according to the given deadline_data """ Sets the linked deadline data according to the given deadline_data
@ -271,7 +297,7 @@ class AbstractCompensationAPISerializerV1Mixin:
obj.deadlines.set(deadlines) obj.deadlines.set(deadlines)
return obj return obj
def set_compensation_states(self, obj, states_data, states_manager): def _set_compensation_states(self, obj, states_data, states_manager):
""" Sets the linked compensation state data according to the given states_data """ Sets the linked compensation state data according to the given states_data
@ -305,7 +331,7 @@ class AbstractCompensationAPISerializerV1Mixin:
else: else:
# Create and add id to list # Create and add id to list
new_state = CompensationState.objects.create( new_state = CompensationState.objects.create(
biotope_type=self.konova_code_from_json(biotope_type, CODELIST_BIOTOPES_ID), biotope_type=self._konova_code_from_json(biotope_type, CODELIST_BIOTOPES_ID),
surface=surface surface=surface
) )
states.append(new_state.id) states.append(new_state.id)
@ -313,7 +339,7 @@ class AbstractCompensationAPISerializerV1Mixin:
states_manager.set(states) states_manager.set(states)
return obj return obj
def set_compensation_actions(self, obj, actions_data): def _set_compensation_actions(self, obj, actions_data):
""" Sets the linked compensation action data according to the given actions_data """ Sets the linked compensation action data according to the given actions_data
@ -352,7 +378,7 @@ class AbstractCompensationAPISerializerV1Mixin:
else: else:
# Create and add id to list # Create and add id to list
new_action = CompensationAction.objects.create( new_action = CompensationAction.objects.create(
action_type=self.konova_code_from_json(action, CODELIST_COMPENSATION_ACTION_ID), action_type=self._konova_code_from_json(action, CODELIST_COMPENSATION_ACTION_ID),
amount=amount, amount=amount,
unit=unit, unit=unit,
comment=comment, comment=comment,
@ -361,7 +387,7 @@ class AbstractCompensationAPISerializerV1Mixin:
obj.actions.set(actions) obj.actions.set(actions)
return obj return obj
def compensation_state_to_json(self, qs: QuerySet): def _compensation_state_to_json(self, qs: QuerySet):
""" Serializes compensation states into json """ Serializes compensation states into json
Args: Args:
@ -372,13 +398,13 @@ class AbstractCompensationAPISerializerV1Mixin:
""" """
return [ return [
{ {
"biotope": self.konova_code_to_json(entry.biotope_type), "biotope": self._konova_code_to_json(entry.biotope_type),
"surface": entry.surface, "surface": entry.surface,
} }
for entry in qs for entry in qs
] ]
def compensation_actions_to_json(self, qs: QuerySet): def _compensation_actions_to_json(self, qs: QuerySet):
""" Serializes CompensationActions into json """ Serializes CompensationActions into json
Args: Args:
@ -389,7 +415,7 @@ class AbstractCompensationAPISerializerV1Mixin:
""" """
return [ return [
{ {
"action": self.konova_code_to_json(entry.action_type), "action": self._konova_code_to_json(entry.action_type),
"amount": entry.amount, "amount": entry.amount,
"unit": entry.unit, "unit": entry.unit,
"comment": entry.comment, "comment": entry.comment,
@ -397,7 +423,7 @@ class AbstractCompensationAPISerializerV1Mixin:
for entry in qs for entry in qs
] ]
def deadlines_to_json(self, qs: QuerySet): def _deadlines_to_json(self, qs: QuerySet):
""" Serializes deadlines into json """ Serializes deadlines into json
Args: Args:

View File

@ -79,7 +79,7 @@ class AbstractAPIViewV1(AbstractAPIView):
id (str): The entries id id (str): The entries id
Returns: Returns:
response (JsonResponse)
""" """
try: try:
body = request.body.decode("utf-8") body = request.body.decode("utf-8")
@ -89,6 +89,27 @@ class AbstractAPIViewV1(AbstractAPIView):
return self.return_error_response(e, 500) return self.return_error_response(e, 500)
return JsonResponse({"id": updated_id}) return JsonResponse({"id": updated_id})
def delete(self, request: HttpRequest, id=None):
""" Handles a DELETE request
Args:
request (HttpRequest): The incoming request
id (str): The object's id
Returns:
response (JsonResponse)
"""
try:
success = self.serializer.delete_entry(id, self.user)
except Exception as e:
return self.return_error_response(e, 500)
return JsonResponse(
{
"success": success,
}
)
class InterventionAPIViewV1(AbstractAPIViewV1): class InterventionAPIViewV1(AbstractAPIViewV1):
serializer = InterventionAPISerializerV1 serializer = InterventionAPISerializerV1

View File

@ -104,7 +104,7 @@ class BaseObject(BaseResource):
def set_status_messages(self, request: HttpRequest): def set_status_messages(self, request: HttpRequest):
raise NotImplementedError raise NotImplementedError
def mark_as_deleted(self, user: User): def mark_as_deleted(self, user: User, send_mail: bool = True):
""" Mark an entry as deleted """ Mark an entry as deleted
Does not delete from database but sets a timestamp for being deleted on and which user deleted the object Does not delete from database but sets a timestamp for being deleted on and which user deleted the object
@ -124,6 +124,7 @@ class BaseObject(BaseResource):
self.deleted = action self.deleted = action
self.log.add(action) self.log.add(action)
if send_mail:
# Send mail # Send mail
shared_users = self.shared_users.values_list("id", flat=True) shared_users = self.shared_users.values_list("id", flat=True)
for user_id in shared_users: for user_id in shared_users: