* 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
214 lines
7.5 KiB
Python
214 lines
7.5 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 django.db.models import QuerySet
|
|
|
|
from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, \
|
|
ResponsibilityAPISerializerV1Mixin, LegalAPISerializerV1Mixin, DeductableAPISerializerV1Mixin
|
|
from compensation.models import Payment
|
|
from intervention.models import Intervention, Responsibility, Legal, Handler
|
|
from konova.models import Geometry
|
|
from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts
|
|
from user.models import UserActionLogEntry
|
|
|
|
|
|
class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
|
|
ResponsibilityAPISerializerV1Mixin,
|
|
LegalAPISerializerV1Mixin,
|
|
DeductableAPISerializerV1Mixin):
|
|
model = Intervention
|
|
|
|
def _compensations_to_json(self, qs: QuerySet):
|
|
return list(
|
|
qs.values(
|
|
"id", "identifier", "title"
|
|
)
|
|
)
|
|
|
|
def _payments_to_json(self, qs: QuerySet):
|
|
""" Serializes payments into json
|
|
|
|
Args:
|
|
qs (QuerySet): A queryset of Payment entries
|
|
|
|
Returns:
|
|
serialized_json (list)
|
|
"""
|
|
return list(qs.values("amount", "due_on", "comment"))
|
|
|
|
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 _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 (Intervention)
|
|
"""
|
|
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 = Intervention()
|
|
resp = Responsibility(
|
|
handler=Handler()
|
|
)
|
|
legal = Legal()
|
|
created = create_action
|
|
obj.legal = legal
|
|
obj.created = created
|
|
obj.modified = created
|
|
obj.geometry = geometry
|
|
obj.responsible = resp
|
|
return obj
|
|
|
|
def _set_payments(self, obj, payment_data):
|
|
""" Sets the linked Payment data according to the given payment_data
|
|
|
|
|
|
Args:
|
|
obj (Compensation): The Compensation object
|
|
payment_data (dict): The posted payment_data
|
|
|
|
Returns:
|
|
obj (intervention)
|
|
"""
|
|
if payment_data is None:
|
|
return obj
|
|
payments = []
|
|
for entry in payment_data:
|
|
due_on = entry["due_on"]
|
|
amount = float(entry["amount"])
|
|
comment = entry["comment"]
|
|
|
|
# Check on validity
|
|
if amount <= 0:
|
|
raise ValueError("Payment amount must be > 0")
|
|
|
|
no_due_on = due_on is None or len(due_on) == 0
|
|
no_comment = comment is None or len(comment) == 0
|
|
|
|
if no_due_on and no_comment:
|
|
raise ValueError("If no due_on can be provided, you need to explain why using the comment")
|
|
|
|
# If this exact data is already existing, we do not create it new. Instead put it's id in the list of
|
|
# entries, we will use to set the new actions
|
|
pre_existing_payment = obj.payments.filter(
|
|
amount=amount,
|
|
due_on=due_on,
|
|
comment=comment,
|
|
).exclude(
|
|
id__in=payments
|
|
).first()
|
|
if pre_existing_payment is not None:
|
|
payments.append(pre_existing_payment.id)
|
|
else:
|
|
# Create and add id to list
|
|
new_payment = Payment.objects.create(
|
|
amount=amount,
|
|
due_on=due_on,
|
|
comment=comment,
|
|
)
|
|
payments.append(new_payment.id)
|
|
payments = Payment.objects.filter(
|
|
id__in=payments
|
|
)
|
|
obj.payments.set(payments)
|
|
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"]
|
|
|
|
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.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()
|
|
obj.geometry.save()
|
|
obj.legal.save()
|
|
obj.save()
|
|
|
|
self._set_external_identifier(obj, external_identifier)
|
|
obj.users.add(user)
|
|
obj.log.add(obj.created)
|
|
|
|
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 Intervention 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"]
|
|
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))
|
|
obj.geometry.geom = self._create_geometry_from_json(json_model)
|
|
obj.geometry.modified = update_action
|
|
|
|
obj.responsible.handler.save()
|
|
obj.responsible.save()
|
|
obj.geometry.save()
|
|
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()
|
|
|
|
celery_update_parcels.delay(obj.geometry.id)
|
|
|
|
return obj.id
|