""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany Contact: michel.peltriaux@sgdnord.rlp.de Created on: 17.11.20 """ from django.contrib.auth.models import User from django.contrib.gis.db import models from django.utils.timezone import now from compensation.settings import COMPENSATION_IDENTIFIER_LENGTH, COMPENSATION_IDENTIFIER_TEMPLATE from konova.models import BaseObject, BaseResource from konova.utils.generators import generate_random_string from process.models import Process class CompensationControl(BaseResource): """ Holds data on how a compensation shall be controlled """ deadline = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True) type = models.CharField(max_length=500, null=True, blank=True) expected_result = models.CharField(max_length=500, null=True, blank=True, help_text="The expected outcome, that needs to be controlled") by_authority = models.CharField(max_length=500, null=True, blank=True) comment = models.TextField() class CompensationState(models.Model): """ Compensations must define the state of an area before and after the compensation. """ biotope_type = models.CharField(max_length=500, null=True, blank=True) amount = models.FloatField() unit = models.CharField(max_length=100, null=True, blank=True) class CompensationAction(BaseResource): """ Compensations include actions like planting trees, refreshing rivers and so on. """ action_type = models.CharField(max_length=500, null=True, blank=True) amount = models.FloatField() unit = models.CharField(max_length=100, null=True, blank=True) control = models.ForeignKey(CompensationControl, on_delete=models.SET_NULL, null=True, blank=True) class Compensation(BaseObject): """ The compensation holds information about which actions have to be performed until which date, who is in charge of this, which legal authority is the point of contact, and so on. """ is_old_law = models.BooleanField(default=False) type = models.CharField(max_length=500, null=True, blank=True) registration_office = models.CharField(max_length=500, null=True, blank=True) # ToDo: Really needed? process = models.ForeignKey("process.Process", related_name="compensations", on_delete=models.CASCADE) ground_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws! action_definitions = models.CharField(max_length=500, null=True, blank=True) # ToDo: Need to be M2M to laws! actions = models.ManyToManyField(CompensationAction) deadline_creation = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="deadline_creation") deadline_maintaining = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True, related_name="deadline_maintaining") initial_states = models.ManyToManyField(CompensationState, blank=True, related_name='+') final_states = models.ManyToManyField(CompensationState, blank=True, related_name='+') geometry = models.MultiPolygonField(null=True, blank=True) documents = models.ManyToManyField("konova.Document", blank=True) def __str__(self): return "{} of {}".format(self.type, self.process) @staticmethod def __generate_new_identifier() -> str: """ Generates a new identifier for the intervention object Returns: str """ curr_month = str(now().month) curr_year = str(now().year) rand_str = generate_random_string( length=COMPENSATION_IDENTIFIER_LENGTH, only_numbers=True, ) _str = "{}{}{}".format(curr_month, curr_year, rand_str) return COMPENSATION_IDENTIFIER_TEMPLATE.format(_str) def save(self, *args, **kwargs): if self.identifier is None or len(self.identifier) == 0: # Create new identifier new_id = self.__generate_new_identifier() while Compensation.objects.filter(identifier=new_id).exists(): new_id = self.__generate_new_identifier() self.identifier = new_id super().save(*args, **kwargs) @staticmethod def get_role_objects(user: User, order_by: str = "-created_on"): """ Returns objects depending on the currently selected role of the user * REGISTRATIONOFFICE * User can see the processes where registration_office is set to the organisation of the currently selected role * User can see self-created processes * LICENSINGOFFICE * same * DATAPROVIDER * User can see only self-created processes Args: user (User): The performing user order_by (str): Order by which Process attribute Returns: """ role = user.current_role if role is None: return Compensation.objects.none() processes = Process.get_role_objects(user, order_by) processes.prefetch_related("compensations") compensations = [] [compensations.extend(process.compensations.all()) for process in processes] return compensations class EcoAccount(BaseResource): """ An eco account is a kind of 'prepaid' compensation. It can be compared to an account that already has been filled with some kind of currency. From this account one is able to 'withdraw' currency for current projects. 'Withdrawing' can only be applied by shrinking the size of the available geometry and declaring the withdrawed geometry as a compensation for a process. """ is_old_law = models.BooleanField(default=False) type = models.CharField(max_length=500, null=True, blank=True) licensing_authority_document_identifier = models.CharField(max_length=500, null=True, blank=True) registration_office = models.CharField(max_length=500, null=True, blank=True) handler = models.CharField(max_length=500, null=True, blank=True) handler_comments = models.TextField() geometry = models.GeometryCollectionField() documents = models.ManyToManyField("konova.Document") initial_states = models.ManyToManyField(CompensationState, blank=True, related_name='+') final_states = models.ManyToManyField(CompensationState, blank=True, related_name='+') actions = models.ManyToManyField(CompensationAction) deadline_maintaining = models.ForeignKey("konova.Deadline", on_delete=models.SET_NULL, null=True, blank=True) deadline_other = models.ManyToManyField("konova.Deadline", blank=True, related_name='+') comments = models.TextField()