Skip to content

Commit

Permalink
✨(dashboard) add validation and data updates for consent management
Browse files Browse the repository at this point in the history
Add validation for company, control authority, and representative data in consent bulk updates.
Enhanced `ConsentFormView` to handle form errors gracefully and updated consent records with validated fields and related data.
Adjusted tests to incorporate mock form data and validated consent updates.
  • Loading branch information
ssorin committed Feb 3, 2025
1 parent a24a96c commit 678a5fe
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 38 deletions.
10 changes: 9 additions & 1 deletion src/dashboard/apps/consent/forms.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Dashboard consent app forms."""

from datetime import datetime

from django import forms
from django.forms.widgets import CheckboxInput
from django.utils.translation import gettext_lazy as _
Expand All @@ -20,7 +22,7 @@ class ConsentForm(forms.Form):
"""

# Specific authorisation checkbox
is_authorized_signatory = forms.BooleanField(
is_authoritative_signatory = forms.BooleanField(
required=True,
initial=False,
widget=ConsentCheckboxInput(
Expand Down Expand Up @@ -101,6 +103,12 @@ class ConsentForm(forms.Form):
),
)

signed_at = forms.DateField(
initial=datetime.now().strftime("%d/%m/%Y"),
required=True,
widget=forms.HiddenInput(attrs={"readonly": "readonly"}),
)

# Global authorisation checkbox - this field must be in last position.
consent_agreed = forms.BooleanField(
required=True,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,3 @@
<br />
<strong>Le :</strong> {% now "d/m/Y" %}
</p>

<input class="fr-input"
type="hidden"
id="text-input-entity-name"
name="text-input-entity-name"
value="{% now "d/m/Y" %}"
readonly="readonly">
19 changes: 13 additions & 6 deletions src/dashboard/apps/consent/templates/consent/manage.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,22 @@ <h2>Gérer les autorisations</h2>
<form action="" method="post">
{% csrf_token %}

<div class="fr-messages-group" id="error-messages" aria-live="assertive">
{% if form.errors %}
{% if form.errors %}
<div class="fr-messages-group" id="error-messages" aria-live="assertive">
<div class="{% if form.consent_agreed.errors %}fr-pl-3v{% endif %} fr-mb-6v">
<p class="fr-message fr-message--error" id="message-error">
{% trans "The form contains errors" %}
</p>
<ul id="message-non-field-error">
<li class="fr-message fr-message--error" id="message-error">
{% trans "The form contains errors" %}
</li>
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<li class="fr-message fr-message--error">{{ error }}</li>
{% endfor %}
{% endif %}
</ul>
</div>
{% endif %}
</div>
{% endif %}

{% include "consent/includes/_manage_consents.html" %}
{% include "consent/includes/_manage_company_informations.html" %}
Expand Down
68 changes: 59 additions & 9 deletions src/dashboard/apps/consent/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Dashboard consent views tests."""

import datetime
import uuid
from http import HTTPStatus
from unittest.mock import MagicMock

import pytest
from django.urls import reverse
Expand All @@ -13,6 +15,16 @@
from apps.consent.views import ConsentFormView
from apps.core.factories import DeliveryPointFactory, EntityFactory

FORM_CLEANED_DATA = {
"is_authoritative_signatory": True,
"allows_measurements": True,
"allows_daily_index_readings": True,
"allows_max_daily_power": True,
"allows_load_curve": True,
"allows_technical_contractual_data": True,
"signed_at": "2025-03-01",
}


@pytest.mark.django_db
def test_bulk_update_consent_status_without_ids(rf):
Expand All @@ -30,14 +42,16 @@ def test_bulk_update_consent_status_without_ids(rf):
assert all(c == AWAITING for c in Consent.objects.values_list("status", flat=True))

# bulk update to VALIDATED of… nothing, and check 0 record have been updated.
assert view._bulk_update_consent([], VALIDATED) == 0
mock_form = MagicMock()
mock_form.cleaned_data = FORM_CLEANED_DATA
assert view._bulk_update_consent([], VALIDATED, mock_form) == 0

# and checks that the data has not changed after the update.
assert all(c == AWAITING for c in Consent.objects.values_list("status", flat=True))


@pytest.mark.django_db
def test_bulk_update_consent_status(rf):
def test_bulk_update_consent_status(rf, settings):
"""Test all consents are correctly updated."""
user = UserFactory()

Expand All @@ -56,19 +70,51 @@ def test_bulk_update_consent_status(rf):
# check data before update
assert all(c == AWAITING for c in Consent.objects.values_list("status", flat=True))

mock_form = MagicMock()
mock_form.cleaned_data = FORM_CLEANED_DATA

# bulk update to VALIDATED, and check all records have been updated.
assert view._bulk_update_consent(ids, VALIDATED) == size
assert view._bulk_update_consent(ids, VALIDATED, mock_form) == size

# and checks that the data has changed to VALIDATED after the update.
assert all(c == VALIDATED for c in Consent.objects.values_list("status", flat=True))
for c in Consent.objects.all():
assert c.signed_at == datetime.datetime(
2025, 3, 1, 0, 0, tzinfo=datetime.timezone.utc
)
assert c.signature_location == settings.CONSENT_SIGNATURE_LOCATION

# check company data are present
assert c.company is not None
assert c.company["name"] == entity.name
assert c.company["company_type"] == entity.company_type
assert c.company["siret"] == entity.siret

# check company representative data are present
assert c.company is not None
assert c.company_representative["email"] == user.email

# check control authority data are presents
assert c.control_authority is not None
assert c.control_authority["name"] == settings.CONSENT_CONTROL_AUTHORITY["name"]
assert (
c.control_authority["email"] == settings.CONSENT_CONTROL_AUTHORITY["email"]
)

# check authorizations (boolean fields)
assert c.is_authoritative_signatory is True
assert c.allows_measurements is True
assert c.allows_max_daily_power is True
assert c.allows_load_curve is True
assert c.allows_technical_contractual_data is True

# bulk update from VALIDATED to AWAITING: no data must be updated
assert view._bulk_update_consent(ids, AWAITING) == 0
# bulk update from VALIDATED to AWAITING: no data must be updated.
assert view._bulk_update_consent(ids, AWAITING, mock_form) == 0
# and checks that the status has not changed after the update.
assert all(c == VALIDATED for c in Consent.objects.values_list("status", flat=True))

# bulk update from VALIDATED to REVOKED: no data must be updated
assert view._bulk_update_consent(ids, REVOKED) == 0
# bulk update from VALIDATED to REVOKED: no data must be updated.
assert view._bulk_update_consent(ids, REVOKED, mock_form) == 0
# and checks that the status has not changed after the update.
assert all(c == VALIDATED for c in Consent.objects.values_list("status", flat=True))

Expand Down Expand Up @@ -98,7 +144,9 @@ def test_bulk_update_consent_status_with_fake_id(rf):

# bulk update to VALIDATED,
# and check all records have been updated except the fake id.
assert view._bulk_update_consent(ids, VALIDATED) == size
mock_form = MagicMock()
mock_form.cleaned_data = FORM_CLEANED_DATA
assert view._bulk_update_consent(ids, VALIDATED, mock_form) == size

# and checks that the data has changed to VALIDATED after the update.
assert all(c == VALIDATED for c in Consent.objects.values_list("status", flat=True))
Expand Down Expand Up @@ -136,7 +184,9 @@ def test_bulk_update_consent_without_user_perms(rf):

# bulk update to VALIDATED,
# and check all records have been updated except the wrong ID.
assert view._bulk_update_consent(ids, VALIDATED) == size
mock_form = MagicMock()
mock_form.cleaned_data = FORM_CLEANED_DATA
assert view._bulk_update_consent(ids, VALIDATED, mock_form) == size

# and checks that the data has changed to VALIDATED after the update.
assert all(
Expand Down
Loading

0 comments on commit 678a5fe

Please sign in to comment.