Skip to content

Commit 04eb56a

Browse files
authored
Migrate schedule invitation type to Strawberry Django (#4758)
1 parent f76a51e commit 04eb56a

5 files changed

Lines changed: 62 additions & 90 deletions

File tree

backend/api/schedule/mutations/update_schedule_invitation.py

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,17 @@
1-
from api.context import Info
1+
import strawberry
22
from django.db import transaction
3-
from api.schedule.types import (
4-
ScheduleInvitationOption,
5-
)
6-
from submissions.models import Submission
7-
from schedule.models import (
8-
ScheduleItem,
9-
)
10-
from typing import Union
3+
4+
from api.context import Info
115
from api.permissions import IsAuthenticated
12-
from api.schedule.types import (
13-
ScheduleInvitation,
14-
)
6+
from api.schedule.types import ScheduleInvitation, ScheduleInvitationOption
157
from api.submissions.permissions import IsSubmissionSpeakerOrStaff
16-
8+
from schedule import models as schedule_models
179
from schedule.tasks import (
1810
create_and_send_voucher_to_speaker,
1911
notify_new_schedule_invitation_answer_slack,
2012
send_schedule_invitation_plain_message,
2113
)
22-
import strawberry
14+
from submissions import models as submission_models
2315

2416

2517
@strawberry.input
@@ -37,8 +29,8 @@ class ScheduleInvitationNotFound:
3729
@strawberry.mutation(permission_classes=[IsAuthenticated])
3830
def update_schedule_invitation(
3931
info: Info, input: UpdateScheduleInvitationInput
40-
) -> Union[ScheduleInvitationNotFound, ScheduleInvitation]:
41-
submission = Submission.objects.get_by_hashid(input.submission_id)
32+
) -> ScheduleInvitationNotFound | ScheduleInvitation:
33+
submission = submission_models.Submission.objects.get_by_hashid(input.submission_id)
4234

4335
if not IsSubmissionSpeakerOrStaff().has_object_permission(info, submission):
4436
return ScheduleInvitationNotFound()
@@ -47,11 +39,11 @@ def update_schedule_invitation(
4739
# since currently we do not schedule the same talk to appear multiple times
4840
# in the future this needs to be fixed :)
4941
schedule_item = (
50-
ScheduleItem.objects.filter(
42+
schedule_models.ScheduleItem.objects.filter(
5143
submission_id=submission.id,
5244
conference_id=submission.conference_id,
5345
)
54-
.exclude(status=ScheduleItem.STATUS.cancelled)
46+
.exclude(status=schedule_models.ScheduleItem.STATUS.cancelled)
5547
.first()
5648
)
5749

@@ -64,14 +56,14 @@ def update_schedule_invitation(
6456

6557
if not status_changed and schedule_item.speaker_invitation_notes == new_notes:
6658
# If nothing changed, do nothing
67-
return ScheduleInvitation.from_django_model(schedule_item)
59+
return schedule_item
6860

6961
with transaction.atomic():
7062
schedule_item.status = new_status
7163
schedule_item.speaker_invitation_notes = new_notes
7264
schedule_item.save()
7365

74-
if status_changed and new_status == ScheduleItem.STATUS.confirmed:
66+
if status_changed and new_status == schedule_models.ScheduleItem.STATUS.confirmed:
7567
create_and_send_voucher_to_speaker.delay(schedule_item.id)
7668

7769
request = info.context.request
@@ -90,4 +82,4 @@ def update_schedule_invitation(
9082
schedule_item_id=schedule_item.id,
9183
message=new_notes,
9284
)
93-
return ScheduleInvitation.from_django_model(schedule_item)
85+
return schedule_item
Lines changed: 13 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,26 @@
1-
from api.context import Info
2-
from schedule.models import ScheduleItem as ScheduleItemModel
3-
from api.submissions.permissions import IsSubmissionSpeakerOrStaff
4-
from submissions.models import Submission as SubmissionModel
51
import strawberry
6-
from api.schedule.types.schedule_invitation import ScheduleInvitation
2+
import strawberry_django
3+
4+
from api.context import Info
75
from api.permissions import IsAuthenticated
6+
from api.schedule.types.schedule_invitation import ScheduleInvitation
7+
from api.submissions.permissions import IsSubmissionSpeakerOrStaff
8+
from schedule import models as schedule_models
9+
from submissions import models as submission_models
810

911

10-
@strawberry.field(permission_classes=[IsAuthenticated])
12+
@strawberry_django.field(permission_classes=[IsAuthenticated])
1113
def schedule_invitation(
1214
info: Info, submission_id: strawberry.ID
1315
) -> ScheduleInvitation | None:
14-
submission = SubmissionModel.objects.get_by_hashid(submission_id)
16+
submission = submission_models.Submission.objects.get_by_hashid(submission_id)
1517

1618
if not IsSubmissionSpeakerOrStaff().has_object_permission(info, submission):
1719
return None
1820

1921
# TODO: A submission could be added to multiple schedule item
2022
# in the future we should support it
21-
schedule_item = (
22-
ScheduleItemModel.objects.filter(
23-
conference_id=submission.conference_id,
24-
submission_id=submission.id,
25-
)
26-
.prefetch_related(
27-
"submission",
28-
"submission__duration",
29-
"slot",
30-
"slot__day",
31-
)
32-
.exclude(status=ScheduleItemModel.STATUS.cancelled)
33-
.first()
34-
)
35-
36-
if not schedule_item:
37-
return None
38-
39-
return ScheduleInvitation.from_django_model(schedule_item)
23+
return schedule_models.ScheduleItem.objects.filter(
24+
conference_id=submission.conference_id,
25+
submission_id=submission.id,
26+
).exclude(status=schedule_models.ScheduleItem.STATUS.cancelled)

backend/api/schedule/tests/test_schedule_invitation_frontend_query.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_schedule_invitation_frontend_query(
6464
)
6565
graphql_client.force_login(user)
6666

67-
with django_assert_num_queries(8):
67+
with django_assert_num_queries(4):
6868
response = graphql_client.query(
6969
SCHEDULE_INVITATION_QUERY,
7070
variables={"language": "en", "submissionId": submission.hashid},

backend/api/schedule/tests/test_update_schedule_invitation.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from submissions.tests.factories import SubmissionFactory
2-
from schedule.tests.factories import DayFactory, ScheduleItemFactory, SlotFactory
31
from pytest import mark
42

53
from schedule.models import ScheduleItem
4+
from schedule.tests.factories import DayFactory, ScheduleItemFactory, SlotFactory
5+
from submissions.tests.factories import SubmissionFactory
66

77
pytestmark = mark.django_db
88

@@ -52,6 +52,7 @@ def test_update_invitation_answer(
5252
updateScheduleInvitation(input: $input) {
5353
__typename
5454
... on ScheduleInvitation {
55+
id
5556
option
5657
notes
5758
}
@@ -69,6 +70,7 @@ def test_update_invitation_answer(
6970
assert not response.get("errors")
7071
assert response["data"]["updateScheduleInvitation"] == {
7172
"__typename": "ScheduleInvitation",
73+
"id": submission.hashid,
7274
"option": option,
7375
"notes": "notes",
7476
}

backend/api/schedule/types/schedule_invitation.py

Lines changed: 31 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,21 @@
22
from enum import Enum
33

44
import strawberry
5+
import strawberry_django
56

67
from api.submissions.types import Submission
7-
from schedule.models import ScheduleItem as ScheduleItemModel
8+
from schedule import models
89

910

10-
@strawberry.type
11+
@strawberry_django.type(models.ScheduleItem)
1112
class ScheduleInvitationDate:
12-
id: strawberry.ID
13+
id: strawberry.auto
1314
start: datetime
1415
end: datetime
15-
duration: int
1616

17-
@classmethod
18-
def from_django(cls, schedule_item):
19-
duration = schedule_item.duration or schedule_item.slot.duration
20-
return cls(
21-
id=schedule_item.id,
22-
start=schedule_item.start,
23-
end=schedule_item.end,
24-
duration=duration,
25-
)
17+
@strawberry_django.field
18+
def duration(self) -> int:
19+
return self.duration or self.slot.duration
2620

2721

2822
@strawberry.enum
@@ -33,43 +27,40 @@ class ScheduleInvitationOption(Enum):
3327
REJECT = "reject"
3428
CANT_ATTEND = "cant_attend"
3529

36-
def to_schedule_item_status(self):
37-
return MAP_OPTION_TO_ITEM_STATUS.get(self)
38-
39-
@staticmethod
40-
def from_schedule_item_status(schedule_item_status: str):
41-
return MAP_ITEM_STATUS_TO_OPTION.get(schedule_item_status)
30+
def to_schedule_item_status(self) -> str:
31+
return MAP_OPTION_TO_ITEM_STATUS[self]
4232

4333

4434
MAP_OPTION_TO_ITEM_STATUS = {
45-
ScheduleInvitationOption.CONFIRM: ScheduleItemModel.STATUS.confirmed,
46-
ScheduleInvitationOption.MAYBE: ScheduleItemModel.STATUS.maybe,
47-
ScheduleInvitationOption.REJECT: ScheduleItemModel.STATUS.rejected,
48-
ScheduleInvitationOption.CANT_ATTEND: ScheduleItemModel.STATUS.cant_attend,
49-
ScheduleInvitationOption.NO_ANSWER: ScheduleItemModel.STATUS.waiting_confirmation,
35+
ScheduleInvitationOption.CONFIRM: models.ScheduleItem.STATUS.confirmed,
36+
ScheduleInvitationOption.MAYBE: models.ScheduleItem.STATUS.maybe,
37+
ScheduleInvitationOption.REJECT: models.ScheduleItem.STATUS.rejected,
38+
ScheduleInvitationOption.CANT_ATTEND: models.ScheduleItem.STATUS.cant_attend,
39+
ScheduleInvitationOption.NO_ANSWER: models.ScheduleItem.STATUS.waiting_confirmation,
5040
}
5141

5242
MAP_ITEM_STATUS_TO_OPTION = {
5343
item: option for option, item in MAP_OPTION_TO_ITEM_STATUS.items()
5444
}
5545

5646

57-
@strawberry.type
47+
@strawberry_django.type(models.ScheduleItem)
5848
class ScheduleInvitation:
59-
id: strawberry.ID
60-
option: ScheduleInvitationOption
61-
notes: str
62-
title: str
49+
id: strawberry.ID = strawberry_django.field(
50+
resolver=lambda self: self.submission.hashid,
51+
select_related=["submission"],
52+
)
53+
option: ScheduleInvitationOption = strawberry_django.field(
54+
resolver=lambda self: MAP_ITEM_STATUS_TO_OPTION[self.status],
55+
only=["status"],
56+
)
57+
notes: str = strawberry_django.field(field_name="speaker_invitation_notes")
58+
title: strawberry.auto
6359
submission: Submission
64-
dates: list[ScheduleInvitationDate]
6560

66-
@classmethod
67-
def from_django_model(cls, instance):
68-
return cls(
69-
id=instance.submission.hashid,
70-
title=instance.title,
71-
option=ScheduleInvitationOption.from_schedule_item_status(instance.status),
72-
notes=instance.speaker_invitation_notes,
73-
submission=instance.submission,
74-
dates=[ScheduleInvitationDate.from_django(instance)],
75-
)
61+
@strawberry_django.field(
62+
only=["duration", "slot__duration", "slot__hour", "slot__day__day"],
63+
select_related=["slot__day"],
64+
)
65+
def dates(self) -> list[ScheduleInvitationDate]:
66+
return [self]

0 commit comments

Comments
 (0)