diff --git a/core/fields.py b/core/fields.py index fd0b2ca..097e2f6 100644 --- a/core/fields.py +++ b/core/fields.py @@ -1,24 +1,27 @@ from django import forms from django.contrib.contenttypes.models import ContentType +from django.core.exceptions import ObjectDoesNotExist +from core.content_types import content_type_str_to_obj -class MultiModelChoiceField(forms.ChoiceField): + +class MultiModelChoiceField(forms.MultipleChoiceField): def __init__(self, model_choices, *args, **kwargs): choices = [] for label, queryset in model_choices: content_type = ContentType.objects.get_for_model(queryset.model) - model_choices = [(f"{content_type.id}-{obj.id}", f"{label}: {obj}") for obj in queryset] + model_choices = [(f"{content_type.id}-{obj.id}", f"{label} : {obj}") for obj in queryset] choices.extend(model_choices) super().__init__(choices=choices, *args, **kwargs) def clean(self, value): - content_type_id, object_id = value.split("-") - content_type = ContentType.objects.get(id=content_type_id) - model_class = content_type.model_class() - try: - return model_class.objects.get(id=object_id) - except model_class.DoesNotExist: - raise forms.ValidationError("L'objet sélectionné n'existe pas.") + list_of_objects = [] + for obj_as_str in value: + try: + list_of_objects.append(content_type_str_to_obj(obj_as_str)) + except ObjectDoesNotExist: + raise forms.ValidationError("L'un des objets sélectionnés n'existe pas.") + return list_of_objects class DSFRCheckboxSelectMultiple(forms.CheckboxSelectMultiple): diff --git a/core/mixins.py b/core/mixins.py index 704e27b..a9afa9c 100644 --- a/core/mixins.py +++ b/core/mixins.py @@ -194,3 +194,17 @@ def can_user_access(self, user): return True case _: return False + + +class WithFreeLinkIdsMixin: + @property + def free_link_ids(self): + content_type = ContentType.objects.get_for_model(self) + links = LienLibre.objects.for_object(self).select_related("content_type_2", "content_type_1") + link_ids = [] + for link in links: + if link.object_id_1 == self.id and link.content_type_1 == content_type: + link_ids.append(f"{link.content_type_2.pk}-{link.object_id_2}") + else: + link_ids.append(f"{link.content_type_1.pk}-{link.object_id_1}") + return link_ids diff --git a/sv/forms.py b/sv/forms.py index 836879b..91f2a82 100644 --- a/sv/forms.py +++ b/sv/forms.py @@ -1,6 +1,5 @@ -from core.forms import DSFRForm, WithNextUrlMixin, VisibiliteUpdateBaseForm +from core.forms import DSFRForm, VisibiliteUpdateBaseForm -from django.contrib.contenttypes.models import ContentType from core.fields import MultiModelChoiceField from django import forms from django.forms.models import inlineformset_factory @@ -15,37 +14,6 @@ from sv.models import FicheZoneDelimitee, ZoneInfestee, OrganismeNuisible, StatutReglementaire, FicheDetection -class FreeLinkForm(DSFRForm, WithNextUrlMixin, forms.ModelForm): - object_id_1 = forms.IntegerField(widget=forms.HiddenInput()) - content_type_1 = forms.ModelChoiceField(widget=forms.HiddenInput(), queryset=ContentType.objects.all()) - - class Meta: - fields = ["object_id_1", "content_type_1"] - model = LienLibre - - def __init__(self, *args, **kwargs): - object_id_1 = kwargs.pop("object_id_1", None) - content_type_1 = kwargs.pop("content_type_1", None) - next = kwargs.pop("next", None) - super().__init__(*args, **kwargs) - self.fields["object_choice"] = MultiModelChoiceField( - label="Sélectioner un objet", - model_choices=[ - ("Fiche Detection", FicheDetection.objects.select_related("numero")), - ("Fiche Zone Delimitee", FicheZoneDelimitee.objects.select_related("numero")), - ], - ) - self.add_next_field(next) - self.fields["object_id_1"].initial = object_id_1 - self.fields["content_type_1"].initial = content_type_1 - - def clean(self): - super().clean() - obj = self.cleaned_data["object_choice"] - self.instance.content_type_2 = ContentType.objects.get_for_model(obj) - self.instance.object_id_2 = obj.id - - class FicheDetectionVisibiliteUpdateForm(VisibiliteUpdateBaseForm, forms.ModelForm): class Meta: model = FicheDetection @@ -129,6 +97,17 @@ def __init__(self, *args, **kwargs): if self.instance.pk: self.fields.pop("visibilite") + qs_detection = FicheDetection.objects.all().get_fiches_user_can_view(self.user).select_related("numero") + qs_zone = FicheZoneDelimitee.objects.all().get_fiches_user_can_view(self.user).select_related("numero") + self.fields["free_link"] = MultiModelChoiceField( + required=False, + label="Sélectionner un objet", + model_choices=[ + ("Fiche Détection", qs_detection), + ("Fiche zone délimitée", qs_zone), + ], + ) + organisme_nuisible_libelle = self.data.get("organisme_nuisible") or self.initial.get("organisme_nuisible") self.fields["detections_hors_zone"].queryset = ( FicheDetection.objects.all() @@ -167,8 +146,23 @@ def save(self, commit=True): if commit: instance.save() self.save_detections_hors_zone(instance) + self.save_free_links(instance) return instance + def save_free_links(self, instance): + links_ids_to_keep = [] + for obj in self.cleaned_data["free_link"]: + link = LienLibre.objects.for_both_objects(obj, instance) + + if link: + links_ids_to_keep.append(link.id) + else: + link = LienLibre.objects.create(related_object_1=instance, related_object_2=obj) + links_ids_to_keep.append(link.id) + + links_to_delete = LienLibre.objects.for_object(instance).exclude(id__in=links_ids_to_keep) + links_to_delete.delete() + def save_detections_hors_zone(self, instance): detections_from_form = set(self.cleaned_data.get("detections_hors_zone", [])) detections_from_db = set(FicheDetection.objects.filter(hors_zone_infestee=instance)) diff --git a/sv/managers.py b/sv/managers.py index 374c717..f704d46 100644 --- a/sv/managers.py +++ b/sv/managers.py @@ -101,3 +101,17 @@ def get_contacts_structures_not_in_fin_suivi(self, fiche_zone_delimitee): fin_suivi_contacts_ids = fiche_zone_delimitee.fin_suivi.values_list("contact", flat=True) contacts_not_in_fin_suivi = contacts_structure_fiche.exclude(id__in=fin_suivi_contacts_ids) return contacts_not_in_fin_suivi + + def get_fiches_user_can_view(self, user): + if user.agent.structure.is_mus_or_bsv: + return self.filter( + Q(visibilite__in=[Visibilite.LOCAL, Visibilite.NATIONAL]) + | Q(visibilite=Visibilite.BROUILLON, createur=user.agent.structure) + ) + return self.filter( + Q(visibilite=Visibilite.NATIONAL) + | Q( + visibilite__in=[Visibilite.BROUILLON, Visibilite.LOCAL], + createur=user.agent.structure, + ) + ) diff --git a/sv/models.py b/sv/models.py index eba12af..7dcbf44 100644 --- a/sv/models.py +++ b/sv/models.py @@ -1,4 +1,3 @@ -from django.contrib.contenttypes.models import ContentType from django.db import models, transaction from django.core.validators import RegexValidator from django.db.models import TextChoices, Q @@ -13,8 +12,9 @@ AllowVisibiliteMixin, IsActiveMixin, WithMessageUrlsMixin, + WithFreeLinkIdsMixin, ) -from core.models import Document, Message, Contact, Structure, FinSuiviContact, UnitesMesure, Visibilite, LienLibre +from core.models import Document, Message, Contact, Structure, FinSuiviContact, UnitesMesure, Visibilite from sv.managers import ( LaboratoireAgreeManager, LaboratoireConfirmationOfficielleManager, @@ -417,6 +417,7 @@ class FicheDetection( AllowVisibiliteMixin, WithEtatMixin, WithMessageUrlsMixin, + WithFreeLinkIdsMixin, models.Model, ): class Meta: @@ -521,18 +522,6 @@ def get_fiche_zone_delimitee(self) -> "FicheZoneDelimitee": if self.zone_infestee and self.zone_infestee.fiche_zone_delimitee: return self.zone_infestee.fiche_zone_delimitee - @property - def free_link_ids(self): - content_type = ContentType.objects.get_for_model(self) - links = LienLibre.objects.for_object(self).select_related("content_type_2", "content_type_1") - link_ids = [] - for link in links: - if link.object_id_1 == self.id and link.content_type_1 == content_type: - link_ids.append(f"{link.content_type_2.pk}-{link.object_id_2}") - else: - link_ids.append(f"{link.content_type_1.pk}-{link.object_id_1}") - return link_ids - class ZoneInfestee(models.Model): class UnitesSurfaceInfesteeTotale(TextChoices): @@ -566,7 +555,7 @@ class Meta: ) -class FicheZoneDelimitee(AllowVisibiliteMixin, WithEtatMixin, WithMessageUrlsMixin, models.Model): +class FicheZoneDelimitee(AllowVisibiliteMixin, WithEtatMixin, WithMessageUrlsMixin, WithFreeLinkIdsMixin, models.Model): class CaracteristiquesPrincipales(models.TextChoices): PLEIN_AIR_ZONE_PRODUCTION_CHAMP = ( "plein_air_zone_production_champ", diff --git a/sv/static/sv/fichezone_detail.js b/sv/static/sv/fichezone_detail.js deleted file mode 100644 index 01f055f..0000000 --- a/sv/static/sv/fichezone_detail.js +++ /dev/null @@ -1,8 +0,0 @@ -document.addEventListener('DOMContentLoaded', function() { - new Choices(document.getElementById('id_object_choice'), { - classNames: { - containerInner: 'fr-select', - }, - itemSelectText: '' - }); -}); diff --git a/sv/static/sv/fichezone_form.js b/sv/static/sv/fichezone_form.js index 93a127d..a8953f6 100644 --- a/sv/static/sv/fichezone_form.js +++ b/sv/static/sv/fichezone_form.js @@ -20,6 +20,26 @@ function initializeAllChoices() { } } +function inititializeFreeLinksChoices(){ + const freeLinksChoices = new Choices(document.getElementById("id_free_link"), { + searchResultLimit: 500, + classNames: { + containerInner: 'fr-select', + }, + removeItemButton: true, + itemSelectText: '', + noResultsText: 'Aucun résultat trouvé', + noChoicesText: 'Aucune fiche à sélectionner', + searchFields: ['label'], + }); + const freeLinksIds = JSON.parse(document.getElementById('free-links-id').textContent); + if (!!freeLinksIds) { + freeLinksIds.forEach(value => { + freeLinksChoices.setChoiceByValue(value); + }); + } +} + function addZoneInfesteeForm() { const totalFormsInput = document.getElementById('id_zoneinfestee_set-TOTAL_FORMS'); let totalForms = parseInt(totalFormsInput.value); @@ -37,6 +57,7 @@ document.addEventListener('DOMContentLoaded', function() { initializeChoices('id_detections_hors_zone'); initializeAllChoices(); + inititializeFreeLinksChoices(); const addZoneButton = document.getElementById('add-zone-infestee'); addZoneButton.addEventListener('click', function(event) { event.preventDefault(); diff --git a/sv/templates/sv/fichezonedelimitee_detail.html b/sv/templates/sv/fichezonedelimitee_detail.html index a7cd8ae..419b8cf 100644 --- a/sv/templates/sv/fichezonedelimitee_detail.html +++ b/sv/templates/sv/fichezonedelimitee_detail.html @@ -9,9 +9,6 @@ {% endblock %} -{% block scripts %} - -{% endblock %} {% block content %}
diff --git a/sv/templates/sv/fichezonedelimitee_form.html b/sv/templates/sv/fichezonedelimitee_form.html index 1d70ee6..0bb1e68 100644 --- a/sv/templates/sv/fichezonedelimitee_form.html +++ b/sv/templates/sv/fichezonedelimitee_form.html @@ -240,7 +240,17 @@

Zones infestées

+ + +
+ {{ form.instance.free_link_ids|json_script:"free-links-id" }} +

Liens libres

+
+ {{ form.free_link }} +
+
+ {% endblock %} diff --git a/sv/tests/test_fichedetection_create.py b/sv/tests/test_fichedetection_create.py index 83f90a0..c5835b7 100644 --- a/sv/tests/test_fichedetection_create.py +++ b/sv/tests/test_fichedetection_create.py @@ -22,7 +22,7 @@ ) from sv.constants import REGIONS, DEPARTEMENTS -from core.models import Contact, LienLibre, Visibilite +from core.models import Contact, LienLibre, Visibilite, Structure from sv.constants import STATUTS_EVENEMENT, STATUTS_REGLEMENTAIRES, CONTEXTES @@ -427,3 +427,25 @@ def test_fiche_detection_with_free_link( assert lien_libre.related_object_1 == fiche_detection assert lien_libre.related_object_2 == fiche_zone + + +@pytest.mark.django_db +def test_fiche_detection_with_free_link_cant_see_draft( + live_server, + page: Page, + form_elements: FicheDetectionFormDomElements, + mocked_authentification_user, + fiche_zone_bakery, + choice_js_fill, +): + fiche_zone = fiche_zone_bakery() + fiche_zone.visibilite = Visibilite.BROUILLON + fiche_zone.createur = baker.make(Structure) + fiche_zone.save() + + page.goto(f"{live_server.url}{reverse('fiche-detection-creation')}") + fiche_input = "Fiche zone délimitée : " + str(fiche_zone.numero) + page.query_selector("#liens-libre .choices").click() + page.wait_for_selector("input:focus", state="visible", timeout=2_000) + page.locator("*:focus").fill(str(fiche_zone.numero)) + expect(page.get_by_role("option", name=fiche_input, exact=True)).not_to_be_visible() diff --git a/sv/tests/test_fichedetection_performances.py b/sv/tests/test_fichedetection_performances.py index 8783ee4..3ad9ae7 100644 --- a/sv/tests/test_fichedetection_performances.py +++ b/sv/tests/test_fichedetection_performances.py @@ -4,7 +4,7 @@ from core.models import Message, Document, Structure, Contact from sv.models import FicheDetection, Lieu, Prelevement -BASE_NUM_QUERIES = 15 # Please note a first call is made without assertion to warm up any possible cache +BASE_NUM_QUERIES = 13 # Please note a first call is made without assertion to warm up any possible cache @pytest.mark.django_db diff --git a/sv/tests/test_fichezonedelimitee_add_performance.py b/sv/tests/test_fichezonedelimitee_add_performance.py index abde845..8718031 100644 --- a/sv/tests/test_fichezonedelimitee_add_performance.py +++ b/sv/tests/test_fichezonedelimitee_add_performance.py @@ -6,7 +6,7 @@ from sv.forms import RattachementChoices from sv.models import Etat, OrganismeNuisible, FicheDetection -BASE_NUM_QUERIES = 9 +BASE_NUM_QUERIES = 12 def test_add_fiche_zone_delimitee_form_with_multiple_existing_fiche_detection( diff --git a/sv/tests/test_fichezonedelimitee_create.py b/sv/tests/test_fichezonedelimitee_create.py index ea11cb8..d880c38 100644 --- a/sv/tests/test_fichezonedelimitee_create.py +++ b/sv/tests/test_fichezonedelimitee_create.py @@ -4,7 +4,7 @@ from django.utils import timezone from django.urls import reverse -from core.models import Visibilite +from core.models import Visibilite, LienLibre from sv.models import FicheZoneDelimitee, ZoneInfestee, FicheDetection, Etat from sv.tests.test_utils import FicheZoneDelimiteeFormPage from sv.forms import RattachementChoices @@ -324,3 +324,31 @@ def test_cant_link_fiche_detection_to_fiche_zone_delimitee_if_fiche_detection_is expect(page.get_by_text("Aucune fiche détection à sélectionner").nth(1)).to_be_visible() page.get_by_text("Rattacher des détections").nth(2).click() expect(page.get_by_text("Aucune fiche détection à sélectionner").nth(2)).to_be_visible() + + +@pytest.mark.django_db +def test_can_create_fiche_zone_with_free_links( + live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection, fiche_zone_bakery +): + other_fiche = fiche_zone_bakery() + other_fiche.visibilite = Visibilite.NATIONAL + other_fiche.save() + fiche_detection.organisme_nuisible = baker.make("OrganismeNuisible") + fiche_detection.statut_reglementaire = baker.make("StatutReglementaire") + fiche_detection.save() + form_page = FicheZoneDelimiteeFormPage(page, choice_js_fill) + + form_page.goto_create_form_page(live_server, fiche_detection.pk, RattachementChoices.HORS_ZONE_INFESTEE) + fiche_input = "Fiche zone délimitée : " + str(other_fiche.numero) + choice_js_fill(page, "#liens-libre .choices", str(other_fiche.numero), fiche_input) + form_page.submit_form() + + form_page.check_message_succes() + assert FicheZoneDelimitee.objects.count() == 2 + fiche_from_db = FicheZoneDelimitee.objects.last() + + assert LienLibre.objects.count() == 1 + lien_libre = LienLibre.objects.get() + + assert lien_libre.related_object_1 == fiche_from_db + assert lien_libre.related_object_2 == other_fiche diff --git a/sv/tests/test_fichezonedelimitee_detail_performances.py b/sv/tests/test_fichezonedelimitee_detail_performances.py index f4f16e1..bec3d27 100644 --- a/sv/tests/test_fichezonedelimitee_detail_performances.py +++ b/sv/tests/test_fichezonedelimitee_detail_performances.py @@ -1,7 +1,7 @@ from model_bakery import baker from sv.models import FicheDetection, ZoneInfestee -BASE_NUM_QUERIES = 16 +BASE_NUM_QUERIES = 14 def test_empty_fiche_zone_delimitee_performances( diff --git a/sv/tests/test_fichezonedelimitee_update.py b/sv/tests/test_fichezonedelimitee_update.py index 2e2c104..18919a4 100644 --- a/sv/tests/test_fichezonedelimitee_update.py +++ b/sv/tests/test_fichezonedelimitee_update.py @@ -1,5 +1,7 @@ from playwright.sync_api import Page, expect from model_bakery import baker + +from core.models import LienLibre from sv.tests.test_utils import FicheZoneDelimiteeFormPage from sv.models import ZoneInfestee, FicheZoneDelimitee, FicheDetection, Etat @@ -174,3 +176,42 @@ def test_update_form_cant_have_same_detection_in_two_zone_infestee( f"Les fiches détection suivantes sont dupliquées dans les zones infestées : {str(fiche_detection.numero)}." ) ).to_be_visible() + + +def test_update_fiche_can_add_and_delete_free_links( + live_server, + page: Page, + fiche_detection: FicheDetection, + fiche_detection_bakery, + choice_js_fill, +): + other_fiche = fiche_detection_bakery() + other_fiche_2 = fiche_detection_bakery() + fiche_zone_delimitee = baker.make( + FicheZoneDelimitee, + etat=Etat.objects.get(id=Etat.get_etat_initial()), + organisme_nuisible=fiche_detection.organisme_nuisible, + statut_reglementaire=fiche_detection.statut_reglementaire, + _fill_optional=True, + ) + LienLibre.objects.create(related_object_1=fiche_zone_delimitee, related_object_2=other_fiche) + form_page = FicheZoneDelimiteeFormPage(page, choice_js_fill) + page.goto(f"{live_server.url}{fiche_zone_delimitee.get_update_url()}") + + expect(page.get_by_text(f"Fiche Détection : {str(other_fiche.numero)}Remove item")).to_be_visible() + # Remove existing link + page.locator(".choices__button").click() + + # Add new link + fiche_input = "Fiche Détection : " + str(other_fiche_2.numero) + choice_js_fill(page, "#liens-libre .choices", str(other_fiche_2.numero), fiche_input) + + form_page.submit_update_form() + + page.wait_for_timeout(600) + + assert LienLibre.objects.count() == 1 + lien_libre = LienLibre.objects.get() + + assert lien_libre.related_object_1 == fiche_zone_delimitee + assert lien_libre.related_object_2 == other_fiche_2 diff --git a/sv/tests/test_fichezonedelimitee_update_performance.py b/sv/tests/test_fichezonedelimitee_update_performance.py index 8ed871c..77f274a 100644 --- a/sv/tests/test_fichezonedelimitee_update_performance.py +++ b/sv/tests/test_fichezonedelimitee_update_performance.py @@ -3,7 +3,7 @@ from core.models import Visibilite from sv.models import Etat, OrganismeNuisible, FicheDetection -BASE_NUM_QUERIES = 10 +BASE_NUM_QUERIES = 13 def test_update_fiche_zone_delimitee_form_with_multiple_existing_fiche_detection( diff --git a/sv/urls.py b/sv/urls.py index 2313a58..8660c25 100644 --- a/sv/urls.py +++ b/sv/urls.py @@ -6,7 +6,6 @@ FicheDetectionDetailView, FicheDetectionCreateView, FicheDetectionUpdateView, - FreeLinkCreateView, FicheDetectionExportView, FicheCloturerView, FicheDetectionVisibiliteUpdateView, @@ -63,11 +62,6 @@ RattachementDetectionView.as_view(), name="rattachement-fiche-zone-delimitee", ), - path( - "lien/ajout/", - FreeLinkCreateView.as_view(), - name="free-link-add", - ), path( "api/espece/recherche/", search_espece_echantillon, diff --git a/sv/views.py b/sv/views.py index 1254e22..e54d8a0 100644 --- a/sv/views.py +++ b/sv/views.py @@ -15,7 +15,7 @@ ) from django.urls import reverse from django.db.models import F, Prefetch -from django.db import transaction, IntegrityError +from django.db import transaction from django.http import HttpResponseBadRequest, HttpResponseRedirect, HttpResponse from django.core.exceptions import ValidationError, PermissionDenied, ObjectDoesNotExist from django.contrib import messages @@ -31,7 +31,6 @@ ) from core.redirect import safe_redirect from sv.forms import ( - FreeLinkForm, FicheDetectionVisibiliteUpdateForm, FicheZoneDelimiteeForm, ZoneInfesteeFormSet, @@ -114,11 +113,6 @@ def get_object(self, queryset=None): self.object = super().get_object(queryset) return self.object - def _get_free_link_form(self): - return FreeLinkForm( - content_type_1=ContentType.objects.get_for_model(self.get_object()).pk, object_id_1=self.get_object().pk - ) - def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["lieux"] = ( @@ -133,7 +127,6 @@ def get_context_data(self, **kwargs): "espece_echantillon", "laboratoire_agree", ) - context["free_link_form"] = self._get_free_link_form() context["content_type"] = ContentType.objects.get_for_model(self.get_object()) contacts_not_in_fin_suivi = FicheDetection.objects.all().get_contacts_structures_not_in_fin_suivi( self.get_object() @@ -156,6 +149,29 @@ def handle_no_permission(self): class FicheDetectionContextMixin: + def _add_status_to_organisme_nuisible(self, context, status): + status_code_to_id = {s.code: s.id for s in status} + oeep_to_nuisible_id = { + organisme.code_oepp: organisme.id + for organisme in OrganismeNuisible.objects.filter(code_oepp__in=KNOWN_OEPPS) + } + context["status_to_organisme_nuisible"] = [ + {"statusID": status_code_to_id[code], "nuisibleIds": [oeep_to_nuisible_id.get(oepp) for oepp in oepps]} + for code, oepps in KNOWN_OEPP_CODES_FOR_STATUS_REGLEMENTAIRES.items() + ] + + def _add_possible_links(self, context, user): + possible_links = [] + + content_type = ContentType.objects.get_for_model(FicheDetection) + queryset = FicheDetection.objects.all().get_fiches_user_can_view(user).select_related("numero") + possible_links.append((content_type.pk, "Fiche Détection", queryset)) + + content_type = ContentType.objects.get_for_model(FicheZoneDelimitee) + queryset = FicheZoneDelimitee.objects.all().get_fiches_user_can_view(user).select_related("numero") + possible_links.append((content_type.pk, "Fiche zone délimitée", queryset)) + context["possible_links"] = possible_links + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["statuts_evenement"] = StatutEvenement.objects.all() @@ -183,26 +199,8 @@ def get_context_data(self, **kwargs): context["types_etablissement"] = TypeExploitant.objects.all().order_by("libelle") context["positions_chaine_distribution"] = PositionChaineDistribution.objects.all().order_by("libelle") - status_code_to_id = {s.code: s.id for s in status} - - oeep_to_nuisible_id = { - organisme.code_oepp: organisme.id - for organisme in OrganismeNuisible.objects.filter(code_oepp__in=KNOWN_OEPPS) - } - context["status_to_organisme_nuisible"] = [ - {"statusID": status_code_to_id[code], "nuisibleIds": [oeep_to_nuisible_id.get(oepp) for oepp in oepps]} - for code, oepps in KNOWN_OEPP_CODES_FOR_STATUS_REGLEMENTAIRES.items() - ] - - possible_links = [] - content_type = ContentType.objects.get_for_model(FicheDetection) - possible_links.append((content_type.pk, "Fiche Détection", FicheDetection.objects.select_related("numero"))) - content_type = ContentType.objects.get_for_model(FicheZoneDelimitee) - possible_links.append( - (content_type.pk, "Fiche zone délimitée", FicheZoneDelimitee.objects.select_related("numero")) - ) - - context["possible_links"] = possible_links + self._add_status_to_organisme_nuisible(context, status) + self._add_possible_links(context, self.request.user) return context @@ -644,25 +642,6 @@ def post(self, request, pk): return redirect(reverse("fiche-detection-vue-detaillee", args=[fiche_detection.pk])) -class FreeLinkCreateView(FormView): - form_class = FreeLinkForm - - def post(self, request, *args, **kwargs): - form = FreeLinkForm(request.POST) - if not form.is_valid(): - messages.error(request, "Ce lien existe déjà.") - return safe_redirect(self.request.POST.get("next")) - - try: - form.save() - except IntegrityError: - messages.error(request, "Vous ne pouvez pas lier un objet à lui même.") - return safe_redirect(self.request.POST.get("next")) - - messages.success(request, "Le lien a été créé avec succès.") - return safe_redirect(self.request.POST.get("next")) - - class FicheDetectionExportView(View): http_method_names = ["post"] @@ -868,11 +847,6 @@ def get_object(self, queryset=None): self.object = super().get_object(queryset) return self.object - def _get_free_link_form(self): - return FreeLinkForm( - content_type_1=ContentType.objects.get_for_model(self.get_object()).pk, object_id_1=self.get_object().pk - ) - def get_queryset(self): zone_infestee_detections_prefetch = Prefetch( "fichedetection_set", queryset=FicheDetection.objects.select_related("numero") @@ -888,7 +862,6 @@ def get_queryset(self): def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) fichezonedelimitee = self.get_object() - context["free_link_form"] = self._get_free_link_form() context["can_update_visibilite"] = self.get_object().can_update_visibilite(self.request.user) context["visibilite_form"] = FicheDetectionVisibiliteUpdateForm(obj=self.get_object()) context["detections_hors_zone_infestee"] = fichezonedelimitee.fichedetection_set.select_related("numero").all()