diff --git a/src/dashboard/CHANGELOG.md b/src/dashboard/CHANGELOG.md index 36884042..32e1b86f 100644 --- a/src/dashboard/CHANGELOG.md +++ b/src/dashboard/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to - introduce new custom user model - add consent app with Consent model - add core app with Entity and DeliveryPoint models +- add consent form to manage consents of one or many entities [unreleased]: https://github.com/MTES-MCT/qualicharge/compare/main...bootstrap-dashboard-project diff --git a/src/dashboard/apps/consent/fixtures/consent.py b/src/dashboard/apps/consent/fixtures/consent.py index 80597646..c25f632e 100644 --- a/src/dashboard/apps/consent/fixtures/consent.py +++ b/src/dashboard/apps/consent/fixtures/consent.py @@ -28,7 +28,6 @@ def seed_consent(): entity3 = EntityFactory(users=(user3,), proxy_for=(entity1, entity2)) entity4 = EntityFactory(users=(user5,)) - # create delivery points for i in range(1, 4): DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) diff --git a/src/dashboard/apps/consent/management/commands/seed_consent.py b/src/dashboard/apps/consent/management/commands/seed_consent.py index fe00986d..2b14b394 100644 --- a/src/dashboard/apps/consent/management/commands/seed_consent.py +++ b/src/dashboard/apps/consent/management/commands/seed_consent.py @@ -14,6 +14,4 @@ def handle(self, *args, **kwargs): """Executes the command for creating development consent fixtures.""" self.stdout.write(self.style.NOTICE("Seeding database with consents...")) seed_consent() - self.stdout.write( - self.style.SUCCESS("Done.") - ) + self.stdout.write(self.style.SUCCESS("Done.")) diff --git a/src/dashboard/apps/consent/models.py b/src/dashboard/apps/consent/models.py index cda5d1eb..1b1af4da 100644 --- a/src/dashboard/apps/consent/models.py +++ b/src/dashboard/apps/consent/models.py @@ -1,11 +1,14 @@ """Dashboard consent app models.""" +from django.core.exceptions import PermissionDenied from django.db import models +from django.db.models import Count, QuerySet, TextField +from django.db.models.functions import Cast from django.utils import timezone from django.utils.translation import gettext_lazy as _ from apps.auth.models import DashboardUser as User -from apps.core.models import DashboardBase, DeliveryPoint +from apps.core.models import DashboardBase, DeliveryPoint, Entity class Consent(DashboardBase): @@ -59,3 +62,130 @@ def save(self, *args, **kwargs): if self.status == self.REVOKED: self.revoked_at = timezone.now() return super(Consent, self).save(*args, **kwargs) + + @classmethod + def get_awaiting(cls, user: User, selected_entity=None) -> QuerySet: + """Retrieves all awaiting consents or consents for a selected entity for a user. + + Parameters: + - user (User): The user for whom the consents should be retrieved. + - selected_entity (Entity, optional): An optional entity qs. If provided, + consents will be filtered by this entity. + + Returns: + QuerySet: A queryset of Consent objects that match the filter criteria, ordered + by entity and start. + """ + queryset_filters = {} + if selected_entity: + if selected_entity.user_has_perms(user): + queryset_filters["delivery_point__entity"] = selected_entity + else: + raise PermissionDenied() + else: + related_entities = Entity.get_by_user(user) + if related_entities: + queryset_filters["delivery_point__entity__in"] = related_entities + else: + queryset_filters["delivery_point__entity__users"] = user + + return cls.objects.filter( + **queryset_filters, + status=cls.AWAITING, + delivery_point__is_active=True, + start__lte=timezone.now(), + end__gte=timezone.now(), + ).order_by("delivery_point__entity", "start") + + @staticmethod + def count_by_entity(user: User, status: str) -> QuerySet: + """Counts and returns the number of consents for a given user for each entity. + + Parameters: + - user (User): The user for whom to count consents. + - status (str): The status of the consents to be counted. Defaults VALIDATED. + """ + queryset_filters = {} + related_entities = Entity.get_by_user(user) + if related_entities: + queryset_filters["delivery_points__entity__in"] = related_entities + else: + queryset_filters["delivery_points__entity__users"] = user + + return Entity.objects.filter( + **queryset_filters, + delivery_points__is_active=True, + delivery_points__consent__status=status, + delivery_points__consent__start__lte=timezone.now(), + delivery_points__consent__end__gte=timezone.now(), + ).annotate(dcount=Count("delivery_points")) + + @classmethod + def count_validated_by_entity(cls, user: User) -> QuerySet: + """Counts the number of validated consents associated with a given entity.""" + return cls.count_by_entity(user, cls.VALIDATED) + + @classmethod + def count_awaiting_by_entity(cls, user: User) -> QuerySet: + """Counts the number of validated consents associated with a given entity.""" + return cls.count_by_entity(user, cls.AWAITING) + + @classmethod + def _bulk_update_consent_status( + cls, + status: str, + consent_ids: list[str], + user: User, + ) -> int: + """Update the consent status to VALIDATED for the given list of consent IDs.""" + return cls.objects.filter(id__in=consent_ids).update( + status=status, + created_by=user, + updated_at=timezone.now(), + ) + + @classmethod + def set_consents_status_by_ids( + cls, + selected_ids: list[str], + user: User, + consents_qs: QuerySet, + ) -> tuple[int, int]: + """Updates user consents to VALIDATED/AWAITING by given IDs. + + This method updates the consents for a given user by processing and filtering + the selected consent IDs and calculating the non-selected consent IDs. + - Selected ids are update to VALIDATED + - Non-selected ids are update to AWAITING + + Parameters: + selected_ids (list[str]): A list of consent IDs selected by the user. + user (User): The user for whom the consents are being updated. + consents_qs (QuerySet): A queryset containing the consent objects to be + processed. + """ + nb_validated = cls._bulk_update_consent_status( + cls.VALIDATED, selected_ids, user + ) + + base_ids = cls._extract_ids_from_queryset(consents_qs) + awaiting_ids = cls._get_non_selected_ids(base_ids, selected_ids) + nb_awaiting = cls._bulk_update_consent_status(cls.AWAITING, awaiting_ids, user) + + return nb_validated, nb_awaiting + + @staticmethod + def _extract_ids_from_queryset(consents_qs: QuerySet) -> list[str]: + """Extracts string representations of IDs from a queryset.""" + return list( + consents_qs.annotate( + str_id=Cast("id", output_field=TextField()) + ).values_list("str_id", flat=True) + ) + + @staticmethod + def _get_non_selected_ids( + base_ids: list[str], selected_ids: list[str] + ) -> list[str]: + """Retrieve ids from the base_ids that are not present in the selected_ids.""" + return [item for item in base_ids if item not in selected_ids] diff --git a/src/dashboard/apps/consent/static/consent/js/app.js b/src/dashboard/apps/consent/static/consent/js/app.js new file mode 100644 index 00000000..938eb111 --- /dev/null +++ b/src/dashboard/apps/consent/static/consent/js/app.js @@ -0,0 +1,8 @@ +/** + * check/uncheck all checkbox in consent form + */ +document.getElementById("toggle-all") + .addEventListener("change", function() { + const checkboxes = document.getElementsByName("status"); + checkboxes.forEach(checkbox => checkbox.checked = this.checked); +}); diff --git a/src/dashboard/apps/consent/templates/consent/consent-management.html b/src/dashboard/apps/consent/templates/consent/consent-management.html deleted file mode 100644 index e267143f..00000000 --- a/src/dashboard/apps/consent/templates/consent/consent-management.html +++ /dev/null @@ -1,9 +0,0 @@ -{% extends "home/base.html" %} - -{% load i18n %} - -{% block content %} -
+ + + {% trans "Validate content for all entities" %} + + +
+ +- - {% trans "Manage consent" %} - -
-{% endblock content %} + {% include "consent/includes/_resume_awaiting_consents.html" %} + {% include "consent/includes/_resume_validated_consents.html" %} + +{% endblock content %} \ No newline at end of file diff --git a/src/dashboard/apps/consent/templates/consent/manage.html b/src/dashboard/apps/consent/templates/consent/manage.html new file mode 100644 index 00000000..411362c2 --- /dev/null +++ b/src/dashboard/apps/consent/templates/consent/manage.html @@ -0,0 +1,67 @@ +{% extends "home/base.html" %} + +{% load i18n static %} + +{% block content %} +{% trans "No consents to validate" %}
+ {% endif %} +{% endblock content %} + +{% block extra_dashboard_js %} + {% if consents %} + + {% endif %} +{% endblock extra_dashboard_js %} diff --git a/src/dashboard/apps/consent/tests/test_models.py b/src/dashboard/apps/consent/tests/test_models.py index fe34a29f..7fed4c08 100644 --- a/src/dashboard/apps/consent/tests/test_models.py +++ b/src/dashboard/apps/consent/tests/test_models.py @@ -3,12 +3,16 @@ from datetime import timedelta import pytest -from django.utils import formats +from django.core.exceptions import PermissionDenied +from django.db.models import TextField +from django.db.models.functions import Cast +from django.utils import formats, timezone from apps.auth.factories import UserFactory from apps.consent.factories import ConsentFactory from apps.consent.models import Consent -from apps.core.factories import DeliveryPointFactory +from apps.core.factories import DeliveryPointFactory, EntityFactory +from apps.core.models import DeliveryPoint @pytest.mark.django_db @@ -67,3 +71,472 @@ def test_update_consent_status(): assert consent.status == Consent.REVOKED assert consent.updated_at > new_updated_at assert consent.revoked_at is not None + + +@pytest.mark.django_db +def test_consent_queryset_user_without_entity(): + """User without an associated entity. + + Test user without an associated entity doesn't have any consents awaiting approval + and can't access directly to an entity. + """ + user = UserFactory() + user2 = UserFactory() + entity2 = EntityFactory(users=(user2,)) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory(delivery_point=delivery_point, created_by=user2) + + assert Consent.get_awaiting(user).exists() is False + + # test by accessing a specific entity + assert Consent.get_awaiting(user2, entity2).exists() is True + with pytest.raises(PermissionDenied): + Consent.get_awaiting(user, entity2) + + +@pytest.mark.django_db +def test_consent_queryset_standard_user(): + """Test user with one entity and delivery points. + + Test that user with an associated entity and delivery points have correct + number of consents awaiting approval. + """ + user1 = UserFactory() + user2 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,)) + + # Create AWAITING consent + for i in range(1, 4): + dp1 = DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + ConsentFactory(delivery_point=dp1, created_by=user1) + dp2 = DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + ConsentFactory(delivery_point=dp2, created_by=user1) + + # Create VALIDATED consent + delivery_point = DeliveryPointFactory( + provider_assigned_id="entity2_4", entity=entity2 + ) + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.VALIDATED + ) + + awaiting_consents = Consent.get_awaiting(user1) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + for consent in awaiting_consents: + assert consent.status == Consent.AWAITING + assert consent.delivery_point.entity.name == "entity1" + + # test by accessing a specific entity + awaiting_consents = Consent.get_awaiting(user1, entity1) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + awaiting_consents = Consent.get_awaiting(user2, entity2) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + + with pytest.raises(PermissionDenied): + Consent.get_awaiting(user1, entity2) + + +@pytest.mark.django_db +def test_consent_queryset_standard_user_without_consent(): + """User with one entity and delivery points, but without consents to validated. + + Test if a user with an associated entity and delivery points but no consent + to validate has no consent pending approval. + """ + user1 = UserFactory() + user2 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,)) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.VALIDATED + ) + + awaiting_consents = Consent.get_awaiting(user1) + assert awaiting_consents.exists() is False + + # test by accessing a specific entity + awaiting_consents = Consent.get_awaiting(user1, entity1) + assert awaiting_consents.exists() is False + + with pytest.raises(PermissionDenied): + Consent.get_awaiting(user1, entity2) + + +@pytest.mark.django_db +def test_consent_queryset_multi_standard_user_by_entity(): + """Multy User with one entity and delivery points. + + Test that multi-user associated on the same entity and delivery points have correct + number of consents awaiting approval. + """ + user1 = UserFactory() + user2 = UserFactory() + entity1 = EntityFactory(users=(user1, user2), name="entity1") + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory(delivery_point=delivery_point, created_by=user1) + + awaiting_consents = Consent.get_awaiting(user1) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + for consent in awaiting_consents: + assert consent.status == Consent.AWAITING + assert consent.delivery_point.entity.name == "entity1" + + awaiting_consents = Consent.get_awaiting(user2) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + for consent in awaiting_consents: + assert consent.status == Consent.AWAITING + assert consent.delivery_point.entity.name == "entity1" + + # test by accessing a specific entity + awaiting_consents = Consent.get_awaiting(user1, entity1) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + awaiting_consents = Consent.get_awaiting(user2, entity1) + assert awaiting_consents.count() == 3 # noqa: PLR2004 + + +@pytest.mark.django_db +def test_consent_queryset_multy_standard_user_without_consent(): + """Multy User with one entity and delivery points but without consents to validated. + + Test if multi-user associated on the same entity and delivery points but with + no consent to validate has no consent pending approval. + """ + user1 = UserFactory() + user2 = UserFactory() + entity1 = EntityFactory(users=(user1, user2), name="entity1") + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.VALIDATED + ) + awaiting_consents = Consent.get_awaiting(user1) + assert awaiting_consents.exists() is False + + awaiting_consents = Consent.get_awaiting(user2) + assert awaiting_consents.exists() is False + + # test by accessing a specific entity + awaiting_consents = Consent.get_awaiting(user1, entity1) + assert awaiting_consents.exists() is False + awaiting_consents = Consent.get_awaiting(user2, entity1) + assert awaiting_consents.exists() is False + + +@pytest.mark.django_db +def test_consent_queryset_user_proxy_for(): + """Ensure a proxy user with consents retrieve the correct 'awaiting consents'. + + This test ensures that the consents awaiting for a user who is a proxy for multiple + entities are correctly identified. + It creates multiple users, entities, and delivery points, associating them + accordingly. + It then verifies that the consents created for these delivery points are fetched + correctly for a proxy user. + + 1. Create users and entities, with one entity being a proxy for others. + 2. Generate delivery points for each entity and associate consents with them. + 3. Assert the total count of delivery points and consents. + 4. Fetch awaiting consents for a proxy user and verify their count and entities. + """ + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + entity4 = EntityFactory(users=(user1,), name="entity4") + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + DeliveryPointFactory(provider_assigned_id=f"entity4_{i}", entity=entity4) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory(delivery_point=delivery_point, created_by=user1) + + assert ( + DeliveryPoint.objects.filter(entity__in=[entity1, entity2, entity3]).count() + == 9 # noqa: PLR2004 + ) + + # Proxy user can access to all delivery points + awaiting_consents = Consent.get_awaiting(user3) + assert awaiting_consents.count() == 9 # noqa: PLR2004 + + entities_name = [] + for consent in awaiting_consents: + assert consent.status == Consent.AWAITING + entities_name.append(consent.delivery_point.entity.name) + + assert len(set(entities_name)) == 3 # noqa: PLR2004 + assert set(entities_name) == {"entity1", "entity2", "entity3"} + + # test by accessing a specific entity + assert Consent.get_awaiting(user3, entity1).exists() is True + assert Consent.get_awaiting(user3, entity2).exists() is True + assert Consent.get_awaiting(user3, entity3).exists() is True + + with pytest.raises(PermissionDenied): + Consent.get_awaiting(user3, entity4) + + +@pytest.mark.django_db +def test_consent_queryset_user_proxy_for_without_consent(): + """Ensure a proxy user without consents does not retrieve any 'awaiting consents'. + + Consents are generated for each delivery point with 'user1' as the creator. + The main assertion verifies that there are no 'awaiting consents' for 'user3', + the user associated with the proxy entity. + """ + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.VALIDATED + ) + + assert DeliveryPoint.objects.all().count() == 9 # noqa: PLR2004 + assert Consent.get_awaiting(user3).count() == 0 + + # test by accessing a specific entity + assert Consent.get_awaiting(user1, entity1).count() == 0 + assert Consent.get_awaiting(user3, entity1).count() == 0 + + +@pytest.mark.django_db +def test_consent_queryset_user_with_proxy(): + """Verify that a user with proxy can access anly his own entity. + + This test ensures that the consents awaiting for a user who has a proxy can + only access to his entity. + """ + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory(delivery_point=delivery_point, created_by=user1) + + assert DeliveryPoint.objects.all().count() == 9 # noqa: PLR2004 + + awaiting_consents = Consent.get_awaiting(user1) + + assert awaiting_consents.count() == 3 # noqa: PLR2004 + entities_name = [] + for consent in awaiting_consents: + assert consent.status == Consent.AWAITING + entities_name.append(consent.delivery_point.entity.name) + + assert len(set(entities_name)) == 1 + assert set(entities_name) != {"entity2", "entity3"} + assert set(entities_name) == {"entity1"} + + # test by accessing a specific entity + assert Consent.get_awaiting(user1, entity1).count() == 3 # noqa: PLR2004 + assert Consent.get_awaiting(user3, entity1).count() == 3 # noqa: PLR2004 + with pytest.raises(PermissionDenied): + Consent.get_awaiting(user2, entity1) + + +@pytest.mark.django_db +def test_count_validated_by_user(): + """Count VALIDATED consents by entities for a given user.""" + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory(delivery_point=delivery_point, created_by=user1) + + for entity in Consent.count_awaiting_by_entity(user1): + assert entity.dcount == 3 # noqa: PLR2004 + for entity in Consent.count_awaiting_by_entity(user2): + assert entity.dcount == 3 # noqa: PLR2004 + + assert Consent.count_awaiting_by_entity(user3).count() == 3 # noqa: PLR2004 + for entity in Consent.count_awaiting_by_entity(user3): + assert entity.dcount == 3 # noqa: PLR2004 + + +@pytest.mark.django_db +def test_count_awaiting_by_user(): + """Count AWAITING consents by entities for a given user.""" + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.VALIDATED + ) + + for entity in Consent.count_validated_by_entity(user1): + assert entity.dcount == 3 # noqa: PLR2004 + for entity in Consent.count_validated_by_entity(user2): + assert entity.dcount == 3 # noqa: PLR2004 + + assert Consent.count_validated_by_entity(user3).count() == 3 # noqa: PLR2004 + for entity in Consent.count_validated_by_entity(user3): + assert entity.dcount == 3 # noqa: PLR2004 + + for entity in Consent.count_awaiting_by_entity(user1): + assert entity.dcount == 0 + for entity in Consent.count_awaiting_by_entity(user2): + assert entity.dcount == 0 + for entity in Consent.count_awaiting_by_entity(user3): + assert entity.dcount == 0 + + +@pytest.mark.django_db +def test_update_validated(): + """Verifies that consents are updated to VALIDATED.""" + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.AWAITING + ) + + # retrieves the consents to be validated for a given user + consents = Consent.get_awaiting(user1) + nb_consents_awaiting = consents.count() + first_consent = consents.first() + ids = list( + consents.annotate(str_id=Cast("id", output_field=TextField())).values_list( + "str_id", flat=True + ) + ) + # remove last item from list, to test awaiting update + ids.pop() + nb_consents_awaiting -= 1 + + # validates all previous consents + result = Consent.set_consents_status_by_ids( + selected_ids=ids, user=user1, consents_qs=consents + ) + assert result[0] == nb_consents_awaiting + assert result[1] == 1 + + # checks that validated consents have been correctly updated + validated_consents = Consent.objects.filter(id__in=ids) + assert validated_consents.count() == nb_consents_awaiting + for consent in validated_consents: + assert consent.status == Consent.VALIDATED + assert consent.created_by == user1 + + # check that the update date has been updated correctly + first_validated_consent = Consent.objects.get(id=first_consent.id) + assert first_validated_consent.updated_at > first_consent.updated_at + + +@pytest.mark.django_db +def test_date(): + """Only consents from the current period are retrieved.""" + user1 = UserFactory() + user2 = UserFactory() + user3 = UserFactory() + entity1 = EntityFactory(users=(user1,), name="entity1") + entity2 = EntityFactory(users=(user2,), name="entity2") + entity3 = EntityFactory( + users=(user3,), proxy_for=(entity1, entity2), name="entity3" + ) + + for i in range(1, 4): + DeliveryPointFactory(provider_assigned_id=f"entity1_{i}", entity=entity1) + DeliveryPointFactory(provider_assigned_id=f"entity2_{i}", entity=entity2) + DeliveryPointFactory(provider_assigned_id=f"entity3_{i}", entity=entity3) + + # create past consents + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, + status=Consent.AWAITING, + start=timezone.now() - timedelta(days=120), + end=timezone.now() - timedelta(days=90), + ) + + # create actual consents + for delivery_point in DeliveryPoint.objects.all(): + ConsentFactory( + delivery_point=delivery_point, created_by=user1, status=Consent.AWAITING + ) + + assert Consent.objects.all().count() == 18 # noqa: PLR2004 + assert Consent.count_awaiting_by_entity(user3).count() == 3 # noqa: PLR2004 + for entity in Consent.count_awaiting_by_entity(user3): + assert entity.dcount == 3 # noqa: PLR2004 diff --git a/src/dashboard/apps/consent/urls.py b/src/dashboard/apps/consent/urls.py index d12e65f8..6f6a0616 100644 --- a/src/dashboard/apps/consent/urls.py +++ b/src/dashboard/apps/consent/urls.py @@ -2,11 +2,12 @@ from django.urls import path -from .views import IndexView, ManageView +from .views import IndexView, consent_form_view app_name = "consent" urlpatterns = [ path("", IndexView.as_view(), name="index"), - path("manage/", ManageView.as_view(), name="manage"), + path("manage/", consent_form_view, name="manage"), + path("manage/