diff --git a/aidants_connect/common/forms.py b/aidants_connect/common/forms.py
index af3012b73..a8b6adc19 100644
--- a/aidants_connect/common/forms.py
+++ b/aidants_connect/common/forms.py
@@ -1,4 +1,4 @@
-from django.forms import ModelForm
+from django.forms import Form, ModelForm
from django.forms.utils import ErrorList
from django.utils.html import format_html
@@ -19,3 +19,10 @@ def __init__(self, **kwargs):
kwargs.setdefault("label_suffix", "")
kwargs.setdefault("error_class", PatchedErrorList)
super().__init__(**kwargs)
+
+
+class PatchedForm(Form):
+ def __init__(self, **kwargs):
+ kwargs.setdefault("error_class", PatchedErrorList)
+ kwargs.setdefault("label_suffix", "")
+ super().__init__(**kwargs)
diff --git a/aidants_connect_habilitation/forms.py b/aidants_connect_habilitation/forms.py
index 7491de2de..f13af2622 100644
--- a/aidants_connect_habilitation/forms.py
+++ b/aidants_connect_habilitation/forms.py
@@ -1,18 +1,24 @@
from django.conf import settings
from django.core.exceptions import ValidationError
from django.forms import (
- Form,
formset_factory,
ChoiceField,
CharField,
BaseFormSet,
+ BooleanField,
FileField,
)
+from django.urls import reverse
+from django.utils.html import format_html
from phonenumber_field.formfields import PhoneNumberField
from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget
from aidants_connect.common.constants import RequestOriginConstants
-from aidants_connect.common.forms import PatchedErrorListForm, PatchedErrorList
+from aidants_connect.common.forms import (
+ PatchedErrorListForm,
+ PatchedErrorList,
+ PatchedForm,
+)
from aidants_connect_habilitation import models
from aidants_connect_habilitation.models import (
AidantRequest,
@@ -36,6 +42,7 @@ class IssuerForm(PatchedErrorListForm):
)
def __init__(self, render_non_editable=False, **kwargs):
+ kwargs.setdefault("label_suffix", "")
super().__init__(**kwargs)
self.render_non_editable = render_non_editable
if self.render_non_editable:
@@ -168,19 +175,9 @@ class Meta:
class BaseAidantRequestFormSet(BaseFormSet):
- def __init__(
- self,
- data=None,
- files=None,
- auto_id="id_%s",
- prefix=None,
- initial=None,
- error_class=PatchedErrorList,
- form_kwargs=None,
- ):
- super().__init__(
- data, files, auto_id, prefix, initial, error_class, form_kwargs
- )
+ def __init__(self, **kwags):
+ kwags.setdefault("error_class", PatchedErrorList)
+ super().__init__(**kwags)
def save(self, organisation: OrganisationRequest, commit=True):
result = []
@@ -226,5 +223,31 @@ def save(self, organisation: OrganisationRequest, commit=True):
)
-class ValidationForm(Form):
- pass
+class ValidationForm(PatchedForm):
+ cgu = BooleanField(
+ required=True,
+ label='J’ai pris connaissance des '
+ "conditions générales d’utilisation et je les valide.",
+ )
+ dpo = BooleanField(
+ required=True,
+ label="Je confirme que le délégué à la protection des données "
+ "de mon organisation est informé de ma demande.",
+ )
+ professionals_only = BooleanField(
+ required=True,
+ label="Je confirme que la liste des aidants à habiliter contient "
+ "exclusivement des aidants professionnels. Elle ne contient "
+ "donc ni service civique, ni bénévole, ni apprenti, ni stagiaire.",
+ )
+ without_elected = BooleanField(
+ required=True,
+ label="Je confirme qu’aucun élu n’est impliqué dans l’habilitation "
+ "Aidants Connect. Le responsable Aidants Connect ainsi que les aidants "
+ "à habiliter ne sont pas des élus.",
+ )
+
+ def __init__(self, **kwargs):
+ super().__init__(**kwargs)
+ cgu = self["cgu"]
+ cgu.label = format_html(cgu.label, url=reverse("cgu"))
diff --git a/aidants_connect_habilitation/models.py b/aidants_connect_habilitation/models.py
index ebf9fa331..b551df074 100644
--- a/aidants_connect_habilitation/models.py
+++ b/aidants_connect_habilitation/models.py
@@ -35,6 +35,9 @@ class Person(models.Model):
def __str__(self):
return f"{self.first_name} {self.last_name}"
+ def get_full_name(self):
+ return str(self)
+
class Meta:
abstract = True
diff --git a/aidants_connect_habilitation/templates/validation_form.html b/aidants_connect_habilitation/templates/validation_form.html
index e69de29bb..5ef67082d 100644
--- a/aidants_connect_habilitation/templates/validation_form.html
+++ b/aidants_connect_habilitation/templates/validation_form.html
@@ -0,0 +1,111 @@
+{% extends 'layouts/main-habilitation.html' %}
+{% load static form_extras %}
+
+{% block title %}
+ Aidants Connect — Récapitulatif
+{% endblock %}
+
+{% block content %}
+
Récapitulatif de la demande
+
+ Vous trouverez ici les informations principales saisies dans le formulaire.
+ Il est possible de les éditer si besoin.
+
+
+ Informations générales
+
+
+
+
+ Vous faites cette demande pour :
+
+
+ {{ organisation.address }}
+ {{ organisation.zipcode }}
+ {{ organisation.city }}
+
+
+ SIRET : {{ organisation.siret }}
+
+
+ Éditer
+
+
+
+
+ Responsable de structure
+
+ {{ organisation.manager.get_full_name }}
+ {{ organisation.manager.profession }}
+
+ {{ organisation.manager.email }}
+ {{ organisation.manager.phone }}
+
+
+ {{ organisation.manager.address }}
+ {{ organisation.manager.zipcode }}
+ {{ organisation.manager.city }}
+
+
+ Ce responsable est aussi aidant : {{ organisation.manager.is_aidant|yesno:"Oui,Non" }}
+
+ Éditer
+
+
+ {% if organisation.data_privacy_officer %}
+
+ {% endif %}
+
+ {% for aidant_request in organisation.aidant_requests.all %}
+
+ {% endfor %}
+
+
+{% endblock %}
diff --git a/aidants_connect_habilitation/tests/test_views.py b/aidants_connect_habilitation/tests/test_views.py
index cee8bf439..fec3cad23 100644
--- a/aidants_connect_habilitation/tests/test_views.py
+++ b/aidants_connect_habilitation/tests/test_views.py
@@ -43,10 +43,11 @@ class NewIssuerFormViewTests(TestCase):
def setUpTestData(cls):
cls.client = Client()
cls.pattern_name = "habilitation_new_issuer"
+ cls.template_name = "issuer_form.html"
def test_template(self):
response = self.client.get(reverse(self.pattern_name))
- self.assertTemplateUsed(response, "issuer_form.html")
+ self.assertTemplateUsed(response, self.template_name)
def test_redirect_valid_post_to_new_organisation(self):
temp_uuid = "d6cc0622-b525-41ee-a8dc-c65de9536dba"
@@ -73,6 +74,8 @@ class ModifyIssuerFormViewTests(TestCase):
def setUpTestData(cls):
cls.client = Client()
cls.pattern_name = "habilitation_modify_issuer"
+ cls.template_name = "issuer_form.html"
+ cls.issuer: Issuer = IssuerFactory()
def test_404_on_bad_issuer_id(self):
response = self.client.get(
@@ -87,18 +90,26 @@ def test_404_on_bad_issuer_id(self):
)
self.assertEqual(response.status_code, 404)
+ def test_template(self):
+ response = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={"issuer_id": self.issuer.issuer_id},
+ )
+ )
+ self.assertTemplateUsed(response, self.template_name)
+
def test_on_correct_issuer_id_post_updates_model(self):
- model: Issuer = IssuerFactory()
new_name = Faker("first_name").evaluate(None, None, {"locale": DEFAULT_LOCALE})
- form = IssuerForm(data={**model_to_dict(model), "first_name": new_name})
+ form = IssuerForm(data={**model_to_dict(self.issuer), "first_name": new_name})
if not form.is_valid():
raise ValueError(str(form.errors))
- self.assertNotEqual(model.first_name, new_name)
+ self.assertNotEqual(self.issuer.first_name, new_name)
response = self.client.post(
- reverse(self.pattern_name, kwargs={"issuer_id": model.issuer_id}),
+ reverse(self.pattern_name, kwargs={"issuer_id": self.issuer.issuer_id}),
form.clean(),
)
@@ -106,13 +117,15 @@ def test_on_correct_issuer_id_post_updates_model(self):
response,
reverse(
"habilitation_new_organisation",
- kwargs={"issuer_id": model.issuer_id},
+ kwargs={"issuer_id": self.issuer.issuer_id},
),
)
- model.refresh_from_db()
+ self.issuer.refresh_from_db()
self.assertEqual(
- model.first_name, new_name, "The model's first_name field wasn't modified"
+ self.issuer.first_name,
+ new_name,
+ "The model's first_name field wasn't modified",
)
@@ -122,6 +135,8 @@ class NewOrganisationRequestFormViewTests(TestCase):
def setUpTestData(cls):
cls.client = Client()
cls.pattern_name = "habilitation_new_organisation"
+ cls.template_name = "organisation_form.html"
+ cls.issuer: Issuer = IssuerFactory()
def test_404_on_bad_issuer_id(self):
uuid = uuid4()
@@ -138,9 +153,13 @@ def test_404_on_bad_issuer_id(self):
)
self.assertEqual(response.status_code, 404)
- def test_redirect_valid_post_to_new_aidants(self):
- issuer: Issuer = IssuerFactory()
+ def test_template(self):
+ response = self.client.get(
+ reverse(self.pattern_name, kwargs={"issuer_id": self.issuer.issuer_id})
+ )
+ self.assertTemplateUsed(response, self.template_name)
+ def test_redirect_valid_post_to_new_aidants(self):
cleaned_data = utils.get_form(OrganisationRequestForm).clean()
cleaned_data["public_service_delegation_attestation"] = ""
cleaned_data["type"] = cleaned_data["type"].id
@@ -148,7 +167,7 @@ def test_redirect_valid_post_to_new_aidants(self):
response = self.client.post(
reverse(
self.pattern_name,
- kwargs={"issuer_id": issuer.issuer_id},
+ kwargs={"issuer_id": self.issuer.issuer_id},
),
cleaned_data,
)
@@ -158,8 +177,8 @@ def test_redirect_valid_post_to_new_aidants(self):
reverse(
"habilitation_new_aidants",
kwargs={
- "issuer_id": issuer.issuer_id,
- "draft_id": issuer.organisation_requests.first().draft_id,
+ "issuer_id": self.issuer.issuer_id,
+ "draft_id": self.issuer.organisation_requests.first().draft_id,
},
),
)
@@ -171,7 +190,38 @@ class ModifyOrganisationRequestFormViewTests(TestCase):
def setUpTestData(cls):
cls.client = Client()
cls.pattern_name = "habilitation_modify_organisation"
+ cls.template_name = "organisation_form.html"
cls.issuer: Issuer = IssuerFactory()
+ cls.organisation: OrganisationRequest = OrganisationRequestFactory(
+ draft_id=uuid4()
+ )
+
+ def test_404_on_bad_issuer_id(self):
+ issuer_id = uuid4()
+
+ response: HttpResponse = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={"issuer_id": issuer_id, "draft_id": self.organisation.draft_id},
+ )
+ )
+ self.assertEqual(response.status_code, 404)
+
+ draft_id = uuid4()
+
+ cleaned_data = utils.get_form(OrganisationRequestForm).clean()
+ cleaned_data["public_service_delegation_attestation"] = ""
+ response = self.client.post(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": draft_id,
+ },
+ ),
+ cleaned_data,
+ )
+ self.assertEqual(response.status_code, 404)
def test_404_on_bad_draft_id(self):
response = self.client.get(
@@ -195,6 +245,18 @@ def test_404_on_bad_draft_id(self):
)
self.assertEqual(response.status_code, 404)
+ def test_template(self):
+ response = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": self.organisation.draft_id,
+ },
+ )
+ )
+ self.assertTemplateUsed(response, self.template_name)
+
def test_on_correct_issuer_id_post_updates_model(self):
model: OrganisationRequest = OrganisationRequestFactory(
issuer=self.issuer, draft_id=uuid4()
@@ -243,16 +305,18 @@ class AidantsRequestFormViewTests(TestCase):
def setUpTestData(cls):
cls.client = Client()
cls.pattern_name = "habilitation_new_aidants"
+ cls.template_name = "personnel_form.html"
+ cls.organisation: OrganisationRequest = OrganisationRequestFactory(
+ draft_id=uuid4()
+ )
def test_404_on_bad_issuer_id(self):
issuer_id = uuid4()
- organisation: OrganisationRequest = OrganisationRequestFactory(draft_id=uuid4())
-
response: HttpResponse = self.client.get(
reverse(
self.pattern_name,
- kwargs={"issuer_id": issuer_id, "draft_id": organisation.draft_id},
+ kwargs={"issuer_id": issuer_id, "draft_id": self.organisation.draft_id},
)
)
self.assertEqual(response.status_code, 404)
@@ -265,7 +329,7 @@ def test_404_on_bad_issuer_id(self):
reverse(
self.pattern_name,
kwargs={
- "issuer_id": organisation.issuer.issuer_id,
+ "issuer_id": self.organisation.issuer.issuer_id,
"draft_id": draft_id,
},
),
@@ -273,7 +337,43 @@ def test_404_on_bad_issuer_id(self):
)
self.assertEqual(response.status_code, 404)
- def test_redirect_valid_post_to_new_issuer(self):
+ def test_404_on_bad_draft_id(self):
+ issuer: Issuer = IssuerFactory()
+
+ response = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={"issuer_id": issuer.issuer_id, "draft_id": uuid4()},
+ )
+ )
+ self.assertEqual(response.status_code, 404)
+
+ cleaned_data = utils.get_form(OrganisationRequestForm).clean()
+ cleaned_data["public_service_delegation_attestation"] = ""
+ cleaned_data["type"] = cleaned_data["type"].id
+
+ response = self.client.post(
+ reverse(
+ self.pattern_name,
+ kwargs={"issuer_id": issuer.issuer_id, "draft_id": uuid4()},
+ ),
+ cleaned_data,
+ )
+ self.assertEqual(response.status_code, 404)
+
+ def test_template(self):
+ response = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": self.organisation.draft_id,
+ },
+ )
+ )
+ self.assertTemplateUsed(response, self.template_name)
+
+ def test_redirect_valid_post_to_validation(self):
organisation: OrganisationRequest = OrganisationRequestFactory(draft_id=uuid4())
manager_data = utils.get_form(ManagerForm).data
@@ -309,3 +409,135 @@ def test_redirect_valid_post_to_new_issuer(self):
},
),
)
+
+
+@tag("habilitation")
+class ValidationRequestFormViewTests(TestCase):
+ @classmethod
+ def setUpTestData(cls):
+ cls.client = Client()
+ cls.pattern_name = "habilitation_validation"
+ cls.template_name = "validation_form.html"
+ cls.organisation: OrganisationRequest = OrganisationRequestFactory(
+ draft_id=uuid4()
+ )
+
+ def test_404_on_bad_issuer_id(self):
+ issuer_id = uuid4()
+
+ organisation: OrganisationRequest = OrganisationRequestFactory(draft_id=uuid4())
+
+ response: HttpResponse = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={"issuer_id": issuer_id, "draft_id": organisation.draft_id},
+ )
+ )
+ self.assertEqual(response.status_code, 404)
+
+ draft_id = uuid4()
+
+ cleaned_data = utils.get_form(OrganisationRequestForm).clean()
+ cleaned_data["public_service_delegation_attestation"] = ""
+ response = self.client.post(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": organisation.issuer.issuer_id,
+ "draft_id": draft_id,
+ },
+ ),
+ cleaned_data,
+ )
+ self.assertEqual(response.status_code, 404)
+
+ def test_404_on_bad_draft_id(self):
+ response = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": uuid4(),
+ },
+ )
+ )
+ self.assertEqual(response.status_code, 404)
+
+ cleaned_data = utils.get_form(OrganisationRequestForm).clean()
+ cleaned_data["public_service_delegation_attestation"] = ""
+ cleaned_data["type"] = cleaned_data["type"].id
+
+ response = self.client.post(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": uuid4(),
+ },
+ ),
+ cleaned_data,
+ )
+ self.assertEqual(response.status_code, 404)
+
+ def test_template(self):
+ response = self.client.get(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": self.organisation.draft_id,
+ },
+ )
+ )
+ self.assertTemplateUsed(response, self.template_name)
+
+ def test_redirect_valid_post_to_new_issuer(self):
+ cleaned_data = {
+ "cgu": True,
+ "dpo": True,
+ "professionals_only": True,
+ "without_elected": True,
+ }
+
+ response = self.client.post(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": self.organisation.draft_id,
+ },
+ ),
+ cleaned_data,
+ )
+
+ self.assertRedirects(response, reverse("habilitation_new_issuer"))
+
+ def test_post_invalid_data(self):
+ valid_data = {
+ "cgu": True,
+ "dpo": True,
+ "professionals_only": True,
+ "without_elected": True,
+ }
+
+ for item in valid_data.keys():
+ invalid_data = valid_data.copy()
+ invalid_data[item] = False
+
+ response = self.client.post(
+ reverse(
+ self.pattern_name,
+ kwargs={
+ "issuer_id": self.organisation.issuer.issuer_id,
+ "draft_id": self.organisation.draft_id,
+ },
+ ),
+ invalid_data,
+ )
+
+ self.assertEqual(response.status_code, 200)
+ self.assertTemplateUsed(response, self.template_name)
+ self.assertIn(
+ "Ce champ est obligatoire",
+ str(response.context_data["form"].errors[item]),
+ )
diff --git a/aidants_connect_habilitation/tests/utils.py b/aidants_connect_habilitation/tests/utils.py
index 4ade3dd0a..6a10d453e 100644
--- a/aidants_connect_habilitation/tests/utils.py
+++ b/aidants_connect_habilitation/tests/utils.py
@@ -49,7 +49,7 @@ def _(form_cls: Type[BaseFormSet], **kwargs) -> BaseFormSet:
subdata = {f"form-{i}-{k}": v for (k, v) in subform.clean().items()}
data.update(subdata)
- form = formset_cls(data)
+ form = formset_cls(data=data)
if not form.is_valid():
raise ValueError(str(form.errors))
diff --git a/aidants_connect_habilitation/views.py b/aidants_connect_habilitation/views.py
index 2fc0619d4..822acb406 100644
--- a/aidants_connect_habilitation/views.py
+++ b/aidants_connect_habilitation/views.py
@@ -8,7 +8,47 @@
PersonnelForm,
ValidationForm,
)
-from aidants_connect_habilitation.models import Issuer, OrganisationRequest
+from aidants_connect_habilitation.models import (
+ Issuer,
+ OrganisationRequest,
+)
+
+
+__all__ = [
+ "NewHabilitationView",
+ "NewIssuerFormView",
+ "ModifyIssuerFormView",
+ "NewOrganisationRequestFormView",
+ "ModifyOrganisationRequestFormView",
+ "PersonnelRequestFormView",
+ "ValidationRequestFormView",
+]
+
+
+"""Mixins"""
+
+
+class RequestDraftView(FormView):
+ def setup(self, request, *args, **kwargs):
+ super().setup(request, *args, **kwargs)
+ self.issuer = get_object_or_404(Issuer, issuer_id=kwargs.get("issuer_id"))
+
+ def get_context_data(self, **kwargs):
+ return {
+ **super().get_context_data(**kwargs),
+ "issuer": self.issuer,
+ }
+
+
+class LateStageRequestDraftView(RequestDraftView):
+ def setup(self, request, *args, **kwargs):
+ super().setup(request, *args, **kwargs)
+ self.organisation = get_object_or_404(
+ OrganisationRequest, draft_id=kwargs.get("draft_id")
+ )
+
+
+"""Real views"""
class NewHabilitationView(RedirectView):
@@ -42,18 +82,6 @@ def get_form_kwargs(self):
return {**super().get_form_kwargs(), "instance": self.initial_issuer}
-class RequestDraftView(FormView):
- def setup(self, request, *args, **kwargs):
- super().setup(request, *args, **kwargs)
- self.issuer = get_object_or_404(Issuer, issuer_id=kwargs.get("issuer_id"))
-
- def get_context_data(self, **kwargs):
- return {
- **super().get_context_data(**kwargs),
- "issuer": self.issuer,
- }
-
-
class NewOrganisationRequestFormView(RequestDraftView):
template_name = "organisation_form.html"
form_class = OrganisationRequestForm
@@ -73,27 +101,17 @@ def get_success_url(self):
)
-class ModifyOrganisationRequestFormView(NewOrganisationRequestFormView):
- def setup(self, request, *args, **kwargs):
- super().setup(request, *args, **kwargs)
- self.initial_org_request = get_object_or_404(
- OrganisationRequest, draft_id=self.kwargs.get("draft_id")
- )
-
+class ModifyOrganisationRequestFormView(
+ LateStageRequestDraftView, NewOrganisationRequestFormView
+):
def get_form_kwargs(self):
- return {**super().get_form_kwargs(), "instance": self.initial_org_request}
+ return {**super().get_form_kwargs(), "instance": self.organisation}
-class PersonnelRequestFormView(RequestDraftView):
+class PersonnelRequestFormView(LateStageRequestDraftView):
template_name = "personnel_form.html"
form_class = PersonnelForm
- def setup(self, request, *args, **kwargs):
- super().setup(request, *args, **kwargs)
- self.organisation: OrganisationRequest = get_object_or_404(
- OrganisationRequest, draft_id=self.kwargs.get("draft_id")
- )
-
def form_valid(self, form):
manager, data_privacy_officer, _ = form.save(self.organisation)
self.organisation.manager = manager
@@ -117,9 +135,17 @@ def get_success_url(self):
)
-class ValidationRequestFormView(RequestDraftView):
+class ValidationRequestFormView(LateStageRequestDraftView):
template_name = "validation_form.html"
form_class = ValidationForm
+ def get_context_data(self, **kwargs):
+ return {
+ **super().get_context_data(**kwargs),
+ "issuer": self.issuer,
+ "organisation": self.organisation,
+ "aidants": self.organisation.aidant_requests,
+ }
+
def get_success_url(self):
return reverse("habilitation_new_issuer")