Merge pull request '50_Overlaying_geometries' (#52) from 50_Overlaying_geometries into master
Reviewed-on: SGD-Nord/konova#52
This commit is contained in:
commit
44dbee0008
@ -2,6 +2,7 @@ from django.contrib import admin
|
|||||||
|
|
||||||
from compensation.models import Compensation, CompensationAction, CompensationState, Payment, \
|
from compensation.models import Compensation, CompensationAction, CompensationState, Payment, \
|
||||||
EcoAccountDeduction, EcoAccount
|
EcoAccountDeduction, EcoAccount
|
||||||
|
from konova.admin import BaseObjectAdmin
|
||||||
|
|
||||||
|
|
||||||
class CompensationStateAdmin(admin.ModelAdmin):
|
class CompensationStateAdmin(admin.ModelAdmin):
|
||||||
@ -22,7 +23,7 @@ class CompensationActionAdmin(admin.ModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class CompensationAdmin(admin.ModelAdmin):
|
class CompensationAdmin(BaseObjectAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
"id",
|
"id",
|
||||||
"identifier",
|
"identifier",
|
||||||
|
@ -7,6 +7,7 @@ Created on: 16.11.21
|
|||||||
"""
|
"""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models import QuerySet, Sum
|
from django.db.models import QuerySet, Sum
|
||||||
@ -16,12 +17,14 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from compensation.managers import CompensationManager
|
from compensation.managers import CompensationManager
|
||||||
from compensation.models import CompensationState, CompensationAction
|
from compensation.models import CompensationState, CompensationAction
|
||||||
from compensation.utils.quality import CompensationQualityChecker
|
from compensation.utils.quality import CompensationQualityChecker
|
||||||
from konova.models import BaseObject, AbstractDocument, Geometry, Deadline, generate_document_file_upload_path
|
from konova.models import BaseObject, AbstractDocument, Deadline, generate_document_file_upload_path, \
|
||||||
|
GeoReferencedMixin
|
||||||
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
|
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
|
||||||
|
from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION
|
||||||
from user.models import UserActionLogEntry
|
from user.models import UserActionLogEntry
|
||||||
|
|
||||||
|
|
||||||
class AbstractCompensation(BaseObject):
|
class AbstractCompensation(BaseObject, GeoReferencedMixin):
|
||||||
"""
|
"""
|
||||||
Abstract compensation model which holds basic attributes, shared by subclasses like the regular Compensation,
|
Abstract compensation model which holds basic attributes, shared by subclasses like the regular Compensation,
|
||||||
EMA or EcoAccount.
|
EMA or EcoAccount.
|
||||||
@ -41,8 +44,6 @@ class AbstractCompensation(BaseObject):
|
|||||||
|
|
||||||
deadlines = models.ManyToManyField("konova.Deadline", blank=True, related_name="+")
|
deadlines = models.ManyToManyField("konova.Deadline", blank=True, related_name="+")
|
||||||
|
|
||||||
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
@ -156,6 +157,22 @@ class AbstractCompensation(BaseObject):
|
|||||||
checker.run_check()
|
checker.run_check()
|
||||||
return checker
|
return checker
|
||||||
|
|
||||||
|
def set_status_messages(self, request: HttpRequest):
|
||||||
|
""" Setter for different information that need to be rendered
|
||||||
|
|
||||||
|
Adds messages to the given HttpRequest
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
request (HttpRequest): The modified request
|
||||||
|
"""
|
||||||
|
if not self.is_shared_with(request.user):
|
||||||
|
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
||||||
|
request = self._set_geometry_conflict_message(request)
|
||||||
|
return request
|
||||||
|
|
||||||
|
|
||||||
class CEFMixin(models.Model):
|
class CEFMixin(models.Model):
|
||||||
""" Provides CEF flag as Mixin
|
""" Provides CEF flag as Mixin
|
||||||
|
@ -184,8 +184,7 @@ def detail_view(request: HttpRequest, id: str):
|
|||||||
sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
|
sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
|
||||||
diff_states = abs(sum_before_states - sum_after_states)
|
diff_states = abs(sum_before_states - sum_after_states)
|
||||||
|
|
||||||
if not is_data_shared:
|
request = comp.set_status_messages(request)
|
||||||
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"obj": comp,
|
"obj": comp,
|
||||||
|
@ -202,8 +202,7 @@ def detail_view(request: HttpRequest, id: str):
|
|||||||
)
|
)
|
||||||
actions = acc.actions.all()
|
actions = acc.actions.all()
|
||||||
|
|
||||||
if not is_data_shared:
|
request = acc.set_status_messages(request)
|
||||||
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"obj": acc,
|
"obj": acc,
|
||||||
|
@ -7,15 +7,17 @@ Created on: 15.11.21
|
|||||||
"""
|
"""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib import messages
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
from django.http import HttpRequest
|
||||||
|
|
||||||
from compensation.models import AbstractCompensation
|
from compensation.models import AbstractCompensation
|
||||||
from ema.managers import EmaManager
|
from ema.managers import EmaManager
|
||||||
from ema.utils.quality import EmaQualityChecker
|
from ema.utils.quality import EmaQualityChecker
|
||||||
from konova.models import AbstractDocument, generate_document_file_upload_path, RecordableObjectMixin, ShareableObjectMixin
|
from konova.models import AbstractDocument, generate_document_file_upload_path, RecordableObjectMixin, ShareableObjectMixin
|
||||||
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
|
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
|
||||||
|
from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION
|
||||||
|
|
||||||
|
|
||||||
class Ema(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin):
|
class Ema(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin):
|
||||||
@ -91,6 +93,22 @@ class Ema(AbstractCompensation, ShareableObjectMixin, RecordableObjectMixin):
|
|||||||
)
|
)
|
||||||
return docs
|
return docs
|
||||||
|
|
||||||
|
def set_status_messages(self, request: HttpRequest):
|
||||||
|
""" Setter for different information that need to be rendered
|
||||||
|
|
||||||
|
Adds messages to the given HttpRequest
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
request (HttpRequest): The modified request
|
||||||
|
"""
|
||||||
|
if not self.is_shared_with(request.user):
|
||||||
|
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
||||||
|
self._set_geometry_conflict_message(request)
|
||||||
|
return request
|
||||||
|
|
||||||
|
|
||||||
class EmaDocument(AbstractDocument):
|
class EmaDocument(AbstractDocument):
|
||||||
"""
|
"""
|
||||||
|
@ -138,8 +138,7 @@ def detail_view(request: HttpRequest, id: str):
|
|||||||
sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
|
sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
|
||||||
diff_states = abs(sum_before_states - sum_after_states)
|
diff_states = abs(sum_before_states - sum_after_states)
|
||||||
|
|
||||||
if not is_data_shared:
|
ema.set_status_messages(request)
|
||||||
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"obj": ema,
|
"obj": ema,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from intervention.models import Intervention, Responsibility, Legal, Revocation, InterventionDocument
|
from intervention.models import Intervention, Responsibility, Legal, Revocation, InterventionDocument
|
||||||
from konova.admin import AbstractDocumentAdmin
|
from konova.admin import AbstractDocumentAdmin, BaseObjectAdmin
|
||||||
|
|
||||||
|
|
||||||
class InterventionAdmin(admin.ModelAdmin):
|
class InterventionAdmin(BaseObjectAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
"id",
|
"id",
|
||||||
"identifier",
|
"identifier",
|
||||||
@ -13,9 +13,11 @@ class InterventionAdmin(admin.ModelAdmin):
|
|||||||
"deleted",
|
"deleted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class InterventionDocumentAdmin(AbstractDocumentAdmin):
|
class InterventionDocumentAdmin(AbstractDocumentAdmin):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ResponsibilityAdmin(admin.ModelAdmin):
|
class ResponsibilityAdmin(admin.ModelAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
"id",
|
"id",
|
||||||
|
@ -7,6 +7,7 @@ Created on: 15.11.21
|
|||||||
"""
|
"""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
@ -18,13 +19,15 @@ from intervention.models.legal import Legal
|
|||||||
from intervention.models.responsibility import Responsibility
|
from intervention.models.responsibility import Responsibility
|
||||||
from intervention.models.revocation import RevocationDocument, Revocation
|
from intervention.models.revocation import RevocationDocument, Revocation
|
||||||
from intervention.utils.quality import InterventionQualityChecker
|
from intervention.utils.quality import InterventionQualityChecker
|
||||||
from konova.models import generate_document_file_upload_path, AbstractDocument, Geometry, BaseObject, ShareableObjectMixin, \
|
from konova.models import generate_document_file_upload_path, AbstractDocument, BaseObject, \
|
||||||
RecordableObjectMixin, CheckableObjectMixin
|
ShareableObjectMixin, \
|
||||||
|
RecordableObjectMixin, CheckableObjectMixin, GeoReferencedMixin
|
||||||
from konova.settings import LANIS_LINK_TEMPLATE, LANIS_ZOOM_LUT, DEFAULT_SRID_RLP
|
from konova.settings import LANIS_LINK_TEMPLATE, LANIS_ZOOM_LUT, DEFAULT_SRID_RLP
|
||||||
|
from konova.utils.message_templates import DATA_UNSHARED_EXPLANATION
|
||||||
from user.models import UserActionLogEntry
|
from user.models import UserActionLogEntry
|
||||||
|
|
||||||
|
|
||||||
class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, CheckableObjectMixin):
|
class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, CheckableObjectMixin, GeoReferencedMixin):
|
||||||
"""
|
"""
|
||||||
Interventions are e.g. construction sites where nature used to be.
|
Interventions are e.g. construction sites where nature used to be.
|
||||||
"""
|
"""
|
||||||
@ -42,7 +45,6 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
|
|||||||
blank=True,
|
blank=True,
|
||||||
help_text="Holds data on legal dates or law"
|
help_text="Holds data on legal dates or law"
|
||||||
)
|
)
|
||||||
geometry = models.ForeignKey(Geometry, null=True, blank=True, on_delete=models.SET_NULL)
|
|
||||||
|
|
||||||
objects = InterventionManager()
|
objects = InterventionManager()
|
||||||
|
|
||||||
@ -263,6 +265,22 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
|
|||||||
if self.checked:
|
if self.checked:
|
||||||
self.set_unchecked()
|
self.set_unchecked()
|
||||||
|
|
||||||
|
def set_status_messages(self, request: HttpRequest):
|
||||||
|
""" Setter for different information that need to be rendered
|
||||||
|
|
||||||
|
Adds messages to the given HttpRequest
|
||||||
|
|
||||||
|
Args:
|
||||||
|
request (HttpRequest): The incoming request
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
request (HttpRequest): The modified request
|
||||||
|
"""
|
||||||
|
if not self.is_shared_with(request.user):
|
||||||
|
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
||||||
|
request = self._set_geometry_conflict_message(request)
|
||||||
|
return request
|
||||||
|
|
||||||
|
|
||||||
class InterventionDocument(AbstractDocument):
|
class InterventionDocument(AbstractDocument):
|
||||||
"""
|
"""
|
||||||
|
@ -255,8 +255,7 @@ def detail_view(request: HttpRequest, id: str):
|
|||||||
"LANIS_LINK": intervention.get_LANIS_link()
|
"LANIS_LINK": intervention.get_LANIS_link()
|
||||||
}
|
}
|
||||||
|
|
||||||
if not is_data_shared:
|
request = intervention.set_status_messages(request)
|
||||||
messages.info(request, DATA_UNSHARED_EXPLANATION)
|
|
||||||
|
|
||||||
context = BaseContext(request, context).context
|
context = BaseContext(request, context).context
|
||||||
return render(request, template, context)
|
return render(request, template, context)
|
||||||
|
@ -7,7 +7,7 @@ Created on: 22.07.21
|
|||||||
"""
|
"""
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from konova.models import Geometry, Deadline
|
from konova.models import Geometry, Deadline, GeometryConflict
|
||||||
|
|
||||||
|
|
||||||
class GeometryAdmin(admin.ModelAdmin):
|
class GeometryAdmin(admin.ModelAdmin):
|
||||||
@ -17,6 +17,14 @@ class GeometryAdmin(admin.ModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryConflictAdmin(admin.ModelAdmin):
|
||||||
|
list_display = [
|
||||||
|
"conflicting_geometry",
|
||||||
|
"affected_geometry",
|
||||||
|
"detected_on",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class AbstractDocumentAdmin(admin.ModelAdmin):
|
class AbstractDocumentAdmin(admin.ModelAdmin):
|
||||||
list_display = [
|
list_display = [
|
||||||
"id",
|
"id",
|
||||||
@ -35,5 +43,14 @@ class DeadlineAdmin(admin.ModelAdmin):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseObjectAdmin(admin.ModelAdmin):
|
||||||
|
readonly_fields = [
|
||||||
|
"modified",
|
||||||
|
"deleted",
|
||||||
|
"created",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
admin.site.register(Geometry, GeometryAdmin)
|
admin.site.register(Geometry, GeometryAdmin)
|
||||||
|
admin.site.register(GeometryConflict, GeometryConflictAdmin)
|
||||||
admin.site.register(Deadline, DeadlineAdmin)
|
admin.site.register(Deadline, DeadlineAdmin)
|
||||||
|
@ -282,11 +282,13 @@ class SimpleGeomForm(BaseForm):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
if self.instance is None or self.instance.geometry is None:
|
||||||
|
raise LookupError
|
||||||
geometry = self.instance.geometry
|
geometry = self.instance.geometry
|
||||||
geometry.geom = self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID))
|
geometry.geom = self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID))
|
||||||
geometry.modified = action
|
geometry.modified = action
|
||||||
geometry.save()
|
geometry.save()
|
||||||
except AttributeError:
|
except LookupError:
|
||||||
# No geometry or linked instance holding a geometry exist --> create a new one!
|
# No geometry or linked instance holding a geometry exist --> create a new one!
|
||||||
geometry = Geometry.objects.create(
|
geometry = Geometry.objects.create(
|
||||||
geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID)),
|
geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID)),
|
||||||
|
@ -208,7 +208,7 @@ class Command(BaseKonovaCommand):
|
|||||||
if num_entries > 0:
|
if num_entries > 0:
|
||||||
self._write_error(f"Found {num_entries} geometries not attached to anything. Delete now...")
|
self._write_error(f"Found {num_entries} geometries not attached to anything. Delete now...")
|
||||||
unattached_geometries.delete()
|
unattached_geometries.delete()
|
||||||
self._write_success("Deadlines deleted.")
|
self._write_success("Geometries deleted.")
|
||||||
else:
|
else:
|
||||||
self._write_success("No unattached geometries found.")
|
self._write_success("No unattached geometries found.")
|
||||||
self._break_line()
|
self._break_line()
|
||||||
|
@ -6,13 +6,110 @@ Created on: 15.11.21
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.contrib.gis.db.models import MultiPolygonField
|
from django.contrib.gis.db.models import MultiPolygonField
|
||||||
|
from django.db import models
|
||||||
|
from django.db.models import Q
|
||||||
|
|
||||||
from konova.models import BaseResource
|
from konova.models import BaseResource, UuidModel
|
||||||
|
|
||||||
|
|
||||||
class Geometry(BaseResource):
|
class Geometry(BaseResource):
|
||||||
"""
|
"""
|
||||||
Outsourced geometry model so multiple versions of the same object can refer to the same geometry if it is not changed
|
Geometry model
|
||||||
"""
|
"""
|
||||||
from konova.settings import DEFAULT_SRID
|
from konova.settings import DEFAULT_SRID
|
||||||
geom = MultiPolygonField(null=True, blank=True, srid=DEFAULT_SRID)
|
geom = MultiPolygonField(null=True, blank=True, srid=DEFAULT_SRID)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
super().save(*args, **kwargs)
|
||||||
|
self.check_for_conflicts()
|
||||||
|
|
||||||
|
def check_for_conflicts(self):
|
||||||
|
""" Checks for new geometry overlaps
|
||||||
|
|
||||||
|
Creates a new GeometryConflict entry for each overlap to another geometry, which has already been there before
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
# If no geometry is given or important data is missing, we can not perform any checks
|
||||||
|
if self.geom is None or (self.created is None and self.modified is None):
|
||||||
|
return None
|
||||||
|
|
||||||
|
self.recheck_existing_conflicts()
|
||||||
|
|
||||||
|
overlapping_geoms = Geometry.objects.filter(
|
||||||
|
geom__intersects=self.geom,
|
||||||
|
).exclude(
|
||||||
|
id=self.id
|
||||||
|
).distinct()
|
||||||
|
|
||||||
|
for match in overlapping_geoms:
|
||||||
|
GeometryConflict.objects.get_or_create(conflicting_geometry=self, affected_geometry=match)
|
||||||
|
|
||||||
|
def recheck_existing_conflicts(self):
|
||||||
|
""" Rechecks GeometryConflict entries
|
||||||
|
|
||||||
|
If a conflict seems to be resolved due to no longer intersection between the two geometries, the entry
|
||||||
|
will be deleted.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
all_conflicts_as_conflicting = self.conflicts_geometries.all()
|
||||||
|
still_conflicting_conflicts = all_conflicts_as_conflicting.filter(
|
||||||
|
affected_geometry__geom__intersects=self.geom
|
||||||
|
)
|
||||||
|
resolved_conflicts = all_conflicts_as_conflicting.exclude(id__in=still_conflicting_conflicts)
|
||||||
|
resolved_conflicts.delete()
|
||||||
|
|
||||||
|
all_conflicted_by_conflicts = self.conflicted_by_geometries.all()
|
||||||
|
still_conflicting_conflicts = all_conflicted_by_conflicts.filter(
|
||||||
|
conflicting_geometry__geom__intersects=self.geom
|
||||||
|
)
|
||||||
|
resolved_conflicts = all_conflicted_by_conflicts.exclude(id__in=still_conflicting_conflicts)
|
||||||
|
resolved_conflicts.delete()
|
||||||
|
|
||||||
|
|
||||||
|
def get_data_objects(self):
|
||||||
|
""" Getter for all objects which are related to this geometry
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
objs (list): The list of objects
|
||||||
|
"""
|
||||||
|
objs = []
|
||||||
|
sets = [
|
||||||
|
self.intervention_set,
|
||||||
|
self.compensation_set,
|
||||||
|
self.ema_set,
|
||||||
|
self.ecoaccount_set,
|
||||||
|
]
|
||||||
|
for _set in sets:
|
||||||
|
set_objs = _set.filter(
|
||||||
|
deleted=None
|
||||||
|
)
|
||||||
|
objs += set_objs
|
||||||
|
return objs
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryConflict(UuidModel):
|
||||||
|
"""
|
||||||
|
Geometry conflicts model
|
||||||
|
|
||||||
|
If a new/edited geometry overlays an existing geometry, there will be a new GeometryConflict on the db
|
||||||
|
"""
|
||||||
|
conflicting_geometry = models.ForeignKey(
|
||||||
|
Geometry,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
help_text="The geometry which came second",
|
||||||
|
related_name="conflicts_geometries"
|
||||||
|
)
|
||||||
|
affected_geometry = models.ForeignKey(
|
||||||
|
Geometry,
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
help_text="The geometry which came first",
|
||||||
|
related_name="conflicted_by_geometries"
|
||||||
|
)
|
||||||
|
detected_on = models.DateTimeField(auto_now_add=True, null=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.conflicting_geometry.id} conflicts with {self.affected_geometry.id}"
|
||||||
|
@ -7,6 +7,7 @@ Created on: 15.11.21
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
@ -20,7 +21,7 @@ from ema.settings import EMA_ACCOUNT_IDENTIFIER_LENGTH, EMA_ACCOUNT_IDENTIFIER_T
|
|||||||
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
|
from intervention.settings import INTERVENTION_IDENTIFIER_LENGTH, INTERVENTION_IDENTIFIER_TEMPLATE
|
||||||
from konova.utils import generators
|
from konova.utils import generators
|
||||||
from konova.utils.generators import generate_random_string
|
from konova.utils.generators import generate_random_string
|
||||||
from konova.utils.message_templates import CHECKED_RECORDED_RESET
|
from konova.utils.message_templates import CHECKED_RECORDED_RESET, GEOMETRY_CONFLICT_WITH_TEMPLATE
|
||||||
from user.models import UserActionLogEntry, UserAction
|
from user.models import UserActionLogEntry, UserAction
|
||||||
|
|
||||||
|
|
||||||
@ -94,6 +95,10 @@ class BaseObject(BaseResource):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def set_status_messages(self, request: HttpRequest):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def mark_as_deleted(self, user: User):
|
def mark_as_deleted(self, user: User):
|
||||||
""" Mark an entry as deleted
|
""" Mark an entry as deleted
|
||||||
|
|
||||||
@ -407,3 +412,29 @@ class ShareableObjectMixin(models.Model):
|
|||||||
id__in=accessing_users
|
id__in=accessing_users
|
||||||
)
|
)
|
||||||
self.share_with_list(users)
|
self.share_with_list(users)
|
||||||
|
|
||||||
|
|
||||||
|
class GeoReferencedMixin(models.Model):
|
||||||
|
geometry = models.ForeignKey("konova.Geometry", null=True, blank=True, on_delete=models.SET_NULL)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
def _set_geometry_conflict_message(self, request: HttpRequest):
|
||||||
|
instance_objs = []
|
||||||
|
add_message = False
|
||||||
|
conflicts = self.geometry.conflicts_geometries.all()
|
||||||
|
for conflict in conflicts:
|
||||||
|
instance_objs += conflict.affected_geometry.get_data_objects()
|
||||||
|
add_message = True
|
||||||
|
conflicts = self.geometry.conflicted_by_geometries.all()
|
||||||
|
for conflict in conflicts:
|
||||||
|
instance_objs += conflict.conflicting_geometry.get_data_objects()
|
||||||
|
add_message = True
|
||||||
|
|
||||||
|
if add_message:
|
||||||
|
instance_identifiers = [x.identifier for x in instance_objs]
|
||||||
|
instance_identifiers = ", ".join(instance_identifiers)
|
||||||
|
message_str = GEOMETRY_CONFLICT_WITH_TEMPLATE.format(instance_identifiers)
|
||||||
|
messages.info(request, message_str)
|
||||||
|
return request
|
||||||
|
49
konova/tests/test_geometries.py
Normal file
49
konova/tests/test_geometries.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||||
|
Created on: 15.12.21
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django.contrib.gis.db.models.functions import Translate
|
||||||
|
|
||||||
|
from konova.models import Geometry, GeometryConflict
|
||||||
|
from konova.tests.test_views import BaseTestCase
|
||||||
|
from user.models import UserActionLogEntry
|
||||||
|
|
||||||
|
|
||||||
|
class GeometryTestCase(BaseTestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
super().setUpTestData()
|
||||||
|
geom = cls.create_dummy_geometry()
|
||||||
|
action = UserActionLogEntry.get_created_action(cls.superuser)
|
||||||
|
cls.geom_1 = Geometry.objects.create(
|
||||||
|
geom=geom,
|
||||||
|
created=action,
|
||||||
|
)
|
||||||
|
cls.geom_2 = Geometry.objects.create(
|
||||||
|
geom=geom,
|
||||||
|
created=action,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_geometry_conflict(self):
|
||||||
|
""" Tests whether a geometry conflict will be present in case of identical/overlaying geometries and
|
||||||
|
if the conflict will be resolved if one geometry is edited.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.geom_1.check_for_conflicts()
|
||||||
|
conflict = GeometryConflict.objects.all().first()
|
||||||
|
self.assertEqual(conflict.conflicting_geometry, self.geom_2)
|
||||||
|
self.assertEqual(conflict.affected_geometry, self.geom_1)
|
||||||
|
|
||||||
|
# Move geom_2 somewhere else, expect the conflict to be resolved
|
||||||
|
Geometry.objects.filter(id=self.geom_2.id).update(
|
||||||
|
geom=Translate('geom', 100000, 100000)
|
||||||
|
)
|
||||||
|
self.geom_2.refresh_from_db()
|
||||||
|
self.geom_1.check_for_conflicts()
|
||||||
|
num_conflict = GeometryConflict.objects.all().count()
|
||||||
|
self.assertEqual(0, num_conflict)
|
@ -26,3 +26,6 @@ EDITED_GENERAL_DATA = _("Edited general data")
|
|||||||
ADDED_COMPENSATION_STATE = _("Added compensation state")
|
ADDED_COMPENSATION_STATE = _("Added compensation state")
|
||||||
ADDED_DEADLINE = _("Added deadline")
|
ADDED_DEADLINE = _("Added deadline")
|
||||||
ADDED_COMPENSATION_ACTION = _("Added compensation action")
|
ADDED_COMPENSATION_ACTION = _("Added compensation action")
|
||||||
|
|
||||||
|
# Geometry conflicts
|
||||||
|
GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}")
|
||||||
|
Binary file not shown.
@ -11,15 +11,15 @@
|
|||||||
#: intervention/forms/forms.py:52 intervention/forms/forms.py:154
|
#: intervention/forms/forms.py:52 intervention/forms/forms.py:154
|
||||||
#: intervention/forms/forms.py:166 intervention/forms/modalForms.py:125
|
#: intervention/forms/forms.py:166 intervention/forms/modalForms.py:125
|
||||||
#: intervention/forms/modalForms.py:138 intervention/forms/modalForms.py:151
|
#: intervention/forms/modalForms.py:138 intervention/forms/modalForms.py:151
|
||||||
#: konova/forms.py:139 konova/forms.py:240 konova/forms.py:306
|
#: konova/forms.py:139 konova/forms.py:240 konova/forms.py:308
|
||||||
#: konova/forms.py:333 konova/forms.py:343 konova/forms.py:356
|
#: konova/forms.py:335 konova/forms.py:345 konova/forms.py:358
|
||||||
#: konova/forms.py:368 konova/forms.py:386 user/forms.py:38
|
#: konova/forms.py:370 konova/forms.py:388 user/forms.py:38
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2021-12-09 12:36+0100\n"
|
"POT-Creation-Date: 2021-12-16 09:17+0100\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -329,7 +329,7 @@ msgstr "Automatisch generiert"
|
|||||||
#: intervention/templates/intervention/detail/includes/documents.html:28
|
#: intervention/templates/intervention/detail/includes/documents.html:28
|
||||||
#: intervention/templates/intervention/detail/view.html:31
|
#: intervention/templates/intervention/detail/view.html:31
|
||||||
#: intervention/templates/intervention/report/report.html:12
|
#: intervention/templates/intervention/report/report.html:12
|
||||||
#: konova/forms.py:332
|
#: konova/forms.py:334
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr "Bezeichnung"
|
msgstr "Bezeichnung"
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ msgstr "Kompensation XY; Flur ABC"
|
|||||||
#: intervention/templates/intervention/detail/includes/documents.html:31
|
#: intervention/templates/intervention/detail/includes/documents.html:31
|
||||||
#: intervention/templates/intervention/detail/includes/payments.html:34
|
#: intervention/templates/intervention/detail/includes/payments.html:34
|
||||||
#: intervention/templates/intervention/detail/includes/revocation.html:38
|
#: intervention/templates/intervention/detail/includes/revocation.html:38
|
||||||
#: konova/forms.py:367 konova/templates/konova/comment_card.html:16
|
#: konova/forms.py:369 konova/templates/konova/comment_card.html:16
|
||||||
msgid "Comment"
|
msgid "Comment"
|
||||||
msgstr "Kommentar"
|
msgstr "Kommentar"
|
||||||
|
|
||||||
@ -472,7 +472,7 @@ msgstr "Zahlung wird an diesem Datum erwartet"
|
|||||||
|
|
||||||
#: compensation/forms/modalForms.py:62 compensation/forms/modalForms.py:239
|
#: compensation/forms/modalForms.py:62 compensation/forms/modalForms.py:239
|
||||||
#: compensation/forms/modalForms.py:317 intervention/forms/modalForms.py:152
|
#: compensation/forms/modalForms.py:317 intervention/forms/modalForms.py:152
|
||||||
#: konova/forms.py:369
|
#: konova/forms.py:371
|
||||||
msgid "Additional comment, maximum {} letters"
|
msgid "Additional comment, maximum {} letters"
|
||||||
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
|
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
|
||||||
|
|
||||||
@ -614,7 +614,7 @@ msgstr ""
|
|||||||
msgid "Pieces"
|
msgid "Pieces"
|
||||||
msgstr "Stück"
|
msgstr "Stück"
|
||||||
|
|
||||||
#: compensation/models/compensation.py:62 konova/utils/message_templates.py:27
|
#: compensation/models/compensation.py:63 konova/utils/message_templates.py:27
|
||||||
msgid "Added deadline"
|
msgid "Added deadline"
|
||||||
msgstr "Frist/Termin hinzugefügt"
|
msgstr "Frist/Termin hinzugefügt"
|
||||||
|
|
||||||
@ -793,7 +793,7 @@ msgstr "Dokumente"
|
|||||||
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:14
|
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:14
|
||||||
#: ema/templates/ema/detail/includes/documents.html:14
|
#: ema/templates/ema/detail/includes/documents.html:14
|
||||||
#: intervention/templates/intervention/detail/includes/documents.html:14
|
#: intervention/templates/intervention/detail/includes/documents.html:14
|
||||||
#: konova/forms.py:385
|
#: konova/forms.py:387
|
||||||
msgid "Add new document"
|
msgid "Add new document"
|
||||||
msgstr "Neues Dokument hinzufügen"
|
msgstr "Neues Dokument hinzufügen"
|
||||||
|
|
||||||
@ -1056,42 +1056,42 @@ msgstr "Kompensation {} hinzugefügt"
|
|||||||
msgid "Compensation {} edited"
|
msgid "Compensation {} edited"
|
||||||
msgstr "Kompensation {} bearbeitet"
|
msgstr "Kompensation {} bearbeitet"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:229 compensation/views/eco_account.py:308
|
#: compensation/views/compensation.py:228 compensation/views/eco_account.py:307
|
||||||
#: ema/views.py:182 intervention/views.py:475
|
#: ema/views.py:181 intervention/views.py:474
|
||||||
msgid "Log"
|
msgid "Log"
|
||||||
msgstr "Log"
|
msgstr "Log"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:252
|
#: compensation/views/compensation.py:251
|
||||||
msgid "Compensation removed"
|
msgid "Compensation removed"
|
||||||
msgstr "Kompensation entfernt"
|
msgstr "Kompensation entfernt"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:273 compensation/views/eco_account.py:460
|
#: compensation/views/compensation.py:272 compensation/views/eco_account.py:459
|
||||||
#: ema/views.py:349 intervention/views.py:129
|
#: ema/views.py:348 intervention/views.py:129
|
||||||
msgid "Document added"
|
msgid "Document added"
|
||||||
msgstr "Dokument hinzugefügt"
|
msgstr "Dokument hinzugefügt"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:342 compensation/views/eco_account.py:354
|
#: compensation/views/compensation.py:341 compensation/views/eco_account.py:353
|
||||||
#: ema/views.py:287
|
#: ema/views.py:286
|
||||||
msgid "State added"
|
msgid "State added"
|
||||||
msgstr "Zustand hinzugefügt"
|
msgstr "Zustand hinzugefügt"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:363 compensation/views/eco_account.py:375
|
#: compensation/views/compensation.py:362 compensation/views/eco_account.py:374
|
||||||
#: ema/views.py:308
|
#: ema/views.py:307
|
||||||
msgid "Action added"
|
msgid "Action added"
|
||||||
msgstr "Maßnahme hinzugefügt"
|
msgstr "Maßnahme hinzugefügt"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:384 compensation/views/eco_account.py:440
|
#: compensation/views/compensation.py:383 compensation/views/eco_account.py:439
|
||||||
#: ema/views.py:329
|
#: ema/views.py:328
|
||||||
msgid "Deadline added"
|
msgid "Deadline added"
|
||||||
msgstr "Frist/Termin hinzugefügt"
|
msgstr "Frist/Termin hinzugefügt"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:406 compensation/views/eco_account.py:397
|
#: compensation/views/compensation.py:405 compensation/views/eco_account.py:396
|
||||||
#: ema/views.py:419
|
#: ema/views.py:418
|
||||||
msgid "State removed"
|
msgid "State removed"
|
||||||
msgstr "Zustand gelöscht"
|
msgstr "Zustand gelöscht"
|
||||||
|
|
||||||
#: compensation/views/compensation.py:428 compensation/views/eco_account.py:419
|
#: compensation/views/compensation.py:427 compensation/views/eco_account.py:418
|
||||||
#: ema/views.py:441
|
#: ema/views.py:440
|
||||||
msgid "Action removed"
|
msgid "Action removed"
|
||||||
msgstr "Maßnahme entfernt"
|
msgstr "Maßnahme entfernt"
|
||||||
|
|
||||||
@ -1103,45 +1103,45 @@ msgstr "Ökokonto {} hinzugefügt"
|
|||||||
msgid "Eco-Account {} edited"
|
msgid "Eco-Account {} edited"
|
||||||
msgstr "Ökokonto {} bearbeitet"
|
msgstr "Ökokonto {} bearbeitet"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:256
|
#: compensation/views/eco_account.py:255
|
||||||
msgid "Eco-account removed"
|
msgid "Eco-account removed"
|
||||||
msgstr "Ökokonto entfernt"
|
msgstr "Ökokonto entfernt"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:284
|
#: compensation/views/eco_account.py:283
|
||||||
msgid "Deduction removed"
|
msgid "Deduction removed"
|
||||||
msgstr "Abbuchung entfernt"
|
msgstr "Abbuchung entfernt"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:329 ema/views.py:262
|
#: compensation/views/eco_account.py:328 ema/views.py:261
|
||||||
#: intervention/views.py:517
|
#: intervention/views.py:516
|
||||||
msgid "{} unrecorded"
|
msgid "{} unrecorded"
|
||||||
msgstr "{} entzeichnet"
|
msgstr "{} entzeichnet"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:329 ema/views.py:262
|
#: compensation/views/eco_account.py:328 ema/views.py:261
|
||||||
#: intervention/views.py:517
|
#: intervention/views.py:516
|
||||||
msgid "{} recorded"
|
msgid "{} recorded"
|
||||||
msgstr "{} verzeichnet"
|
msgstr "{} verzeichnet"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:530 intervention/views.py:498
|
#: compensation/views/eco_account.py:529 intervention/views.py:497
|
||||||
msgid "Deduction added"
|
msgid "Deduction added"
|
||||||
msgstr "Abbuchung hinzugefügt"
|
msgstr "Abbuchung hinzugefügt"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:613 ema/views.py:517
|
#: compensation/views/eco_account.py:612 ema/views.py:516
|
||||||
#: intervention/views.py:373
|
#: intervention/views.py:372
|
||||||
msgid "{} has already been shared with you"
|
msgid "{} has already been shared with you"
|
||||||
msgstr "{} wurde bereits für Sie freigegeben"
|
msgstr "{} wurde bereits für Sie freigegeben"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:618 ema/views.py:522
|
#: compensation/views/eco_account.py:617 ema/views.py:521
|
||||||
#: intervention/views.py:378
|
#: intervention/views.py:377
|
||||||
msgid "{} has been shared with you"
|
msgid "{} has been shared with you"
|
||||||
msgstr "{} ist nun für Sie freigegeben"
|
msgstr "{} ist nun für Sie freigegeben"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:625 ema/views.py:529
|
#: compensation/views/eco_account.py:624 ema/views.py:528
|
||||||
#: intervention/views.py:385
|
#: intervention/views.py:384
|
||||||
msgid "Share link invalid"
|
msgid "Share link invalid"
|
||||||
msgstr "Freigabelink ungültig"
|
msgstr "Freigabelink ungültig"
|
||||||
|
|
||||||
#: compensation/views/eco_account.py:648 ema/views.py:552
|
#: compensation/views/eco_account.py:647 ema/views.py:551
|
||||||
#: intervention/views.py:408
|
#: intervention/views.py:407
|
||||||
msgid "Share settings updated"
|
msgid "Share settings updated"
|
||||||
msgstr "Freigabe Einstellungen aktualisiert"
|
msgstr "Freigabe Einstellungen aktualisiert"
|
||||||
|
|
||||||
@ -1185,11 +1185,11 @@ msgstr "Ersatzzahlungsmaßnahme"
|
|||||||
msgid "EMA {} added"
|
msgid "EMA {} added"
|
||||||
msgstr "EMA {} hinzugefügt"
|
msgstr "EMA {} hinzugefügt"
|
||||||
|
|
||||||
#: ema/views.py:211
|
#: ema/views.py:210
|
||||||
msgid "EMA {} edited"
|
msgid "EMA {} edited"
|
||||||
msgstr "EMA {} bearbeitet"
|
msgstr "EMA {} bearbeitet"
|
||||||
|
|
||||||
#: ema/views.py:243
|
#: ema/views.py:242
|
||||||
msgid "EMA removed"
|
msgid "EMA removed"
|
||||||
msgstr "EMA entfernt"
|
msgstr "EMA entfernt"
|
||||||
|
|
||||||
@ -1333,7 +1333,7 @@ msgstr "Kompensationen und Zahlungen geprüft"
|
|||||||
msgid "Run check"
|
msgid "Run check"
|
||||||
msgstr "Prüfung vornehmen"
|
msgstr "Prüfung vornehmen"
|
||||||
|
|
||||||
#: intervention/forms/modalForms.py:196 konova/forms.py:451
|
#: intervention/forms/modalForms.py:196 konova/forms.py:453
|
||||||
msgid ""
|
msgid ""
|
||||||
"I, {} {}, confirm that all necessary control steps have been performed by "
|
"I, {} {}, confirm that all necessary control steps have been performed by "
|
||||||
"myself."
|
"myself."
|
||||||
@ -1476,27 +1476,27 @@ msgstr "Eingriff {} hinzugefügt"
|
|||||||
msgid "This intervention has {} revocations"
|
msgid "This intervention has {} revocations"
|
||||||
msgstr "Dem Eingriff liegen {} Widersprüche vor"
|
msgstr "Dem Eingriff liegen {} Widersprüche vor"
|
||||||
|
|
||||||
#: intervention/views.py:291
|
#: intervention/views.py:290
|
||||||
msgid "Intervention {} edited"
|
msgid "Intervention {} edited"
|
||||||
msgstr "Eingriff {} bearbeitet"
|
msgstr "Eingriff {} bearbeitet"
|
||||||
|
|
||||||
#: intervention/views.py:326
|
#: intervention/views.py:325
|
||||||
msgid "{} removed"
|
msgid "{} removed"
|
||||||
msgstr "{} entfernt"
|
msgstr "{} entfernt"
|
||||||
|
|
||||||
#: intervention/views.py:347
|
#: intervention/views.py:346
|
||||||
msgid "Revocation removed"
|
msgid "Revocation removed"
|
||||||
msgstr "Widerspruch entfernt"
|
msgstr "Widerspruch entfernt"
|
||||||
|
|
||||||
#: intervention/views.py:429
|
#: intervention/views.py:428
|
||||||
msgid "Check performed"
|
msgid "Check performed"
|
||||||
msgstr "Prüfung durchgeführt"
|
msgstr "Prüfung durchgeführt"
|
||||||
|
|
||||||
#: intervention/views.py:451
|
#: intervention/views.py:450
|
||||||
msgid "Revocation added"
|
msgid "Revocation added"
|
||||||
msgstr "Widerspruch hinzugefügt"
|
msgstr "Widerspruch hinzugefügt"
|
||||||
|
|
||||||
#: intervention/views.py:522
|
#: intervention/views.py:521
|
||||||
msgid "There are errors on this intervention:"
|
msgid "There are errors on this intervention:"
|
||||||
msgstr "Es liegen Fehler in diesem Eingriff vor:"
|
msgstr "Es liegen Fehler in diesem Eingriff vor:"
|
||||||
|
|
||||||
@ -1525,11 +1525,11 @@ msgstr "Speichern"
|
|||||||
msgid "Not editable"
|
msgid "Not editable"
|
||||||
msgstr "Nicht editierbar"
|
msgstr "Nicht editierbar"
|
||||||
|
|
||||||
#: konova/forms.py:138 konova/forms.py:305
|
#: konova/forms.py:138 konova/forms.py:307
|
||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr "Bestätige"
|
msgstr "Bestätige"
|
||||||
|
|
||||||
#: konova/forms.py:150 konova/forms.py:314
|
#: konova/forms.py:150 konova/forms.py:316
|
||||||
msgid "Remove"
|
msgid "Remove"
|
||||||
msgstr "Löschen"
|
msgstr "Löschen"
|
||||||
|
|
||||||
@ -1542,56 +1542,56 @@ msgstr "Sie sind dabei {} {} zu löschen"
|
|||||||
msgid "Geometry"
|
msgid "Geometry"
|
||||||
msgstr "Geometrie"
|
msgstr "Geometrie"
|
||||||
|
|
||||||
#: konova/forms.py:315
|
#: konova/forms.py:317
|
||||||
msgid "Are you sure?"
|
msgid "Are you sure?"
|
||||||
msgstr "Sind Sie sicher?"
|
msgstr "Sind Sie sicher?"
|
||||||
|
|
||||||
#: konova/forms.py:342
|
#: konova/forms.py:344
|
||||||
msgid "Created on"
|
msgid "Created on"
|
||||||
msgstr "Erstellt"
|
msgstr "Erstellt"
|
||||||
|
|
||||||
#: konova/forms.py:344
|
#: konova/forms.py:346
|
||||||
msgid "When has this file been created? Important for photos."
|
msgid "When has this file been created? Important for photos."
|
||||||
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
|
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
|
||||||
|
|
||||||
#: konova/forms.py:355
|
#: konova/forms.py:357
|
||||||
#: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231
|
#: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231
|
||||||
msgid "File"
|
msgid "File"
|
||||||
msgstr "Datei"
|
msgstr "Datei"
|
||||||
|
|
||||||
#: konova/forms.py:357
|
#: konova/forms.py:359
|
||||||
msgid "Allowed formats: pdf, jpg, png. Max size 15 MB."
|
msgid "Allowed formats: pdf, jpg, png. Max size 15 MB."
|
||||||
msgstr "Formate: pdf, jpg, png. Maximal 15 MB."
|
msgstr "Formate: pdf, jpg, png. Maximal 15 MB."
|
||||||
|
|
||||||
#: konova/forms.py:403
|
#: konova/forms.py:405
|
||||||
msgid "Unsupported file type"
|
msgid "Unsupported file type"
|
||||||
msgstr "Dateiformat nicht unterstützt"
|
msgstr "Dateiformat nicht unterstützt"
|
||||||
|
|
||||||
#: konova/forms.py:410
|
#: konova/forms.py:412
|
||||||
msgid "File too large"
|
msgid "File too large"
|
||||||
msgstr "Datei zu groß"
|
msgstr "Datei zu groß"
|
||||||
|
|
||||||
#: konova/forms.py:419
|
#: konova/forms.py:421
|
||||||
msgid "Added document"
|
msgid "Added document"
|
||||||
msgstr "Dokument hinzugefügt"
|
msgstr "Dokument hinzugefügt"
|
||||||
|
|
||||||
#: konova/forms.py:442
|
#: konova/forms.py:444
|
||||||
msgid "Confirm record"
|
msgid "Confirm record"
|
||||||
msgstr "Verzeichnen bestätigen"
|
msgstr "Verzeichnen bestätigen"
|
||||||
|
|
||||||
#: konova/forms.py:450
|
#: konova/forms.py:452
|
||||||
msgid "Record data"
|
msgid "Record data"
|
||||||
msgstr "Daten verzeichnen"
|
msgstr "Daten verzeichnen"
|
||||||
|
|
||||||
#: konova/forms.py:457
|
#: konova/forms.py:459
|
||||||
msgid "Confirm unrecord"
|
msgid "Confirm unrecord"
|
||||||
msgstr "Entzeichnen bestätigen"
|
msgstr "Entzeichnen bestätigen"
|
||||||
|
|
||||||
#: konova/forms.py:458
|
#: konova/forms.py:460
|
||||||
msgid "Unrecord data"
|
msgid "Unrecord data"
|
||||||
msgstr "Daten entzeichnen"
|
msgstr "Daten entzeichnen"
|
||||||
|
|
||||||
#: konova/forms.py:459
|
#: konova/forms.py:461
|
||||||
msgid "I, {} {}, confirm that this data must be unrecorded."
|
msgid "I, {} {}, confirm that this data must be unrecorded."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
|
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
|
||||||
@ -1726,6 +1726,8 @@ msgid ""
|
|||||||
"Action canceled. Eco account is recorded or deductions exist. Only "
|
"Action canceled. Eco account is recorded or deductions exist. Only "
|
||||||
"conservation office member can perform this action."
|
"conservation office member can perform this action."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Aktion abgebrochen. Ökokonto ist bereits verzeichnet oder Abbuchungen liegen vor. Nur "
|
||||||
|
"Eintragungsstellennutzer können diese Aktion jetzt durchführen."
|
||||||
|
|
||||||
#: konova/utils/message_templates.py:25
|
#: konova/utils/message_templates.py:25
|
||||||
msgid "Edited general data"
|
msgid "Edited general data"
|
||||||
@ -1739,6 +1741,10 @@ msgstr "Zustand hinzugefügt"
|
|||||||
msgid "Added compensation action"
|
msgid "Added compensation action"
|
||||||
msgstr "Maßnahme hinzufügen"
|
msgstr "Maßnahme hinzufügen"
|
||||||
|
|
||||||
|
#: konova/utils/message_templates.py:31
|
||||||
|
msgid "Geometry conflict detected with {}"
|
||||||
|
msgstr "Geometriekonflikt mit folgenden Einträgen erkannt: {}"
|
||||||
|
|
||||||
#: konova/utils/messenger.py:69
|
#: konova/utils/messenger.py:69
|
||||||
msgid "{} checked"
|
msgid "{} checked"
|
||||||
msgstr "{} geprüft"
|
msgstr "{} geprüft"
|
||||||
|
Loading…
Reference in New Issue
Block a user