Skip to content

Commit c73b1ab

Browse files
authored
Merge pull request #143 from City-of-Helsinki/release/1.4.0
Release 1.4.0
2 parents 54ec57c + e16048b commit c73b1ab

12 files changed

Lines changed: 213 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
<!-- REMINDER: While updating changelog, also remember to update
22
the version in kukkuu/__init.py__ -->
33

4+
## [1.4.0] - 15 Sep 2020
5+
### Added
6+
- Add nullable field `capacityOverride` and API for it which allows setting capacity per occurrence
7+
- Add ability to search children and guardians in admin UI
8+
49
## [1.3.0] - 2 Sep 2020
510
### Added
611
- Add occurrence url to event notifications' contexts
@@ -96,7 +101,8 @@ the version in kukkuu/__init.py__ -->
96101

97102

98103

99-
[Unreleased]: https://github.com/City-of-Helsinki/kukkuu/compare/v1.3.0...HEAD
104+
[Unreleased]: https://github.com/City-of-Helsinki/kukkuu/compare/v1.4.0...HEAD
105+
[1.4.0]: https://github.com/City-of-Helsinki/kukkuu/compare/v1.3.0...v1.4.0
100106
[1.3.0]: https://github.com/City-of-Helsinki/kukkuu/compare/v1.2.0...v1.3.0
101107
[1.2.0]: https://github.com/City-of-Helsinki/kukkuu/compare/v1.1.0...v1.2.0
102108
[1.1.0]: https://github.com/City-of-Helsinki/kukkuu/compare/v1.0.0...v1.1.0

children/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ChildAdmin(admin.ModelAdmin):
4444
)
4545
list_select_related = ("project",)
4646
fields = ("project", "first_name", "last_name", "birthdate", "postal_code")
47+
search_fields = ("first_name", "last_name")
4748
inlines = (RelationshipInline, EnrolmentInline, LanguagesSpokenAtHomeInline)
4849

4950
def get_project_year(self, obj):

events/admin.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,18 @@ class EnrolmentsInline(admin.TabularInline):
7272
@admin.register(Occurrence)
7373
class OccurrenceAdmin(admin.ModelAdmin):
7474
list_display = (
75-
"id",
7675
"time",
7776
"event",
7877
"venue",
78+
"get_enrolments",
7979
"occurrence_language",
8080
"created_at",
8181
"updated_at",
8282
)
83-
list_display_links = ("id", "time")
84-
fields = ("time", "event", "venue", "occurrence_language")
83+
fields = ("time", "event", "venue", "occurrence_language", "capacity_override")
8584
inlines = [EnrolmentsInline]
85+
86+
def get_enrolments(self, obj):
87+
return f"{obj.get_enrolment_count()} / {obj.get_capacity()}"
88+
89+
get_enrolments.short_description = _("enrolments")
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 2.2.13 on 2020-09-04 14:03
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("events", "0013_add_choice_child_and_1_or_2_guardians"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="occurrence",
15+
name="capacity_override",
16+
field=models.PositiveSmallIntegerField(
17+
blank=True,
18+
help_text="When set will be used as the capacity of this occurrence instead of the value coming from the event.",
19+
null=True,
20+
verbose_name="capacity override",
21+
),
22+
),
23+
]

events/models.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ class Occurrence(TimestampedModel):
134134
verbose_name=_("occurrence language"),
135135
default=settings.LANGUAGES[0][0],
136136
)
137+
capacity_override = models.PositiveSmallIntegerField(
138+
verbose_name=_("capacity override"),
139+
null=True,
140+
blank=True,
141+
help_text=_(
142+
"When set will be used as the capacity of this occurrence instead of "
143+
"the value coming from the event."
144+
),
145+
)
146+
137147
objects = OccurrenceQueryset.as_manager()
138148

139149
class Meta:
@@ -167,6 +177,9 @@ def get_enrolment_count(self):
167177
except AttributeError:
168178
return self.enrolments.count()
169179

180+
def get_capacity(self):
181+
return self.capacity_override or self.event.capacity_per_occurrence
182+
170183
def can_user_administer(self, user):
171184
# There shouldn't ever be a situation where event.project != venue.project
172185
# so we can just check one of them

events/schema.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def validate_enrolment(child, occurrence):
4848
)
4949
if child.occurrences.filter(event=occurrence.event).exists():
5050
raise ChildAlreadyJoinedEventError("Child already joined this event")
51-
if occurrence.enrolments.count() >= occurrence.event.capacity_per_occurrence:
51+
if occurrence.enrolments.count() >= occurrence.get_capacity():
5252
raise OccurrenceIsFullError("Maximum enrolments created")
5353
if occurrence.time < timezone.now():
5454
raise PastOccurrenceError("Cannot join occurrence in the past")
@@ -116,6 +116,7 @@ class OccurrenceNode(DjangoObjectType):
116116
remaining_capacity = graphene.Int()
117117
occurrence_language = LanguageEnum(required=True)
118118
enrolment_count = graphene.Int(required=True)
119+
capacity = graphene.Int()
119120

120121
@classmethod
121122
@login_required
@@ -132,15 +133,33 @@ def get_node(cls, info, id):
132133
return super().get_node(info, id)
133134

134135
def resolve_remaining_capacity(self, info, **kwargs):
135-
return self.event.capacity_per_occurrence - self.get_enrolment_count()
136+
return max(self.get_capacity() - self.get_enrolment_count(), 0)
136137

137138
def resolve_enrolment_count(self, info, **kwargs):
138139
return self.get_enrolment_count()
139140

141+
def resolve_capacity(self, info, **kwargs):
142+
return self.get_capacity()
143+
140144
class Meta:
141145
model = Occurrence
142146
interfaces = (relay.Node,)
143147
filterset_class = OccurrenceFilter
148+
fields = (
149+
"id",
150+
"created_at",
151+
"updated_at",
152+
"time",
153+
"event",
154+
"venue",
155+
"children",
156+
"occurrence_language",
157+
"enrolments",
158+
"capacity",
159+
"capacity_override",
160+
"remaining_capacity",
161+
"enrolment_count",
162+
)
144163

145164

146165
class EnrolmentNode(DjangoObjectType):
@@ -347,6 +366,7 @@ class Input:
347366
event_id = graphene.GlobalID()
348367
venue_id = graphene.GlobalID()
349368
occurrence_language = LanguageEnum()
369+
capacity_override = graphene.Int()
350370

351371
occurrence = graphene.Field(OccurrenceNode)
352372

@@ -381,6 +401,7 @@ class Input:
381401
event_id = graphene.GlobalID(required=False)
382402
venue_id = graphene.GlobalID(required=False)
383403
occurrence_language = LanguageEnum()
404+
capacity_override = graphene.Int()
384405

385406
occurrence = graphene.Field(OccurrenceNode)
386407

events/tests/snapshots/snap_test_api.py

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,8 @@
420420
"data": {
421421
"addOccurrence": {
422422
"occurrence": {
423+
"capacity": 50,
424+
"capacityOverride": None,
423425
"event": {"createdAt": "2020-12-12T00:00:00+00:00"},
424426
"occurrenceLanguage": "FI",
425427
"time": "1986-12-12T16:40:48+00:00",
@@ -433,10 +435,12 @@
433435
"data": {
434436
"updateOccurrence": {
435437
"occurrence": {
438+
"capacity": 5,
439+
"capacityOverride": 5,
436440
"enrolmentCount": 0,
437441
"event": {"createdAt": "2020-12-12T00:00:00+00:00"},
438442
"occurrenceLanguage": "SV",
439-
"remainingCapacity": 43,
443+
"remainingCapacity": 5,
440444
"time": "1986-12-12T16:40:48+00:00",
441445
"venue": {"createdAt": "2020-12-12T00:00:00+00:00"},
442446
}
@@ -719,3 +723,91 @@
719723
snapshots["test_set_enrolment_attendance[None] 1"] = {
720724
"data": {"setEnrolmentAttendance": {"enrolment": {"attended": None}}}
721725
}
726+
727+
snapshots["test_occurrence_capacity[5-0] 1"] = {
728+
"data": {
729+
"occurrence": {
730+
"capacity": 5,
731+
"capacityOverride": 5,
732+
"enrolmentCount": 0,
733+
"remainingCapacity": 5,
734+
}
735+
}
736+
}
737+
738+
snapshots["test_occurrence_capacity[5-4] 1"] = {
739+
"data": {
740+
"occurrence": {
741+
"capacity": 5,
742+
"capacityOverride": 5,
743+
"enrolmentCount": 4,
744+
"remainingCapacity": 1,
745+
}
746+
}
747+
}
748+
749+
snapshots["test_occurrence_capacity[5-5] 1"] = {
750+
"data": {
751+
"occurrence": {
752+
"capacity": 5,
753+
"capacityOverride": 5,
754+
"enrolmentCount": 5,
755+
"remainingCapacity": 0,
756+
}
757+
}
758+
}
759+
760+
snapshots["test_occurrence_capacity[5-6] 1"] = {
761+
"data": {
762+
"occurrence": {
763+
"capacity": 5,
764+
"capacityOverride": 5,
765+
"enrolmentCount": 6,
766+
"remainingCapacity": 0,
767+
}
768+
}
769+
}
770+
771+
snapshots["test_occurrence_capacity[None-0] 1"] = {
772+
"data": {
773+
"occurrence": {
774+
"capacity": 10,
775+
"capacityOverride": None,
776+
"enrolmentCount": 0,
777+
"remainingCapacity": 10,
778+
}
779+
}
780+
}
781+
782+
snapshots["test_occurrence_capacity[None-9] 1"] = {
783+
"data": {
784+
"occurrence": {
785+
"capacity": 10,
786+
"capacityOverride": None,
787+
"enrolmentCount": 9,
788+
"remainingCapacity": 1,
789+
}
790+
}
791+
}
792+
793+
snapshots["test_occurrence_capacity[None-10] 1"] = {
794+
"data": {
795+
"occurrence": {
796+
"capacity": 10,
797+
"capacityOverride": None,
798+
"enrolmentCount": 10,
799+
"remainingCapacity": 0,
800+
}
801+
}
802+
}
803+
804+
snapshots["test_occurrence_capacity[None-11] 1"] = {
805+
"data": {
806+
"occurrence": {
807+
"capacity": 10,
808+
"capacityOverride": None,
809+
"enrolmentCount": 11,
810+
"remainingCapacity": 0,
811+
}
812+
}
813+
}

events/tests/snapshots/snap_test_notifications.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424

2525
snapshots["test_occurrence_enrolment_notifications_on_model_level 1"] = [
2626
"""kukkuu@example.com|['mperez@cox.com']|Occurrence enrolment FI|
27-
Event FI: Up always sport return. Light a point charge stand store.
28-
Guardian FI: Kathryn Scott
27+
Event FI: Free heart significant machine try.
28+
Guardian FI: Willie Frey
2929
Occurrence: 2020-12-12 00:00:00+00:00
30-
Child: Jessica Sanders (2020-09-25)
30+
Child: Andrea Ward (2020-06-23)
3131
Occurrence URL: http://localhost:3000/fi/profile/child/Q2hpbGROb2RlOjU0NWM1ZmU1LTIzNWItNDZmZC1hYTJhLWNkNWRlNmZkZDBmYw==/occurrence/T2NjdXJyZW5jZU5vZGU6NzQ="""
3232
]
3333

events/tests/test_api.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ def autouse_db(db):
371371
}
372372
time
373373
occurrenceLanguage
374+
capacity
375+
capacityOverride
374376
}
375377
}
376378
}
@@ -395,6 +397,8 @@ def autouse_db(db):
395397
occurrenceLanguage
396398
enrolmentCount
397399
remainingCapacity
400+
capacity
401+
capacityOverride
398402
}
399403
}
400404
}
@@ -408,6 +412,7 @@ def autouse_db(db):
408412
"venueId": "",
409413
"time": "1986-12-12T16:40:48+00:00",
410414
"occurrenceLanguage": "SV",
415+
"capacityOverride": 5,
411416
}
412417
}
413418

@@ -1281,3 +1286,38 @@ def test_set_enrolment_attendance_another_project_child(
12811286
)
12821287

12831288
assert_match_error_code(executed, OBJECT_DOES_NOT_EXIST_ERROR)
1289+
1290+
1291+
@pytest.mark.parametrize(
1292+
"capacity_override, enrolment_count",
1293+
((5, 0), (5, 4), (5, 5), (5, 6), (None, 0), (None, 9), (None, 10), (None, 11),),
1294+
)
1295+
def test_occurrence_capacity(
1296+
snapshot, guardian_api_client, project, capacity_override, enrolment_count
1297+
):
1298+
occurrence = OccurrenceFactory(
1299+
event__project=project,
1300+
venue__project=project,
1301+
event__published_at=now(),
1302+
event__capacity_per_occurrence=10,
1303+
capacity_override=capacity_override,
1304+
)
1305+
EnrolmentFactory.create_batch(
1306+
enrolment_count, occurrence=occurrence, child__project=project
1307+
)
1308+
1309+
executed = guardian_api_client.execute(
1310+
"""
1311+
query OccurrenceCapacity($id: ID!) {
1312+
occurrence(id: $id){
1313+
capacity
1314+
capacityOverride
1315+
enrolmentCount
1316+
remainingCapacity
1317+
}
1318+
}
1319+
""",
1320+
variables={"id": get_global_id(occurrence)},
1321+
)
1322+
1323+
snapshot.assert_match(executed)

events/tests/test_notifications.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,9 @@ def test_occurrence_enrolment_notifications_on_model_level(
110110
user_api_client,
111111
notification_template_occurrence_unenrolment_fi,
112112
notification_template_occurrence_enrolment_fi,
113-
occurrence,
114113
project,
115114
):
115+
occurrence = OccurrenceFactory(id=74, time=now())
116116
child = ChildWithGuardianFactory(
117117
pk="545c5fe5-235b-46fd-aa2a-cd5de6fdd0fc",
118118
relationship__guardian__user=user_api_client.user,

0 commit comments

Comments
 (0)