From 5bfd1e0cb0111386947426501ca68598c9d527aa Mon Sep 17 00:00:00 2001 From: Eemeli Ranta Date: Mon, 13 Jan 2025 16:29:55 +0200 Subject: [PATCH 1/4] Refactor address property for cleaner output with missing address_zip --- tests/test_integrations/test_email/helpers.py | 6 +- .../test_email/test_reservation_context.py | 80 +++++++++---------- tilavarauspalvelu/models/location/model.py | 2 +- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/tests/test_integrations/test_email/helpers.py b/tests/test_integrations/test_email/helpers.py index cf48d00d3..856624155 100644 --- a/tests/test_integrations/test_email/helpers.py +++ b/tests/test_integrations/test_email/helpers.py @@ -108,7 +108,7 @@ RESERVATION_BASIC_INFO_CONTEXT_EN = { "reservation_unit_name": "Test reservation unit", "unit_name": "Test unit", - "unit_location": "Test location", + "unit_location": "Test Street, City", "begins_label": "From", "begin_date": "1.1.2024", "begin_time": "12:00", @@ -120,7 +120,7 @@ RESERVATION_BASIC_INFO_CONTEXT_FI = { "reservation_unit_name": "Test reservation unit", "unit_name": "Test unit", - "unit_location": "Test location", + "unit_location": "Test Street, City", "begins_label": "Alkamisaika", "begin_date": "1.1.2024", "begin_time": "12:00", @@ -132,7 +132,7 @@ RESERVATION_BASIC_INFO_CONTEXT_SV = { "reservation_unit_name": "Test reservation unit", "unit_name": "Test unit", - "unit_location": "Test location", + "unit_location": "Test Street, City", "begins_label": "Börjar", "begin_date": "1.1.2024", "begin_time": "12:00", diff --git a/tests/test_integrations/test_email/test_reservation_context.py b/tests/test_integrations/test_email/test_reservation_context.py index 15782b802..c83af6ad9 100644 --- a/tests/test_integrations/test_email/test_reservation_context.py +++ b/tests/test_integrations/test_email/test_reservation_context.py @@ -67,7 +67,7 @@ def test_get_context__reservation_approved__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -100,7 +100,7 @@ def test_get_context__reservation_approved__discount__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -133,7 +133,7 @@ def test_get_context__reservation_approved__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -166,7 +166,7 @@ def test_get_context__reservation_approved__discount__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -199,7 +199,7 @@ def test_get_context__reservation_approved__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -232,7 +232,7 @@ def test_get_context__reservation_approved__discount__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -269,7 +269,7 @@ def test_get_context__reservation_cancelled__en(): cancel_reason="This is a reason", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -303,7 +303,7 @@ def test_get_context__reservation_cancelled__fi(): cancel_reason="Tässä on syyni", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -337,7 +337,7 @@ def test_get_context__reservation_cancelled__sv(): cancel_reason="Här är anledningen", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -373,7 +373,7 @@ def test_get_context__reservation_confirmed__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -405,7 +405,7 @@ def test_get_context__reservation_confirmed__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -437,7 +437,7 @@ def test_get_context__reservation_confirmed__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -472,7 +472,7 @@ def test_get_context__reservation_modified__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -504,7 +504,7 @@ def test_get_context__reservation_modified__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -536,7 +536,7 @@ def test_get_context__reservation_modified__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -571,7 +571,7 @@ def test_get_context__reservation_rejected__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), rejection_reason="This is the rejection reason", @@ -604,7 +604,7 @@ def test_get_context__reservation_rejected__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), rejection_reason="Tässä on hylkäyksen syy", @@ -637,7 +637,7 @@ def test_get_context__reservation_rejected__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), rejection_reason="Här är orsaken till avslagningen", @@ -673,7 +673,7 @@ def test_get_context__reservation_requires_handling__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -711,7 +711,7 @@ def test_get_context__reservation_requires_handling__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -749,7 +749,7 @@ def test_get_context__reservation_requires_handling__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -787,7 +787,7 @@ def test_get_context__reservation_requires_handling__subsidised(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -830,7 +830,7 @@ def test_get_context__reservation_requires_payment__en(): email_recipient_name="John Doe", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -867,7 +867,7 @@ def test_get_context__reservation_requires_payment__fi(): email_recipient_name="Mikko Mallikas", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -904,7 +904,7 @@ def test_get_context__reservation_requires_payment__sv(): email_recipient_name="Magnus Persson", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), price=Decimal("12.30"), @@ -944,7 +944,7 @@ def test_get_context_for_seasonal_reservation_cancelled_single__en(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), cancel_reason="[PERUUTUKSEN SYY]", @@ -974,7 +974,7 @@ def test_get_context_for_seasonal_reservation_cancelled_single__fi(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), cancel_reason="[PERUUTUKSEN SYY]", @@ -1004,7 +1004,7 @@ def test_get_context_for_seasonal_reservation_cancelled_single__sv(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), cancel_reason="[PERUUTUKSEN SYY]", @@ -1130,7 +1130,7 @@ def test_get_context_for_seasonal_reservation_modified_single__en(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), language="en", @@ -1155,7 +1155,7 @@ def test_get_context_for_seasonal_reservation_modified_single__fi(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), language="fi", @@ -1180,7 +1180,7 @@ def test_get_context_for_seasonal_reservation_modified_single__sv(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), language="sv", @@ -1310,7 +1310,7 @@ def test_get_context_for_seasonal_reservation_rejected_single__en(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), rejection_reason="[HYLKÄYKSEN SYY]", @@ -1338,7 +1338,7 @@ def test_get_context_for_seasonal_reservation_rejected_single__fi(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), rejection_reason="[HYLKÄYKSEN SYY]", @@ -1366,7 +1366,7 @@ def test_get_context_for_seasonal_reservation_rejected_single__sv(): email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), rejection_reason="[HYLKÄYKSEN SYY]", @@ -1398,7 +1398,7 @@ def test_get_context__staff_notification_reservation_made__en(): reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), reservation_id=12, @@ -1434,7 +1434,7 @@ def test_get_context__staff_notification_reservation_made__fi(): reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), reservation_id=12, @@ -1470,7 +1470,7 @@ def test_get_context__staff_notification_reservation_made__sv(): reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), reservation_id=12, @@ -1509,7 +1509,7 @@ def test_get_context__staff_notification_reservation_requires_handling__en(): reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), reservation_id=12, @@ -1547,7 +1547,7 @@ def test_get_context__staff_notification_reservation_requires_handling__fi(): reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), reservation_id=12, @@ -1585,7 +1585,7 @@ def test_get_context__staff_notification_reservation_requires_handling__sv(): reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", - unit_location="Test location", + unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), reservation_id=12, diff --git a/tilavarauspalvelu/models/location/model.py b/tilavarauspalvelu/models/location/model.py index 54576da9b..d6156c02b 100644 --- a/tilavarauspalvelu/models/location/model.py +++ b/tilavarauspalvelu/models/location/model.py @@ -81,7 +81,7 @@ def actions(self) -> LocationActions: @property def address(self) -> str: - return f"{self.address_street}, {self.address_zip} {self.address_city}" + return ", ".join([self.address_street, f"{self.address_zip} {self.address_city}".strip()]) @property def lat(self) -> float | None: From c98c4da967758e1a015c682d984e71a858cd1e46 Mon Sep 17 00:00:00 2001 From: Eemeli Ranta Date: Mon, 13 Jan 2025 17:25:33 +0200 Subject: [PATCH 2/4] Fix invalid series keys in application section staff emails --- ...cation_application_section_cancelled.jinja | 2 +- ...cation_application_section_cancelled.jinja | 2 +- .../test_email/test_application_context.py | 72 +++++++++---------- .../admin/email_template/utils.py | 8 +-- .../email/template_context/application.py | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/templates/email/html/staff_notification_application_section_cancelled.jinja b/templates/email/html/staff_notification_application_section_cancelled.jinja index 9a922810b..96dcfe416 100644 --- a/templates/email/html/staff_notification_application_section_cancelled.jinja +++ b/templates/email/html/staff_notification_application_section_cancelled.jinja @@ -8,7 +8,7 @@ {{ view_booking_at_label | safe }}: {% for series in cancelled_reservation_series %} - {{ series.weekday | safe }}: {{ series.time | safe }} + {{ series.weekday_value | safe }}: {{ series.time_value | safe }} {{ series.url | safe }} {% endfor %} {% endblock %} diff --git a/templates/email/text/staff_notification_application_section_cancelled.jinja b/templates/email/text/staff_notification_application_section_cancelled.jinja index da8c82682..fc644f12b 100644 --- a/templates/email/text/staff_notification_application_section_cancelled.jinja +++ b/templates/email/text/staff_notification_application_section_cancelled.jinja @@ -8,7 +8,7 @@ {{ view_booking_at_label | safe }}: -{% for series in cancelled_reservation_series %}{{ series.weekday | safe }} {{ series.time | safe }} +{% for series in cancelled_reservation_series %}{{ series.weekday_value | safe }} {{ series.time_value | safe }} {{ series.url | safe }} {% endfor %} {% include "email/text/partials/closing_staff.jinja" %} diff --git a/tests/test_integrations/test_email/test_application_context.py b/tests/test_integrations/test_email/test_application_context.py index 989ee6d0a..4106d0cf7 100644 --- a/tests/test_integrations/test_email/test_application_context.py +++ b/tests/test_integrations/test_email/test_application_context.py @@ -371,14 +371,14 @@ def test_get_context_for_staff_notification_application_section_cancelled__en(): language="en", cancelled_reservation_series=[ { - "weekday": WeekdayChoice.MONDAY.label, - "time": "13:00-15:00", - "url": get_staff_reservations_ext_link(reservation_id=1234), + "weekday_value": WeekdayChoice.MONDAY.label, + "time_value": "12:00:00-14:00:00", + "reservation_url": get_staff_reservations_ext_link(reservation_id=1234), }, { - "weekday": WeekdayChoice.TUESDAY.label, - "time": "21:00-22:00", - "url": get_staff_reservations_ext_link(reservation_id=5678), + "weekday_value": WeekdayChoice.TUESDAY.label, + "time_value": "21:00:00-22:00:00", + "reservation_url": get_staff_reservations_ext_link(reservation_id=5678), }, ], ) @@ -397,14 +397,14 @@ def test_get_context_for_staff_notification_application_section_cancelled__en(): "view_booking_at_label": "You can view the booking at", "cancelled_reservation_series": [ { - "weekday": "Monday", - "time": "13:00-15:00", - "url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", + "weekday_value": "Monday", + "time_value": "12:00:00-14:00:00", + "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", }, { - "weekday": "Tuesday", - "time": "21:00-22:00", - "url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", + "weekday_value": "Tuesday", + "time_value": "21:00:00-22:00:00", + "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", }, ], **BASE_TEMPLATE_CONTEXT_EN, @@ -423,14 +423,14 @@ def test_get_context_for_staff_notification_application_section_cancelled__fi(): language="fi", cancelled_reservation_series=[ { - "weekday": WeekdayChoice.MONDAY.label, - "time": "13:00-15:00", - "url": get_staff_reservations_ext_link(reservation_id=1234), + "weekday_value": WeekdayChoice.MONDAY.label, + "time_value": "12:00:00-14:00:00", + "reservation_url": get_staff_reservations_ext_link(reservation_id=1234), }, { - "weekday": WeekdayChoice.TUESDAY.label, - "time": "21:00-22:00", - "url": get_staff_reservations_ext_link(reservation_id=5678), + "weekday_value": WeekdayChoice.TUESDAY.label, + "time_value": "21:00:00-22:00:00", + "reservation_url": get_staff_reservations_ext_link(reservation_id=5678), }, ], ) @@ -447,14 +447,14 @@ def test_get_context_for_staff_notification_application_section_cancelled__fi(): "view_booking_at_label": "Voit tarkistaa varauksen tiedot osoitteessa", "cancelled_reservation_series": [ { - "weekday": "Monday", - "time": "13:00-15:00", - "url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", + "weekday_value": "Monday", + "time_value": "12:00:00-14:00:00", + "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", }, { - "weekday": "Tuesday", - "time": "21:00-22:00", - "url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", + "weekday_value": "Tuesday", + "time_value": "21:00:00-22:00:00", + "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", }, ], **BASE_TEMPLATE_CONTEXT_FI, @@ -473,14 +473,14 @@ def test_get_context_for_staff_notification_application_section_cancelled_sv(): language="sv", cancelled_reservation_series=[ { - "weekday": WeekdayChoice.MONDAY.label, - "time": "13:00-15:00", - "url": get_staff_reservations_ext_link(reservation_id=1234), + "weekday_value": WeekdayChoice.MONDAY.label, + "time_value": "12:00:00-14:00:00", + "reservation_url": get_staff_reservations_ext_link(reservation_id=1234), }, { - "weekday": WeekdayChoice.TUESDAY.label, - "time": "21:00-22:00", - "url": get_staff_reservations_ext_link(reservation_id=5678), + "weekday_value": WeekdayChoice.TUESDAY.label, + "time_value": "21:00:00-22:00:00", + "reservation_url": get_staff_reservations_ext_link(reservation_id=5678), }, ], ) @@ -497,14 +497,14 @@ def test_get_context_for_staff_notification_application_section_cancelled_sv(): "view_booking_at_label": "Du kan se bokningen på", "cancelled_reservation_series": [ { - "weekday": "Monday", - "time": "13:00-15:00", - "url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", + "weekday_value": "Monday", + "time_value": "12:00:00-14:00:00", + "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", }, { - "weekday": "Tuesday", - "time": "21:00-22:00", - "url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", + "weekday_value": "Tuesday", + "time_value": "21:00:00-22:00:00", + "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", }, ], **BASE_TEMPLATE_CONTEXT_SV, diff --git a/tilavarauspalvelu/admin/email_template/utils.py b/tilavarauspalvelu/admin/email_template/utils.py index c345de692..f970f63c4 100644 --- a/tilavarauspalvelu/admin/email_template/utils.py +++ b/tilavarauspalvelu/admin/email_template/utils.py @@ -72,13 +72,13 @@ def get_mock_data(*, email_type: EmailType, language: Lang, **kwargs: Any) -> Em "cancelled_reservation_series", [ { - "weekday": str(WeekdayChoice.MONDAY.label), - "time": "13:00-15:00", + "weekday_value": str(WeekdayChoice.MONDAY.label), + "time_value": "13:00-15:00", "url": get_staff_reservations_ext_link(reservation_id=1234), }, { - "weekday": str(WeekdayChoice.TUESDAY.label), - "time": "21:00-22:00", + "weekday_value": str(WeekdayChoice.TUESDAY.label), + "time_value": "21:00-22:00", "url": get_staff_reservations_ext_link(reservation_id=5678), }, ], diff --git a/tilavarauspalvelu/integrations/email/template_context/application.py b/tilavarauspalvelu/integrations/email/template_context/application.py index ce40ac821..2539ac1c2 100644 --- a/tilavarauspalvelu/integrations/email/template_context/application.py +++ b/tilavarauspalvelu/integrations/email/template_context/application.py @@ -184,7 +184,7 @@ def get_context_for_staff_notification_application_section_cancelled( { **params_for_reservation_series_info(reservation_series=series), "reservation_url": get_staff_reservations_ext_link( - reservation_id=series.reservations.values_list("pk").last() + reservation_id=series.reservations.values_list("pk", flat=True).last() ), } for series in application_section.actions.get_reservation_series() From b7942616578e317a77fba58fbf88a24bd4650d46 Mon Sep 17 00:00:00 2001 From: Eemeli Ranta Date: Tue, 14 Jan 2025 23:43:39 +0200 Subject: [PATCH 3/4] Add tests for creating email contexts from model instances --- tests/factories/reservation.py | 8 +- .../test_integrations/test_email/conftest.py | 82 +++++ .../test_email/test_application_context.py | 34 +- .../test_email/test_reservation_context.py | 321 ++++++++++++------ .../models/application_section/actions.py | 10 +- .../models/reservation/actions.py | 7 +- 6 files changed, 343 insertions(+), 119 deletions(-) create mode 100644 tests/test_integrations/test_email/conftest.py diff --git a/tests/factories/reservation.py b/tests/factories/reservation.py index 296e58c96..6558f7a95 100644 --- a/tests/factories/reservation.py +++ b/tests/factories/reservation.py @@ -62,10 +62,10 @@ class Meta: created_at = None # Pricing details - price = 0 - non_subsidised_price = 0 - unit_price = 0 - tax_percentage_value = 0 + price = Decimal(0) + non_subsidised_price = Decimal(0) + unit_price = Decimal(0) + tax_percentage_value = Decimal(0) # Free of charge information applying_for_free_of_charge = False diff --git a/tests/test_integrations/test_email/conftest.py b/tests/test_integrations/test_email/conftest.py new file mode 100644 index 000000000..2d82c9ffc --- /dev/null +++ b/tests/test_integrations/test_email/conftest.py @@ -0,0 +1,82 @@ +from __future__ import annotations + +import datetime +from typing import TYPE_CHECKING + +import pytest + +from tilavarauspalvelu.enums import WeekdayChoice +from utils.date_utils import local_datetime + +from tests.factories import ( + ApplicationSectionFactory, + RecurringReservationFactory, + ReservationFactory, + ReservationUnitFactory, +) + +if TYPE_CHECKING: + from tilavarauspalvelu.models import Reservation + + +@pytest.fixture +def email_reservation() -> Reservation: + reservation_unit = ReservationUnitFactory.create( + name_en="Test reservation unit", + unit__name_en="Test unit", + unit__location__address_street_en="Test Street", + unit__location__address_zip="", + unit__location__address_city_en="City", + reservation_confirmed_instructions_en="[HYVÄKSYTYN VARAUKSEN OHJEET]", + reservation_cancelled_instructions_en="[PERUUTETUN VARAUKSEN OHJEET]", + reservation_pending_instructions_en="[KÄSITELTÄVÄN VARAUKSEN OHJEET]", + pricings__lowest_price=0, + pricings__highest_price=0, + ) + application_section = ApplicationSectionFactory.create( + name="[HAKEMUKSEN OSAN NIMI]", + application__application_round__name_en="[KAUSIVARAUSKIERROKSEN NIMI]", + application__organisation__name_en="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + ) + recurring_reservation = RecurringReservationFactory.create( + weekdays=f"{WeekdayChoice.MONDAY}", + begin_date=datetime.date(2024, 1, 1), + begin_time=datetime.time(12), + end_time=datetime.time(14), + allocated_time_slot__reservation_unit_option__reservation_unit=reservation_unit, + allocated_time_slot__reservation_unit_option__application_section=application_section, + ) + reservation = ReservationFactory.create_for_reservation_unit( + name="Test reservation", + reservation_unit=reservation_unit, + user=application_section.application.user, + reservee_first_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + reservee_last_name="", + cancel_reason__reason_en="[PERUUTUKSEN SYY]", + deny_reason__reason_en="[HYLKÄYKSEN SYY]", + begin=local_datetime(2024, 1, 1, 12, 0), + end=local_datetime(2024, 1, 1, 14, 0), + recurring_reservation=recurring_reservation, + ) + + recurring_reservation_2 = RecurringReservationFactory.create( + weekdays=f"{WeekdayChoice.TUESDAY}", + begin_date=datetime.date(2024, 1, 2), + begin_time=datetime.time(21), + end_time=datetime.time(22), + allocated_time_slot__reservation_unit_option__reservation_unit=reservation_unit, + allocated_time_slot__reservation_unit_option__application_section=application_section, + ) + ReservationFactory.create_for_reservation_unit( + reservation_unit=reservation_unit, + user=application_section.application.user, + reservee_first_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + reservee_last_name="", + cancel_reason__reason_en="[PERUUTUKSEN SYY]", + deny_reason__reason_en="[HYLKÄYKSEN SYY]", + begin=local_datetime(2024, 1, 2, 12, 0), + end=local_datetime(2024, 1, 2, 14, 0), + recurring_reservation=recurring_reservation_2, + ) + + return reservation diff --git a/tests/test_integrations/test_email/test_application_context.py b/tests/test_integrations/test_email/test_application_context.py index 4106d0cf7..a187ed25a 100644 --- a/tests/test_integrations/test_email/test_application_context.py +++ b/tests/test_integrations/test_email/test_application_context.py @@ -1,6 +1,7 @@ # ruff: noqa: RUF001 from __future__ import annotations +import pytest from freezegun import freeze_time from tilavarauspalvelu.enums import WeekdayChoice @@ -14,6 +15,7 @@ get_context_for_staff_notification_application_section_cancelled, ) from tilavarauspalvelu.integrations.email.template_context.common import get_staff_reservations_ext_link +from tilavarauspalvelu.models import Reservation from tests.helpers import TranslationsFromPOFiles from tests.test_integrations.test_email.helpers import ( @@ -37,6 +39,11 @@ SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_SV, ) +# Applied to all tests +pytestmark = [ + pytest.mark.django_db, +] + # type: EmailType.APPLICATION_HANDLED ################################################################################## @@ -272,7 +279,7 @@ def test_get_context__application_received__sv(): @freeze_time("2024-01-01") -def test_get_context_for_application_section_cancelled__en(): +def test_get_context_for_application_section_cancelled__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_application_section_cancelled( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", @@ -299,6 +306,12 @@ def test_get_context_for_application_section_cancelled__en(): **AUTOMATIC_REPLY_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_application_section_cancelled( + application_section=email_reservation.actions.get_application_section(), + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_application_section_cancelled__fi(): @@ -362,7 +375,10 @@ def test_get_context_for_application_section_cancelled_sv(): @freeze_time("2024-01-01") -def test_get_context_for_staff_notification_application_section_cancelled__en(): +def test_get_context_for_staff_notification_application_section_cancelled__en(email_reservation): + reservation_id_1 = email_reservation.id + reservation_id_2 = Reservation.objects.exclude(id=reservation_id_1).first().id + with TranslationsFromPOFiles(): context = get_context_for_staff_notification_application_section_cancelled( application_section_name="[HAKEMUKSEN OSAN NIMI]", @@ -373,12 +389,12 @@ def test_get_context_for_staff_notification_application_section_cancelled__en(): { "weekday_value": WeekdayChoice.MONDAY.label, "time_value": "12:00:00-14:00:00", - "reservation_url": get_staff_reservations_ext_link(reservation_id=1234), + "reservation_url": get_staff_reservations_ext_link(reservation_id=reservation_id_1), }, { "weekday_value": WeekdayChoice.TUESDAY.label, "time_value": "21:00:00-22:00:00", - "reservation_url": get_staff_reservations_ext_link(reservation_id=5678), + "reservation_url": get_staff_reservations_ext_link(reservation_id=reservation_id_2), }, ], ) @@ -399,12 +415,12 @@ def test_get_context_for_staff_notification_application_section_cancelled__en(): { "weekday_value": "Monday", "time_value": "12:00:00-14:00:00", - "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/1234", + "reservation_url": f"https://fake.varaamo.hel.fi/kasittely/reservations/{reservation_id_1}", }, { "weekday_value": "Tuesday", "time_value": "21:00:00-22:00:00", - "reservation_url": "https://fake.varaamo.hel.fi/kasittely/reservations/5678", + "reservation_url": f"https://fake.varaamo.hel.fi/kasittely/reservations/{reservation_id_2}", }, ], **BASE_TEMPLATE_CONTEXT_EN, @@ -412,6 +428,12 @@ def test_get_context_for_staff_notification_application_section_cancelled__en(): **CLOSING_STAFF_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_staff_notification_application_section_cancelled( + application_section=email_reservation.actions.get_application_section(), + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_staff_notification_application_section_cancelled__fi(): diff --git a/tests/test_integrations/test_email/test_reservation_context.py b/tests/test_integrations/test_email/test_reservation_context.py index c83af6ad9..c195af97e 100644 --- a/tests/test_integrations/test_email/test_reservation_context.py +++ b/tests/test_integrations/test_email/test_reservation_context.py @@ -4,8 +4,10 @@ import datetime from decimal import Decimal +import pytest from freezegun import freeze_time +from tilavarauspalvelu.enums import ReservationStateChoice, WeekdayChoice from tilavarauspalvelu.integrations.email.template_context import ( get_context_for_reservation_approved, get_context_for_reservation_cancelled, @@ -57,32 +59,38 @@ SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_SV, ) +# Applied to all tests +pytestmark = [ + pytest.mark.django_db, +] + + # type: EmailType.RESERVATION_APPROVED ################################################################################# @freeze_time("2024-01-01") -def test_get_context__reservation_approved__en(): +def test_get_context__reservation_approved__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_approved( - email_recipient_name="John Doe", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - price=Decimal("12.30"), - non_subsidised_price=Decimal("12.30"), - tax_percentage=Decimal("25.5"), - reservation_id=12, - confirmed_instructions="These are the instructions", + price=Decimal(0), + non_subsidised_price=Decimal(0), + tax_percentage=Decimal(0), + reservation_id=email_reservation.id, + confirmed_instructions="[HYVÄKSYTYN VARAUKSEN OHJEET]", language="en", ) assert context == { - "email_recipient_name": "John Doe", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", "text_reservation_approved": "Your booking is now confirmed", "instructions_label": "Additional information about your booking", - "instructions": "These are the instructions", + "instructions": "[HYVÄKSYTYN VARAUKSEN OHJEET]", "title": "Your booking is confirmed", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, @@ -90,8 +98,17 @@ def test_get_context__reservation_approved__en(): **RESERVATION_MANAGE_LINK_CONTEXT_EN, **CLOSING_POLITE_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, + "reservation_id": f"{email_reservation.id}", + "price": Decimal(0), + "tax_percentage": Decimal(0), } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_approved( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_approved__discount__en(): @@ -262,29 +279,29 @@ def test_get_context__reservation_approved__discount__sv(): @freeze_time("2024-01-01") -def test_get_context__reservation_cancelled__en(): +def test_get_context__reservation_cancelled__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_cancelled( - email_recipient_name="John Doe", - cancel_reason="This is a reason", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + cancel_reason="[PERUUTUKSEN SYY]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - price=Decimal("12.30"), - tax_percentage=Decimal("25.5"), - reservation_id=12, - cancelled_instructions="This are the instructions", + price=Decimal(0), + tax_percentage=Decimal(0), + reservation_id=email_reservation.id, + cancelled_instructions="[PERUUTETUN VARAUKSEN OHJEET]", language="en", ) assert context == { - "cancel_reason": "This is a reason", + "cancel_reason": "[PERUUTUKSEN SYY]", "cancel_reason_label": "Your reason for cancellation", - "instructions": "This are the instructions", + "instructions": "[PERUUTETUN VARAUKSEN OHJEET]", "instructions_label": "Additional information about cancellation", - "email_recipient_name": "John Doe", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", "title": "Your booking has been cancelled", "text_reservation_cancelled": "Your booking has been cancelled", **BASE_TEMPLATE_CONTEXT_EN, @@ -292,8 +309,17 @@ def test_get_context__reservation_cancelled__en(): **RESERVATION_PRICE_INFO_CONTEXT_EN, **CLOSING_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, + "reservation_id": f"{email_reservation.id}", + "price": Decimal(0), + "tax_percentage": Decimal(0), } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_cancelled( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_cancelled__fi(): @@ -367,25 +393,25 @@ def test_get_context__reservation_cancelled__sv(): @freeze_time("2024-01-01") -def test_get_context__reservation_confirmed__en(): +def test_get_context__reservation_confirmed__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_confirmed( - email_recipient_name="John Doe", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - price=Decimal("12.30"), - tax_percentage=Decimal("25.5"), - reservation_id=12, - confirmed_instructions="These are the instructions", + price=Decimal(0), + tax_percentage=Decimal(0), + reservation_id=email_reservation.id, + confirmed_instructions="[HYVÄKSYTYN VARAUKSEN OHJEET]", language="en", ) assert context == { - "email_recipient_name": "John Doe", - "instructions": "These are the instructions", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + "instructions": "[HYVÄKSYTYN VARAUKSEN OHJEET]", "instructions_label": "Additional information about your booking", "text_reservation_confirmed": "You have made a new booking", "title": "Thank you for your booking at Varaamo", @@ -395,8 +421,17 @@ def test_get_context__reservation_confirmed__en(): **RESERVATION_MANAGE_LINK_CONTEXT_EN, **CLOSING_POLITE_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, + "reservation_id": f"{email_reservation.id}", + "price": Decimal(0), + "tax_percentage": Decimal(0), } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_confirmed( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_confirmed__fi(): @@ -466,27 +501,27 @@ def test_get_context__reservation_confirmed__sv(): @freeze_time("2024-01-01") -def test_get_context__reservation_modified__en(): +def test_get_context__reservation_modified__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_modified( - email_recipient_name="John Doe", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - price=Decimal("12.30"), - tax_percentage=Decimal("25.5"), - reservation_id=12, - confirmed_instructions="These are the instructions", + price=Decimal(0), + tax_percentage=Decimal(0), + reservation_id=email_reservation.id, + confirmed_instructions="[HYVÄKSYTYN VARAUKSEN OHJEET]", language="en", ) assert context == { - "email_recipient_name": "John Doe", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", "text_reservation_modified": "Your booking has been updated", "instructions_label": "Additional information about your booking", - "instructions": "These are the instructions", + "instructions": "[HYVÄKSYTYN VARAUKSEN OHJEET]", "title": "Your booking has been updated", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, @@ -494,8 +529,17 @@ def test_get_context__reservation_modified__en(): **RESERVATION_MANAGE_LINK_CONTEXT_EN, **CLOSING_POLITE_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, + "reservation_id": f"{email_reservation.id}", + "price": Decimal(0), + "tax_percentage": Decimal(0), } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_modified( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_modified__fi(): @@ -565,30 +609,30 @@ def test_get_context__reservation_modified__sv(): @freeze_time("2024-01-01") -def test_get_context__reservation_rejected__en(): +def test_get_context__reservation_rejected__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_rejected( - email_recipient_name="John Doe", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - rejection_reason="This is the rejection reason", - reservation_id=12, - cancelled_instructions="These are the instructions", + rejection_reason="[HYLKÄYKSEN SYY]", + reservation_id=email_reservation.id, + cancelled_instructions="[PERUUTETUN VARAUKSEN OHJEET]", language="en", ) assert context == { - "email_recipient_name": "John Doe", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", "booking_number_label": "Booking number", - "reservation_id": "12", + "reservation_id": f"{email_reservation.id}", "rejection_reason_label": "Reason", - "rejection_reason": "This is the rejection reason", + "rejection_reason": "[HYLKÄYKSEN SYY]", "text_reservation_rejected": "Unfortunately your booking cannot be confirmed", "instructions_label": "Additional information", - "instructions": "These are the instructions", + "instructions": "[PERUUTETUN VARAUKSEN OHJEET]", "title": "Unfortunately your booking cannot be confirmed", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, @@ -596,6 +640,12 @@ def test_get_context__reservation_rejected__en(): **AUTOMATIC_REPLY_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_rejected( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_rejected__fi(): @@ -667,33 +717,33 @@ def test_get_context__reservation_rejected__sv(): @freeze_time("2024-01-01") -def test_get_context__reservation_requires_handling__en(): +def test_get_context__reservation_requires_handling__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_requires_handling( - email_recipient_name="John Doe", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - price=Decimal("12.30"), - subsidised_price=Decimal("12.30"), + price=Decimal(0), + subsidised_price=Decimal(0), applying_for_free_of_charge=True, - tax_percentage=Decimal("25.5"), - reservation_id=12, - pending_instructions="These are the instructions", + tax_percentage=Decimal(0), + reservation_id=email_reservation.id, + pending_instructions="[KÄSITELTÄVÄN VARAUKSEN OHJEET]", language="en", ) assert context == { - "email_recipient_name": "John Doe", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", "text_pending_notification": ( "You will receive a confirmation email once your booking has been processed. " "We will contact you if further information is needed regarding your booking request." ), "text_reservation_requires_handling": "You have made a new booking request", "instructions_label": "Additional information about your booking", - "instructions": "These are the instructions", + "instructions": "[KÄSITELTÄVÄN VARAUKSEN OHJEET]", "title": "Your booking is waiting for processing", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, @@ -701,8 +751,18 @@ def test_get_context__reservation_requires_handling__en(): **RESERVATION_MANAGE_LINK_CONTEXT_EN, **CLOSING_POLITE_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, + "price": Decimal(0), + "subsidised_price": Decimal(0), + "tax_percentage": Decimal(0), + "reservation_id": f"{email_reservation.id}", } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_requires_handling( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_requires_handling__fi(): @@ -824,32 +884,32 @@ def test_get_context__reservation_requires_handling__subsidised(): @freeze_time("2024-01-01") -def test_get_context__reservation_requires_payment__en(): +def test_get_context__reservation_requires_payment__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_reservation_requires_payment( - email_recipient_name="John Doe", + email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - price=Decimal("12.30"), - tax_percentage=Decimal("25.5"), - payment_due_date=datetime.date(2024, 2, 1), - reservation_id=12, - confirmed_instructions="These are the instructions", + price=Decimal(0), + tax_percentage=Decimal(0), + payment_due_date=datetime.date(2024, 1, 1), + reservation_id=email_reservation.id, + confirmed_instructions="[HYVÄKSYTYN VARAUKSEN OHJEET]", language="en", ) assert context == { - "email_recipient_name": "John Doe", + "email_recipient_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", "payment_due_date_label": "Due date", - "payment_due_date": "1.2.2024", + "payment_due_date": "1.1.2024", "text_reservation_requires_payment": "Your booking has been confirmed, and can be paid", "pay_reservation_link_html": 'Pay the booking', "pay_reservation_link": "Pay the booking: https://fake.varaamo.hel.fi/en/reservations", "instructions_label": "Additional information about your booking", - "instructions": "These are the instructions", + "instructions": "[HYVÄKSYTYN VARAUKSEN OHJEET]", "title": "Your booking has been confirmed, and can be paid", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, @@ -857,8 +917,17 @@ def test_get_context__reservation_requires_payment__en(): **RESERVATION_MANAGE_LINK_CONTEXT_EN, **CLOSING_POLITE_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, + "reservation_id": f"{email_reservation.id}", + "price": 0, + "tax_percentage": 0, } + with TranslationsFromPOFiles(): + assert context == get_context_for_reservation_requires_payment( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__reservation_requires_payment__fi(): @@ -938,7 +1007,7 @@ def test_get_context__reservation_requires_payment__sv(): @freeze_time("2024-01-01") -def test_get_context_for_seasonal_reservation_cancelled_single__en(): +def test_get_context_for_seasonal_reservation_cancelled_single__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_cancelled_single( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", @@ -957,15 +1026,19 @@ def test_get_context_for_seasonal_reservation_cancelled_single__en(): "text_reservation_cancelled": "The space reservation included in your seasonal booking has been cancelled", "cancel_reason_label": "Reason", "cancel_reason": "[PERUUTUKSEN SYY]", - "check_booking_details_text": "You can check your booking details at", - "check_booking_details_url": "https://fake.varaamo.hel.fi/en/applications", - "check_booking_details_url_html": 'https://fake.varaamo.hel.fi/en/applications', + **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_EN, **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, **CLOSING_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_seasonal_reservation_cancelled_single( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_seasonal_reservation_cancelled_single__fi(): @@ -1031,12 +1104,12 @@ def test_get_context_for_seasonal_reservation_cancelled_single__sv(): @freeze_time("2024-01-01") -def test_get_context_for_seasonal_reservation_modified_series__en(): +def test_get_context_for_seasonal_reservation_modified_series__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_modified_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", - weekday_value="[VIIKONPÄIVÄ]", - time_value="[KELLONAIKA]", + weekday_value=WeekdayChoice.MONDAY.label, + time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", language="en", @@ -1050,15 +1123,21 @@ def test_get_context_for_seasonal_reservation_modified_series__en(): "application_section_name": "[HAKEMUKSEN OSAN NIMI]", "application_round_name": "[KAUSIVARAUSKIERROKSEN NIMI]", "weekday_label": "Day", - "weekday_value": "[VIIKONPÄIVÄ]", + "weekday_value": "Monday", "time_label": "Time", - "time_value": "[KELLONAIKA]", + "time_value": "12:00:00-14:00:00", **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_EN, **BASE_TEMPLATE_CONTEXT_EN, **CLOSING_CONTEXT_EN, **AUTOMATIC_REPLY_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_seasonal_reservation_modified_series( + reservation_series=email_reservation.recurring_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_seasonal_reservation_modified_series__fi(): @@ -1066,7 +1145,7 @@ def test_get_context_for_seasonal_reservation_modified_series__fi(): context = get_context_for_seasonal_reservation_modified_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", weekday_value="[VIIKONPÄIVÄ]", - time_value="[KELLONAIKA]", + time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", language="fi", @@ -1082,7 +1161,7 @@ def test_get_context_for_seasonal_reservation_modified_series__fi(): "weekday_label": "Päivä", "weekday_value": "[VIIKONPÄIVÄ]", "time_label": "Kellonaika", - "time_value": "[KELLONAIKA]", + "time_value": "12:00:00-14:00:00", **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_FI, **BASE_TEMPLATE_CONTEXT_FI, **CLOSING_CONTEXT_FI, @@ -1096,7 +1175,7 @@ def test_get_context_for_seasonal_reservation_modified_series__sv(): context = get_context_for_seasonal_reservation_modified_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", weekday_value="[VIIKONPÄIVÄ]", - time_value="[KELLONAIKA]", + time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", language="sv", @@ -1112,7 +1191,7 @@ def test_get_context_for_seasonal_reservation_modified_series__sv(): "weekday_label": "Dag", "weekday_value": "[VIIKONPÄIVÄ]", "time_label": "Tid", - "time_value": "[KELLONAIKA]", + "time_value": "12:00:00-14:00:00", **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_SV, **BASE_TEMPLATE_CONTEXT_SV, **CLOSING_CONTEXT_SV, @@ -1124,7 +1203,7 @@ def test_get_context_for_seasonal_reservation_modified_series__sv(): @freeze_time("2024-01-01") -def test_get_context_for_seasonal_reservation_modified_single__en(): +def test_get_context_for_seasonal_reservation_modified_single__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_modified_single( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", @@ -1147,6 +1226,12 @@ def test_get_context_for_seasonal_reservation_modified_single__en(): **AUTOMATIC_REPLY_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_seasonal_reservation_modified_single( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_seasonal_reservation_modified_single__fi(): @@ -1202,12 +1287,12 @@ def test_get_context_for_seasonal_reservation_modified_single__sv(): @freeze_time("2024-01-01") -def test_get_context_for_seasonal_reservation_rejected_series__en(): +def test_get_context_for_seasonal_reservation_rejected_series__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_rejected_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", - weekday_value="[VIIKONPÄIVÄ]", - time_value="[KELLONAIKA]", + weekday_value=WeekdayChoice.MONDAY.label, + time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", language="en", @@ -1222,9 +1307,9 @@ def test_get_context_for_seasonal_reservation_rejected_series__en(): "application_section_name": "[HAKEMUKSEN OSAN NIMI]", "application_round_name": "[KAUSIVARAUSKIERROKSEN NIMI]", "weekday_label": "Day", - "weekday_value": "[VIIKONPÄIVÄ]", + "weekday_value": "Monday", "time_label": "Time", - "time_value": "[KELLONAIKA]", + "time_value": "12:00:00-14:00:00", "rejection_reason_label": "Reason", "rejection_reason": "[HYLKÄYKSEN SYY]", **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_EN, @@ -1233,6 +1318,14 @@ def test_get_context_for_seasonal_reservation_rejected_series__en(): **AUTOMATIC_REPLY_CONTEXT_EN, } + email_reservation.state = ReservationStateChoice.DENIED + email_reservation.save() + with TranslationsFromPOFiles(): + assert context == get_context_for_seasonal_reservation_rejected_series( + reservation_series=email_reservation.recurring_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_seasonal_reservation_rejected_series__fi(): @@ -1240,7 +1333,7 @@ def test_get_context_for_seasonal_reservation_rejected_series__fi(): context = get_context_for_seasonal_reservation_rejected_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", weekday_value="[VIIKONPÄIVÄ]", - time_value="[KELLONAIKA]", + time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", rejection_reason="[HYLKÄYKSEN SYY]", @@ -1257,7 +1350,7 @@ def test_get_context_for_seasonal_reservation_rejected_series__fi(): "weekday_label": "Päivä", "weekday_value": "[VIIKONPÄIVÄ]", "time_label": "Kellonaika", - "time_value": "[KELLONAIKA]", + "time_value": "12:00:00-14:00:00", "rejection_reason_label": "Syy", "rejection_reason": "[HYLKÄYKSEN SYY]", **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_FI, @@ -1273,7 +1366,7 @@ def test_get_context_for__seasonal_reservation_rejected_series_sv(): context = get_context_for_seasonal_reservation_rejected_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", weekday_value="[VIIKONPÄIVÄ]", - time_value="[KELLONAIKA]", + time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", rejection_reason="[HYLKÄYKSEN SYY]", @@ -1290,7 +1383,7 @@ def test_get_context_for__seasonal_reservation_rejected_series_sv(): "weekday_label": "Dag", "weekday_value": "[VIIKONPÄIVÄ]", "time_label": "Tid", - "time_value": "[KELLONAIKA]", + "time_value": "12:00:00-14:00:00", "rejection_reason_label": "Orsak", "rejection_reason": "[HYLKÄYKSEN SYY]", **SEASONAL_RESERVATION_CHECK_BOOKING_DETAILS_LINK_SV, @@ -1304,7 +1397,7 @@ def test_get_context_for__seasonal_reservation_rejected_series_sv(): @freeze_time("2024-01-01") -def test_get_context_for_seasonal_reservation_rejected_single__en(): +def test_get_context_for_seasonal_reservation_rejected_single__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_rejected_single( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", @@ -1330,6 +1423,12 @@ def test_get_context_for_seasonal_reservation_rejected_single__en(): **AUTOMATIC_REPLY_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_seasonal_reservation_rejected_single( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context_for_seasonal_reservation_rejected_single__fi(): @@ -1391,17 +1490,17 @@ def test_get_context_for_seasonal_reservation_rejected_single__sv(): @freeze_time("2024-01-01") -def test_get_context__staff_notification_reservation_made__en(): +def test_get_context__staff_notification_reservation_made__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_staff_notification_reservation_made( - reservee_name="John Doe", + reservee_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - reservation_id=12, + reservation_id=email_reservation.id, language="en", ) @@ -1409,22 +1508,28 @@ def test_get_context__staff_notification_reservation_made__en(): "email_recipient_name": None, "reservation_name": "Test reservation", "booking_number_label": "Booking number", - "reservation_id": "12", + "reservation_id": f"{email_reservation.id}", "reservee_name_label": "Reservee name", - "reservee_name": "John Doe", - "staff_reservations_ext_link": "https://fake.varaamo.hel.fi/kasittely/reservations/12", + "reservee_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + "staff_reservations_ext_link": f"https://fake.varaamo.hel.fi/kasittely/reservations/{email_reservation.id}", "staff_reservations_ext_link_html": ( - '' - "https://fake.varaamo.hel.fi/kasittely/reservations/12" + f'' + f"https://fake.varaamo.hel.fi/kasittely/reservations/{email_reservation.id}" ), "text_check_details": "You can view the booking at", "text_staff_reservation_made": "A new booking has been confirmed for Test reservation unit", - "title": "New booking 12 has been made for Test unit", + "title": f"New booking {email_reservation.id} has been made for Test unit", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, **CLOSING_STAFF_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_staff_notification_reservation_made( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__staff_notification_reservation_made__fi(): @@ -1502,17 +1607,17 @@ def test_get_context__staff_notification_reservation_made__sv(): @freeze_time("2024-01-01") -def test_get_context__staff_notification_reservation_requires_handling__en(): +def test_get_context__staff_notification_reservation_requires_handling__en(email_reservation): with TranslationsFromPOFiles(): context = get_context_for_staff_notification_reservation_requires_handling( - reservee_name="John Doe", + reservee_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", reservation_name="Test reservation", reservation_unit_name="Test reservation unit", unit_name="Test unit", unit_location="Test Street, City", begin_datetime=datetime.datetime(2024, 1, 1, 12), end_datetime=datetime.datetime(2024, 1, 1, 14), - reservation_id=12, + reservation_id=email_reservation.id, language="en", ) @@ -1520,24 +1625,30 @@ def test_get_context__staff_notification_reservation_requires_handling__en(): "email_recipient_name": None, "reservation_name": "Test reservation", "booking_number_label": "Booking number", - "reservation_id": "12", + "reservation_id": f"{email_reservation.id}", "reservee_name_label": "Reservee name", - "reservee_name": "John Doe", - "staff_reservations_ext_link": "https://fake.varaamo.hel.fi/kasittely/reservations/12", + "reservee_name": "[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", + "staff_reservations_ext_link": f"https://fake.varaamo.hel.fi/kasittely/reservations/{email_reservation.id}", "staff_reservations_ext_link_html": ( - '' - "https://fake.varaamo.hel.fi/kasittely/reservations/12" + f'' + f"https://fake.varaamo.hel.fi/kasittely/reservations/{email_reservation.id}" ), "text_check_details": "You can view and handle the booking at", "text_staff_reservation_requires_handling": ( "A booking request for Test reservation unit is waiting for processing" ), - "title": "New booking 12 requires handling at unit Test unit", + "title": f"New booking {email_reservation.id} requires handling at unit Test unit", **BASE_TEMPLATE_CONTEXT_EN, **RESERVATION_BASIC_INFO_CONTEXT_EN, **CLOSING_STAFF_CONTEXT_EN, } + with TranslationsFromPOFiles(): + assert context == get_context_for_staff_notification_reservation_requires_handling( + reservation=email_reservation, + language="en", + ) + @freeze_time("2024-01-01") def test_get_context__staff_notification_reservation_requires_handling__fi(): diff --git a/tilavarauspalvelu/models/application_section/actions.py b/tilavarauspalvelu/models/application_section/actions.py index 319ec2d9b..79a2d98f2 100644 --- a/tilavarauspalvelu/models/application_section/actions.py +++ b/tilavarauspalvelu/models/application_section/actions.py @@ -15,9 +15,13 @@ def __init__(self, application_section: ApplicationSection) -> None: self.application_section = application_section def get_reservation_series(self) -> QuerySet[RecurringReservation]: - return RecurringReservation.objects.filter( - allocated_time_slot__reservation_unit_option__application_section=self.application_section - ).prefetch_related("reservations") + return ( + RecurringReservation.objects.filter( + allocated_time_slot__reservation_unit_option__application_section=self.application_section + ) + .prefetch_related("reservations") + .order_by("begin_date") + ) def get_last_reservation(self) -> Reservation | None: return Reservation.objects.filter( diff --git a/tilavarauspalvelu/models/reservation/actions.py b/tilavarauspalvelu/models/reservation/actions.py index 8888d05c5..4452dcd1d 100644 --- a/tilavarauspalvelu/models/reservation/actions.py +++ b/tilavarauspalvelu/models/reservation/actions.py @@ -15,7 +15,7 @@ TimezoneProperty, TimezoneRuleProperty, ) -from tilavarauspalvelu.models import Space +from tilavarauspalvelu.models import ApplicationSection, Space from tilavarauspalvelu.translation import get_attr_by_language, get_translated from utils.date_utils import DEFAULT_TIMEZONE, local_datetime @@ -229,3 +229,8 @@ def calculate_full_price( duration = end_datetime - begin_datetime return pricing.actions.calculate_reservation_price(duration, subsidised=subsidised) + + def get_application_section(self) -> ApplicationSection | None: + return ApplicationSection.objects.filter( + reservation_unit_options__allocated_time_slots__recurring_reservation__reservations=self.reservation + ).first() From 43c0761496f0a4cc1f4ed6818bafa6b33b142c98 Mon Sep 17 00:00:00 2001 From: Eemeli Ranta Date: Wed, 15 Jan 2025 18:16:32 +0200 Subject: [PATCH 4/4] Add application and section ids to email links --- .../test_email/test_application_context.py | 13 +++- .../test_email/test_reservation_context.py | 41 ++++++++++- .../email/template_context/application.py | 10 ++- .../email/template_context/common.py | 37 +++++++--- .../email/template_context/reservation.py | 72 +++++++++++++++---- .../models/recurring_reservation/actions.py | 7 +- 6 files changed, 151 insertions(+), 29 deletions(-) diff --git a/tests/test_integrations/test_email/test_application_context.py b/tests/test_integrations/test_email/test_application_context.py index a187ed25a..25997a4e9 100644 --- a/tests/test_integrations/test_email/test_application_context.py +++ b/tests/test_integrations/test_email/test_application_context.py @@ -307,6 +307,13 @@ def test_get_context_for_application_section_cancelled__en(email_reservation): } with TranslationsFromPOFiles(): + # Add application and section ID to the url, which are always taken from actual instances to the context + section = email_reservation.actions.get_application_section() + old_url = context["check_booking_details_url"] + new_url = f"{old_url}/{section.application_id}/view?tab=reservations§ion={section.id}" + context["check_booking_details_url"] = context["check_booking_details_url"].replace(old_url, new_url) + context["check_booking_details_url_html"] = context["check_booking_details_url_html"].replace(old_url, new_url) + assert context == get_context_for_application_section_cancelled( application_section=email_reservation.actions.get_application_section(), language="en", @@ -384,19 +391,19 @@ def test_get_context_for_staff_notification_application_section_cancelled__en(em application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", cancel_reason="[PERUUTUKSEN SYY]", - language="en", cancelled_reservation_series=[ { - "weekday_value": WeekdayChoice.MONDAY.label, + "weekday_value": "Monday", "time_value": "12:00:00-14:00:00", "reservation_url": get_staff_reservations_ext_link(reservation_id=reservation_id_1), }, { - "weekday_value": WeekdayChoice.TUESDAY.label, + "weekday_value": "Tuesday", "time_value": "21:00:00-22:00:00", "reservation_url": get_staff_reservations_ext_link(reservation_id=reservation_id_2), }, ], + language="en", ) assert context == { diff --git a/tests/test_integrations/test_email/test_reservation_context.py b/tests/test_integrations/test_email/test_reservation_context.py index c195af97e..29d151818 100644 --- a/tests/test_integrations/test_email/test_reservation_context.py +++ b/tests/test_integrations/test_email/test_reservation_context.py @@ -7,7 +7,7 @@ import pytest from freezegun import freeze_time -from tilavarauspalvelu.enums import ReservationStateChoice, WeekdayChoice +from tilavarauspalvelu.enums import ReservationStateChoice from tilavarauspalvelu.integrations.email.template_context import ( get_context_for_reservation_approved, get_context_for_reservation_cancelled, @@ -1034,6 +1034,13 @@ def test_get_context_for_seasonal_reservation_cancelled_single__en(email_reserva } with TranslationsFromPOFiles(): + # Add application and section ID to the url, which are always taken from actual instances to the context + section = email_reservation.actions.get_application_section() + old_url = context["check_booking_details_url"] + new_url = f"{old_url}/{section.application_id}/view?tab=reservations§ion={section.id}" + context["check_booking_details_url"] = context["check_booking_details_url"].replace(old_url, new_url) + context["check_booking_details_url_html"] = context["check_booking_details_url_html"].replace(old_url, new_url) + assert context == get_context_for_seasonal_reservation_cancelled_single( reservation=email_reservation, language="en", @@ -1108,7 +1115,7 @@ def test_get_context_for_seasonal_reservation_modified_series__en(email_reservat with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_modified_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", - weekday_value=WeekdayChoice.MONDAY.label, + weekday_value="Monday", time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", @@ -1133,6 +1140,13 @@ def test_get_context_for_seasonal_reservation_modified_series__en(email_reservat } with TranslationsFromPOFiles(): + # Add application and section ID to the url, which are always taken from actual instances to the context + section = email_reservation.actions.get_application_section() + old_url = context["check_booking_details_url"] + new_url = f"{old_url}/{section.application_id}/view?tab=reservations§ion={section.id}" + context["check_booking_details_url"] = context["check_booking_details_url"].replace(old_url, new_url) + context["check_booking_details_url_html"] = context["check_booking_details_url_html"].replace(old_url, new_url) + assert context == get_context_for_seasonal_reservation_modified_series( reservation_series=email_reservation.recurring_reservation, language="en", @@ -1227,6 +1241,13 @@ def test_get_context_for_seasonal_reservation_modified_single__en(email_reservat } with TranslationsFromPOFiles(): + # Add application and section ID to the url, which are always taken from actual instances to the context + section = email_reservation.actions.get_application_section() + old_url = context["check_booking_details_url"] + new_url = f"{old_url}/{section.application_id}/view?tab=reservations§ion={section.id}" + context["check_booking_details_url"] = context["check_booking_details_url"].replace(old_url, new_url) + context["check_booking_details_url_html"] = context["check_booking_details_url_html"].replace(old_url, new_url) + assert context == get_context_for_seasonal_reservation_modified_single( reservation=email_reservation, language="en", @@ -1291,7 +1312,7 @@ def test_get_context_for_seasonal_reservation_rejected_series__en(email_reservat with TranslationsFromPOFiles(): context = get_context_for_seasonal_reservation_rejected_series( email_recipient_name="[SÄHKÖPOSTIN VASTAANOTTAJAN NIMI]", - weekday_value=WeekdayChoice.MONDAY.label, + weekday_value="Monday", time_value="12:00:00-14:00:00", application_section_name="[HAKEMUKSEN OSAN NIMI]", application_round_name="[KAUSIVARAUSKIERROKSEN NIMI]", @@ -1321,6 +1342,13 @@ def test_get_context_for_seasonal_reservation_rejected_series__en(email_reservat email_reservation.state = ReservationStateChoice.DENIED email_reservation.save() with TranslationsFromPOFiles(): + # Add application and section ID to the url, which are always taken from actual instances to the context + section = email_reservation.actions.get_application_section() + old_url = context["check_booking_details_url"] + new_url = f"{old_url}/{section.application_id}/view?tab=reservations§ion={section.id}" + context["check_booking_details_url"] = context["check_booking_details_url"].replace(old_url, new_url) + context["check_booking_details_url_html"] = context["check_booking_details_url_html"].replace(old_url, new_url) + assert context == get_context_for_seasonal_reservation_rejected_series( reservation_series=email_reservation.recurring_reservation, language="en", @@ -1424,6 +1452,13 @@ def test_get_context_for_seasonal_reservation_rejected_single__en(email_reservat } with TranslationsFromPOFiles(): + # Add application and section ID to the url, which are always taken from actual instances to the context + section = email_reservation.actions.get_application_section() + old_url = context["check_booking_details_url"] + new_url = f"{old_url}/{section.application_id}/view?tab=reservations§ion={section.id}" + context["check_booking_details_url"] = context["check_booking_details_url"].replace(old_url, new_url) + context["check_booking_details_url_html"] = context["check_booking_details_url_html"].replace(old_url, new_url) + assert context == get_context_for_seasonal_reservation_rejected_single( reservation=email_reservation, language="en", diff --git a/tilavarauspalvelu/integrations/email/template_context/application.py b/tilavarauspalvelu/integrations/email/template_context/application.py index 2539ac1c2..e8df0ef9f 100644 --- a/tilavarauspalvelu/integrations/email/template_context/application.py +++ b/tilavarauspalvelu/integrations/email/template_context/application.py @@ -134,7 +134,13 @@ def get_context_for_application_section_cancelled( "email_recipient_name": application_section.application.applicant, "cancel_reason": get_attr_by_language(reservation.cancel_reason, "reason", language), **params_for_application_section_info(application_section=application_section, language=language), + **get_contex_for_seasonal_reservation_check_details_url( + language=language, + application_section=application_section, + ), } + else: + data.update(get_contex_for_seasonal_reservation_check_details_url(language=language)) return { "title": pgettext("Email", "Your seasonal booking has been cancelled"), @@ -147,8 +153,10 @@ def get_context_for_application_section_cancelled( "application_section_name": data["application_section_name"], "application_round_name": data["application_round_name"], **get_contex_for_base_template(email_recipient_name=data["email_recipient_name"]), - **get_contex_for_seasonal_reservation_check_details_url(language=language), **get_contex_for_closing(language=language), + "check_booking_details_text": data["check_booking_details_text"], + "check_booking_details_url_html": data["check_booking_details_url_html"], + "check_booking_details_url": data["check_booking_details_url"], } diff --git a/tilavarauspalvelu/integrations/email/template_context/common.py b/tilavarauspalvelu/integrations/email/template_context/common.py index f704b01f6..5881c0ec2 100644 --- a/tilavarauspalvelu/integrations/email/template_context/common.py +++ b/tilavarauspalvelu/integrations/email/template_context/common.py @@ -149,8 +149,12 @@ def get_contex_for_reservation_price_range( } -def get_contex_for_seasonal_reservation_check_details_url(*, language: Lang) -> EmailContext: - link = get_my_applications_ext_link(language=language) +def get_contex_for_seasonal_reservation_check_details_url( + *, + language: Lang, + application_section: ApplicationSection | None = None, +) -> EmailContext: + link = get_my_applications_ext_link(language=language, application_section=application_section) return { "check_booking_details_text": pgettext("Email", "You can check your booking details at"), @@ -198,7 +202,7 @@ def params_for_price_range_info(*, reservation: Reservation) -> dict[str, Any]: } -def params_for_reservation_series_info(*, reservation_series: RecurringReservation) -> dict[str, Any]: +def params_for_reservation_series_info(*, reservation_series: RecurringReservation) -> dict[str, str]: weekdays = ", ".join(str(Weekday.from_week_day(int(val)).label) for val in reservation_series.weekdays.split(",")) return { "weekday_value": weekdays, @@ -206,7 +210,7 @@ def params_for_reservation_series_info(*, reservation_series: RecurringReservati } -def params_for_application_section_info(*, application_section: ApplicationSection, language: Lang) -> dict[str, Any]: +def params_for_application_section_info(*, application_section: ApplicationSection, language: Lang) -> dict[str, str]: return { "application_section_name": application_section.name, "application_round_name": get_attr_by_language( @@ -225,11 +229,28 @@ def get_varaamo_ext_link(*, language: Lang) -> str: return url_base -def get_my_applications_ext_link(*, language: Lang) -> str: - url_base = settings.EMAIL_VARAAMO_EXT_LINK.removesuffix("/") +def get_my_applications_ext_link( + *, + language: Lang, + application_section: ApplicationSection | None = None, +) -> str: + """ + Return the link to the 'My applications' page: + e.g. https://varaamo.hel.fi/applications/{application_id}/view?tab=reservations§ion={application_section_id} + """ + url = settings.EMAIL_VARAAMO_EXT_LINK.removesuffix("/") + if language != "fi": - return f"{url_base}/{language}/applications" - return f"{url_base}/applications" + url = f"{url}/{language}" + url = f"{url}/applications" + + if application_section: + application_id = getattr(application_section, "application_id", None) + application_section_id = getattr(application_section, "id", None) + + url = f"{url}/{application_id}/view?tab=reservations§ion={application_section_id}" + + return url def get_my_reservations_ext_link(*, language: Lang) -> str: diff --git a/tilavarauspalvelu/integrations/email/template_context/reservation.py b/tilavarauspalvelu/integrations/email/template_context/reservation.py index f05ea60e4..3af518cdf 100644 --- a/tilavarauspalvelu/integrations/email/template_context/reservation.py +++ b/tilavarauspalvelu/integrations/email/template_context/reservation.py @@ -579,11 +579,19 @@ def get_context_for_seasonal_reservation_cancelled_single( **data: Any, ) -> EmailContext: if reservation is not None: + application_section = reservation.actions.get_application_section() + data: dict[str, Any] = { "email_recipient_name": reservation.actions.get_email_reservee_name(), "cancel_reason": get_attr_by_language(reservation.cancel_reason, "reason", language=language), **params_for_base_info(reservation=reservation, language=language), + **get_contex_for_seasonal_reservation_check_details_url( + language=language, + application_section=application_section, + ), } + else: + data.update(get_contex_for_seasonal_reservation_check_details_url(language=language)) title = pgettext("Email", "The space reservation included in your seasonal booking has been cancelled") return { @@ -599,8 +607,10 @@ def get_context_for_seasonal_reservation_cancelled_single( begin_datetime=data["begin_datetime"], end_datetime=data["end_datetime"], ), - **get_contex_for_seasonal_reservation_check_details_url(language=language), **get_contex_for_closing(language=language), + "check_booking_details_text": data["check_booking_details_text"], + "check_booking_details_url_html": data["check_booking_details_url_html"], + "check_booking_details_url": data["check_booking_details_url"], } @@ -633,13 +643,19 @@ def get_context_for_seasonal_reservation_modified_series( **data: Any, ) -> EmailContext: if reservation_series is not None: - section = reservation_series.allocated_time_slot.reservation_unit_option.application_section + application_section = reservation_series.actions.get_application_section() data: dict[str, Any] = { - "email_recipient_name": section.application.applicant, + "email_recipient_name": application_section.application.applicant, **params_for_reservation_series_info(reservation_series=reservation_series), - **params_for_application_section_info(application_section=section, language=language), + **params_for_application_section_info(application_section=application_section, language=language), + **get_contex_for_seasonal_reservation_check_details_url( + language=language, + application_section=application_section, + ), } + else: + data.update(get_contex_for_seasonal_reservation_check_details_url(language=language)) title = pgettext("Email", "The time of the space reservation included in your seasonal booking has changed") return { @@ -653,8 +669,10 @@ def get_context_for_seasonal_reservation_modified_series( "time_label": pgettext("Email", "Time"), "time_value": data["time_value"], **get_contex_for_base_template(email_recipient_name=data["email_recipient_name"]), - **get_contex_for_seasonal_reservation_check_details_url(language=language), **get_contex_for_closing(language=language), + "check_booking_details_text": data["check_booking_details_text"], + "check_booking_details_url_html": data["check_booking_details_url_html"], + "check_booking_details_url": data["check_booking_details_url"], } @@ -688,10 +706,18 @@ def get_context_for_seasonal_reservation_modified_single( **data: Any, ) -> EmailContext: if reservation is not None: + application_section = reservation.actions.get_application_section() + data: dict[str, Any] = { "email_recipient_name": reservation.actions.get_email_reservee_name(), **params_for_base_info(reservation=reservation, language=language), + **get_contex_for_seasonal_reservation_check_details_url( + language=language, + application_section=application_section, + ), } + else: + data.update(get_contex_for_seasonal_reservation_check_details_url(language=language)) title = pgettext("Email", "The time of the space reservation included in your seasonal booking has changed") return { @@ -705,8 +731,10 @@ def get_context_for_seasonal_reservation_modified_single( begin_datetime=data["begin_datetime"], end_datetime=data["end_datetime"], ), - **get_contex_for_seasonal_reservation_check_details_url(language=language), **get_contex_for_closing(language=language), + "check_booking_details_text": data["check_booking_details_text"], + "check_booking_details_url_html": data["check_booking_details_url_html"], + "check_booking_details_url": data["check_booking_details_url"], } @@ -740,15 +768,21 @@ def get_context_for_seasonal_reservation_rejected_series( **data: Any, ) -> EmailContext: if reservation_series is not None: - section = reservation_series.allocated_time_slot.reservation_unit_option.application_section - reservation = reservation_series.reservations.filter(state=ReservationStateChoice.DENIED).last() + application_section = reservation_series.actions.get_application_section() + latest_denied_reservation = reservation_series.reservations.filter(state=ReservationStateChoice.DENIED).last() data: dict[str, Any] = { - "email_recipient_name": section.application.applicant, - "rejection_reason": get_attr_by_language(reservation.deny_reason, "reason", language), + "email_recipient_name": application_section.application.applicant, + "rejection_reason": get_attr_by_language(latest_denied_reservation.deny_reason, "reason", language), **params_for_reservation_series_info(reservation_series=reservation_series), - **params_for_application_section_info(application_section=section, language=language), + **params_for_application_section_info(application_section=application_section, language=language), + **get_contex_for_seasonal_reservation_check_details_url( + language=language, + application_section=application_section, + ), } + else: + data.update(get_contex_for_seasonal_reservation_check_details_url(language=language)) return { "title": pgettext("Email", "Your seasonal booking has been cancelled"), @@ -765,8 +799,10 @@ def get_context_for_seasonal_reservation_rejected_series( "time_label": pgettext("Email", "Time"), "time_value": data["time_value"], **get_contex_for_base_template(email_recipient_name=data["email_recipient_name"]), - **get_contex_for_seasonal_reservation_check_details_url(language=language), **get_contex_for_closing(language=language), + "check_booking_details_text": data["check_booking_details_text"], + "check_booking_details_url_html": data["check_booking_details_url_html"], + "check_booking_details_url": data["check_booking_details_url"], } @@ -801,11 +837,19 @@ def get_context_for_seasonal_reservation_rejected_single( **data: Any, ) -> EmailContext: if reservation is not None: + application_section = reservation.actions.get_application_section() + data: dict[str, Any] = { "email_recipient_name": reservation.actions.get_email_reservee_name(), "rejection_reason": get_attr_by_language(reservation.deny_reason, "reason", language), **params_for_base_info(reservation=reservation, language=language), + **get_contex_for_seasonal_reservation_check_details_url( + language=language, + application_section=application_section, + ), } + else: + data.update(get_contex_for_seasonal_reservation_check_details_url(language=language)) title = pgettext("Email", "The space reservation included in your seasonal booking has been cancelled") return { @@ -821,8 +865,10 @@ def get_context_for_seasonal_reservation_rejected_single( begin_datetime=data["begin_datetime"], end_datetime=data["end_datetime"], ), - **get_contex_for_seasonal_reservation_check_details_url(language=language), **get_contex_for_closing(language=language), + "check_booking_details_text": data["check_booking_details_text"], + "check_booking_details_url_html": data["check_booking_details_url_html"], + "check_booking_details_url": data["check_booking_details_url"], } diff --git a/tilavarauspalvelu/models/recurring_reservation/actions.py b/tilavarauspalvelu/models/recurring_reservation/actions.py index bedafd53a..3763935c8 100644 --- a/tilavarauspalvelu/models/recurring_reservation/actions.py +++ b/tilavarauspalvelu/models/recurring_reservation/actions.py @@ -7,7 +7,7 @@ from tilavarauspalvelu.enums import RejectionReadinessChoice from tilavarauspalvelu.integrations.opening_hours.time_span_element import TimeSpanElement -from tilavarauspalvelu.models import AffectingTimeSpan, RejectedOccurrence, Reservation +from tilavarauspalvelu.models import AffectingTimeSpan, ApplicationSection, RejectedOccurrence, Reservation from utils.date_utils import DEFAULT_TIMEZONE, combine, get_periods_between if TYPE_CHECKING: @@ -334,3 +334,8 @@ def get_email_reservee_name(self) -> str: if reservation is not None: return reservation.actions.get_email_reservee_name() return "" + + def get_application_section(self) -> ApplicationSection | None: + return ApplicationSection.objects.filter( + reservation_unit_options__allocated_time_slots__recurring_reservation=self.recurring_reservation + ).first()