diff --git a/api/utils/serializer/v1/serializer.py b/api/utils/serializer/v1/serializer.py index 8779f4ef..03ca0e07 100644 --- a/api/utils/serializer/v1/serializer.py +++ b/api/utils/serializer/v1/serializer.py @@ -16,7 +16,8 @@ from api.utils.serializer.serializer import AbstractModelAPISerializer from codelist.models import KonovaCode from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID, CODELIST_PROCESS_TYPE_ID, \ CODELIST_LAW_ID, CODELIST_REGISTRATION_OFFICE_ID, CODELIST_CONSERVATION_OFFICE_ID, \ - CODELIST_COMPENSATION_ACTION_DETAIL_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, CODELIST_HANDLER_ID + CODELIST_COMPENSATION_ACTION_DETAIL_ID, CODELIST_HANDLER_ID, \ + CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID from compensation.models import CompensationAction, UnitChoices, CompensationState from intervention.models import Responsibility, Legal, Handler from konova.models import Deadline, DeadlineType @@ -347,7 +348,7 @@ class AbstractCompensationAPISerializerV1Mixin: try: biotope_type = entry["biotope"] biotope_details = [ - self._konova_code_from_json(e, CODELIST_BIOTOPES_EXTRA_CODES_ID) for e in entry["biotope_details"] + self._konova_code_from_json(e, CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID) for e in entry["biotope_details"] ] surface = float(entry["surface"]) except KeyError: diff --git a/codelist/autocomplete/biotope.py b/codelist/autocomplete/biotope.py index 5e56b7f3..4fe1e30b 100644 --- a/codelist/autocomplete/biotope.py +++ b/codelist/autocomplete/biotope.py @@ -9,7 +9,8 @@ import collections from django.core.exceptions import ImproperlyConfigured -from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID +from codelist.settings import CODELIST_BIOTOPES_ID, \ + CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID from codelist.autocomplete.base import KonovaCodeAutocomplete from konova.utils.message_templates import UNGROUPED @@ -84,11 +85,11 @@ class BiotopeExtraCodeAutocomplete(KonovaCodeAutocomplete): Due to limitations of the django dal package, we need to subclass for each code list """ group_by_related = "parent" - related_field_name = "long_name" + related_field_name = "short_name" paginate_by = 200 def __init__(self, *args, **kwargs): - self.c = CODELIST_BIOTOPES_EXTRA_CODES_ID + self.c = CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID super().__init__(*args, **kwargs) def order_by(self, qs): @@ -103,8 +104,11 @@ class BiotopeExtraCodeAutocomplete(KonovaCodeAutocomplete): qs (QuerySet): The ordered queryset """ return qs.order_by( - "long_name", + "short_name", ) def get_result_label(self, result): return f"{result.long_name} ({result.short_name})" + + def get_selected_result_label(self, result): + return f"{result.parent.short_name} > {result.long_name} ({result.short_name})" \ No newline at end of file diff --git a/codelist/management/commands/update_codelist.py b/codelist/management/commands/update_codelist.py index d29b272b..d514c993 100644 --- a/codelist/management/commands/update_codelist.py +++ b/codelist/management/commands/update_codelist.py @@ -13,7 +13,7 @@ from codelist.settings import CODELIST_INTERVENTION_HANDLER_ID, CODELIST_CONSERV CODELIST_REGISTRATION_OFFICE_ID, CODELIST_BIOTOPES_ID, CODELIST_LAW_ID, CODELIST_HANDLER_ID, \ CODELIST_COMPENSATION_ACTION_ID, CODELIST_COMPENSATION_ACTION_CLASS_ID, CODELIST_COMPENSATION_ADDITIONAL_TYPE_ID, \ CODELIST_BASE_URL, CODELIST_PROCESS_TYPE_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, \ - CODELIST_COMPENSATION_ACTION_DETAIL_ID + CODELIST_COMPENSATION_ACTION_DETAIL_ID, CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID from konova.management.commands.setup import BaseKonovaCommand from konova.settings import PROXIES @@ -34,6 +34,7 @@ class Command(BaseKonovaCommand): CODELIST_REGISTRATION_OFFICE_ID, CODELIST_BIOTOPES_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID, + CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID, CODELIST_LAW_ID, CODELIST_HANDLER_ID, CODELIST_COMPENSATION_ACTION_ID, @@ -55,7 +56,7 @@ class Command(BaseKonovaCommand): content = result.content.decode("utf-8") root = etree.fromstring(content) items = root.findall("item") - self._write_warning("Found {} codes. Process now...".format(len(items))) + self._write_warning(" Found {} codes. Process now...".format(len(items))) code_list = KonovaCodeList.objects.get_or_create( id=list_id, @@ -74,7 +75,7 @@ class Command(BaseKonovaCommand): if items is None: return else: - self._write_warning(" --- Found {} subcodes. Process now...".format(len(items))) + self._write_warning(" --- Found {} subcodes. Process now...".format(len(items))) for element in items: children = element.find("items") _id = element.find("id").text diff --git a/codelist/migrations/0002_migrate_975_to_288.py b/codelist/migrations/0002_migrate_975_to_288.py new file mode 100644 index 00000000..cf0d87cf --- /dev/null +++ b/codelist/migrations/0002_migrate_975_to_288.py @@ -0,0 +1,49 @@ +# Generated by Django 5.0.7 on 2024-08-06 13:40 + +from django.db import migrations +from django.db.models import Q + +from codelist.settings import CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID + + +def migrate_975_to_288(apps, schema_editor): + KonovaCodeList = apps.get_model('codelist', 'KonovaCodeList') + CompensationState = apps.get_model('compensation', 'CompensationState') + + list_288 = KonovaCodeList.objects.get( + id=CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID + ).codes.all() + + states_with_extra_code = CompensationState.objects.filter( + ~Q(biotope_type_details=None) + ) + + print(f"... Found {states_with_extra_code.count()} biotope state entries") + for state in states_with_extra_code: + extra_codes_975 = state.biotope_type_details.filter( + code_lists__in=[CODELIST_BIOTOPES_EXTRA_CODES_ID] + ) + count_extra_codes_975 = extra_codes_975.count() + if count_extra_codes_975 > 0: + print(f" --> Found {count_extra_codes_975} codes from list 975 in biotope entry {state.id}") + extra_codes_288 = [] + for extra_code_975 in extra_codes_975: + atom_id = extra_code_975.atom_id + codes_from_288 = list_288.filter( + atom_id=atom_id, + ) + extra_codes_288 += codes_from_288 + + state.biotope_type_details.set(extra_codes_288) + print(" --> Migrated to list 288 for all biotope entries") + + +class Migration(migrations.Migration): + + dependencies = [ + ('codelist', '0001_initial'), + ] + + operations = [ + migrations.RunPython(migrate_975_to_288) + ] diff --git a/codelist/models.py b/codelist/models.py index a5b91a33..1bd5da32 100644 --- a/codelist/models.py +++ b/codelist/models.py @@ -25,13 +25,11 @@ class KonovaCode(models.Model): ) short_name = models.CharField( max_length=500, - null=True, blank=True, help_text="Short version of long name", ) long_name = models.CharField( max_length=1000, - null=True, blank=True, help_text="", ) @@ -50,12 +48,28 @@ class KonovaCode(models.Model): def __str__(self, with_parent: bool = True): ret_val = "" - if self.parent and self.parent.long_name and with_parent: - ret_val += self.parent.long_name + " > " - ret_val += self.long_name - if self.short_name and self.short_name != self.long_name: - # Only add short name, if we won't have stupid repition like 'thing a (thing a)' due to misused long-short names - ret_val += f" ({self.short_name})" + + long_name = self.long_name + short_name = self.short_name + + both_names_exist = long_name is not None and short_name is not None + + if both_names_exist: + if with_parent and self.parent: + parent_short_name_exists = self.parent.short_name is not None + parent_long_name_exists = self.parent.long_name is not None + if parent_long_name_exists: + ret_val += self.parent.long_name + " > " + elif parent_short_name_exists: + ret_val += self.parent.short_name + " > " + + ret_val += long_name + + if short_name and short_name != long_name: + ret_val += f" ({short_name})" + else: + ret_val += str(long_name or short_name) + return ret_val @property diff --git a/codelist/settings.py b/codelist/settings.py index 3bd70328..10324234 100644 --- a/codelist/settings.py +++ b/codelist/settings.py @@ -15,7 +15,8 @@ CODELIST_CONSERVATION_OFFICE_ID = 907 # CLNaturschutzbehörden CODELIST_REGISTRATION_OFFICE_ID = 1053 # CLZulassungsbehörden CODELIST_BIOTOPES_ID = 654 # CL_Biotoptypen CODELIST_AFTER_STATE_BIOTOPES_ID = 974 # CL-KSP_ZielBiotoptypen - USAGE HAS BEEN DROPPED IN 2022 IN FAVOR OF 654 -CODELIST_BIOTOPES_EXTRA_CODES_ID = 975 # CLZusatzbezeichnung +CODELIST_BIOTOPES_EXTRA_CODES_ID = 975 # CLZusatzbezeichnung - Subset of 288. Migration usage 975->288 in 08/2024 +CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID = 288 # CLBiotoptypZusatzcode CODELIST_LAW_ID = 1048 # CLVerfahrensrecht CODELIST_PROCESS_TYPE_ID = 44382 # CLVerfahrenstyp diff --git a/compensation/forms/modals/state.py b/compensation/forms/modals/state.py index 5a1dde55..7340c95f 100644 --- a/compensation/forms/modals/state.py +++ b/compensation/forms/modals/state.py @@ -14,7 +14,8 @@ from django.shortcuts import render from django.utils.translation import gettext_lazy as _ from codelist.models import KonovaCode -from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID +from codelist.settings import CODELIST_BIOTOPES_ID, \ + CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID from intervention.inputs import CompensationStateTreeRadioSelect from konova.contexts import BaseContext from konova.forms.modals import RemoveModalForm, BaseModalForm @@ -43,7 +44,7 @@ class NewCompensationStateModalForm(BaseModalForm): queryset=KonovaCode.objects.filter( is_archived=False, is_leaf=True, - code_lists__in=[CODELIST_BIOTOPES_EXTRA_CODES_ID], + code_lists__in=[CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID], ), widget=autocomplete.ModelSelect2Multiple( url="codelist:biotope-extra-type-autocomplete", diff --git a/compensation/models/state.py b/compensation/models/state.py index 77026b55..01fc2aa2 100644 --- a/compensation/models/state.py +++ b/compensation/models/state.py @@ -6,10 +6,10 @@ Created on: 16.11.21 """ from django.db import models -from django.db.models import Q from codelist.models import KonovaCode -from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_BIOTOPES_EXTRA_CODES_ID +from codelist.settings import CODELIST_BIOTOPES_ID, \ + CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID from compensation.managers import CompensationStateManager from konova.models import UuidModel @@ -34,7 +34,7 @@ class CompensationState(UuidModel): KonovaCode, blank=True, limit_choices_to={ - "code_lists__in": [CODELIST_BIOTOPES_EXTRA_CODES_ID], + "code_lists__in": [CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID], "is_selectable": True, "is_archived": False, }, diff --git a/compensation/templates/compensation/detail/compensation/includes/actions.html b/compensation/templates/compensation/detail/compensation/includes/actions.html index e4ec5b60..d832ad10 100644 --- a/compensation/templates/compensation/detail/compensation/includes/actions.html +++ b/compensation/templates/compensation/detail/compensation/includes/actions.html @@ -52,7 +52,7 @@
{% endfor %} {% for detail in action.action_type_details.all %} - {{detail.long_name}} + {{ detail.parent.long_name }} > {{detail.long_name}} {% empty %} {% trans 'No action type details' %} {% endfor %} diff --git a/compensation/templates/compensation/detail/compensation/includes/states-after.html b/compensation/templates/compensation/detail/compensation/includes/states-after.html index dfda6aee..39e62048 100644 --- a/compensation/templates/compensation/detail/compensation/includes/states-after.html +++ b/compensation/templates/compensation/detail/compensation/includes/states-after.html @@ -51,7 +51,7 @@ {{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})
{% for detail in state.biotope_type_details.all %} - {{detail.long_name}} + {{ detail.parent.short_name }} > {{ detail.long_name }} {% empty %} {% trans 'No biotope type details' %} {% endfor %} diff --git a/compensation/templates/compensation/detail/compensation/includes/states-before.html b/compensation/templates/compensation/detail/compensation/includes/states-before.html index ff3d2673..25524c0c 100644 --- a/compensation/templates/compensation/detail/compensation/includes/states-before.html +++ b/compensation/templates/compensation/detail/compensation/includes/states-before.html @@ -51,7 +51,7 @@ {{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})
{% for detail in state.biotope_type_details.all %} - {{detail.long_name}} + {{ detail.parent.short_name }} > {{ detail.long_name }} {% empty %} {% trans 'No biotope type details' %} {% endfor %} diff --git a/compensation/templates/compensation/detail/eco_account/includes/actions.html b/compensation/templates/compensation/detail/eco_account/includes/actions.html index 52f86486..d83820a2 100644 --- a/compensation/templates/compensation/detail/eco_account/includes/actions.html +++ b/compensation/templates/compensation/detail/eco_account/includes/actions.html @@ -51,7 +51,7 @@
{% endfor %} {% for detail in action.action_type_details.all %} - {{detail.long_name}} + {{ detail.parent.long_name }} > {{detail.long_name}} {% empty %} {% trans 'No action type details' %} {% endfor %} diff --git a/compensation/templates/compensation/detail/eco_account/includes/states-after.html b/compensation/templates/compensation/detail/eco_account/includes/states-after.html index d188f081..02ac15c1 100644 --- a/compensation/templates/compensation/detail/eco_account/includes/states-after.html +++ b/compensation/templates/compensation/detail/eco_account/includes/states-after.html @@ -51,7 +51,7 @@ {{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})
{% for detail in state.biotope_type_details.all %} - {{detail.long_name}} + {{ detail.parent.short_name }} > {{ detail.long_name }} {% empty %} {% trans 'No biotope type details' %} {% endfor %} diff --git a/compensation/templates/compensation/detail/eco_account/includes/states-before.html b/compensation/templates/compensation/detail/eco_account/includes/states-before.html index 56fe0b07..135c4c03 100644 --- a/compensation/templates/compensation/detail/eco_account/includes/states-before.html +++ b/compensation/templates/compensation/detail/eco_account/includes/states-before.html @@ -51,7 +51,7 @@ {{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})
{% for detail in state.biotope_type_details.all %} - {{detail.long_name}} + {{ detail.parent.short_name }} > {{ detail.long_name }} {% empty %} {% trans 'No biotope type details' %} {% endfor %} diff --git a/ema/templates/ema/detail/includes/actions.html b/ema/templates/ema/detail/includes/actions.html index 8a77c79d..0088bfe8 100644 --- a/ema/templates/ema/detail/includes/actions.html +++ b/ema/templates/ema/detail/includes/actions.html @@ -49,7 +49,7 @@
{% endfor %} {% for detail in action.action_type_details.all %} - {{detail.long_name}} + {{ detail.parent.long_name }} > {{detail.long_name}} {% empty %} {% trans 'No action type details' %} {% endfor %} diff --git a/ema/templates/ema/detail/includes/states-after.html b/ema/templates/ema/detail/includes/states-after.html index 0277e021..fbee2899 100644 --- a/ema/templates/ema/detail/includes/states-after.html +++ b/ema/templates/ema/detail/includes/states-after.html @@ -49,7 +49,7 @@ {{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})
{% for detail in state.biotope_type_details.all %} - {{detail.long_name}} + {{ detail.parent.short_name }} > {{ detail.long_name }} {% empty %} {% trans 'No biotope type details' %} {% endfor %} diff --git a/ema/templates/ema/detail/includes/states-before.html b/ema/templates/ema/detail/includes/states-before.html index f0d4eddd..a69709ad 100644 --- a/ema/templates/ema/detail/includes/states-before.html +++ b/ema/templates/ema/detail/includes/states-before.html @@ -49,7 +49,7 @@ {{ state.biotope_type.parent.long_name }} {% fa5_icon 'angle-right' %} {{ state.biotope_type.long_name }} ({{state.biotope_type.short_name}})
{% for detail in state.biotope_type_details.all %} - {{detail.long_name}} + {{ detail.parent.short_name }} > {{ detail.long_name }} {% empty %} {% trans 'No biotope type details' %} {% endfor %} diff --git a/requirements.txt b/requirements.txt index 8d7889ca..3b897925 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ billiard==4.2.0 cached-property==1.5.2 celery==5.4.0 certifi==2024.7.4 -cffi==1.17.0rc1 +cffi==1.17.0 chardet==5.2.0 charset-normalizer==3.3.2 click==8.1.7 @@ -14,14 +14,14 @@ click-didyoumean==0.3.1 click-plugins==1.1.1 click-repl==0.3.0 coverage==7.5.4 -cryptography==42.0.8 +cryptography==43.0.0 Deprecated==1.2.14 -Django==5.0.7 +Django==5.0.8 django-autocomplete-light==3.11.0 django-bootstrap-modal-forms==3.0.4 django-bootstrap4==24.3 django-environ==0.11.2 -django-filter==24.2 +django-filter==24.3 django-fontawesome-5==1.0.18 django-oauth-toolkit==2.4.0 django-simple-sso==1.2.0 @@ -29,7 +29,7 @@ django-tables2==2.7.0 et-xmlfile==1.1.0 gunicorn==22.0.0 idna==3.7 -importlib_metadata==8.0.0 +importlib_metadata==8.2.0 itsdangerous==0.24 jwcrypto==1.5.6 kombu==5.4.0rc1 @@ -47,13 +47,13 @@ pypng==0.20220715.0 pyproj==3.6.1 python-dateutil==2.9.0.post0 pytz==2024.1 -PyYAML==6.0.2rc1 +PyYAML==6.0.2 qrcode==7.3.1 redis==5.1.0b6 -requests<2.32.0 +requests==2.32.3 six==1.16.0 soupsieve==2.5 -sqlparse==0.5.0 +sqlparse==0.5.1 typing_extensions==4.12.2 tzdata==2024.1 urllib3==2.2.2