From 934c1df88d00d15992ab37efae7b13c9ac7ddccf Mon Sep 17 00:00:00 2001 From: Matti Lamppu Date: Thu, 23 Jan 2025 09:26:07 +0200 Subject: [PATCH] Fix errors in Pindora client - Only account for CONFIRMED reservations - Add PindoraClientError to differentiate non-API errors - Use `local_iso_format` to format datetimes - Fix a couple of typos --- .../test_reservation_series.py | 60 ++++++++++++---- .../test_reservation_unit.py | 6 +- .../test_seasonal_booking.py | 69 +++++++++++++++++-- .../integrations/keyless_entry/client.py | 66 ++++++++++-------- .../integrations/keyless_entry/exceptions.py | 16 +++-- 5 files changed, 161 insertions(+), 56 deletions(-) diff --git a/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_series.py b/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_series.py index 91793b2fc4..98f3312bd7 100644 --- a/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_series.py +++ b/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_series.py @@ -11,8 +11,9 @@ HTTP_418_IM_A_TEAPOT, ) +from tilavarauspalvelu.enums import ReservationStateChoice from tilavarauspalvelu.integrations.keyless_entry import PindoraClient -from tilavarauspalvelu.integrations.keyless_entry.exceptions import PindoraAPIError +from tilavarauspalvelu.integrations.keyless_entry.exceptions import PindoraAPIError, PindoraClientError from utils.date_utils import DEFAULT_TIMEZONE, local_datetime from utils.external_service.base_external_service_client import BaseExternalServiceClient @@ -141,6 +142,7 @@ def test_pindora_client__create_reservation_series(is_active: bool): reservation = ReservationFactory.create( recurring_reservation=recurring_reservation, created_at=local_datetime(), + state=ReservationStateChoice.CONFIRMED, ) data = default_reservation_series_response(reservation, access_code_is_active=is_active) @@ -177,7 +179,7 @@ def test_pindora_client__create_reservation_series(is_active: bool): @pytest.mark.django_db def test_pindora_client__create_reservation_series__403(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = "Pindora API key is invalid." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -191,7 +193,7 @@ def test_pindora_client__create_reservation_series__403(): @pytest.mark.django_db def test_pindora_client__create_reservation_series__400(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = "Invalid Pindora API request: bad request." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -205,7 +207,7 @@ def test_pindora_client__create_reservation_series__400(): @pytest.mark.django_db def test_pindora_client__create_reservation_series__409(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = f"Reservation series '{recurring_reservation.ext_uuid}' already exists in Pindora." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -219,7 +221,7 @@ def test_pindora_client__create_reservation_series__409(): @pytest.mark.django_db def test_pindora_client__create_reservation_series__not_200(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = ( f"Unexpected response from Pindora when creating reservation series '{recurring_reservation.ext_uuid}': " @@ -237,8 +239,22 @@ def test_pindora_client__create_reservation_series__not_200(): def test_pindora_client__create_reservation_series__no_reservations(): recurring_reservation = RecurringReservationFactory.create() - msg = f"No reservations in for reservation series '{recurring_reservation.ext_uuid}'." - with pytest.raises(PindoraAPIError, match=exact(msg)): + msg = f"No confirmed reservations in reservation series '{recurring_reservation.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): + PindoraClient.create_reservation_series(recurring_reservation) + + +@patch_method( + BaseExternalServiceClient.generic, + return_value=ResponseMock(status_code=HTTP_200_OK), +) +@pytest.mark.django_db +def test_pindora_client__create_reservation_series__no_confirmed_reservations(): + recurring_reservation = RecurringReservationFactory.create() + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.DENIED) + + msg = f"No confirmed reservations in reservation series '{recurring_reservation.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): PindoraClient.create_reservation_series(recurring_reservation) @@ -250,7 +266,7 @@ def test_pindora_client__create_reservation_series__no_reservations(): @pytest.mark.parametrize("is_active", [True, False]) def test_pindora_client__update_reservation_series(is_active: bool): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) PindoraClient.update_reservation_series(recurring_reservation, is_active=is_active) @@ -264,7 +280,7 @@ def test_pindora_client__update_reservation_series(is_active: bool): @pytest.mark.django_db def test_pindora_client__update_reservation_series__403(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = "Pindora API key is invalid." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -278,7 +294,7 @@ def test_pindora_client__update_reservation_series__403(): @pytest.mark.django_db def test_pindora_client__update_reservation_series__400(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = "Invalid Pindora API request: bad request." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -292,7 +308,7 @@ def test_pindora_client__update_reservation_series__400(): @pytest.mark.django_db def test_pindora_client__update_reservation_series__404(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = f"Reservation series '{recurring_reservation.ext_uuid}' not found from Pindora." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -306,7 +322,7 @@ def test_pindora_client__update_reservation_series__404(): @pytest.mark.django_db def test_pindora_client__update_reservation_series__409(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = f"Reservation series '{recurring_reservation.ext_uuid}' already exists in Pindora." with pytest.raises(PindoraAPIError, match=exact(msg)): @@ -320,7 +336,7 @@ def test_pindora_client__update_reservation_series__409(): @pytest.mark.django_db def test_pindora_client__update_reservation_series__not_204(): recurring_reservation = RecurringReservationFactory.create() - ReservationFactory.create(recurring_reservation=recurring_reservation) + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.CONFIRMED) msg = ( f"Unexpected response from Pindora when updating reservation series '{recurring_reservation.ext_uuid}': " @@ -338,8 +354,22 @@ def test_pindora_client__update_reservation_series__not_204(): def test_pindora_client__update_reservation_series__no_reservations(): recurring_reservation = RecurringReservationFactory.create() - msg = f"No reservations in for reservation series '{recurring_reservation.ext_uuid}'." - with pytest.raises(PindoraAPIError, match=exact(msg)): + msg = f"No confirmed reservations in reservation series '{recurring_reservation.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): + PindoraClient.update_reservation_series(recurring_reservation) + + +@patch_method( + BaseExternalServiceClient.generic, + return_value=ResponseMock(status_code=HTTP_200_OK), +) +@pytest.mark.django_db +def test_pindora_client__update_reservation_series__no_confirmed_reservations(): + recurring_reservation = RecurringReservationFactory.create() + ReservationFactory.create(recurring_reservation=recurring_reservation, state=ReservationStateChoice.DENIED) + + msg = f"No confirmed reservations in reservation series '{recurring_reservation.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): PindoraClient.update_reservation_series(recurring_reservation) diff --git a/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_unit.py b/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_unit.py index 54de776227..60ac6a3cf6 100644 --- a/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_unit.py +++ b/tests/test_integrations/test_keyless_entry/test_pindora_client/test_reservation_unit.py @@ -4,7 +4,7 @@ from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_403_FORBIDDEN, HTTP_404_NOT_FOUND, HTTP_418_IM_A_TEAPOT from tilavarauspalvelu.integrations.keyless_entry import PindoraClient -from tilavarauspalvelu.integrations.keyless_entry.exceptions import PindoraAPIConfigurationError, PindoraAPIError +from tilavarauspalvelu.integrations.keyless_entry.exceptions import PindoraAPIError, PindoraClientConfigurationError from utils.external_service.base_external_service_client import BaseExternalServiceClient from tests.factories import ReservationUnitFactory @@ -34,7 +34,7 @@ def test_pindora_client__get_reservation_unit__missing_api_key(settings): reservation_unit = ReservationUnitFactory.build() msg = "'PINDORA_API_KEY' setting must to be configured for Pindora client to work." - with pytest.raises(PindoraAPIConfigurationError, match=exact(msg)): + with pytest.raises(PindoraClientConfigurationError, match=exact(msg)): PindoraClient.get_reservation_unit(reservation_unit) @@ -44,7 +44,7 @@ def test_pindora_client__get_reservation_unit__missing_api_url(settings): reservation_unit = ReservationUnitFactory.build() msg = "'PINDORA_API_URL' setting must to be configured for Pindora client to work." - with pytest.raises(PindoraAPIConfigurationError, match=exact(msg)): + with pytest.raises(PindoraClientConfigurationError, match=exact(msg)): PindoraClient.get_reservation_unit(reservation_unit) diff --git a/tests/test_integrations/test_keyless_entry/test_pindora_client/test_seasonal_booking.py b/tests/test_integrations/test_keyless_entry/test_pindora_client/test_seasonal_booking.py index d04cbfb0f2..9fabb2c7ae 100644 --- a/tests/test_integrations/test_keyless_entry/test_pindora_client/test_seasonal_booking.py +++ b/tests/test_integrations/test_keyless_entry/test_pindora_client/test_seasonal_booking.py @@ -11,8 +11,9 @@ HTTP_418_IM_A_TEAPOT, ) +from tilavarauspalvelu.enums import ReservationStateChoice from tilavarauspalvelu.integrations.keyless_entry import PindoraClient -from tilavarauspalvelu.integrations.keyless_entry.exceptions import PindoraAPIError +from tilavarauspalvelu.integrations.keyless_entry.exceptions import PindoraAPIError, PindoraClientError from utils.date_utils import DEFAULT_TIMEZONE, local_datetime from utils.external_service.base_external_service_client import BaseExternalServiceClient @@ -121,6 +122,7 @@ def test_pindora_client__create_seasonal_booking(is_active: bool): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) data = default_seasonal_booking_response(reservation, access_code_is_active=is_active) @@ -165,6 +167,7 @@ def test_pindora_client__create_seasonal_booking__403(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = "Pindora API key is invalid." @@ -187,6 +190,7 @@ def test_pindora_client__create_seasonal_booking__400(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = "Invalid Pindora API request: bad request." @@ -209,6 +213,7 @@ def test_pindora_client__create_seasonal_booking__404(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = f"Seasonal booking '{application_section.ext_uuid}' not found from Pindora." @@ -231,6 +236,7 @@ def test_pindora_client__create_seasonal_booking__409(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = f"Seasonal booking '{application_section.ext_uuid}' already exists in Pindora." @@ -253,6 +259,7 @@ def test_pindora_client__create_seasonal_booking__not_200(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = ( @@ -271,8 +278,31 @@ def test_pindora_client__create_seasonal_booking__not_200(): def test_pindora_client__create_seasonal_booking__no_reservations(): application_section = ApplicationSectionFactory.create() - msg = f"No reservations in for seasonal booking '{application_section.ext_uuid}'." - with pytest.raises(PindoraAPIError, match=exact(msg)): + msg = f"No confirmed reservations in seasonal booking '{application_section.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): + PindoraClient.create_seasonal_booking(application_section) + + +@patch_method( + BaseExternalServiceClient.generic, + return_value=ResponseMock(status_code=HTTP_200_OK), +) +@pytest.mark.django_db +def test_pindora_client__create_seasonal_booking__no_confirmed_reservations(): + application_section = ApplicationSectionFactory.create() + reservation_unit_option = ReservationUnitOptionFactory.create(application_section=application_section) + allocation = AllocatedTimeSlotFactory.create(reservation_unit_option=reservation_unit_option) + recurring_reservation = RecurringReservationFactory.create(allocated_time_slot=allocation) + + ReservationFactory.create( + recurring_reservation=recurring_reservation, + created_at=local_datetime(), + user=application_section.application.user, + state=ReservationStateChoice.DENIED, + ) + + msg = f"No confirmed reservations in seasonal booking '{application_section.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): PindoraClient.create_seasonal_booking(application_section) @@ -292,6 +322,7 @@ def test_pindora_client__update_seasonal_booking(is_active: bool): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) PindoraClient.update_seasonal_reservation(application_section, is_active=is_active) @@ -314,6 +345,7 @@ def test_pindora_client__update_seasonal_booking__403(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = "Pindora API key is invalid." @@ -336,6 +368,7 @@ def test_pindora_client__update_seasonal_booking__400(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = "Invalid Pindora API request: bad request." @@ -358,6 +391,7 @@ def test_pindora_client__update_seasonal_booking__404(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = f"Seasonal booking '{application_section.ext_uuid}' not found from Pindora." @@ -380,6 +414,7 @@ def test_pindora_client__update_seasonal_booking__409(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = f"Seasonal booking '{application_section.ext_uuid}' already exists in Pindora." @@ -402,6 +437,7 @@ def test_pindora_client__update_seasonal_booking__not_204(): recurring_reservation=recurring_reservation, created_at=local_datetime(), user=application_section.application.user, + state=ReservationStateChoice.CONFIRMED, ) msg = ( @@ -420,8 +456,31 @@ def test_pindora_client__update_seasonal_booking__not_204(): def test_pindora_client__update_seasonal_booking__no_reservations(): application_section = ApplicationSectionFactory.create() - msg = f"No reservations in for seasonal booking '{application_section.ext_uuid}'." - with pytest.raises(PindoraAPIError, match=exact(msg)): + msg = f"No confirmed reservations in seasonal booking '{application_section.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): + PindoraClient.update_seasonal_reservation(application_section) + + +@patch_method( + BaseExternalServiceClient.generic, + return_value=ResponseMock(status_code=HTTP_200_OK), +) +@pytest.mark.django_db +def test_pindora_client__update_seasonal_booking__no_confirmed_reservations(): + application_section = ApplicationSectionFactory.create() + reservation_unit_option = ReservationUnitOptionFactory.create(application_section=application_section) + allocation = AllocatedTimeSlotFactory.create(reservation_unit_option=reservation_unit_option) + recurring_reservation = RecurringReservationFactory.create(allocated_time_slot=allocation) + + ReservationFactory.create( + recurring_reservation=recurring_reservation, + created_at=local_datetime(), + user=application_section.application.user, + state=ReservationStateChoice.DENIED, + ) + + msg = f"No confirmed reservations in seasonal booking '{application_section.ext_uuid}'." + with pytest.raises(PindoraClientError, match=exact(msg)): PindoraClient.update_seasonal_reservation(application_section) diff --git a/tilavarauspalvelu/integrations/keyless_entry/client.py b/tilavarauspalvelu/integrations/keyless_entry/client.py index 4b48177b2a..dc31f51dc5 100644 --- a/tilavarauspalvelu/integrations/keyless_entry/client.py +++ b/tilavarauspalvelu/integrations/keyless_entry/client.py @@ -14,10 +14,16 @@ HTTP_409_CONFLICT, ) -from utils.date_utils import DEFAULT_TIMEZONE +from tilavarauspalvelu.enums import ReservationStateChoice +from utils.date_utils import local_iso_format from utils.external_service.base_external_service_client import BaseExternalServiceClient -from .exceptions import PindoraAPIConfigurationError, PindoraAPIError, PindoraUnexpectedResponseError +from .exceptions import ( + PindoraAPIError, + PindoraClientConfigurationError, + PindoraClientError, + PindoraUnexpectedResponseError, +) from .typing import ( PindoraReservationCreateData, PindoraReservationResponse, @@ -99,8 +105,8 @@ def create_reservation(cls, reservation: Reservation, *, is_active: bool = False data = PindoraReservationCreateData( reservation_id=str(reservation.ext_uuid), reservation_unit_id=str(reservation_unit.uuid), - begin=reservation.begin.astimezone(DEFAULT_TIMEZONE).isoformat(), - end=reservation.end.astimezone(DEFAULT_TIMEZONE).isoformat(), + begin=local_iso_format(reservation.begin), + end=local_iso_format(reservation.end), is_active=is_active, ) @@ -120,8 +126,8 @@ def update_reservation(cls, reservation: Reservation, *, is_active: bool = False url = cls._build_url(f"reservation/{reservation.ext_uuid}") data = PindoraUpdateReservationData( - begin=reservation.begin.astimezone(DEFAULT_TIMEZONE).isoformat(), - end=reservation.end.astimezone(DEFAULT_TIMEZONE).isoformat(), + begin=local_iso_format(reservation.begin), + end=local_iso_format(reservation.end), is_active=is_active, ) @@ -191,20 +197,22 @@ def create_seasonal_booking( url = cls._build_url("seasonal-bookings") reservations: list[Reservation] = list( - application_section.actions.get_reservations().select_related("recurring_reservation__reservation_unit") + application_section.actions.get_reservations() + .filter(state=ReservationStateChoice.CONFIRMED) + .select_related("recurring_reservation__reservation_unit") ) if not reservations: - msg = f"No reservations in for seasonal booking '{application_section.ext_uuid}'." - raise PindoraAPIError(msg) + msg = f"No confirmed reservations in seasonal booking '{application_section.ext_uuid}'." + raise PindoraClientError(msg) data = PindoraSeasonalBookingCreateData( seasonal_booking_id=str(application_section.ext_uuid), series=[ PindoraSeasonalBookingReservationData( reservation_unit_id=str(reservation.recurring_reservation.reservation_unit.uuid), - begin=reservation.begin.astimezone(DEFAULT_TIMEZONE).isoformat(), - end=reservation.end.astimezone(DEFAULT_TIMEZONE).isoformat(), + begin=local_iso_format(reservation.begin), + end=local_iso_format(reservation.end), ) for reservation in reservations ], @@ -232,19 +240,21 @@ def update_seasonal_reservation( url = cls._build_url(f"seasonal-booking/{application_section.ext_uuid}") reservations: list[Reservation] = list( - application_section.actions.get_reservations().select_related("recurring_reservation__reservation_unit") + application_section.actions.get_reservations() + .filter(state=ReservationStateChoice.CONFIRMED) + .select_related("recurring_reservation__reservation_unit") ) if not reservations: - msg = f"No reservations in for seasonal booking '{application_section.ext_uuid}'." - raise PindoraAPIError(msg) + msg = f"No confirmed reservations in seasonal booking '{application_section.ext_uuid}'." + raise PindoraClientError(msg) data = PindoraSeasonalBookingUpdateData( series=[ PindoraSeasonalBookingReservationData( reservation_unit_id=str(reservation.recurring_reservation.reservation_unit.uuid), - begin=reservation.begin.astimezone(DEFAULT_TIMEZONE).isoformat(), - end=reservation.end.astimezone(DEFAULT_TIMEZONE).isoformat(), + begin=local_iso_format(reservation.begin), + end=local_iso_format(reservation.end), ) for reservation in reservations ], @@ -322,19 +332,19 @@ def create_reservation_series( """Create a new reservation series in Pindora.""" url = cls._build_url("reservation-series") - reservations: list[Reservation] = list(series.reservations.all()) + reservations: list[Reservation] = list(series.reservations.filter(state=ReservationStateChoice.CONFIRMED)) if not reservations: - msg = f"No reservations in for reservation series '{series.ext_uuid}'." - raise PindoraAPIError(msg) + msg = f"No confirmed reservations in reservation series '{series.ext_uuid}'." + raise PindoraClientError(msg) data = PindoraReservationSeriesCreateData( reservation_serie_id=str(series.ext_uuid), reservation_unit_id=str(series.reservation_unit.uuid), series=[ PindoraReservationSeriesReservationData( - begin=reservation.begin.astimezone(DEFAULT_TIMEZONE).isoformat(), - end=reservation.end.astimezone(DEFAULT_TIMEZONE).isoformat(), + begin=local_iso_format(reservation.begin), + end=local_iso_format(reservation.end), ) for reservation in reservations ], @@ -361,17 +371,17 @@ def update_reservation_series( """Create a new reservation series in Pindora.""" url = cls._build_url(f"reservation-serie/{series.ext_uuid}") - reservations: list[Reservation] = list(series.reservations.all()) + reservations: list[Reservation] = list(series.reservations.filter(state=ReservationStateChoice.CONFIRMED)) if not reservations: - msg = f"No reservations in for reservation series '{series.ext_uuid}'." - raise PindoraAPIError(msg) + msg = f"No confirmed reservations in reservation series '{series.ext_uuid}'." + raise PindoraClientError(msg) data = PindoraReservationSeriesUpdateData( series=[ PindoraReservationSeriesReservationData( - begin=reservation.begin.astimezone(DEFAULT_TIMEZONE).isoformat(), - end=reservation.end.astimezone(DEFAULT_TIMEZONE).isoformat(), + begin=local_iso_format(reservation.begin), + end=local_iso_format(reservation.end), ) for reservation in reservations ], @@ -532,7 +542,7 @@ def _parse_reservation_series_response(cls, data: dict[str, Any]) -> PindoraRese @classmethod def _build_url(cls, endpoint: str) -> str: if not settings.PINDORA_API_URL: - raise PindoraAPIConfigurationError(config="PINDORA_API_URL") + raise PindoraClientConfigurationError(config="PINDORA_API_URL") base_url = settings.PINDORA_API_URL.removesuffix("/") return f"{base_url}/{endpoint}" @@ -540,7 +550,7 @@ def _build_url(cls, endpoint: str) -> str: @classmethod def _get_headers(cls, headers: dict[str, Any] | None) -> dict[str, str]: if not settings.PINDORA_API_KEY: - raise PindoraAPIConfigurationError(config="PINDORA_API_KEY") + raise PindoraClientConfigurationError(config="PINDORA_API_KEY") return { "Pindora-Api-Key": str(settings.PINDORA_API_KEY), diff --git a/tilavarauspalvelu/integrations/keyless_entry/exceptions.py b/tilavarauspalvelu/integrations/keyless_entry/exceptions.py index dbb66246b6..127e7505cc 100644 --- a/tilavarauspalvelu/integrations/keyless_entry/exceptions.py +++ b/tilavarauspalvelu/integrations/keyless_entry/exceptions.py @@ -6,15 +6,17 @@ from utils.external_service.errors import ExternalServiceError __all__ = [ - "PindoraAPIConfigurationError", "PindoraAPIError", + "PindoraClientConfigurationError", + "PindoraClientError", + "PindoraUnexpectedResponseError", ] -class PindoraAPIError(ExternalServiceError): - """Error in Pindora API""" +class PindoraClientError(ExternalServiceError): + """Error in Pindora client, not related to the API""" - msg: str = "Pindora API error" + msg: str = "Pindora client error" error_formatter: Formatter = Formatter() def __init__(self, msg: str = "", /, **kwargs: Any) -> None: @@ -22,12 +24,16 @@ def __init__(self, msg: str = "", /, **kwargs: Any) -> None: super().__init__(msg) -class PindoraAPIConfigurationError(PindoraAPIError): +class PindoraClientConfigurationError(PindoraClientError): """Pindora API settings are not configured correctly""" msg = "'{config}' setting must to be configured for Pindora client to work." +class PindoraAPIError(PindoraClientError): + """Error in Pindora API""" + + class PindoraUnexpectedResponseError(PindoraAPIError): """Error when an unexpected response was received from Pindora"""