Skip to content

Commit

Permalink
Pas de numéro de fiche zone délimitée si visibilité brouillon
Browse files Browse the repository at this point in the history
- model FicheZoneDelimitee: le champ numero devient nullable
- model FicheZoneDelimitee: ajout d'une contrainte pour s'assurer que numero est null quand la visibilite est brouillon
- model FicheZoneDelimitee: ajout d'une méthode save pour attribuer automatiquement un numéro quand la visibilité est local
- modification du template de détail pour affichage conditionnel du champ numero
- ajout de tests du modèle pour valider la contrainte de base ajoutée (check_fiche_zone_delimitee_numero_fiche_is_null_when_visibilite_is_brouillon)
- ajout d'un test e2e
- refactoring de certains tests pour respecter la contrainte
  • Loading branch information
alanzirek committed Nov 28, 2024
1 parent 480f8ef commit bfa0c72
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 51 deletions.
63 changes: 63 additions & 0 deletions sv/migrations/0041_alter_fichezonedelimitee_numero_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Generated by Django 5.0.8 on 2024-11-22 20:45
import datetime

import django.db.models.deletion
from django.db import migrations, models, transaction


def set_numero_to_none_for_existing_fiche_zone_delimitee_in_brouillon(apps, schema_editor):
FicheZoneDelimitee = apps.get_model("sv", "FicheZoneDelimitee")
fiches_brouillon = FicheZoneDelimitee.objects.filter(visibilite="brouillon")
for fiche in fiches_brouillon:
if fiche.numero:
numero = fiche.numero
fiche.numero = None
fiche.save()
numero.delete()


def reverse_set_numero_to_none_for_existing_fiche_zone_delimitee_in_brouillon(apps, schema_editor):
FicheZoneDelimitee = apps.get_model("sv", "FicheZoneDelimitee")
NumeroFiche = apps.get_model("sv", "NumeroFiche")

with transaction.atomic():
annee_courante = datetime.datetime.now().year
dernier_numero = NumeroFiche.objects.filter(annee=annee_courante).order_by("-numero").first()
prochain_numero = 1 if not dernier_numero else dernier_numero.numero + 1

for fiche in FicheZoneDelimitee.objects.filter(visibilite="brouillon"):
nouveau_numero = NumeroFiche.objects.create(annee=annee_courante, numero=prochain_numero)
FicheZoneDelimitee.objects.filter(id=fiche.id).update(numero=nouveau_numero)
prochain_numero += 1


class Migration(migrations.Migration):
dependencies = [
("core", "0020_create_access_admin_group"),
("sv", "0040_rename_OE_prefix_20241119_1541"),
]

operations = [
migrations.AlterField(
model_name="fichezonedelimitee",
name="numero",
field=models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="sv.numerofiche",
verbose_name="Numéro de fiche",
),
),
migrations.RunPython(
set_numero_to_none_for_existing_fiche_zone_delimitee_in_brouillon,
reverse_set_numero_to_none_for_existing_fiche_zone_delimitee_in_brouillon,
),
migrations.AddConstraint(
model_name="fichezonedelimitee",
constraint=models.CheckConstraint(
check=models.Q(("visibilite", "brouillon"), ("numero__isnull", False), _negated=True),
name="check_fiche_zone_delimitee_numero_fiche_is_null_when_visibilite_is_brouillon",
),
),
]
12 changes: 10 additions & 2 deletions sv/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,9 +598,17 @@ class UnitesSurfaceTamponTolale(TextChoices):
class Meta:
verbose_name = "Fiche zone délimitée"
verbose_name_plural = "Fiches zones délimitées"
constraints = [
models.CheckConstraint(
check=~(Q(visibilite="brouillon") & Q(numero__isnull=False)),
name="check_fiche_zone_delimitee_numero_fiche_is_null_when_visibilite_is_brouillon",
),
]

date_creation = models.DateTimeField(auto_now_add=True, verbose_name="Date de création")
numero = models.OneToOneField(NumeroFiche, on_delete=models.PROTECT, verbose_name="Numéro de fiche")
numero = models.OneToOneField(
NumeroFiche, on_delete=models.PROTECT, verbose_name="Numéro de fiche", null=True, blank=True
)
createur = models.ForeignKey(Structure, on_delete=models.PROTECT, verbose_name="Créateur")
organisme_nuisible = models.ForeignKey(
OrganismeNuisible,
Expand Down Expand Up @@ -639,7 +647,7 @@ class Meta:
objects = FicheZoneManager()

def save(self, *args, **kwargs):
if not self.pk:
if not self.numero and self.visibilite == Visibilite.LOCAL:
self.numero = NumeroFiche.get_next_numero()
super().save(*args, **kwargs)

Expand Down
2 changes: 1 addition & 1 deletion sv/templates/sv/fichezonedelimitee_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<div class="fr-container--fluid fr-m-4w ">
<div class="fiche-header">
<div>
<h1 class="fr-mb-0-5v">Fiche zone délimitée n° {{ fiche.numero }}</h1>
<h1 class="fr-mb-0-5v">Fiche zone délimitée{% if fiche.numero %} n° {{ fiche.numero }}{% endif %}</h1>
<p class="fr-badge fr-badge--no-icon">{{ fiche.visibilite }}</p>
<p class="fr-badge fr-badge--{{fiche.etat.libelle|etat_fiche_color}} fr-badge--no-icon">{{ fiche.etat }}</p>
</div>
Expand Down
1 change: 1 addition & 0 deletions sv/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def _fiche_zone_bakery():
_fill_optional=True,
createur=mocked_authentification_user.agent.structure,
etat=etat,
visibilite=Visibilite.LOCAL,
)

return _fiche_zone_bakery
Expand Down
17 changes: 7 additions & 10 deletions sv/tests/test_fichedetection_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
Region,
StructurePreleveur,
SiteInspection,
FicheZoneDelimitee,
)

from sv.constants import REGIONS, DEPARTEMENTS
Expand Down Expand Up @@ -452,8 +453,6 @@ def test_fiche_detection_with_free_link(
choice_js_fill,
):
fiche_zone = fiche_zone_bakery()
fiche_zone.visibilite = Visibilite.LOCAL
fiche_zone.save()
page.goto(f"{live_server.url}{reverse('fiche-detection-creation')}")
fiche_input = "Fiche zone délimitée : " + str(fiche_zone.numero)
choice_js_fill(page, "#liens-libre .choices", str(fiche_zone.numero), fiche_input)
Expand All @@ -474,16 +473,14 @@ def test_fiche_detection_with_free_link(
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_cant_pick,
):
fiche_zone = fiche_zone_bakery()
fiche_zone.visibilite = Visibilite.BROUILLON
fiche_zone.createur = baker.make(Structure)
fiche_zone.save()

fiche_zone = FicheZoneDelimitee.objects.create(
visibilite=Visibilite.BROUILLON,
createur=baker.make(Structure),
organisme_nuisible=baker.make(OrganismeNuisible),
statut_reglementaire=baker.make(StatutReglementaire),
)
page.goto(f"{live_server.url}{reverse('fiche-detection-creation')}")
fiche_input = "Fiche zone délimitée : " + str(fiche_zone.numero)
choice_js_cant_pick(page, "#liens-libre .choices", str(fiche_zone.numero), fiche_input)
Expand Down
16 changes: 11 additions & 5 deletions sv/tests/test_fichedetection_form.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import pytest
from model_bakery import baker
from playwright.sync_api import Page, expect
from django.urls import reverse

Expand All @@ -10,6 +11,9 @@
Region,
StructurePreleveur,
FicheDetection,
FicheZoneDelimitee,
StatutReglementaire,
OrganismeNuisible,
)

from sv.constants import REGIONS, DEPARTEMENTS, STRUCTURES_PRELEVEUR
Expand Down Expand Up @@ -748,14 +752,16 @@ def test_add_prelevement_btn_is_visible_if_lieu_exists(


@pytest.mark.django_db
def test_cant_see_fiches_brouillon_in_liens_libres_in_add_form(
page, form_elements: FicheDetectionFormDomElements, mocked_authentification_user, fiche_zone
):
def test_cant_see_fiches_brouillon_in_liens_libres_in_add_form(page, mocked_authentification_user):
FicheDetection.objects.create(
visibilite=Visibilite.BROUILLON, createur=mocked_authentification_user.agent.structure
)
fiche_zone.visibilite = Visibilite.BROUILLON
fiche_zone.save()
FicheZoneDelimitee.objects.create(
visibilite=Visibilite.BROUILLON,
createur=mocked_authentification_user.agent.structure,
organisme_nuisible=baker.make(OrganismeNuisible),
statut_reglementaire=baker.make(StatutReglementaire),
)
page.reload()
select_options = page.locator("#liens-libre .choices__list--dropdown .choices__item")
expect(select_options).to_have_count(1)
Expand Down
12 changes: 8 additions & 4 deletions sv/tests/test_fichedetection_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
StructurePreleveur,
Etat,
SiteInspection,
FicheZoneDelimitee,
StatutReglementaire,
)
from ..models import (
Region,
Expand Down Expand Up @@ -1120,16 +1122,18 @@ def test_can_publish_fiche_detection_in_visibilite_brouillon_from_update_form(
def test_cant_see_fiches_brouillon_in_liens_libres_in_update_form(
live_server,
page,
form_elements: FicheDetectionFormDomElements,
mocked_authentification_user,
fiche_detection,
fiche_zone,
):
FicheDetection.objects.create(
visibilite=Visibilite.BROUILLON, createur=mocked_authentification_user.agent.structure
)
fiche_zone.visibilite = Visibilite.BROUILLON
fiche_zone.save()
FicheZoneDelimitee.objects.create(
visibilite=Visibilite.BROUILLON,
createur=mocked_authentification_user.agent.structure,
organisme_nuisible=baker.make(OrganismeNuisible),
statut_reglementaire=baker.make(StatutReglementaire),
)
page.goto(f"{live_server.url}{get_fiche_detection_update_form_url(fiche_detection)}")
select_options = page.locator("#liens-libre .choices__list--dropdown .choices__item")
expect(select_options).to_have_count(1)
Expand Down
14 changes: 10 additions & 4 deletions sv/tests/test_fichezonedelimite_visibilite_update.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pytest
from model_bakery import baker
from playwright.sync_api import Page, expect
from core.models import Structure, Visibilite
from core.constants import BSV_STRUCTURE, MUS_STRUCTURE, AC_STRUCTURE
from sv.models import FicheZoneDelimitee, OrganismeNuisible, StatutReglementaire


def _update_visibilite_fiche(fiche, visibilite_libelle):
Expand All @@ -20,13 +22,18 @@ def test_cannot_update_fiche_zone_delimitee_visibilite_by_other_structures(
expect(page.get_by_text("Modifier la visibilité")).not_to_be_visible()


@pytest.mark.django_db
def test_agent_in_structure_createur_can_update_fiche_zone_delimitee_visibilite_brouillon(
live_server, page: Page, fiche_zone, mocked_authentification_user
live_server, page: Page, mocked_authentification_user
):
"""Test qu'un agent appartenant à la structure créatrice d'une fiche
peut modifier la visibilité de cette fiche (passer en local) si elle est en visibilité brouillon"""
fiche_zone.createur = mocked_authentification_user.agent.structure
fiche_zone.save()
fiche_zone = FicheZoneDelimitee.objects.create(
visibilite=Visibilite.BROUILLON,
createur=mocked_authentification_user.agent.structure,
organisme_nuisible=baker.make(OrganismeNuisible),
statut_reglementaire=baker.make(StatutReglementaire),
)
page.goto(f"{live_server.url}{fiche_zone.get_absolute_url()}")
page.get_by_role("button", name="Actions").click()
expect(page.get_by_role("link", name="Modifier la visibilité")).to_be_visible()
Expand Down Expand Up @@ -61,7 +68,6 @@ def test_agent_ac_can_update_fiche_zone_delimitee_visibilite_local_to_national(
live_server, page: Page, fiche_zone, mocked_authentification_user, structure_ac: str
):
"""Test qu'un agent appartenant à l'AC peut modifier la visibilité d'une fiche de local à national"""
_update_visibilite_fiche(fiche_zone, Visibilite.LOCAL)
mocked_authentification_user.agent.structure, _ = Structure.objects.get_or_create(
niveau1=AC_STRUCTURE, niveau2=structure_ac
)
Expand Down
33 changes: 29 additions & 4 deletions sv/tests/test_fichezonedelimitee_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from django.urls import reverse

from core.models import Visibilite, LienLibre
from sv.models import FicheZoneDelimitee, ZoneInfestee, FicheDetection, Etat
from sv.models import FicheZoneDelimitee, ZoneInfestee, FicheDetection, Etat, OrganismeNuisible, StatutReglementaire
from sv.tests.test_utils import FicheZoneDelimiteeFormPage
from sv.forms import RattachementChoices

Expand Down Expand Up @@ -161,6 +161,27 @@ def test_can_create_fiche_zone_delimitee_in_draft(
assert fiche_from_db.visibilite == Visibilite.BROUILLON


@pytest.mark.django_db
def test_fiche_zone_delimitee_numero_is_null_when_save_with_visibilite_brouillon(
live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection
):
fiche_detection.organisme_nuisible = baker.make("OrganismeNuisible")
fiche_detection.statut_reglementaire = baker.make("StatutReglementaire")
fiche_detection.save()
fiche = baker.prepare(FicheZoneDelimitee, _fill_optional=True, etat=Etat.objects.get(id=Etat.get_etat_initial()))
form_page = FicheZoneDelimiteeFormPage(page, choice_js_fill)

form_page.goto_create_form_page(live_server, fiche_detection.pk, RattachementChoices.HORS_ZONE_INFESTEE)
form_page.fill_form(fiche)
page.get_by_role("button", name="Enregistrer le brouillon", exact=True).click()

form_page.check_message_succes()
assert FicheZoneDelimitee.objects.count() == 1
fiche_from_db = FicheZoneDelimitee.objects.get()
assert fiche_from_db.visibilite == Visibilite.BROUILLON
assert fiche_from_db.numero is None


@pytest.mark.django_db
def test_can_create_fiche_zone_delimitee_with_2_zones_infestees(
live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection
Expand Down Expand Up @@ -423,11 +444,15 @@ def test_free_links_are_ordered_in_form(

@pytest.mark.django_db
def test_cant_see_fiches_brouillon_in_liens_libres(
live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection, fiche_zone
live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection
):
FicheDetection.objects.create(visibilite=Visibilite.BROUILLON, createur=fiche_detection.createur)
fiche_zone.visibilite = Visibilite.BROUILLON
fiche_zone.save()
FicheZoneDelimitee.objects.create(
visibilite=Visibilite.BROUILLON,
createur=fiche_detection.createur,
organisme_nuisible=baker.make(OrganismeNuisible),
statut_reglementaire=baker.make(StatutReglementaire),
)
form_page = FicheZoneDelimiteeFormPage(page, choice_js_fill)
form_page.goto_create_form_page(live_server, fiche_detection.pk, RattachementChoices.HORS_ZONE_INFESTEE)
select_options = page.locator("#liens-libre .choices__list--dropdown .choices__item")
Expand Down
17 changes: 11 additions & 6 deletions sv/tests/test_fichezonedelimitee_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from core.models import LienLibre, Visibilite
from sv.forms import RattachementChoices
from sv.tests.test_utils import FicheZoneDelimiteeFormPage
from sv.models import ZoneInfestee, FicheZoneDelimitee, FicheDetection, Etat
from sv.models import ZoneInfestee, FicheZoneDelimitee, FicheDetection, Etat, OrganismeNuisible, StatutReglementaire


def test_fichezonedelimitee_update_form_content(
Expand Down Expand Up @@ -135,7 +135,7 @@ def test_update_form_cant_have_same_detection_in_hors_zone_infestee_and_zone_inf
etat=Etat.objects.get(id=Etat.get_etat_initial()),
organisme_nuisible=fiche_detection.organisme_nuisible,
statut_reglementaire=fiche_detection.statut_reglementaire,
_fill_optional=True,
visibilite=Visibilite.BROUILLON,
)
baker.make(ZoneInfestee, fiche_zone_delimitee=fiche_zone_delimitee, _fill_optional=True)
fiche_detection.hors_zone_infestee = fiche_zone_delimitee
Expand All @@ -161,7 +161,7 @@ def test_update_form_cant_have_same_detection_in_two_zone_infestee(
etat=Etat.objects.get(id=Etat.get_etat_initial()),
organisme_nuisible=fiche_detection.organisme_nuisible,
statut_reglementaire=fiche_detection.statut_reglementaire,
_fill_optional=True,
visibilite=Visibilite.BROUILLON,
)
zone_infestee = baker.make(ZoneInfestee, fiche_zone_delimitee=fiche_zone_delimitee, _fill_optional=True)
fiche_detection.zone_infestee = zone_infestee
Expand Down Expand Up @@ -191,6 +191,7 @@ def test_update_fiche_can_add_and_delete_free_links(
etat=Etat.objects.get(id=Etat.get_etat_initial()),
organisme_nuisible=fiche_detection.organisme_nuisible,
statut_reglementaire=fiche_detection.statut_reglementaire,
visibilite=Visibilite.LOCAL,
_fill_optional=True,
)
LienLibre.objects.create(related_object_1=fiche_zone_delimitee, related_object_2=other_fiche)
Expand Down Expand Up @@ -241,11 +242,15 @@ def test_update_fiche_zone_cant_add_self_links(

@pytest.mark.django_db
def test_cant_see_fiches_brouillon_in_liens_libres(
live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection, fiche_zone
live_server, page: Page, choice_js_fill, fiche_detection: FicheDetection
):
FicheDetection.objects.create(visibilite=Visibilite.BROUILLON, createur=fiche_detection.createur)
fiche_zone.visibilite = Visibilite.BROUILLON
fiche_zone.save()
FicheZoneDelimitee.objects.create(
visibilite=Visibilite.BROUILLON,
createur=fiche_detection.createur,
organisme_nuisible=baker.make(OrganismeNuisible),
statut_reglementaire=baker.make(StatutReglementaire),
)
form_page = FicheZoneDelimiteeFormPage(page, choice_js_fill)
form_page.goto_create_form_page(live_server, fiche_detection.pk, RattachementChoices.HORS_ZONE_INFESTEE)
select_options = page.locator("#liens-libre .choices__list--dropdown .choices__item")
Expand Down
Loading

0 comments on commit bfa0c72

Please sign in to comment.