* adds support for sending "external_identifier" in POST and PUT requests * if an external identifier already exists on the database, the client will be informed that the entry should not be POSTed again but rather an update via PUT should be performed
208 lines
8.4 KiB
Python
208 lines
8.4 KiB
Python
"""
|
|
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 api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, AbstractCompensationAPISerializerV1Mixin, \
|
|
LegalAPISerializerV1Mixin, ResponsibilityAPISerializerV1Mixin, DeductableAPISerializerV1Mixin
|
|
from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_ID
|
|
from compensation.models import EcoAccount
|
|
from intervention.models import Legal, Responsibility, Handler
|
|
from konova.models import Geometry
|
|
from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts
|
|
from user.models import UserActionLogEntry
|
|
|
|
|
|
class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
|
|
AbstractCompensationAPISerializerV1Mixin,
|
|
LegalAPISerializerV1Mixin,
|
|
ResponsibilityAPISerializerV1Mixin,
|
|
DeductableAPISerializerV1Mixin):
|
|
model = EcoAccount
|
|
|
|
def _extend_properties_data(self, entry):
|
|
self.properties_data["is_pik"] = entry.is_pik
|
|
self.properties_data["deductable_surface"] = entry.deductable_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["legal"] = self._legal_to_json(entry.legal)
|
|
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["deductions"] = self._deductions_to_json(entry.deductions.all())
|
|
|
|
def _legal_to_json(self, legal: Legal):
|
|
return {
|
|
"agreement_date": legal.registration_date,
|
|
}
|
|
|
|
def _responsible_to_json(self, responsible: Responsibility):
|
|
return {
|
|
"conservation_office": self._konova_code_to_json(responsible.conservation_office),
|
|
"conservation_file_number": responsible.conservation_file_number,
|
|
"handler": self._handler_to_json(responsible.handler),
|
|
}
|
|
|
|
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
|
|
"""
|
|
if responsibility_data is None:
|
|
return obj
|
|
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.type = self._konova_code_from_json(
|
|
responsibility_data["handler"]["type"],
|
|
CODELIST_HANDLER_ID,
|
|
)
|
|
obj.responsible.handler.detail = responsibility_data["handler"]["detail"]
|
|
return obj
|
|
|
|
def _set_legal(self, obj, legal_data):
|
|
obj.legal.registration_date = legal_data.get("agreement_date", None)
|
|
return obj
|
|
|
|
def _initialize_objects(self, json_model, user):
|
|
""" Initializes all needed objects from the json_model data
|
|
|
|
Does not persist data to the DB!
|
|
|
|
Args:
|
|
json_model (dict): The json data
|
|
user (User): The API user
|
|
|
|
Returns:
|
|
obj (Compensation)
|
|
"""
|
|
create_action = UserActionLogEntry.get_created_action(user, comment="API Import")
|
|
# Create geometry
|
|
json_geom = self._create_geometry_from_json(json_model)
|
|
geometry = Geometry()
|
|
geometry.geom = json_geom
|
|
geometry.created = create_action
|
|
|
|
# Create linked objects
|
|
obj = EcoAccount()
|
|
obj.responsible = Responsibility(
|
|
handler=Handler()
|
|
)
|
|
obj.legal = Legal()
|
|
created = create_action
|
|
obj.created = created
|
|
obj.modified = created
|
|
obj.geometry = geometry
|
|
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 EcoAccount entry
|
|
"""
|
|
with transaction.atomic():
|
|
obj = self._initialize_objects(json_model, user)
|
|
|
|
# Fill in data to objects
|
|
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)
|
|
|
|
try:
|
|
obj.deductable_surface = float(properties["deductable_surface"])
|
|
except TypeError:
|
|
raise ValueError("Deductable surface (m²) must be a number >= 0")
|
|
if obj.deductable_surface < 0:
|
|
raise ValueError("Deductable surface (m²) must be greater or equal 0")
|
|
|
|
obj = self._set_responsibility(obj, properties["responsible"])
|
|
obj = self._set_legal(obj, properties["legal"])
|
|
|
|
obj.geometry.save()
|
|
obj.responsible.handler.save()
|
|
obj.responsible.save()
|
|
obj.legal.save()
|
|
obj.save()
|
|
|
|
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["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)
|
|
|
|
celery_update_parcels.delay(obj.geometry.id)
|
|
celery_check_for_geometry_conflicts.delay(obj.geometry.id)
|
|
|
|
return obj.id
|
|
|
|
def update_model_from_json(self, id, json_model, user):
|
|
""" Updates an entry for the model based on the contents of json_model
|
|
|
|
Args:
|
|
id (str): The object's id
|
|
json_model (dict): The json containing data
|
|
user (User): The API user
|
|
|
|
Returns:
|
|
created_id (str): The id of the newly created EcoAccount entry
|
|
"""
|
|
with transaction.atomic():
|
|
update_action = UserActionLogEntry.get_edited_action(user, "API update")
|
|
obj = self._get_obj_from_db(id, user)
|
|
|
|
# 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"])
|
|
obj.modified = update_action
|
|
obj.geometry.geom = self._create_geometry_from_json(json_model)
|
|
obj.geometry.modified = update_action
|
|
obj = self._set_responsibility(obj, properties["responsible"])
|
|
obj = self._set_legal(obj, properties["legal"])
|
|
|
|
obj.geometry.save()
|
|
obj.responsible.handler.save()
|
|
obj.responsible.save()
|
|
obj.legal.save()
|
|
obj.save()
|
|
|
|
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["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)
|
|
|
|
return obj.id
|