Merge branch 'master' into 132_Old_entries

# Conflicts:
#	intervention/utils/egon_export.py
This commit is contained in:
mpeltriaux 2022-12-16 07:56:07 +01:00
commit 34ab63e903
65 changed files with 442 additions and 138 deletions

View File

@ -104,9 +104,9 @@ class TimespanReport:
"iterable": self.evaluated_laws,
"attrs": [
"short_name",
"num",
"num_checked",
"num_recorded",
"num",
]
},
"i_laws_checked": self.law_sum_checked,

View File

@ -64,6 +64,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
obj = Compensation()
created = create_action
obj.created = created
obj.modified = created
obj.geometry = geometry
return obj

View File

@ -103,6 +103,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
obj.legal = Legal()
created = create_action
obj.created = created
obj.modified = created
obj.geometry = geometry
return obj

View File

@ -85,6 +85,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
)
created = create_action
obj.created = created
obj.modified = created
obj.geometry = geometry
return obj

View File

@ -76,6 +76,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
created = create_action
obj.legal = legal
obj.created = created
obj.modified = created
obj.geometry = geometry
obj.responsible = resp
return obj
@ -132,7 +133,6 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
id__in=payments
)
obj.payments.set(payments)
obj.send_data_to_egon()
return obj
def create_model_from_json(self, json_model, user):
@ -200,6 +200,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
obj.save()
obj.mark_as_edited(user, edit_comment="API update")
obj.send_data_to_egon()
celery_update_parcels.delay(obj.geometry.id)

View File

@ -30,11 +30,12 @@ class AbstractCompensationForm(BaseForm):
label=_("Identifier"),
label_suffix="",
max_length=255,
help_text=_("Generated automatically"),
help_text=_("Generated automatically - not editable"),
widget=GenerateInput(
attrs={
"class": "form-control",
"url": None, # Needs to be set in inheriting constructors
"readonly": True,
}
)
)
@ -156,6 +157,7 @@ class NewCompensationForm(AbstractCompensationForm,
title=title,
intervention=intervention,
created=action,
modified=action,
is_cef=is_cef,
is_coherence_keeping=is_coherence_keeping,
is_pik=is_pik,

View File

@ -117,6 +117,7 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
responsible=responsible,
deductable_surface=surface,
created=action,
modified=action,
comment=comment,
is_pik=is_pik,
legal=legal

View File

@ -21,7 +21,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing finished deadline ' %}
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m²
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m²
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing finished deadline ' %}
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m²
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m²
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -71,6 +71,7 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(new_compensation.title, test_title)
self.assert_equal_geometries(new_compensation.geometry.geom, test_geom)
self.assertEqual(new_compensation.log.count(), 1)
self.assertEqual(new_compensation.created, new_compensation.modified)
# Expect logs to be set
self.assertEqual(pre_creation_intervention_log_count + 1, self.intervention.log.count())

View File

@ -65,6 +65,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(acc.deductable_rest, test_deductable_surface)
self.assert_equal_geometries(acc.geometry.geom, test_geom)
self.assertEqual(acc.log.count(), 1)
self.assertEqual(acc.created, acc.modified)
# Expect logs to be set
self.assertEqual(acc.log.count(), 1)

View File

@ -46,6 +46,8 @@ def index_view(request: HttpRequest):
compensations = Compensation.objects.filter(
deleted=None, # only show those which are not deleted individually
intervention__deleted=None, # and don't show the ones whose intervention has been deleted
).order_by(
"-modified__timestamp"
)
table = CompensationTable(
request=request,
@ -201,7 +203,12 @@ def detail_view(request: HttpRequest, id: str):
"""
template = "compensation/detail/compensation/view.html"
comp = get_object_or_404(Compensation, id=id)
comp = get_object_or_404(
Compensation,
id=id,
deleted=None,
intervention__deleted=None,
)
geom_form = SimpleGeomForm(instance=comp)
parcels = comp.get_underlying_parcels()
_user = request.user

View File

@ -73,6 +73,7 @@ def report_view(request: HttpRequest, id: str):
"geom_form": geom_form,
"parcels": parcels,
"actions": actions,
"tables_scrollable": False,
TAB_TITLE_IDENTIFIER: tab_title,
}
context = BaseContext(request, context).context

View File

@ -41,6 +41,8 @@ def index_view(request: HttpRequest):
template = "generic_index.html"
eco_accounts = EcoAccount.objects.filter(
deleted=None,
).order_by(
"-modified__timestamp"
)
table = EcoAccountTable(
request=request,
@ -182,7 +184,8 @@ def detail_view(request: HttpRequest, id: str):
'geometry',
'responsible',
),
id=id
id=id,
deleted=None,
)
geom_form = SimpleGeomForm(instance=acc)
parcels = acc.get_underlying_parcels()

View File

@ -80,6 +80,7 @@ def report_view(request: HttpRequest, id: str):
"parcels": parcels,
"actions": actions,
"deductions": deductions,
"tables_scrollable": False,
TAB_TITLE_IDENTIFIER: tab_title,
}
context = BaseContext(request, context).context

View File

@ -81,6 +81,7 @@ class NewEmaForm(AbstractCompensationForm, CompensationResponsibleFormMixin, Pik
title=title,
responsible=responsible,
created=action,
modified=action,
comment=comment,
is_pik=is_pik,
)

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing finished deadline ' %}
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing surfaces according to states before: ' %}{{ diff_states|floatformat:2 }} m²
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'Missing surfaces according to states after: ' %}{{ diff_states|floatformat:2 }} m²
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -62,6 +62,7 @@ class EmaWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(ema.title, test_title)
self.assert_equal_geometries(ema.geometry.geom, test_geom)
self.assertEqual(ema.log.count(), 1)
self.assertEqual(ema.created, ema.modified)
# Expect logs to be set
self.assertEqual(ema.log.count(), 1)

View File

@ -39,6 +39,8 @@ def index_view(request: HttpRequest):
template = "generic_index.html"
emas = Ema.objects.filter(
deleted=None,
).order_by(
"-modified__timestamp"
)
table = EmaTable(

View File

@ -73,6 +73,7 @@ def report_view(request:HttpRequest, id: str):
"geom_form": geom_form,
"parcels": parcels,
"actions": actions,
"tables_scrollable": False,
TAB_TITLE_IDENTIFIER: tab_title,
}
context = BaseContext(request, context).context

View File

@ -29,11 +29,12 @@ class NewInterventionForm(BaseForm):
label=_("Identifier"),
label_suffix="",
max_length=255,
help_text=_("Generated automatically"),
help_text=_("Generated automatically - not editable"),
widget=GenerateInput(
attrs={
"class": "form-control",
"url": reverse_lazy("intervention:new-id"),
"readonly": True,
}
)
)
@ -270,6 +271,7 @@ class NewInterventionForm(BaseForm):
responsible=responsibility_data,
legal=legal_data,
created=action,
modified=action,
comment=comment,
)
@ -384,6 +386,7 @@ class EditInterventionForm(NewInterventionForm):
geometry = geom_form.save(user_action)
self.instance.geometry = geometry
self.instance.save()
self.instance.send_data_to_egon()
return self.instance

View File

@ -25,8 +25,6 @@ class NewInterventionDocumentModalForm(NewDocumentModalForm):
"""
doc = super().save(*args, **kwargs)
if self.instance.payments.exists():
self.instance.send_data_to_egon()
return doc

View File

@ -145,11 +145,13 @@ class Intervention(BaseObject,
Returns:
"""
if self.payments.exists():
celery_export_to_egon.delay(self.id)
def set_recorded(self, user: User) -> UserActionLogEntry:
log_entry = super().set_recorded(user)
self.add_log_entry_to_compensations(log_entry)
self.send_data_to_egon()
return log_entry
def add_log_entry_to_compensations(self, log_entry: UserActionLogEntry):

View File

@ -22,7 +22,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -25,7 +25,7 @@
{% trans 'You entered a payment. Please upload the legal document which defines the payment`s amount.' %}
</div>
{% endif %}
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -23,7 +23,7 @@
</div>
</div>
</div>
<div class="card-body scroll-300 p-2">
<div class="card-body {% if tables_scrollable %}scroll-300{% endif %} p-2">
<table class="table table-hover">
<thead>
<tr>

View File

@ -62,6 +62,8 @@
{{deduction.account.identifier}} - {{deduction.account.title}}
</a>
<br>
{% empty %}
{% trans 'None' %}
{% endfor %}
</td>
</tr>
@ -101,7 +103,7 @@
<div class="row">
{% include 'konova/includes/parcels/parcels.html' %}
</div>
<div class="row">
<div class="row qrcodes">
{% include 'konova/includes/report/qrcodes.html' %}
</div>

View File

@ -78,6 +78,7 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(1, obj.log.count())
self.assertEqual(obj.log.first().action, UserAction.CREATED)
self.assertEqual(obj.log.first().user, self.superuser)
self.assertEqual(obj.created, obj.modified)
except ObjectDoesNotExist:
# Fail if there is no such object
self.fail()

View File

@ -11,7 +11,7 @@ import json
import pika
import xmltodict
from django.db.models import Sum
from django.utils import formats, timezone
from django.utils import formats
from intervention.settings import EGON_RABBITMQ_HOST, EGON_RABBITMQ_USER, EGON_RABBITMQ_PW, EGON_RABBITMQ_PORT
from konova.sub_settings.django_settings import DEFAULT_DATE_FORMAT
@ -43,6 +43,7 @@ class EgonExporter:
"nachricht": self.gml_builder.gml,
}
msg = json.dumps(msg)
print(msg)
credentials = pika.PlainCredentials(EGON_RABBITMQ_USER, EGON_RABBITMQ_PW)
params = pika.ConnectionParameters(
EGON_RABBITMQ_HOST,
@ -67,6 +68,7 @@ class EgonGmlBuilder:
"""
intervention = None
gml = None
_PAYMENT_FALLBACK_DATE = ""
def __init__(self, intervention):
self.intervention = intervention
@ -164,9 +166,10 @@ class EgonGmlBuilder:
payment_date = None
if payment is not None:
payment_date = payment.due_on
if payment_date is None:
payment_date = timezone.datetime.fromisoformat("1970-01-01")
if payment_date is not None:
payment_date = payment_date.strftime(DEFAULT_DATE_FORMAT)
else:
payment_date = self._PAYMENT_FALLBACK_DATE
cons_office = self.intervention.responsible.conservation_office
reg_office = self.intervention.responsible.registration_office
@ -188,14 +191,14 @@ class EgonGmlBuilder:
"@gml:id": self.intervention.identifier,
"oneo:azEintragungsstelle": self.intervention.responsible.conservation_file_number,
"oneo:azZulassungsstelle": self.intervention.responsible.registration_file_number,
"oneo:bemerkungZulassungsstelle": None,
"oneo:bemerkungZulassungsstelle": "",
"oneo:eintragungsstelle": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/907/{cons_office.atom_id if cons_office else None}",
"#text": cons_office.long_name if cons_office else None
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/907/{cons_office.atom_id if cons_office else ''}",
"#text": cons_office.long_name if cons_office else ""
},
"oneo:zulassungsstelle": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{reg_office.atom_id if reg_office else None}",
"#text": reg_office.long_name if reg_office else None
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{reg_office.atom_id if reg_office else ''}",
"#text": reg_office.long_name if reg_office else ""
},
"oneo:ersatzzahlung": self._float_to_localized_string(self._sum_all_payments()),
"oneo:kompensationsart": {
@ -203,33 +206,33 @@ class EgonGmlBuilder:
"#text": comp_type
},
"oneo:verfahrensrecht": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1048/{law.atom_id if law else None}",
"#text": law.short_name if law else None
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1048/{law.atom_id if law else ''}",
"#text": law.short_name if law else ""
},
"oneo:verfahrenstyp": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/44382/{process_type.atom_id if process_type else None}",
"#text": process_type.long_name if process_type else None,
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/44382/{process_type.atom_id if process_type else ''}",
"#text": process_type.long_name if process_type else "",
},
"oneo:eingreifer": {
"oneo:Eingreifer": {
"oneo:art": {
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{handler.type.atom_id if handler.type else None}",
"#text": handler.type.long_name if handler.type else None,
"@xlink:href": f"http://register.naturschutz.rlp.de/repository/services/referenzliste/1053/{handler.type.atom_id if handler.type else ''}",
"#text": handler.type.long_name if handler.type else "",
},
"oneo:bemerkung": handler.detail if handler else None,
"oneo:bemerkung": handler.detail if handler else "",
}
},
"oneo:erfasser": {
"oneo:Erfasser": {
"oneo:name": None,
"oneo:bemerkung": None,
"oneo:name": "",
"oneo:bemerkung": "",
}
},
"oneo:zulassung": {
"oneo:Zulassungstermin": {
"oneo:bauBeginn": payment_date,
"oneo:erlass": reg_date.strftime(DEFAULT_DATE_FORMAT) if reg_date else None,
"oneo:rechtsKraft": bind_date.strftime(DEFAULT_DATE_FORMAT) if bind_date else None,
"oneo:erlass": reg_date.strftime(DEFAULT_DATE_FORMAT) if reg_date else "",
"oneo:rechtsKraft": bind_date.strftime(DEFAULT_DATE_FORMAT) if bind_date else "",
}
},
"oneo:geometrie": {
@ -243,8 +246,8 @@ class EgonGmlBuilder:
"oneo:kennung": self.intervention.identifier,
"oneo:bezeichnung": self.intervention.title,
"oneo:bemerkung": self.intervention.comment,
"oneo:verantwortlicheStelle": None,
"oneo:veroffentlichtAm": None,
"oneo:verantwortlicheStelle": "",
"oneo:veroffentlichtAm": "",
"oneo:raumreferenz": {
"oneo:Raumreferenz": self._gen_raumreferenz(),
},

View File

@ -45,6 +45,8 @@ def index_view(request: HttpRequest):
deleted=None, # not deleted
).select_related(
"legal"
).order_by(
"-modified__timestamp"
)
table = InterventionTable(
request=request,
@ -141,7 +143,8 @@ def detail_view(request: HttpRequest, id: str):
"legal",
"responsible",
),
id=id
id=id,
deleted=None
)
compensations = intervention.compensations.filter(
deleted=None,

View File

@ -67,6 +67,7 @@ def report_view(request:HttpRequest, id: str):
},
"geom_form": geom_form,
"parcels": parcels,
"tables_scrollable": False,
TAB_TITLE_IDENTIFIER: tab_title,
}
context = BaseContext(request, context).context

View File

@ -28,6 +28,7 @@ class BaseContext:
"help_link": HELP_LINK,
"impressum_link": IMPRESSUM_LINK,
"CONTACT_MAIL": EMAIL_REPLY_TO,
"tables_scrollable": True, # tables in boxes
}
# Add additional context, derived from given parameters

View File

@ -19,7 +19,7 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
Specialized on filtering GeoReferenced model types
"""
# Parcel gmrkng
# District
di = django_filters.CharFilter(
method="filter_district",
label=_(""),
@ -72,7 +72,7 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
),
)
# Parcel counter
# Parcel number
pn = django_filters.NumberFilter(
method="filter_parcel_number",
label=_(""),
@ -112,7 +112,7 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
return queryset
def filter_district(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value for 'Gemarkung'
""" Filters queryset depending on value for 'Kreis'
Args:
queryset ():
@ -122,10 +122,13 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
Returns:
"""
matching_districts = District.objects.filter(
Q(name__icontains=value) |
Q(key__icontains=value)
).distinct()
values = value.split(",")
q = Q()
for val in values:
val = val.strip()
q |= Q(name__icontains=val) | Q(key__icontains=val)
matching_districts = District.objects.filter(q).distinct()
matching_parcels = Parcel.objects.filter(
district__in=matching_districts
)
@ -148,9 +151,14 @@ class GeoReferencedTableFilterMixin(django_filters.FilterSet):
Returns:
"""
values = value.split(",")
q = Q()
for val in values:
val = val.strip()
q |= Q(parcel_group__name__icontains=val) | Q(parcel_group__key__icontains=val)
queryset = self._filter_parcel_reference(
queryset,
Q(parcel_group__name__icontains=value) | Q(parcel_group__key__icontains=value),
q,
)
return queryset

View File

@ -24,6 +24,7 @@ class RecordableTableFilterMixin(django_filters.FilterSet):
widget=forms.CheckboxInput(
attrs={
"class": "form-check-input",
"title": _("If activated also shows entries which have been already recorded"),
}
)
)

View File

@ -0,0 +1,53 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 06.12.22
"""
import django_filters
from django import forms
from django.db.models import QuerySet
from django.utils.translation import gettext_lazy as _
class SelfCreatedTableFilterMixin(django_filters.FilterSet):
""" A mixin for AbstractTableFilter
Specialized on filtering recordable model types
"""
sc = django_filters.BooleanFilter(
method='filter_show_self_created',
label=_("Show only self created"),
label_suffix=_(""),
widget=forms.CheckboxInput(
attrs={
"class": "form-check-input",
"title": _("If activated only shows entries which have been created by you"),
}
),
)
class Meta:
abstract = True
def filter_show_self_created(self, queryset, name, value) -> QuerySet:
""" Filters queryset depending on value of 'self_created' setting
Args:
queryset ():
name ():
value ():
Returns:
"""
if value:
return queryset.filter(
created__user=self.user,
)
else:
return queryset

View File

@ -24,6 +24,7 @@ class ShareableTableFilterMixin(django_filters.FilterSet):
widget=forms.CheckboxInput(
attrs={
"class": "form-check-input",
"title": _("If activated also shows entries which are not shared with you"),
}
)
)

View File

@ -12,6 +12,7 @@ from konova.filters.mixins.geo_reference import GeoReferencedTableFilterMixin
from konova.filters.mixins.keyword import KeywordTableFilterMixin
from konova.filters.mixins.office import ConservationOfficeTableFilterMixin, RegistrationOfficeTableFilterMixin
from konova.filters.mixins.record import RecordableTableFilterMixin
from konova.filters.mixins.self_created import SelfCreatedTableFilterMixin
from konova.filters.mixins.share import ShareableTableFilterMixin
@ -46,7 +47,9 @@ class QueryTableFilter(KeywordTableFilterMixin,
pass
class CheckboxTableFilter(ShareableTableFilterMixin, RecordableTableFilterMixin):
class CheckboxTableFilter(ShareableTableFilterMixin,
RecordableTableFilterMixin,
SelfCreatedTableFilterMixin):
""" TableFilter holding different filter options for checkbox related filtering
"""

View File

@ -29,6 +29,7 @@ class BaseForm(forms.Form):
form_attrs = {} # Holds additional attributes, that can be used in the template
has_required_fields = False # Automatically set. Triggers hint rendering in templates
show_cancel_btn = True
label_input_ratio = (3, 9) # used for col-sm-xy in the template. Must sum up to 12. Specify on inheriting forms
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop("instance", None)
@ -42,12 +43,26 @@ class BaseForm(forms.Form):
break
self.check_for_recorded_instance()
self.__check_valid_label_input_ratio()
@abstractmethod
def save(self):
# To be implemented in subclasses!
pass
def __check_valid_label_input_ratio(self):
""" Checks whether the configured label-input ratio is valid
If not valid an AssertionError will be raised.
The valid sum of label-input ratio is defined by bootstrap's column layout system.
Returns:
"""
ratio = self.label_input_ratio[0] + self.label_input_ratio[1]
if ratio != 12:
raise AssertionError(f"Label-input ratio on form must sum up to 12! It's {self.label_input_ratio}")
def disable_form_field(self, field: str):
"""
Disables a form field for user editing

View File

@ -24,6 +24,7 @@ class RemoveModalForm(BaseModalForm):
widget=forms.CheckboxInput(),
required=True,
)
label_input_ratio = (2, 10)
def __init__(self, *args, **kwargs):
self.template = "modal/modal_form.html"

View File

@ -0,0 +1,137 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 26.10.22
"""
import zipfile
from io import BytesIO
from django.core.mail import EmailMessage
from django.utils import timezone
from django.utils.datetime_safe import datetime
from analysis.utils.excel.excel import TempExcelFile
from analysis.utils.report import TimespanReport
from codelist.models import KonovaCode
from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID
from konova.management.commands.setup import BaseKonovaCommand
from konova.sub_settings.django_settings import DEFAULT_FROM_EMAIL, ADMINS
class Command(BaseKonovaCommand):
help = "Generates reports for conservation offices"
__from_key = "from"
__to_key = "to"
__for_key = "for"
from_date = None
to_date = None
offices = None
def add_arguments(self, parser):
try:
parser.add_argument(f"--{self.__from_key}", type=str, nargs="+")
parser.add_argument(f"--{self.__to_key}", type=str, nargs="+")
parser.add_argument(f"--{self.__for_key}", type=str, nargs="*")
except ValueError as e:
self._write_error(f"Argument error: {e}")
exit(-1)
def handle(self, *args, **options):
self.__check_arguments(options)
in_memory_zipped_reports = self.generate_reports_in_memory_zipped()
self.send_mail_to_admins(in_memory_zipped_reports)
def generate_reports_in_memory_zipped(self):
"""
Generates in-memory reports and zips into in-memory zip file.
Returns:
"""
memory_zip = BytesIO()
with zipfile.ZipFile(memory_zip, "w", compression=zipfile.ZIP_DEFLATED) as zf:
for office in self.offices:
self._write_warning(f" Process report for {office.long_name}...")
report = TimespanReport(office.id, self.from_date, self.to_date)
excel_file = TempExcelFile(report.excel_template_path, report.excel_map)
zf.writestr(zinfo_or_arcname=f"{office.long_name}_{self.from_date.date()}_{self.to_date.date()}.xlsx", data=excel_file.stream)
self._write_success(f"Reports generated for {self.offices.count()} offices and zipped.")
return memory_zip.getvalue()
def __check_arguments(self, options):
"""
Checks given parameters for validity
Args:
options ():
Returns:
"""
_from_value = options.get(self.__from_key, [None])[0]
_to_value = options.get(self.__to_key, [None])[0]
_for_value = options.get(self.__for_key, [])
# Check ISO dates
try:
_from_date = timezone.make_aware(datetime.fromisoformat(_from_value))
_to_date = timezone.make_aware(datetime.fromisoformat(_to_value))
except Exception as e:
self._write_warning(f"One of the dates is not in ISO format (YYYY-MM-DD). {e}")
exit(-1)
# Check conservation office IDs
_filter = {
"is_archived": False,
"is_leaf": True,
"code_lists__in": [CODELIST_CONSERVATION_OFFICE_ID],
}
offices = KonovaCode.objects.filter(**_filter)
if _for_value is not None and len(_for_value) != 0:
# Specifc offices requested
offices = offices.filter(short_name__in=_for_value)
all_requested_offices_exist = offices.count() == len(_for_value)
if not all_requested_offices_exist:
offices_short_name = set(offices.values_list("short_name", flat=True))
missing_ids = []
for val in _for_value:
if val not in offices_short_name:
missing_ids.append(val)
self._write_warning(
f"Unknown offices: {missing_ids}"
)
exit(-1)
self.offices = offices
self.from_date = _from_date
self.to_date = _to_date
def send_mail_to_admins(self, attachment):
office_names = [office.long_name for office in self.offices]
admin_mails = [admin[1] for admin in ADMINS]
date_from_date = self.from_date.date()
date_to_date = self.to_date.date()
mail = EmailMessage(
subject="Konova reports generated",
body=f"Zipped reports attached from {date_from_date} to {date_to_date} for {office_names}.",
from_email=DEFAULT_FROM_EMAIL,
to=admin_mails,
attachments=[
(
f"reports_{date_from_date}_{date_to_date}.zip",
attachment,
"application/zip"
)
]
)
success = mail.send()
if success == 1:
self._write_success(f"Mails with zip as attachment sent to {admin_mails}.")
else:
self._write_error(f"Something went wrong during mail sending. Returned sending code was '{success}'")

View File

@ -39,6 +39,9 @@ class Command(BaseKonovaCommand):
for obj in all_objs:
obj.resubmit()
self._write_success("Mails have been sent.")
resubmissions = Resubmission.objects.filter(
resubmission_sent=True,
)
resubmissions.delete()
self._write_success("Resubmissions have been deleted.")
except KeyboardInterrupt:

View File

@ -87,7 +87,7 @@ class AbstractDocument(BaseResource):
"""
try:
os.remove(self.file.file.name)
except FileNotFoundError:
except (FileNotFoundError, ValueError):
# File seems to missing anyway - continue!
pass
super().delete(using=using, keep_parents=keep_parents)
@ -113,7 +113,7 @@ class AbstractDocument(BaseResource):
"""
try:
os.remove(self.file.file.name)
except FileNotFoundError:
except (FileNotFoundError, ValueError):
pass
self.file = new_file
self.save()

View File

@ -60,6 +60,10 @@ a {
color: var(--rlp-red);
}
.form-label {
width: 100%;
}
.form-control:focus{
outline: none;
border-color: var(--rlp-red);

View File

@ -429,7 +429,7 @@ class Mailer:
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/resubmission/resubmission.html", context)
user_mail_address = [SUPPORT_MAIL_RECIPIENT]
user_mail_address = [resubmission.user.email]
self.send(
user_mail_address,
_("Resubmission - {}").format(obj_identifier),

View File

@ -5,11 +5,13 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
Created on: 19.08.22
"""
from django.contrib.gis.geos import MultiPolygon
from django.http import HttpResponse, HttpRequest
from django.shortcuts import get_object_or_404
from django.template.loader import render_to_string
from konova.models import Geometry, Municipal
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
def get_geom_parcels(request: HttpRequest, id: str):
@ -30,7 +32,7 @@ def get_geom_parcels(request: HttpRequest, id: str):
template = "konova/includes/parcels/parcel_table_frame.html"
geom = get_object_or_404(Geometry, id=id)
parcels = geom.get_underlying_parcels()
geos_geom = geom.geom
geos_geom = geom.geom or MultiPolygon(srid=DEFAULT_SRID_RLP)
geometry_exists = not geos_geom.empty
parcels_are_currently_calculated = geometry_exists and geos_geom.area > 0 and len(parcels) == 0

Binary file not shown.

View File

@ -28,8 +28,8 @@
#: konova/filters/mixins/geo_reference.py:79 konova/filters/mixins/office.py:24
#: konova/filters/mixins/office.py:25 konova/filters/mixins/office.py:56
#: konova/filters/mixins/office.py:57 konova/filters/mixins/record.py:23
#: konova/filters/mixins/share.py:23 konova/forms/geometry_form.py:30
#: konova/forms/modals/document_form.py:25
#: konova/filters/mixins/self_created.py:24 konova/filters/mixins/share.py:23
#: konova/forms/geometry_form.py:31 konova/forms/modals/document_form.py:25
#: konova/forms/modals/document_form.py:35
#: konova/forms/modals/document_form.py:48
#: konova/forms/modals/document_form.py:60
@ -43,7 +43,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-11-16 13:36+0100\n"
"POT-Creation-Date: 2022-12-06 08:23+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -77,7 +77,7 @@ msgstr "Einträge erstellt bis..."
#: intervention/forms/intervention.py:103
#: intervention/templates/intervention/detail/view.html:56
#: intervention/templates/intervention/report/report.html:37
#: intervention/utils/quality.py:49 konova/filters/mixins/office.py:34
#: intervention/utils/quality.py:62 konova/filters/mixins/office.py:34
msgid "Conservation office"
msgstr "Eintragungsstelle"
@ -365,8 +365,8 @@ msgstr "Kennung"
#: compensation/forms/compensation.py:33 intervention/forms/intervention.py:32
#: user/forms/user.py:77
msgid "Generated automatically"
msgstr "Automatisch generiert"
msgid "Generated automatically - not editable"
msgstr "Automatisch generiert - nicht bearbeitbar"
#: compensation/forms/compensation.py:42 compensation/tables/compensation.py:28
#: compensation/tables/eco_account.py:28
@ -392,7 +392,7 @@ msgstr "Bezeichnung"
msgid "An explanatory name"
msgstr "Aussagekräftiger Titel"
#: compensation/forms/compensation.py:48 ema/forms.py:51 ema/forms.py:111
#: compensation/forms/compensation.py:48 ema/forms.py:51 ema/forms.py:114
msgid "Compensation XY; Location ABC"
msgstr "Kompensation XY; Flur ABC"
@ -438,11 +438,11 @@ msgid "Select the intervention for which this compensation compensates"
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
#: compensation/forms/compensation.py:113
#: compensation/views/compensation/compensation.py:113
#: compensation/views/compensation/compensation.py:115
msgid "New compensation"
msgstr "Neue Kompensation"
#: compensation/forms/compensation.py:186
#: compensation/forms/compensation.py:189
msgid "Edit compensation"
msgstr "Bearbeite Kompensation"
@ -465,7 +465,7 @@ msgid "When did the parties agree on this?"
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
#: compensation/forms/eco_account.py:70
#: compensation/views/eco_account/eco_account.py:94
#: compensation/views/eco_account/eco_account.py:96
msgid "New Eco-Account"
msgstr "Neues Ökokonto"
@ -473,11 +473,11 @@ msgstr "Neues Ökokonto"
msgid "Eco-Account XY; Location ABC"
msgstr "Ökokonto XY; Flur ABC"
#: compensation/forms/eco_account.py:143
#: compensation/forms/eco_account.py:145
msgid "Edit Eco-Account"
msgstr "Ökokonto bearbeiten"
#: compensation/forms/eco_account.py:228
#: compensation/forms/eco_account.py:230
msgid "The account can not be removed, since there are still deductions."
msgstr ""
"Das Ökokonto kann nicht entfernt werden, da hierzu noch Abbuchungen "
@ -491,7 +491,7 @@ msgstr ""
#: intervention/forms/intervention.py:131
#: intervention/templates/intervention/detail/view.html:60
#: intervention/templates/intervention/report/report.html:41
#: intervention/utils/quality.py:42
#: intervention/utils/quality.py:55
msgid "Conservation office file number"
msgstr "Aktenzeichen Eintragungsstelle"
@ -725,18 +725,22 @@ msgid "m"
msgstr ""
#: compensation/models/action.py:22
msgid "km"
msgstr ""
#: compensation/models/action.py:23
msgid "m²"
msgstr ""
#: compensation/models/action.py:23
msgid "m³"
msgstr ""
#: compensation/models/action.py:24
msgid "ha"
msgid "km"
msgstr ""
#: compensation/models/action.py:25
msgid "ha"
msgstr ""
#: compensation/models/action.py:26
msgid "Pieces"
msgstr "Stück"
@ -971,6 +975,7 @@ msgstr "Frist löschen"
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:8
#: ema/templates/ema/detail/includes/documents.html:8
#: intervention/templates/intervention/detail/includes/documents.html:8
#: intervention/utils/quality.py:37
msgid "Documents"
msgstr "Dokumente"
@ -1135,7 +1140,7 @@ msgstr "Verzeichnet am"
#: ema/templates/ema/detail/view.html:71
#: ema/templates/ema/report/report.html:34
#: intervention/templates/intervention/detail/view.html:113
#: intervention/templates/intervention/report/report.html:87
#: intervention/templates/intervention/report/report.html:89
msgid "Last modified"
msgstr "Zuletzt bearbeitet"
@ -1240,7 +1245,8 @@ msgstr "Abbuchungen für"
#: compensation/templates/compensation/report/eco_account/report.html:42
#: intervention/templates/intervention/report/report.html:53
#: intervention/templates/intervention/report/report.html:74
#: intervention/templates/intervention/report/report.html:66
#: intervention/templates/intervention/report/report.html:76
msgid "None"
msgstr "-"
@ -1252,7 +1258,7 @@ msgstr "Ungleiche Zustandsflächenmengen"
msgid "Finished deadlines"
msgstr "Umsetzungstermin"
#: compensation/utils/quality.py:85 intervention/utils/quality.py:84
#: compensation/utils/quality.py:85 intervention/utils/quality.py:97
msgid "Legal data"
msgstr "Rechtliche Daten"
@ -1263,22 +1269,22 @@ msgstr ""
"überschreiten"
#: compensation/utils/quality.py:115 ema/utils/quality.py:30
#: intervention/utils/quality.py:55
#: intervention/utils/quality.py:68
msgid "Responsible data"
msgstr "Daten zu den verantwortlichen Stellen"
#: compensation/views/compensation/compensation.py:56
#: compensation/views/compensation/compensation.py:58
msgid "Compensations - Overview"
msgstr "Kompensationen - Übersicht"
#: compensation/views/compensation/compensation.py:175
#: compensation/views/compensation/compensation.py:177
#: konova/utils/message_templates.py:37
msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation/compensation.py:185
#: compensation/views/eco_account/eco_account.py:159 ema/views/ema.py:210
#: intervention/views/intervention.py:228
#: compensation/views/compensation/compensation.py:187
#: compensation/views/eco_account/eco_account.py:161 ema/views/ema.py:212
#: intervention/views/intervention.py:230
msgid "Edit {}"
msgstr "Bearbeite {}"
@ -1288,27 +1294,27 @@ msgstr "Bearbeite {}"
msgid "Report {}"
msgstr "Bericht {}"
#: compensation/views/eco_account/eco_account.py:51
#: compensation/views/eco_account/eco_account.py:53
msgid "Eco-account - Overview"
msgstr "Ökokonten - Übersicht"
#: compensation/views/eco_account/eco_account.py:84
#: compensation/views/eco_account/eco_account.py:86
msgid "Eco-Account {} added"
msgstr "Ökokonto {} hinzugefügt"
#: compensation/views/eco_account/eco_account.py:149
#: compensation/views/eco_account/eco_account.py:151
msgid "Eco-Account {} edited"
msgstr "Ökokonto {} bearbeitet"
#: compensation/views/eco_account/eco_account.py:265
#: compensation/views/eco_account/eco_account.py:267
msgid "Eco-account removed"
msgstr "Ökokonto entfernt"
#: ema/forms.py:42 ema/views/ema.py:93
#: ema/forms.py:42 ema/views/ema.py:95
msgid "New EMA"
msgstr "Neue EMA hinzufügen"
#: ema/forms.py:105
#: ema/forms.py:108
msgid "Edit EMA"
msgstr "Bearbeite EMA"
@ -1332,19 +1338,19 @@ msgstr ""
msgid "Payment funded compensation"
msgstr "Ersatzzahlungsmaßnahme"
#: ema/views/ema.py:50
#: ema/views/ema.py:52
msgid "EMAs - Overview"
msgstr "EMAs - Übersicht"
#: ema/views/ema.py:83
#: ema/views/ema.py:85
msgid "EMA {} added"
msgstr "EMA {} hinzugefügt"
#: ema/views/ema.py:200
#: ema/views/ema.py:202
msgid "EMA {} edited"
msgstr "EMA {} bearbeitet"
#: ema/views/ema.py:234
#: ema/views/ema.py:236
msgid "EMA removed"
msgstr "EMA entfernt"
@ -1355,7 +1361,7 @@ msgstr "Bauvorhaben XY; Flur ABC"
#: intervention/forms/intervention.py:53
#: intervention/templates/intervention/detail/view.html:35
#: intervention/templates/intervention/report/report.html:16
#: intervention/utils/quality.py:82
#: intervention/utils/quality.py:95
msgid "Process type"
msgstr "Verfahrenstyp"
@ -1366,14 +1372,14 @@ msgstr "Mehrfachauswahl möglich"
#: intervention/forms/intervention.py:87
#: intervention/templates/intervention/detail/view.html:48
#: intervention/templates/intervention/report/report.html:29
#: intervention/utils/quality.py:46 konova/filters/mixins/office.py:66
#: intervention/utils/quality.py:59 konova/filters/mixins/office.py:66
msgid "Registration office"
msgstr "Zulassungsbehörde"
#: intervention/forms/intervention.py:119
#: intervention/templates/intervention/detail/view.html:52
#: intervention/templates/intervention/report/report.html:33
#: intervention/utils/quality.py:39
#: intervention/utils/quality.py:52
msgid "Registration office file number"
msgstr "Aktenzeichen Zulassungsbehörde"
@ -1395,22 +1401,23 @@ msgstr "Detailangabe zum Eingriffsverursacher"
#: intervention/forms/intervention.py:174
#: intervention/templates/intervention/detail/view.html:101
#: intervention/templates/intervention/report/report.html:79
#: intervention/utils/quality.py:73
#: intervention/templates/intervention/report/report.html:81
#: intervention/utils/quality.py:86
msgid "Registration date"
msgstr "Datum Zulassung bzw. Satzungsbeschluss"
#: intervention/forms/intervention.py:186
#: intervention/templates/intervention/detail/view.html:105
#: intervention/templates/intervention/report/report.html:83
#: intervention/templates/intervention/report/report.html:85
msgid "Binding on"
msgstr "Datum Bestandskraft bzw. Rechtskraft"
#: intervention/forms/intervention.py:212 intervention/views/intervention.py:98
#: intervention/forms/intervention.py:212
#: intervention/views/intervention.py:100
msgid "New intervention"
msgstr "Neuer Eingriff"
#: intervention/forms/intervention.py:299
#: intervention/forms/intervention.py:302
msgid "Edit intervention"
msgstr "Eingriff bearbeiten"
@ -1559,10 +1566,11 @@ msgid ""
"You entered a payment. Please upload the legal document which defines the "
"payment`s amount."
msgstr ""
"Sie haben Ersatzzahlungen angegeben. Laden Sie bitte den Zahlungsbescheid als Dokument hoch."
"Sie haben Ersatzzahlungen angegeben. Laden Sie bitte den Zahlungsbescheid "
"als Dokument hoch."
#: intervention/templates/intervention/detail/includes/payments.html:8
#: intervention/templates/intervention/report/report.html:69
#: intervention/templates/intervention/report/report.html:71
msgid "Payments"
msgstr "Ersatzzahlungen"
@ -1598,7 +1606,7 @@ msgid "Remove revocation"
msgstr "Widerspruch entfernen"
#: intervention/templates/intervention/detail/view.html:64
#: intervention/utils/quality.py:52
#: intervention/utils/quality.py:65
msgid "Intervention handler"
msgstr "Eingriffsverursacher"
@ -1610,24 +1618,24 @@ msgstr "vorhanden"
msgid "Deductions of eco-accounts"
msgstr "Abbuchungen von Ökokonten"
#: intervention/templates/intervention/report/report.html:72
#: intervention/templates/intervention/report/report.html:74
msgid "Exist"
msgstr "Vorhanden"
#: intervention/utils/quality.py:70
#: intervention/utils/quality.py:83
#: templates/table/revocation_warning_col.html:5
msgid "Revocations exists"
msgstr "Widersprüche liegen vor"
#: intervention/utils/quality.py:76
#: intervention/utils/quality.py:89
msgid "Binding date"
msgstr "Datum Bestandskraft bzw. Rechtskraft"
#: intervention/utils/quality.py:79
#: intervention/utils/quality.py:92
msgid "Laws"
msgstr "Gesetze"
#: intervention/utils/quality.py:101
#: intervention/utils/quality.py:114
msgid "No compensation of any type found (Compensation, Payment, Deduction)"
msgstr ""
"Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, "
@ -1637,19 +1645,19 @@ msgstr ""
msgid "Check performed"
msgstr "Prüfung durchgeführt"
#: intervention/views/intervention.py:55
#: intervention/views/intervention.py:57
msgid "Interventions - Overview"
msgstr "Eingriffe - Übersicht"
#: intervention/views/intervention.py:88
#: intervention/views/intervention.py:90
msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt"
#: intervention/views/intervention.py:216
#: intervention/views/intervention.py:218
msgid "Intervention {} edited"
msgstr "Eingriff {} bearbeitet"
#: intervention/views/intervention.py:253
#: intervention/views/intervention.py:255
msgid "{} removed"
msgstr "{} entfernt"
@ -1734,10 +1742,26 @@ msgstr "Nach Zulassungsbehörde suchen"
msgid "Show recorded"
msgstr "Verzeichnete anzeigen"
#: konova/filters/mixins/record.py:27
msgid "If activated also shows entries which have been already recorded"
msgstr "Wenn aktiviert werden auch Einträge angezeigt, die bereits verzeichnet wurden"
#: konova/filters/mixins/self_created.py:23
msgid "Show only self created"
msgstr "Nur selbst erstellte anzeigen"
#: konova/filters/mixins/self_created.py:28
msgid "If activated only shows entries which have been created by you"
msgstr "Wenn aktiviert werden nur Einträge angezeigt, die von Ihnen erstellt worden sind"
#: konova/filters/mixins/share.py:22
msgid "Show unshared"
msgstr "Nicht freigegebene anzeigen"
#: konova/filters/mixins/share.py:27
msgid "If activated also shows entries which are not shared with you"
msgstr "Wenn aktiviert werden auch Einträge angezeigt, die nicht für Sie freigegeben sind"
#: konova/forms/base_form.py:23 templates/form/collapsable/form.html:62
msgid "Save"
msgstr "Speichern"
@ -1746,12 +1770,12 @@ msgstr "Speichern"
msgid "Not editable"
msgstr "Nicht editierbar"
#: konova/forms/geometry_form.py:29 konova/utils/quality.py:44
#: konova/forms/geometry_form.py:30 konova/utils/quality.py:44
#: konova/utils/quality.py:46 templates/form/collapsable/form.html:45
msgid "Geometry"
msgstr "Geometrie"
#: konova/forms/geometry_form.py:80
#: konova/forms/geometry_form.py:99
msgid "Only surfaces allowed. Points or lines must be buffered."
msgstr ""
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
@ -1904,6 +1928,10 @@ msgstr "Gemarkungsschlüssel"
msgid "Spatial reference"
msgstr "Raumreferenz"
#: konova/templates/konova/includes/parcels/parcels.html:28
msgid "No geometry entry found on database. Please contact an admin!"
msgstr ""
#: konova/templates/konova/includes/quickstart/compensations.html:20
#: konova/templates/konova/includes/quickstart/ecoaccounts.html:20
#: konova/templates/konova/includes/quickstart/interventions.html:20
@ -2308,7 +2336,9 @@ msgstr ""
#: templates/500.html:10
msgid "Something happened. Admins have been informed. We are working on it!"
msgstr "Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir arbeiten daran!"
msgstr ""
"Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir "
"arbeiten daran!"
#: templates/email/api/verify_token.html:7
msgid "Hello support"

View File

@ -4,12 +4,18 @@
<tbody>
{% for field in form %}
<tr title="{{ field.help_text }}" class="{% if field.errors %}alert-danger{% endif %}">
<th scope="row" class="col-sm-3">
<label for="id_{{ field.name }}">{{ field.label }}<span class="label-required">{% if field.field.required %}*{% endif %}</span></label>
{{form.small_label_column}}
<th scope="row" class="col-sm-{{form.label_input_ratio.0}}">
<label class="form-label" for="id_{{ field.name }}">
{{ field.label }}
<span class="label-required">
{% if field.field.required %}*{% endif %}
</span>
<br>
<small>{{ field.help_text }}</small>
</label>
</th>
<td class="col-sm-9">
<td class="col-sm-{{form.label_input_ratio.1}}">
{{ field }}
{% for error in field.errors %}
<br>

View File

@ -4,9 +4,9 @@
Encapsules the rendering and initializing of a geometry view component, e.g. used in the detail views.
{% endcomment %}
{% if geom_form.empty %}
{% if geom_form.empty and geom_form.read_only %}
<div class="w-100">
<div class="alert alert-info">
<div class="alert alert-danger">
{% fa5_icon 'search-location' %}
{% trans 'No geometry added, yet.' %}
</div>

View File

@ -74,7 +74,7 @@ class UserAPITokenForm(BaseForm):
label_suffix="",
max_length=255,
required=True,
help_text=_("Generated automatically"),
help_text=_("Generated automatically - not editable"),
widget=GenerateInput(
attrs={
"class": "form-control",