diff --git a/greg/tasks.py b/greg/tasks.py index 59a5c03ef25a5d1cd8c22f193c52d1c04b0a859c..ad6b3af909d5a394a720f402e8b725d39f34bd56 100644 --- a/greg/tasks.py +++ b/greg/tasks.py @@ -44,11 +44,18 @@ def notify_sponsors_roles_ending() -> list[str]: sp2unit = {s.id: list(s.get_allowed_units()) for s in sponsors} # Map sponsors to ending roles - sp2roles = defaultdict(list) - for sp, units in sp2unit.items(): - for unit in units: - for role in unit2roles[unit.id]: - sp2roles[sp].append(role) + # Make sure only the sponsor(s) closest to the role is notified + sp2roles: dict = defaultdict(list) + for unit_id, roles in unit2roles.items(): + for role in roles: + role_notified = False + for sp, units in reversed(sp2unit.items()): + for unit in units: + if unit_id == unit.id and ( + not role_notified or unit.parent not in units + ): + sp2roles[sp].append(role) + role_notified = True # Send emails to sponsors remindermailer = RolesEnding() diff --git a/greg/tests/test_tasks.py b/greg/tests/test_tasks.py index 583d470aa47a954d8c3c8112a61b929166846b08..762a8e775b25cd6aa3b5473b46398b62da8189fb 100644 --- a/greg/tests/test_tasks.py +++ b/greg/tests/test_tasks.py @@ -4,9 +4,17 @@ import pytest from django.conf import settings from django.core import mail from django.test import override_settings -from orgreg_client import OrgUnit, OrgUnitList - -from greg.models import OrganizationalUnit, OuIdentifier +from orgreg_client.models import OrgUnit, OrgUnitList + +from greg.models import ( + OrganizationalUnit, + OuIdentifier, + Person, + Role, + RoleType, + Sponsor, + SponsorOrganizationalUnit, +) from greg.tasks import import_from_orgreg, notify_sponsors_roles_ending from gregui.models import EmailTemplate @@ -27,6 +35,69 @@ To extend the guest role please use the web interface.""", return EmailTemplate.objects.get(id=et.id) +@pytest.fixture +def org_tree_with_sponsors( + person_foo: Person, role_type_test_guest: RoleType, role_type_foo: RoleType +): + # Create all units + a = OrganizationalUnit.objects.create() + b = OrganizationalUnit.objects.create(parent=a) + c = OrganizationalUnit.objects.create(parent=b) + + # Create all sponsors + d = Sponsor.objects.create( + feide_id="d@example.org", + first_name="D", + last_name="Guy", + work_email="d_guy@example.com", + ) + e = Sponsor.objects.create( + feide_id="e@example.org", + first_name="E", + last_name="Guy", + work_email="e_guy@example.com", + ) + f = Sponsor.objects.create( + feide_id="f@example.org", + first_name="F", + last_name="Guy", + work_email="f_guy@example.com", + ) + g = Sponsor.objects.create( + feide_id="g@example.org", + first_name="G", + last_name="Guy", + work_email="g_guy@example.com", + ) + # Connect them to units + SponsorOrganizationalUnit.objects.create( + sponsor=d, organizational_unit=a, hierarchical_access=True + ) + SponsorOrganizationalUnit.objects.create( + sponsor=e, organizational_unit=b, hierarchical_access=True + ) + + # Create person with role on unit c and b + Role.objects.create( + person=person_foo, + type=role_type_test_guest, + start_date=datetime.date.today(), + end_date=datetime.date.today() + datetime.timedelta(days=5), + sponsor=f, + orgunit=c, + ) + Role.objects.create( + person=person_foo, + type=role_type_foo, + start_date=datetime.date.today(), + end_date=datetime.date.today() + datetime.timedelta(days=5), + sponsor=e, + orgunit=b, + ) + + return a, b, c, d, e, f, g + + @pytest.mark.django_db def test_notify_sponsors_roles_ending( role_end_reminder_template, role_person_foo2, sponsor_org_unit @@ -36,6 +107,29 @@ def test_notify_sponsors_roles_ending( assert len(task_ids) == 1 +@pytest.mark.django_db +def test_sponsor_get_email(role_end_reminder_template, org_tree_with_sponsors): + mail.outbox = [] + task_ids = notify_sponsors_roles_ending() + assert len(task_ids) == 1 + + +@pytest.mark.django_db +def test_only_close_sponsors_get_email( + role_end_reminder_template, org_tree_with_sponsors +): + _, _, c, _, _, f, g = org_tree_with_sponsors + SponsorOrganizationalUnit.objects.create( + sponsor=f, organizational_unit=c, hierarchical_access=True + ) + SponsorOrganizationalUnit.objects.create( + sponsor=g, organizational_unit=c, hierarchical_access=True + ) + mail.outbox = [] + task_ids = notify_sponsors_roles_ending() + assert len(task_ids) == 3 + + @pytest.fixture def old_unit(): ou = OrganizationalUnit.objects.create(name_nb="a", name_en="b")