Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pas de numéro de fiche zone délimitée si visibilité brouillon #490

Merged
merged 1 commit into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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