Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Pindora service & fix Pindora integration issues #1613

Merged
merged 9 commits into from
Mar 3, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
RecurringReservationFactory,
ReservationFactory,
SuitableTimeRangeFactory,
UserFactory,
)
from tests.helpers import patch_method

from .helpers import section_query, sections_query

if TYPE_CHECKING:
from tilavarauspalvelu.models import ApplicationSection
from tilavarauspalvelu.models import ApplicationSection, ReservationUnit

# Applied to all tests
pytestmark = [
Expand Down Expand Up @@ -180,7 +181,7 @@ def test_application_section__all_statuses(graphql):
assert len(response.queries) in {8, 9}, response.query_log


def pindora_response(section: ApplicationSection) -> PindoraSeasonalBookingResponse:
def pindora_response(reservation_unit: ReservationUnit) -> PindoraSeasonalBookingResponse:
return PindoraSeasonalBookingResponse(
access_code="1234",
access_code_generated_at=local_datetime(2022, 1, 1, 12),
Expand All @@ -191,7 +192,7 @@ def pindora_response(section: ApplicationSection) -> PindoraSeasonalBookingRespo
access_code_sms_message="123456789",
reservation_unit_code_validity=[
PindoraSeasonalBookingAccessCodeValidity(
reservation_unit_id=section.reservation_unit_options.first().reservation_unit.uuid,
reservation_unit_id=reservation_unit.uuid,
access_code_valid_minutes_before=10,
access_code_valid_minutes_after=5,
begin=local_datetime(2022, 1, 1, 12),
Expand Down Expand Up @@ -225,17 +226,21 @@ def pindora_query(section: ApplicationSection) -> str:

@freeze_time(local_datetime(2022, 1, 1))
def test_application_section__query__pindora_info(graphql):
user = UserFactory.create()
section = ApplicationSectionFactory.create_in_status_unallocated(
application__user=user,
reservations_begin_date=local_date(2022, 1, 1),
reservations_end_date=local_date(2022, 1, 1),
)
series = RecurringReservationFactory.create(
allocated_time_slot__reservation_unit_option__application_section=section,
)
reservation = ReservationFactory.create(
user=user,
reservation_units=[series.reservation_unit],
recurring_reservation=series,
begin=local_datetime(2022, 1, 1, 12),
end=local_datetime(2022, 1, 1, 13),
recurring_reservation=series,
access_type=AccessType.ACCESS_CODE,
state=ReservationStateChoice.CONFIRMED,
type=ReservationTypeChoice.NORMAL,
Expand All @@ -245,7 +250,9 @@ def test_application_section__query__pindora_info(graphql):

graphql.login_with_superuser()

with patch_method(PindoraClient.get_seasonal_booking, return_value=pindora_response(section)):
data = pindora_response(series.reservation_unit)

with patch_method(PindoraClient.get_seasonal_booking, return_value=data):
response = graphql(query)

assert response.has_errors is False, response.errors
Expand All @@ -272,13 +279,20 @@ def test_application_section__query__pindora_info(graphql):
@freeze_time(local_datetime(2022, 1, 1))
@pytest.mark.parametrize("as_reservee", [True, False])
def test_application_section__query__pindora_info__access_code_not_active(graphql, as_reservee):
user = UserFactory.create()
section = ApplicationSectionFactory.create_in_status_unallocated(
application__user=user,
reservations_begin_date=local_date(2022, 1, 1),
reservations_end_date=local_date(2022, 1, 1),
)
series = RecurringReservationFactory.create(
allocated_time_slot__reservation_unit_option__application_section=section,
)

ReservationFactory.create(
recurring_reservation__allocated_time_slot__reservation_unit_option__application_section=section,
user=user,
reservation_units=[series.reservation_unit],
recurring_reservation=series,
access_type=AccessType.ACCESS_CODE,
state=ReservationStateChoice.CONFIRMED,
type=ReservationTypeChoice.NORMAL,
Expand All @@ -291,7 +305,7 @@ def test_application_section__query__pindora_info__access_code_not_active(graphq
else:
graphql.login_with_superuser()

response = pindora_response(section)
response = pindora_response(series.reservation_unit)
response["access_code_is_active"] = False

with patch_method(PindoraClient.get_seasonal_booking, return_value=response):
Expand All @@ -307,13 +321,20 @@ def test_application_section__query__pindora_info__access_code_not_active(graphq

@freeze_time(local_datetime(2022, 1, 1))
def test_application_section__query__pindora_info__access_type_not_access_code(graphql):
user = UserFactory.create()
section = ApplicationSectionFactory.create_in_status_unallocated(
application__user=user,
reservations_begin_date=local_date(2022, 1, 1),
reservations_end_date=local_date(2022, 1, 1),
)
series = RecurringReservationFactory.create(
allocated_time_slot__reservation_unit_option__application_section=section,
)

ReservationFactory.create(
recurring_reservation__allocated_time_slot__reservation_unit_option__application_section=section,
user=user,
reservation_units=[series.reservation_unit],
recurring_reservation=series,
access_type=AccessType.PHYSICAL_KEY,
state=ReservationStateChoice.CONFIRMED,
type=ReservationTypeChoice.NORMAL,
Expand All @@ -323,7 +344,9 @@ def test_application_section__query__pindora_info__access_type_not_access_code(g

graphql.login_with_superuser()

with patch_method(PindoraClient.get_seasonal_booking, return_value=pindora_response(section)):
data = pindora_response(series.reservation_unit)

with patch_method(PindoraClient.get_seasonal_booking, return_value=data):
response = graphql(query)

assert response.has_errors is False, response.errors
Expand All @@ -333,13 +356,20 @@ def test_application_section__query__pindora_info__access_type_not_access_code(g

@freeze_time(local_datetime(2022, 1, 1))
def test_application_section__query__pindora_info__pindora_call_fails(graphql):
user = UserFactory.create()
section = ApplicationSectionFactory.create_in_status_unallocated(
application__user=user,
reservations_begin_date=local_date(2022, 1, 1),
reservations_end_date=local_date(2022, 1, 1),
)
series = RecurringReservationFactory.create(
allocated_time_slot__reservation_unit_option__application_section=section,
)

ReservationFactory.create(
recurring_reservation__allocated_time_slot__reservation_unit_option__application_section=section,
user=user,
reservation_units=[series.reservation_unit],
recurring_reservation=series,
access_type=AccessType.ACCESS_CODE,
state=ReservationStateChoice.CONFIRMED,
type=ReservationTypeChoice.NORMAL,
Expand All @@ -359,13 +389,20 @@ def test_application_section__query__pindora_info__pindora_call_fails(graphql):

@freeze_time(local_datetime(2022, 1, 3))
def test_application_section__query__pindora_info__section_past(graphql):
user = UserFactory.create()
section = ApplicationSectionFactory.create_in_status_unallocated(
application__user=user,
reservations_begin_date=local_date(2022, 1, 1),
reservations_end_date=local_date(2022, 1, 1),
)
series = RecurringReservationFactory.create(
allocated_time_slot__reservation_unit_option__application_section=section,
)

ReservationFactory.create(
recurring_reservation__allocated_time_slot__reservation_unit_option__application_section=section,
user=user,
reservation_units=[series.reservation_unit],
recurring_reservation=series,
access_type=AccessType.ACCESS_CODE,
state=ReservationStateChoice.CONFIRMED,
type=ReservationTypeChoice.NORMAL,
Expand All @@ -375,7 +412,9 @@ def test_application_section__query__pindora_info__section_past(graphql):

graphql.login_with_superuser()

with patch_method(PindoraClient.get_seasonal_booking, return_value=pindora_response(section)):
data = pindora_response(series.reservation_unit)

with patch_method(PindoraClient.get_seasonal_booking, return_value=data):
response = graphql(query)

assert response.has_errors is False, response.errors
Expand Down
55 changes: 11 additions & 44 deletions backend/tests/test_graphql_api/test_reservation/test_adjust_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from tilavarauspalvelu.enums import AccessType, ReservationStartInterval, ReservationStateChoice
from tilavarauspalvelu.integrations.email.main import EmailService
from tilavarauspalvelu.integrations.keyless_entry import PindoraClient
from tilavarauspalvelu.integrations.keyless_entry import PindoraClient, PindoraService
from tilavarauspalvelu.models import Reservation, ReservationUnitHierarchy
from utils.date_utils import DEFAULT_TIMEZONE, local_date, local_datetime

Expand Down Expand Up @@ -505,8 +505,7 @@ def test_reservation__adjust_time__update_reservation_buffer_on_adjust(graphql):


@patch_method(PindoraClient.get_reservation) # Called by email sending
@patch_method(PindoraClient.reschedule_reservation)
@patch_method(PindoraClient.deactivate_reservation_access_code)
@patch_method(PindoraService.sync_access_code)
def test_reservation__adjust_time__same_access_type(graphql):
reservation = ReservationFactory.create_for_time_adjustment(
access_type=AccessType.ACCESS_CODE,
Expand All @@ -520,15 +519,13 @@ def test_reservation__adjust_time__same_access_type(graphql):

assert response.has_errors is False, response.errors

assert PindoraClient.reschedule_reservation.called is True
assert PindoraClient.deactivate_reservation_access_code.called is False
assert PindoraService.sync_access_code.call_count == 1

reservation.refresh_from_db()
assert reservation.access_code_is_active is True


@patch_method(PindoraClient.reschedule_reservation)
@patch_method(PindoraClient.deactivate_reservation_access_code)
@patch_method(PindoraService.sync_access_code)
def test_reservation__adjust_time__same_access_type__requires_handling(graphql):
reservation = ReservationFactory.create_for_time_adjustment(
access_type=AccessType.ACCESS_CODE,
Expand All @@ -543,21 +540,11 @@ def test_reservation__adjust_time__same_access_type__requires_handling(graphql):

assert response.has_errors is False, response.errors

assert PindoraClient.reschedule_reservation.called is True
assert PindoraClient.deactivate_reservation_access_code.called is True

reservation.refresh_from_db()
assert reservation.access_code_is_active is False
assert PindoraService.sync_access_code.call_count == 1


@patch_method(PindoraClient.get_reservation) # Called by email sending
@patch_method(
PindoraClient.create_reservation,
return_value={
"access_code_generated_at": datetime.datetime(2025, 1, 1, tzinfo=DEFAULT_TIMEZONE),
"access_code_is_active": True,
},
)
@patch_method(PindoraService.sync_access_code)
def test_reservation__adjust_time__change_to_access_code(graphql):
reservation = ReservationFactory.create_for_time_adjustment(
access_type=AccessType.UNRESTRICTED,
Expand All @@ -571,21 +558,10 @@ def test_reservation__adjust_time__change_to_access_code(graphql):

assert response.has_errors is False, response.errors

assert PindoraClient.create_reservation.called is True
assert PindoraClient.create_reservation.call_args.kwargs["is_active"] is True

reservation.refresh_from_db()
assert reservation.access_code_generated_at == datetime.datetime(2025, 1, 1, tzinfo=DEFAULT_TIMEZONE)
assert reservation.access_code_is_active is True
assert PindoraService.sync_access_code.call_count == 1


@patch_method(
PindoraClient.create_reservation,
return_value={
"access_code_generated_at": datetime.datetime(2025, 1, 1, tzinfo=DEFAULT_TIMEZONE),
"access_code_is_active": False,
},
)
@patch_method(PindoraService.sync_access_code)
def test_reservation__adjust_time__change_to_access_code__requires_handling(graphql):
reservation = ReservationFactory.create_for_time_adjustment(
access_type=AccessType.UNRESTRICTED,
Expand All @@ -600,15 +576,10 @@ def test_reservation__adjust_time__change_to_access_code__requires_handling(grap

assert response.has_errors is False, response.errors

assert PindoraClient.create_reservation.called is True
assert PindoraClient.create_reservation.call_args.kwargs["is_active"] is False

reservation.refresh_from_db()
assert reservation.access_code_generated_at == datetime.datetime(2025, 1, 1, tzinfo=DEFAULT_TIMEZONE)
assert reservation.access_code_is_active is False
assert PindoraService.sync_access_code.call_count == 1


@patch_method(PindoraClient.delete_reservation)
@patch_method(PindoraService.sync_access_code)
def test_reservation__adjust_time__change_from_access_code(graphql):
reservation = ReservationFactory.create_for_time_adjustment(
access_type=AccessType.ACCESS_CODE,
Expand All @@ -623,8 +594,4 @@ def test_reservation__adjust_time__change_from_access_code(graphql):

assert response.has_errors is False, response.errors

assert PindoraClient.delete_reservation.called is True

reservation.refresh_from_db()
assert reservation.access_code_generated_at is None
assert reservation.access_code_is_active is False
assert PindoraService.sync_access_code.call_count == 1
Loading
Loading