From aa7605e8362c031181a58ea90b2fe82b18e450df Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:04:37 +0200 Subject: [PATCH 1/7] Add FK's to ticket_types full week/one day tickets for both adults/childs --- ...mp_ticket_type_full_week_adult_and_more.py | 63 +++++++++++++++++++ src/camps/models.py | 36 +++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py diff --git a/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py b/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py new file mode 100644 index 000000000..e1e7fe16e --- /dev/null +++ b/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py @@ -0,0 +1,63 @@ +# Generated by Django 4.2.21 on 2025-07-01 13:04 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("tickets", "0028_alter_prizeticket_comment"), + ("camps", "0039_camp_kickoff"), + ] + + operations = [ + migrations.AddField( + model_name="camp", + name="ticket_type_full_week_adult", + field=models.ForeignKey( + blank=True, + help_text="The ticket type for 'Adult Full Week' for this camp", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="full_week_adult_camps", + to="tickets.tickettype", + ), + ), + migrations.AddField( + model_name="camp", + name="ticket_type_full_week_child", + field=models.ForeignKey( + blank=True, + help_text="The ticket type for 'Child Full Week' for this camp", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="full_week_child_camps", + to="tickets.tickettype", + ), + ), + migrations.AddField( + model_name="camp", + name="ticket_type_one_day_adult", + field=models.ForeignKey( + blank=True, + help_text="The ticket type for 'Adult One Day' for this camp", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="one_day_adult_camps", + to="tickets.tickettype", + ), + ), + migrations.AddField( + model_name="camp", + name="ticket_type_one_day_child", + field=models.ForeignKey( + blank=True, + help_text="The ticket type for 'Child One Day' for this camp", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="one_day_child_camps", + to="tickets.tickettype", + ), + ), + ] diff --git a/src/camps/models.py b/src/camps/models.py index 9523cbdd0..409433f70 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -128,6 +128,42 @@ class Meta: related_name="+", ) + ticket_type_full_week_adult = models.ForeignKey( + "tickets.TicketType", + on_delete=models.SET_NULL, + help_text="The ticket type for 'Adult Full Week' for this camp", + null=True, + blank=True, + related_name="full_week_adult_camps" + ) + + ticket_type_one_day_adult = models.ForeignKey( + "tickets.TicketType", + on_delete=models.SET_NULL, + help_text="The ticket type for 'Adult One Day' for this camp", + null=True, + blank=True, + related_name="one_day_adult_camps" + ) + + ticket_type_full_week_child = models.ForeignKey( + "tickets.TicketType", + on_delete=models.SET_NULL, + help_text="The ticket type for 'Child Full Week' for this camp", + null=True, + blank=True, + related_name="full_week_child_camps" + ) + + ticket_type_one_day_child = models.ForeignKey( + "tickets.TicketType", + on_delete=models.SET_NULL, + help_text="The ticket type for 'Child One Day' for this camp", + null=True, + blank=True, + related_name="one_day_child_camps" + ) + def get_absolute_url(self): return reverse("camp_detail", kwargs={"camp_slug": self.slug}) From 702f58633cdc85ff06a1332b05c54754659c4373 Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Thu, 3 Jul 2025 12:51:48 +0200 Subject: [PATCH 2/7] Not working: Add tests for full week tickets with bootstrapping --- src/camps/models.py | 42 ++++++++ src/camps/tests.py | 45 +++++++++ src/utils/bootstrap/base.py | 185 ++++++++++++++++++++++++++++-------- 3 files changed, 235 insertions(+), 37 deletions(-) diff --git a/src/camps/models.py b/src/camps/models.py index 409433f70..bf8afaf5f 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -1,5 +1,7 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import logging from datetime import timedelta from django.conf import settings @@ -15,6 +17,11 @@ from django_prometheus.models import ExportModelOperationsMixin from psycopg2.extras import DateTimeTZRange +if TYPE_CHECKING: + from django.db.models import QuerySet + +from tickets.models import ShopTicket +from tickets.models import SponsorTicket from utils.models import CreatedUpdatedModel from utils.models import UUIDModel @@ -339,3 +346,38 @@ def event_sessions(self): def event_slots(self): EventSlot = apps.get_model("program", "EventSlot") return EventSlot.objects.filter(event_session__in=self.event_sessions.all()) + + @property + def checked_in_full_week_adults(self) -> int: + """ + Return the adult tickets checked in and being valid for today + """ + shop_tickets = ( + ShopTicket.objects.filter( + ticket_type=self.ticket_type_full_week_adult + ) + .exclude(used_at=None) + ).count() + sponsor_tickets = ( + SponsorTicket.objects.filter( + ticket_type=self.ticket_type_full_week_adult + ) + .exclude(used_at=None) + ).count() + # TODO + # prize_tickets + return shop_tickets + sponsor_tickets + + @property + def checked_in_full_week_children(self) -> QuerySet: + """ + Return the children tickets checked in and being valid for today + """ + shop_tickets = ( + ShopTicket.objects.filter( + ticket_type=self.ticket_type_full_week_child + ) + .exclude(used_at=None) + ).count() + return shop_tickets + diff --git a/src/camps/tests.py b/src/camps/tests.py index d9546b6d0..06b131b7f 100644 --- a/src/camps/tests.py +++ b/src/camps/tests.py @@ -5,6 +5,10 @@ from django.test import TestCase from django.urls import reverse +from tickets.models import ShopTicket +from tickets.models import SponsorTicket +from tickets.models import PrizeTicket +from utils.tests import BornhackTestBase class CampMenuTest(TestCase): def test_this_year_shown_on_homepage(self): @@ -15,3 +19,44 @@ def test_this_year_shown_on_homepage(self): year = (datetime.date.today() - datetime.timedelta(days=59)).year href = reverse("camp_detail", kwargs={"camp_slug": f"bornhack-{year}"}) assert href in response.content.decode("utf-8") + + +class TestCampModel(BornhackTestBase): + """Tests for the Camp model""" + + def setUp(self) -> None: + super().setUp() + self.full_week_adults = { + "shop_tickets": ( + ShopTicket.objects.filter(ticket_type__camp=self.camp) + .filter(ticket_type=self.camp.ticket_type_full_week_adult) + ), + "sponsor_tickets": ( + SponsorTicket.objects.filter(ticket_type__camp=self.camp) + .filter(ticket_type=self.camp.ticket_type_full_week_adult) + ), + } + self.full_week_children = ( + ShopTicket.objects.filter(ticket_type__camp=self.camp) + .filter(ticket_type=self.camp.ticket_type_full_week_child) + ) + + def test_checked_in_full_week_adults(self) -> None: + """Test the return value of checked in full week adults""" + tickets = [ + self.full_week_adults["shop_tickets"][0], + self.full_week_adults["sponsor_tickets"][0], + ] + for ticket in tickets: + ticket.used_at = self.camp.camp.lower + ticket.save() + + assert self.camp.checked_in_full_week_adults == 2 + + def test_checked_in_full_week_children(self) -> None: + """Test the return value of checked in full week children""" + ticket1 = self.full_week_children[0] + ticket1.used_at = self.camp.camp.lower + ticket1.save() + assert self.camp.checked_in_full_week_children == 1 + diff --git a/src/utils/bootstrap/base.py b/src/utils/bootstrap/base.py index ded23177b..05b24cc4f 100644 --- a/src/utils/bootstrap/base.py +++ b/src/utils/bootstrap/base.py @@ -88,7 +88,7 @@ from teams.models import TeamMember from teams.models import TeamShift from teams.models import TeamTask -from tickets.models import TicketType +from tickets.models import PrizeTicket, SponsorTicket, TicketType from tokens.models import Token from tokens.models import TokenFind from utils.slugs import unique_slugify @@ -599,18 +599,22 @@ def create_camp_ticket_types(self, camp: Camp) -> dict: name="Adult Full Week", camp=camp, ) + camp.ticket_type_full_week_adult = types["adult_full_week"] types["adult_one_day"] = TicketType.objects.create( name="Adult One Day", camp=camp, ) + camp.ticket_type_one_day_adult = types["adult_one_day"] types["child_full_week"] = TicketType.objects.create( name="Child Full Week", camp=camp, ) + camp.ticket_type_full_week_child = types["child_full_week"] types["child_one_day"] = TicketType.objects.create( name="Child One Day", camp=camp, ) + camp.ticket_type_one_day_child = types["child_one_day"] types["village"] = TicketType.objects.create( name="Village", camp=camp, @@ -675,6 +679,25 @@ def create_camp_products(self, camp: Camp, categories: dict, ticket_types: dict) ticket_type=ticket_types["adult_full_week"], ) + name = f"{camp_prefix} Child Ticket (5-15 year old)" + products["child_ticket"] = Product.objects.create( + name=name, + description="A child ticket", + price=495, + category=categories["tickets"], + available_in=( + datetime(year, 1, 1, 12, 0, tzinfo=tz), + datetime(year, 12, 20, 12, 0, tzinfo=tz), + ), + slug=unique_slugify( + name, + slugs_in_use=Product.objects.filter( + category=categories["tickets"], + ).values_list("slug", flat=True), + ), + ticket_type=ticket_types["child_full_week"], + ) + name = f"{camp_prefix} One day ticket" products["one_day_ticket"] = Product.objects.create( name=name, @@ -694,6 +717,25 @@ def create_camp_products(self, camp: Camp, categories: dict, ticket_types: dict) ticket_type=ticket_types["adult_one_day"], ) + name = f"{camp_prefix} One day ticket child" + products["one_day_ticket_child"] = Product.objects.create( + name=name, + description="One day ticket child", + price=165, + category=categories["tickets"], + available_in=( + datetime(year, 1, 1, 12, 0, tzinfo=tz), + datetime(year, 12, 20, 12, 0, tzinfo=tz), + ), + slug=unique_slugify( + name, + slugs_in_use=Product.objects.filter( + category=categories["tickets"], + ).values_list("slug", flat=True), + ), + ticket_type=ticket_types["child_one_day"], + ) + name = f"{camp_prefix} Village tent 3x3 meters, no floor" products["tent1"] = Product.objects.create( name=name, @@ -899,6 +941,24 @@ def create_orders(self, users: dict, camp_products: dict) -> dict: orders[3].oprs.create(product=camp_products["hax"], quantity=30) orders[3].mark_as_paid(request=None) + orders[4] = Order.objects.create( + user=users[5], + payment_method="in_person", + open=None, + ) + orders[4].oprs.create(product=camp_products["ticket1"], quantity=1) + orders[4].oprs.create(product=camp_products["child_ticket"], quantity=1) + orders[4].mark_as_paid(request=None) + + orders[5] = Order.objects.create( + user=users[6], + payment_method="in_person", + open=None, + ) + orders[5].oprs.create(product=camp_products["one_day_ticket"], quantity=2) + orders[5].oprs.create(product=camp_products["one_day_ticket_child"], quantity=2) + orders[5].mark_as_paid(request=None) + return orders def create_camp_tracks(self, camp: Camp) -> dict: @@ -1811,46 +1871,77 @@ def create_camp_sponsor_tiers(self, camp: Camp) -> dict: return tiers - def create_camp_sponsors(self, camp: Camp, tiers: dict) -> None: + def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: """Create the camp sponsors.""" year = camp.camp.lower.year + sponsors = [] self.output(f"Creating sponsors for {year}...") - Sponsor.objects.create( - name="PROSA", - tier=tiers["platinum"], - description="Bus Trip", - logo_filename="PROSA-logo.png", - url="https://www.prosa.dk", - ) - Sponsor.objects.create( - name="DKUUG", - tier=tiers["platinum"], - description="Speakers tent", - logo_filename="DKUUGlogo.jpeg", - url="http://www.dkuug.dk/", - ) - Sponsor.objects.create( - name="LetsGo", - tier=tiers["silver"], - description="Shuttle", - logo_filename="letsgo.png", - url="https://letsgo.dk", - ) - Sponsor.objects.create( - name="Saxo Bank", - tier=tiers["gold"], - description="Cash Sponsorship", - logo_filename="saxobank.png", - url="https://home.saxo", - ) - Sponsor.objects.create( - name="CSIS", - tier=tiers["sponsor"], - description="Cash Sponsorship", - logo_filename="CSIS_PRI_LOGO_TURQUOISE_RGB.jpg", - url="https://csis.dk", + sponsors.append( + Sponsor.objects.create( + name="PROSA", + tier=tiers["platinum"], + description="Bus Trip", + logo_filename="PROSA-logo.png", + url="https://www.prosa.dk", + ) + ) + sponsors.append( + Sponsor.objects.create( + name="DKUUG", + tier=tiers["platinum"], + description="Speakers tent", + logo_filename="DKUUGlogo.jpeg", + url="http://www.dkuug.dk/", + ) + ) + sponsors.append( + Sponsor.objects.create( + name="LetsGo", + tier=tiers["silver"], + description="Shuttle", + logo_filename="letsgo.png", + url="https://letsgo.dk", + ) + ) + sponsors.append( + Sponsor.objects.create( + name="Saxo Bank", + tier=tiers["gold"], + description="Cash Sponsorship", + logo_filename="saxobank.png", + url="https://home.saxo", + ) + ) + sponsors.append( + Sponsor.objects.create( + name="CSIS", + tier=tiers["sponsor"], + description="Cash Sponsorship", + logo_filename="CSIS_PRI_LOGO_TURQUOISE_RGB.jpg", + url="https://csis.dk", + ) ) + return sponsors + + def create_camp_sponsor_tickets(self, camp: Camp, sponsors: list, tiers: dict, ticket_types: dict) -> None: + """Create tickets for camp sponsors""" + year = camp.camp.lower.year + self.output(f"Creating sponsor tickets for {year}...") + for sponsor in sponsors: + if sponsor.tier == tiers["platinum"]: + for _ in range(10): + SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + elif sponsor.tier == tiers["gold"]: + for _ in range(10): + SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + elif sponsor.tier == tiers["silver"]: + for _ in range(5): + SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + elif sponsor.tier == tiers["sponsor"]: + for _ in range(2): + SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + def create_camp_tokens(self, camp: Camp) -> dict[Token]: """Create the camp tokens.""" tokens = {} @@ -1914,6 +2005,13 @@ def create_camp_token_finds(self, camp: Camp, tokens: dict[Token], users: dict[U for i in range(6): TokenFind.objects.create(token=tokens[i], user=users[1]) + def create_prize_ticket(self, camp: Camp, ticket_types: dict) -> None: + """Create prize tickets""" + year = camp.camp.lower.year + self.output(f"Creating prize tickets for {year}...") + PrizeTicket.objects.create(user=self.users.keys(), ticket_type=ticket_types["adult_full_week"]) + + def create_camp_expenses(self, camp: Camp) -> None: """Create camp expenses.""" self.output(f"Creating expenses for {camp}...") @@ -2167,9 +2265,22 @@ def bootstrap_tests(self) -> None: self.create_camps(camps) self.create_users(16) self.create_event_types() + self.create_product_categories() teams = {} for camp, read_only in self.camps: year = camp.camp.lower.year + if year <= settings.UPCOMING_CAMP_YEAR: + ticket_types = self.create_camp_ticket_types(camp) + camp_products = self.create_camp_products( + camp, + self.product_categories, + ticket_types, + ) + self.create_orders(self.users, camp_products) + sponsor_tiers = self.create_camp_sponsor_tiers(camp) + camp_sponsors = self.create_camp_sponsors(camp, sponsor_tiers) + self.create_camp_sponsor_tickets(camp, camp_sponsors, sponsor_tiers, ticket_types) + self.create_prize_ticket(camp, ticket_types) teams[year] = self.create_camp_teams(camp) self.create_camp_team_memberships(camp, teams[year], self.users) @@ -2281,7 +2392,7 @@ def bootstrap_camp(self, options: dict) -> None: sponsor_tiers = self.create_camp_sponsor_tiers(camp) - self.create_camp_sponsors(camp, sponsor_tiers) + camp_sponsors = self.create_camp_sponsors(camp, sponsor_tiers) tokens = self.create_camp_tokens(camp) From 1139e83aaacbd7e185b510a590b3b7cdf3d81ff7 Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Fri, 4 Jul 2025 10:39:57 +0200 Subject: [PATCH 3/7] Add prize ticket creation and query with tests --- src/camps/models.py | 51 +++++++++++++++++++++++++++++-------- src/camps/tests.py | 31 +++++++++++++++++++++- src/utils/bootstrap/base.py | 7 +++-- 3 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/camps/models.py b/src/camps/models.py index bf8afaf5f..29de0e9ea 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -20,6 +20,7 @@ if TYPE_CHECKING: from django.db.models import QuerySet +from tickets.models import PrizeTicket from tickets.models import ShopTicket from tickets.models import SponsorTicket from utils.models import CreatedUpdatedModel @@ -349,35 +350,65 @@ def event_slots(self): @property def checked_in_full_week_adults(self) -> int: - """ - Return the adult tickets checked in and being valid for today - """ + """Return the count of full week adult tickets checked in""" shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_full_week_adult ) .exclude(used_at=None) ).count() + sponsor_tickets = ( SponsorTicket.objects.filter( ticket_type=self.ticket_type_full_week_adult ) .exclude(used_at=None) ).count() - # TODO - # prize_tickets - return shop_tickets + sponsor_tickets + + prize_tickets = ( + PrizeTicket.objects.filter( + ticket_type=self.ticket_type_full_week_adult + ) + .exclude(used_at=None) + ).count() + + return shop_tickets + sponsor_tickets + prize_tickets @property - def checked_in_full_week_children(self) -> QuerySet: - """ - Return the children tickets checked in and being valid for today - """ + def checked_in_full_week_children(self) -> int: + """Return the count of full week children tickets checked in""" shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_full_week_child ) .exclude(used_at=None) ).count() + return shop_tickets + @property + def checked_in_one_day_adults(self) -> int: + """ + Return the count of todays one day adult tickets checked in. + + Count tickets with a checked in timestamp from 0600-0600 next day. + Reason being early arriving participants might get checked in before 10. + """ + start = timezone.localtime().replace(hour=6, minute=00) + end = start + timezone.timedelta(days=1) + shop_tickets = ( + ShopTicket.objects.filter( + ticket_type=self.ticket_type_one_day_adult + ) + .filter(used_at__gte=start, used_at__lte=end) + ).count() + + sponsor_tickets = ( + SponsorTicket.objects.filter( + ticket_type=self.ticket_type_one_day_adult + ) + .filter(used_at__gte=start, used_at__lte=end) + ).count() + + return shop_tickets + sponsor_tickets + diff --git a/src/camps/tests.py b/src/camps/tests.py index 06b131b7f..88fa54b11 100644 --- a/src/camps/tests.py +++ b/src/camps/tests.py @@ -4,6 +4,7 @@ from django.test import TestCase from django.urls import reverse +from django.utils import timezone from tickets.models import ShopTicket from tickets.models import SponsorTicket @@ -35,23 +36,32 @@ def setUp(self) -> None: SponsorTicket.objects.filter(ticket_type__camp=self.camp) .filter(ticket_type=self.camp.ticket_type_full_week_adult) ), + "prize_tickets": ( + PrizeTicket.objects.filter(ticket_type__camp=self.camp) + .filter(ticket_type=self.camp.ticket_type_full_week_adult) + ), } self.full_week_children = ( ShopTicket.objects.filter(ticket_type__camp=self.camp) .filter(ticket_type=self.camp.ticket_type_full_week_child) ) + self.one_day_adults = ( + ShopTicket.objects.filter(ticket_type__camp=self.camp) + .filter(ticket_type=self.camp.ticket_type_one_day_adult) + ) def test_checked_in_full_week_adults(self) -> None: """Test the return value of checked in full week adults""" tickets = [ self.full_week_adults["shop_tickets"][0], self.full_week_adults["sponsor_tickets"][0], + self.full_week_adults["prize_tickets"][0], ] for ticket in tickets: ticket.used_at = self.camp.camp.lower ticket.save() - assert self.camp.checked_in_full_week_adults == 2 + assert self.camp.checked_in_full_week_adults == 3 def test_checked_in_full_week_children(self) -> None: """Test the return value of checked in full week children""" @@ -60,3 +70,22 @@ def test_checked_in_full_week_children(self) -> None: ticket1.save() assert self.camp.checked_in_full_week_children == 1 + def test_checked_in_one_day_adults(self) -> None: + """Test the return value of checked in one day adults today""" + for ticket in self.one_day_adults: + ticket.used_at = timezone.localtime() + ticket.save() + + assert self.camp.checked_in_one_day_adults == 2 + + def test_checked_in_one_day_adults_before_yesterday(self) -> None: + """Test check in before 06 yesterday don't count""" + valid = self.one_day_adults[0] + valid.used_at = timezone.localtime() + valid.save() + not_valid = self.one_day_adults[1] + not_valid.used_at = timezone.localtime() - timezone.timedelta(days=2) + not_valid.save() + + assert self.camp.checked_in_one_day_adults == 1 + diff --git a/src/utils/bootstrap/base.py b/src/utils/bootstrap/base.py index 05b24cc4f..f7bb136aa 100644 --- a/src/utils/bootstrap/base.py +++ b/src/utils/bootstrap/base.py @@ -2009,8 +2009,11 @@ def create_prize_ticket(self, camp: Camp, ticket_types: dict) -> None: """Create prize tickets""" year = camp.camp.lower.year self.output(f"Creating prize tickets for {year}...") - PrizeTicket.objects.create(user=self.users.keys(), ticket_type=ticket_types["adult_full_week"]) - + PrizeTicket.objects.create( + user=self.users[5], + comment="Prize winner", + ticket_type=ticket_types["adult_full_week"] + ) def create_camp_expenses(self, camp: Camp) -> None: """Create camp expenses.""" From d9a40766ec06f9562bbcd6c33231377b9835873d Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Fri, 4 Jul 2025 10:59:01 +0200 Subject: [PATCH 4/7] Add 'SponsorTicket' and 'PrizeTicket' queries for 'checked_in_full_week_children' property with tests --- src/camps/models.py | 16 +++++++++++++++- src/camps/tests.py | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/camps/models.py b/src/camps/models.py index 29de0e9ea..c857d2565 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -384,7 +384,21 @@ def checked_in_full_week_children(self) -> int: .exclude(used_at=None) ).count() - return shop_tickets + sponsor_tickets = ( + SponsorTicket.objects.filter( + ticket_type=self.ticket_type_full_week_child + ) + .exclude(used_at=None) + ).count() + + prize_tickets = ( + PrizeTicket.objects.filter( + ticket_type=self.ticket_type_full_week_child + ) + .exclude(used_at=None) + ).count() + + return shop_tickets + sponsor_tickets + prize_tickets @property def checked_in_one_day_adults(self) -> int: diff --git a/src/camps/tests.py b/src/camps/tests.py index 88fa54b11..5891ba9a8 100644 --- a/src/camps/tests.py +++ b/src/camps/tests.py @@ -6,6 +6,7 @@ from django.urls import reverse from django.utils import timezone +from sponsors.models import Sponsor from tickets.models import ShopTicket from tickets.models import SponsorTicket from tickets.models import PrizeTicket @@ -70,6 +71,30 @@ def test_checked_in_full_week_children(self) -> None: ticket1.save() assert self.camp.checked_in_full_week_children == 1 + def test_checked_in_full_week_children_with_sponsor_ticket(self) -> None: + """ + Test the return value of checked in full week children with sponsor ticket + """ + sponsor = Sponsor.objects.all().first() + SponsorTicket.objects.create( + sponsor=sponsor, + ticket_type=self.camp.ticket_type_full_week_child, + used_at = self.camp.camp.lower + ) + assert self.camp.checked_in_full_week_children == 1 + + def test_checked_in_full_week_children_with_prize_ticket(self) -> None: + """ + Test the return value of checked in full week children with prize ticket + """ + PrizeTicket.objects.create( + user=self.users[0], + ticket_type=self.camp.ticket_type_full_week_child, + comment="Prize winner", + used_at = self.camp.camp.lower + ) + assert self.camp.checked_in_full_week_children == 1 + def test_checked_in_one_day_adults(self) -> None: """Test the return value of checked in one day adults today""" for ticket in self.one_day_adults: From 20d3c87ee76cecfaaed5ce1ad3aec67a6401baf5 Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Fri, 4 Jul 2025 14:21:53 +0200 Subject: [PATCH 5/7] Add logic for getting right time window for one day tickets. Add property for 'one day child' and property for 'participant count' with tests. --- src/camps/models.py | 81 ++++++++++++++++++++--- src/camps/tests.py | 125 ++++++++++++++++++++++++++++++++---- src/utils/bootstrap/base.py | 4 +- 3 files changed, 187 insertions(+), 23 deletions(-) diff --git a/src/camps/models.py b/src/camps/models.py index c857d2565..4b069a5e9 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -1,7 +1,5 @@ from __future__ import annotations -from typing import TYPE_CHECKING - import logging from datetime import timedelta from django.conf import settings @@ -17,9 +15,6 @@ from django_prometheus.models import ExportModelOperationsMixin from psycopg2.extras import DateTimeTZRange -if TYPE_CHECKING: - from django.db.models import QuerySet - from tickets.models import PrizeTicket from tickets.models import ShopTicket from tickets.models import SponsorTicket @@ -408,21 +403,87 @@ def checked_in_one_day_adults(self) -> int: Count tickets with a checked in timestamp from 0600-0600 next day. Reason being early arriving participants might get checked in before 10. """ - start = timezone.localtime().replace(hour=6, minute=00) - end = start + timezone.timedelta(days=1) + now = timezone.localtime() + today_06_hour = now.replace(hour=6, minute=0, second=0) + if now < today_06_hour: + start = today_06_hour - timezone.timedelta(days=1) + end = today_06_hour + else: + start = today_06_hour + end = today_06_hour + timezone.timedelta(days=1) + shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_one_day_adult ) - .filter(used_at__gte=start, used_at__lte=end) + .filter(used_at__gte=start, used_at__lt=end) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( ticket_type=self.ticket_type_one_day_adult ) - .filter(used_at__gte=start, used_at__lte=end) + .filter(used_at__gte=start, used_at__lt=end) + ).count() + + prize_tickets = ( + PrizeTicket.objects.filter( + ticket_type=self.ticket_type_one_day_adult + ) + .filter(used_at__gte=start, used_at__lt=end) + ).count() + + return shop_tickets + sponsor_tickets + prize_tickets + + @property + def checked_in_one_day_children(self) -> int: + """ + Return the count of todays one day children tickets checked in. + + Count tickets with a checked in timestamp from 0600-0600 next day. + Reason being early arriving participants might get checked in before 10. + """ + now = timezone.localtime() + today_06_hour = now.replace(hour=6, minute=0, second=0) + if now < today_06_hour: + start = today_06_hour - timezone.timedelta(days=1) + end = today_06_hour + else: + start = today_06_hour + end = today_06_hour + timezone.timedelta(days=1) + + shop_tickets = ( + ShopTicket.objects.filter( + ticket_type=self.ticket_type_one_day_child + ) + .filter(used_at__gte=start, used_at__lt=end) ).count() - return shop_tickets + sponsor_tickets + sponsor_tickets = ( + SponsorTicket.objects.filter( + ticket_type=self.ticket_type_one_day_child + ) + .filter(used_at__gte=start, used_at__lt=end) + ).count() + prize_tickets = ( + PrizeTicket.objects.filter( + ticket_type=self.ticket_type_one_day_child + ) + .filter(used_at__gte=start, used_at__lt=end) + ).count() + + return shop_tickets + sponsor_tickets + prize_tickets + + @property + def participant_count(self) -> int: + """ + Retrieve the participant count for all used 'full week' tickets + and todays used 'one day' tickets. + """ + return ( + self.checked_in_full_week_adults + + self.checked_in_full_week_children + + self.checked_in_one_day_adults + + self.checked_in_one_day_children + ) diff --git a/src/camps/tests.py b/src/camps/tests.py index 5891ba9a8..e240a4acf 100644 --- a/src/camps/tests.py +++ b/src/camps/tests.py @@ -28,7 +28,7 @@ class TestCampModel(BornhackTestBase): def setUp(self) -> None: super().setUp() - self.full_week_adults = { + self.full_week_adults = { # All tickets are created by bootstrapping "shop_tickets": ( ShopTicket.objects.filter(ticket_type__camp=self.camp) .filter(ticket_type=self.camp.ticket_type_full_week_adult) @@ -42,17 +42,21 @@ def setUp(self) -> None: .filter(ticket_type=self.camp.ticket_type_full_week_adult) ), } - self.full_week_children = ( + self.full_week_children = ( # ShopTickets created by bootstrapping ShopTicket.objects.filter(ticket_type__camp=self.camp) .filter(ticket_type=self.camp.ticket_type_full_week_child) ) - self.one_day_adults = ( + self.one_day_adults = ( # ShopTickets created by bootstrapping ShopTicket.objects.filter(ticket_type__camp=self.camp) .filter(ticket_type=self.camp.ticket_type_one_day_adult) ) + self.one_day_children = ( # ShopTickets created by bootstrapping + ShopTicket.objects.filter(ticket_type__camp=self.camp) + .filter(ticket_type=self.camp.ticket_type_one_day_child) + ) - def test_checked_in_full_week_adults(self) -> None: - """Test the return value of checked in full week adults""" + def test_checked_in_full_week_adults_all_ticket_types(self) -> None: + """Test the return value of checked in full week adults for all tickets""" tickets = [ self.full_week_adults["shop_tickets"][0], self.full_week_adults["sponsor_tickets"][0], @@ -64,11 +68,11 @@ def test_checked_in_full_week_adults(self) -> None: assert self.camp.checked_in_full_week_adults == 3 - def test_checked_in_full_week_children(self) -> None: - """Test the return value of checked in full week children""" - ticket1 = self.full_week_children[0] - ticket1.used_at = self.camp.camp.lower - ticket1.save() + def test_checked_in_full_week_children_shop_tickets(self) -> None: + """Test the return value of checked in full week children with shop ticket""" + ticket = self.full_week_children[0] + ticket.used_at = self.camp.camp.lower + ticket.save() assert self.camp.checked_in_full_week_children == 1 def test_checked_in_full_week_children_with_sponsor_ticket(self) -> None: @@ -97,20 +101,117 @@ def test_checked_in_full_week_children_with_prize_ticket(self) -> None: def test_checked_in_one_day_adults(self) -> None: """Test the return value of checked in one day adults today""" - for ticket in self.one_day_adults: + for ticket in self.one_day_adults[:2]: ticket.used_at = timezone.localtime() ticket.save() assert self.camp.checked_in_one_day_adults == 2 - def test_checked_in_one_day_adults_before_yesterday(self) -> None: + def test_checked_in_one_day_adults_with_sponsor_ticket(self) -> None: + """ + Test the return value of checked in one day adults + with sponsor ticket today + """ + sponsor = Sponsor.objects.all().first() + SponsorTicket.objects.create( + sponsor=sponsor, + ticket_type=self.camp.ticket_type_one_day_adult, + used_at = timezone.localtime() + ) + + assert self.camp.checked_in_one_day_adults == 1 + + def test_checked_in_one_day_adults_with_prize_ticket(self) -> None: + """ + Test the return value of checked in one day adults + with prize ticket today + """ + PrizeTicket.objects.create( + user=self.users[0], + ticket_type=self.camp.ticket_type_one_day_adult, + comment="Prize winner", + used_at = timezone.localtime() + ) + + assert self.camp.checked_in_one_day_adults == 1 + + def test_checked_in_one_day_adults_timing(self) -> None: """Test check in before 06 yesterday don't count""" valid = self.one_day_adults[0] valid.used_at = timezone.localtime() valid.save() + not_valid = self.one_day_adults[1] not_valid.used_at = timezone.localtime() - timezone.timedelta(days=2) not_valid.save() assert self.camp.checked_in_one_day_adults == 1 + def test_checked_in_one_day_children(self) -> None: + """Test the return value of checked in one day children today""" + for ticket in self.one_day_children[:2]: + ticket.used_at = timezone.localtime() + ticket.save() + + assert self.camp.checked_in_one_day_children == 2 + + def test_checked_in_one_day_children_with_sponsor_ticket(self) -> None: + """ + Test the return value of checked in one day children + with sponsor ticket today + """ + sponsor = Sponsor.objects.all().first() + SponsorTicket.objects.create( + sponsor=sponsor, + ticket_type=self.camp.ticket_type_one_day_child, + used_at = timezone.localtime() + ) + + assert self.camp.checked_in_one_day_children == 1 + + def test_checked_in_one_day_children_with_prize_ticket(self) -> None: + """ + Test the return value of checked in one day children + with prize ticket today + """ + PrizeTicket.objects.create( + user=self.users[0], + ticket_type=self.camp.ticket_type_one_day_child, + comment="Prize winner", + used_at = timezone.localtime() + ) + + assert self.camp.checked_in_one_day_children == 1 + + def test_checked_in_one_day_children_timing(self) -> None: + """Test check in before 06 yesterday don't count""" + valid = self.one_day_children[0] + valid.used_at = timezone.localtime() + valid.save() + + not_valid = self.one_day_children[1] + not_valid.used_at = timezone.localtime() - timezone.timedelta(days=2) + not_valid.save() + + assert self.camp.checked_in_one_day_children == 1 + + def test_participant_count(self) -> None: + """Test the count of all participants""" + adult_full_week = self.full_week_adults["shop_tickets"][0] + adult_full_week.used_at = self.camp.camp.lower + adult_full_week.save() + + child_full_week = self.full_week_children[0] + child_full_week.used_at = self.camp.camp.lower + child_full_week.save() + + adult_one_day = self.one_day_adults[0] + adult_one_day.used_at = timezone.localtime() + adult_one_day.save() + + child_one_day = self.one_day_children[0] + child_one_day.used_at = timezone.localtime() + child_one_day.save() + + assert self.camp.participant_count == 4 + diff --git a/src/utils/bootstrap/base.py b/src/utils/bootstrap/base.py index f7bb136aa..329b72bc0 100644 --- a/src/utils/bootstrap/base.py +++ b/src/utils/bootstrap/base.py @@ -88,7 +88,9 @@ from teams.models import TeamMember from teams.models import TeamShift from teams.models import TeamTask -from tickets.models import PrizeTicket, SponsorTicket, TicketType +from tickets.models import PrizeTicket +from tickets.models import SponsorTicket +from tickets.models import TicketType from tokens.models import Token from tokens.models import TokenFind from utils.slugs import unique_slugify From 1e06652b059ffe93219367a2e781c239412ce4c4 Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Fri, 4 Jul 2025 14:43:33 +0200 Subject: [PATCH 6/7] Black code style (pre-commit is linting stuff I did not touch, and will be done in a dedicated PR to minimize scope of changes) --- src/camps/models.py | 61 +++++++++++++------------------ src/camps/tests.py | 52 ++++++++++++++------------ src/utils/bootstrap/base.py | 73 +++++++++++++++++++++++++++---------- 3 files changed, 109 insertions(+), 77 deletions(-) diff --git a/src/camps/models.py b/src/camps/models.py index 4b069a5e9..1a17c8a47 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -65,7 +65,12 @@ class Meta: help_text="Abbreviated version of the slug. Used in IRC channel names and other places with restricted name length.", ) - kickoff = DateTimeRangeField(null=True, blank=True, verbose_name="Camp Kickoff", help_text="The camp kickoff period.") + kickoff = DateTimeRangeField( + null=True, + blank=True, + verbose_name="Camp Kickoff", + help_text="The camp kickoff period.", + ) buildup = DateTimeRangeField( verbose_name="Buildup Period", @@ -137,7 +142,7 @@ class Meta: help_text="The ticket type for 'Adult Full Week' for this camp", null=True, blank=True, - related_name="full_week_adult_camps" + related_name="full_week_adult_camps", ) ticket_type_one_day_adult = models.ForeignKey( @@ -146,7 +151,7 @@ class Meta: help_text="The ticket type for 'Adult One Day' for this camp", null=True, blank=True, - related_name="one_day_adult_camps" + related_name="one_day_adult_camps", ) ticket_type_full_week_child = models.ForeignKey( @@ -155,7 +160,7 @@ class Meta: help_text="The ticket type for 'Child Full Week' for this camp", null=True, blank=True, - related_name="full_week_child_camps" + related_name="full_week_child_camps", ) ticket_type_one_day_child = models.ForeignKey( @@ -164,7 +169,7 @@ class Meta: help_text="The ticket type for 'Child One Day' for this camp", null=True, blank=True, - related_name="one_day_child_camps" + related_name="one_day_child_camps", ) def get_absolute_url(self): @@ -191,7 +196,6 @@ def clean(self) -> None: def __str__(self) -> str: return f"{self.title} - {self.tagline}" - def activate_team_permissions(self) -> None: """Add permissions to this camps teams.""" permission_content_type = ContentType.objects.get_for_model(Permission) @@ -220,7 +224,6 @@ def deactivate_team_permissions(self) -> None: group.permissions.remove(permission) logger.debug(f"Removed permission {permission} from group {group}") - @property def logo_small(self) -> str: return f"img/{self.slug}/logo/{self.slug}-logo-s.png" @@ -349,22 +352,19 @@ def checked_in_full_week_adults(self) -> int: shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_full_week_adult - ) - .exclude(used_at=None) + ).exclude(used_at=None) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( ticket_type=self.ticket_type_full_week_adult - ) - .exclude(used_at=None) + ).exclude(used_at=None) ).count() prize_tickets = ( PrizeTicket.objects.filter( ticket_type=self.ticket_type_full_week_adult - ) - .exclude(used_at=None) + ).exclude(used_at=None) ).count() return shop_tickets + sponsor_tickets + prize_tickets @@ -375,22 +375,19 @@ def checked_in_full_week_children(self) -> int: shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_full_week_child - ) - .exclude(used_at=None) + ).exclude(used_at=None) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( ticket_type=self.ticket_type_full_week_child - ) - .exclude(used_at=None) + ).exclude(used_at=None) ).count() prize_tickets = ( PrizeTicket.objects.filter( ticket_type=self.ticket_type_full_week_child - ) - .exclude(used_at=None) + ).exclude(used_at=None) ).count() return shop_tickets + sponsor_tickets + prize_tickets @@ -415,22 +412,19 @@ def checked_in_one_day_adults(self) -> int: shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_one_day_adult - ) - .filter(used_at__gte=start, used_at__lt=end) + ).filter(used_at__gte=start, used_at__lt=end) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( ticket_type=self.ticket_type_one_day_adult - ) - .filter(used_at__gte=start, used_at__lt=end) + ).filter(used_at__gte=start, used_at__lt=end) ).count() prize_tickets = ( PrizeTicket.objects.filter( ticket_type=self.ticket_type_one_day_adult - ) - .filter(used_at__gte=start, used_at__lt=end) + ).filter(used_at__gte=start, used_at__lt=end) ).count() return shop_tickets + sponsor_tickets + prize_tickets @@ -455,22 +449,19 @@ def checked_in_one_day_children(self) -> int: shop_tickets = ( ShopTicket.objects.filter( ticket_type=self.ticket_type_one_day_child - ) - .filter(used_at__gte=start, used_at__lt=end) + ).filter(used_at__gte=start, used_at__lt=end) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( ticket_type=self.ticket_type_one_day_child - ) - .filter(used_at__gte=start, used_at__lt=end) + ).filter(used_at__gte=start, used_at__lt=end) ).count() prize_tickets = ( PrizeTicket.objects.filter( ticket_type=self.ticket_type_one_day_child - ) - .filter(used_at__gte=start, used_at__lt=end) + ).filter(used_at__gte=start, used_at__lt=end) ).count() return shop_tickets + sponsor_tickets + prize_tickets @@ -482,8 +473,8 @@ def participant_count(self) -> int: and todays used 'one day' tickets. """ return ( - self.checked_in_full_week_adults + - self.checked_in_full_week_children + - self.checked_in_one_day_adults + - self.checked_in_one_day_children + self.checked_in_full_week_adults + + self.checked_in_full_week_children + + self.checked_in_one_day_adults + + self.checked_in_one_day_children ) diff --git a/src/camps/tests.py b/src/camps/tests.py index e240a4acf..d96054598 100644 --- a/src/camps/tests.py +++ b/src/camps/tests.py @@ -12,6 +12,7 @@ from tickets.models import PrizeTicket from utils.tests import BornhackTestBase + class CampMenuTest(TestCase): def test_this_year_shown_on_homepage(self): """By March, the current year's camp should be on the homepage.""" @@ -28,31 +29,37 @@ class TestCampModel(BornhackTestBase): def setUp(self) -> None: super().setUp() - self.full_week_adults = { # All tickets are created by bootstrapping + self.full_week_adults = { # All tickets are created by bootstrapping "shop_tickets": ( - ShopTicket.objects.filter(ticket_type__camp=self.camp) - .filter(ticket_type=self.camp.ticket_type_full_week_adult) + ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( + ticket_type=self.camp.ticket_type_full_week_adult + ) ), "sponsor_tickets": ( - SponsorTicket.objects.filter(ticket_type__camp=self.camp) - .filter(ticket_type=self.camp.ticket_type_full_week_adult) + SponsorTicket.objects.filter(ticket_type__camp=self.camp).filter( + ticket_type=self.camp.ticket_type_full_week_adult + ) ), "prize_tickets": ( - PrizeTicket.objects.filter(ticket_type__camp=self.camp) - .filter(ticket_type=self.camp.ticket_type_full_week_adult) + PrizeTicket.objects.filter(ticket_type__camp=self.camp).filter( + ticket_type=self.camp.ticket_type_full_week_adult + ) ), } - self.full_week_children = ( # ShopTickets created by bootstrapping - ShopTicket.objects.filter(ticket_type__camp=self.camp) - .filter(ticket_type=self.camp.ticket_type_full_week_child) + self.full_week_children = ( # ShopTickets created by bootstrapping + ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( + ticket_type=self.camp.ticket_type_full_week_child + ) ) - self.one_day_adults = ( # ShopTickets created by bootstrapping - ShopTicket.objects.filter(ticket_type__camp=self.camp) - .filter(ticket_type=self.camp.ticket_type_one_day_adult) + self.one_day_adults = ( # ShopTickets created by bootstrapping + ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( + ticket_type=self.camp.ticket_type_one_day_adult + ) ) - self.one_day_children = ( # ShopTickets created by bootstrapping - ShopTicket.objects.filter(ticket_type__camp=self.camp) - .filter(ticket_type=self.camp.ticket_type_one_day_child) + self.one_day_children = ( # ShopTickets created by bootstrapping + ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( + ticket_type=self.camp.ticket_type_one_day_child + ) ) def test_checked_in_full_week_adults_all_ticket_types(self) -> None: @@ -83,7 +90,7 @@ def test_checked_in_full_week_children_with_sponsor_ticket(self) -> None: SponsorTicket.objects.create( sponsor=sponsor, ticket_type=self.camp.ticket_type_full_week_child, - used_at = self.camp.camp.lower + used_at=self.camp.camp.lower, ) assert self.camp.checked_in_full_week_children == 1 @@ -95,7 +102,7 @@ def test_checked_in_full_week_children_with_prize_ticket(self) -> None: user=self.users[0], ticket_type=self.camp.ticket_type_full_week_child, comment="Prize winner", - used_at = self.camp.camp.lower + used_at=self.camp.camp.lower, ) assert self.camp.checked_in_full_week_children == 1 @@ -116,7 +123,7 @@ def test_checked_in_one_day_adults_with_sponsor_ticket(self) -> None: SponsorTicket.objects.create( sponsor=sponsor, ticket_type=self.camp.ticket_type_one_day_adult, - used_at = timezone.localtime() + used_at=timezone.localtime(), ) assert self.camp.checked_in_one_day_adults == 1 @@ -130,7 +137,7 @@ def test_checked_in_one_day_adults_with_prize_ticket(self) -> None: user=self.users[0], ticket_type=self.camp.ticket_type_one_day_adult, comment="Prize winner", - used_at = timezone.localtime() + used_at=timezone.localtime(), ) assert self.camp.checked_in_one_day_adults == 1 @@ -164,7 +171,7 @@ def test_checked_in_one_day_children_with_sponsor_ticket(self) -> None: SponsorTicket.objects.create( sponsor=sponsor, ticket_type=self.camp.ticket_type_one_day_child, - used_at = timezone.localtime() + used_at=timezone.localtime(), ) assert self.camp.checked_in_one_day_children == 1 @@ -178,7 +185,7 @@ def test_checked_in_one_day_children_with_prize_ticket(self) -> None: user=self.users[0], ticket_type=self.camp.ticket_type_one_day_child, comment="Prize winner", - used_at = timezone.localtime() + used_at=timezone.localtime(), ) assert self.camp.checked_in_one_day_children == 1 @@ -214,4 +221,3 @@ def test_participant_count(self) -> None: child_one_day.save() assert self.camp.participant_count == 4 - diff --git a/src/utils/bootstrap/base.py b/src/utils/bootstrap/base.py index 329b72bc0..11bfef744 100644 --- a/src/utils/bootstrap/base.py +++ b/src/utils/bootstrap/base.py @@ -337,7 +337,9 @@ def create_facilities(self, facility_types: dict) -> dict: ) return facilities - def create_facility_feedbacks(self, facilities: dict, options: dict, users: dict) -> None: + def create_facility_feedbacks( + self, facilities: dict, options: dict, users: dict + ) -> None: """Create facility feedbacks.""" self.output("Creating facility feedbacks...") FacilityFeedback.objects.create( @@ -637,7 +639,9 @@ def create_camp_ticket_types(self, camp: Camp) -> dict: return types - def create_camp_products(self, camp: Camp, categories: dict, ticket_types: dict) -> dict: + def create_camp_products( + self, camp: Camp, categories: dict, ticket_types: dict + ) -> dict: """Create camp shop products.""" products = {} year = camp.camp.lower.year @@ -1053,7 +1057,9 @@ def create_camp_news(self, camp: Camp) -> None: published_at=datetime(year, 9, 4, 12, 0, tzinfo=tz), ) - def create_camp_event_sessions(self, camp: Camp, event_types: dict, event_locations: dict) -> None: + def create_camp_event_sessions( + self, camp: Camp, event_types: dict, event_locations: dict + ) -> None: """Create camp event sessions.""" self.output(f"Creating EventSessions for {camp}...") days = camp.get_days(camppart="camp")[1:-1] @@ -1084,7 +1090,8 @@ def create_camp_event_sessions(self, camp: Camp, event_types: dict, event_locati event_location=event_locations["bar_area"], when=( datetime(start.year, start.month, start.day, 22, 0, tzinfo=tz), - datetime(start.year, start.month, start.day, 22, 0, tzinfo=tz) + timedelta(hours=3), + datetime(start.year, start.month, start.day, 22, 0, tzinfo=tz) + + timedelta(hours=3), ), ) EventSession.objects.create( @@ -1121,7 +1128,9 @@ def create_camp_event_sessions(self, camp: Camp, event_types: dict, event_locati event_type=event_types["keynote"], event_location=event_locations["speakers_tent"], when=( - datetime(day.lower.year, day.lower.month, day.lower.day, 20, 0, tzinfo=tz), + datetime( + day.lower.year, day.lower.month, day.lower.day, 20, 0, tzinfo=tz + ), datetime( day.lower.year, day.lower.month, @@ -1245,7 +1254,9 @@ class FakeForm: if not data: continue # 90% chance this speaker is available for any given chunk - form.cleaned_data[data["fieldname"]] = random.randint(1, 100) < 90 # noqa: PLR2004, S311 + form.cleaned_data[data["fieldname"]] = ( + random.randint(1, 100) < 90 + ) # noqa: PLR2004, S311 # print(f"saving availability for speaker {sp}: {form.cleaned_data}") save_speaker_availability(form, sp) @@ -1276,7 +1287,9 @@ def approve_event_proposals(self, camp: Camp) -> None: break else: # all speakers are approved, approve the event? always approve keynotes! - if random.randint(1, 100) < 90 or ep.event_type.name == "Keynote": # noqa: PLR2004, S311 + if ( + random.randint(1, 100) < 90 or ep.event_type.name == "Keynote" + ): # noqa: PLR2004, S311 ep.mark_as_approved() else: ep.mark_as_rejected() @@ -1521,7 +1534,9 @@ def create_camp_team_tasks(self, camp: Camp, teams: dict) -> None: description="We need ice cubes and crushed ice in the bar", ) - def create_camp_team_memberships(self, camp: Camp, teams: dict, users: dict) -> dict: + def create_camp_team_memberships( + self, camp: Camp, teams: dict, users: dict + ) -> dict: """Create camp team memberships.""" memberships = {} year = camp.camp.lower.year @@ -1635,7 +1650,9 @@ def create_camp_team_memberships(self, camp: Camp, teams: dict, users: dict) -> ) return memberships - def create_camp_team_shifts(self, camp: Camp, teams: dict, team_memberships: dict) -> None: + def create_camp_team_shifts( + self, camp: Camp, teams: dict, team_memberships: dict + ) -> None: """Create camp team shifts.""" shifts = {} year = camp.camp.lower.year @@ -1926,23 +1943,33 @@ def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: return sponsors - def create_camp_sponsor_tickets(self, camp: Camp, sponsors: list, tiers: dict, ticket_types: dict) -> None: + def create_camp_sponsor_tickets( + self, camp: Camp, sponsors: list, tiers: dict, ticket_types: dict + ) -> None: """Create tickets for camp sponsors""" year = camp.camp.lower.year self.output(f"Creating sponsor tickets for {year}...") for sponsor in sponsors: if sponsor.tier == tiers["platinum"]: for _ in range(10): - SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + SponsorTicket.objects.create( + sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + ) elif sponsor.tier == tiers["gold"]: for _ in range(10): - SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + SponsorTicket.objects.create( + sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + ) elif sponsor.tier == tiers["silver"]: for _ in range(5): - SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + SponsorTicket.objects.create( + sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + ) elif sponsor.tier == tiers["sponsor"]: for _ in range(2): - SponsorTicket.objects.create(sponsor=sponsor, ticket_type=ticket_types["adult_full_week"]) + SponsorTicket.objects.create( + sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + ) def create_camp_tokens(self, camp: Camp) -> dict[Token]: """Create the camp tokens.""" @@ -1994,7 +2021,9 @@ def create_camp_tokens(self, camp: Camp) -> dict[Token]: return tokens - def create_camp_token_finds(self, camp: Camp, tokens: dict[Token], users: dict[User]) -> None: + def create_camp_token_finds( + self, camp: Camp, tokens: dict[Token], users: dict[User] + ) -> None: """Create the camp token finds.""" year = camp.camp.lower.year self.output(f"Creating token finds for {year}...") @@ -2014,7 +2043,7 @@ def create_prize_ticket(self, camp: Camp, ticket_types: dict) -> None: PrizeTicket.objects.create( user=self.users[5], comment="Prize winner", - ticket_type=ticket_types["adult_full_week"] + ticket_type=ticket_types["adult_full_week"], ) def create_camp_expenses(self, camp: Camp) -> None: @@ -2284,7 +2313,9 @@ def bootstrap_tests(self) -> None: self.create_orders(self.users, camp_products) sponsor_tiers = self.create_camp_sponsor_tiers(camp) camp_sponsors = self.create_camp_sponsors(camp, sponsor_tiers) - self.create_camp_sponsor_tickets(camp, camp_sponsors, sponsor_tiers, ticket_types) + self.create_camp_sponsor_tickets( + camp, camp_sponsors, sponsor_tiers, ticket_types + ) self.create_prize_ticket(camp, ticket_types) teams[year] = self.create_camp_teams(camp) @@ -2336,7 +2367,9 @@ def bootstrap_camp(self, options: dict) -> None: self.create_camp_team_tasks(camp, teams) - team_memberships = self.create_camp_team_memberships(camp, teams, self.users) + team_memberships = self.create_camp_team_memberships( + camp, teams, self.users + ) self.create_camp_team_shifts(camp, teams, team_memberships) @@ -2383,7 +2416,9 @@ def bootstrap_camp(self, options: dict) -> None: facilities = self.create_facilities(facility_types) - self.create_facility_feedbacks(facilities, self.quickfeedback_options, self.users) + self.create_facility_feedbacks( + facilities, self.quickfeedback_options, self.users + ) info_categories = self.create_camp_info_categories(camp, teams) From 7e67bcb4707e08c2cceb4f394be4db0a671ad367 Mon Sep 17 00:00:00 2001 From: 0xUnicorn <17219001+0xUnicorn@users.noreply.github.com> Date: Sun, 6 Jul 2025 10:24:48 +0200 Subject: [PATCH 7/7] pre-commit --- src/camps/migrations/0039_camp_kickoff.py | 12 ++- ...mp_ticket_type_full_week_adult_and_more.py | 5 +- src/camps/models.py | 39 ++++---- src/camps/tests.py | 34 +++---- src/utils/bootstrap/base.py | 93 ++++++++++++------- 5 files changed, 101 insertions(+), 82 deletions(-) diff --git a/src/camps/migrations/0039_camp_kickoff.py b/src/camps/migrations/0039_camp_kickoff.py index 26d222268..476560237 100644 --- a/src/camps/migrations/0039_camp_kickoff.py +++ b/src/camps/migrations/0039_camp_kickoff.py @@ -1,19 +1,21 @@ # Generated by Django 4.2.21 on 2025-05-28 22:50 +from __future__ import annotations import django.contrib.postgres.fields.ranges from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('camps', '0038_alter_permission_options'), + ("camps", "0038_alter_permission_options"), ] operations = [ migrations.AddField( - model_name='camp', - name='kickoff', - field=django.contrib.postgres.fields.ranges.DateTimeRangeField(blank=True, help_text='The camp kickoff period.', null=True, verbose_name='Camp Kickoff'), + model_name="camp", + name="kickoff", + field=django.contrib.postgres.fields.ranges.DateTimeRangeField( + blank=True, help_text="The camp kickoff period.", null=True, verbose_name="Camp Kickoff" + ), ), ] diff --git a/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py b/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py index e1e7fe16e..dea7193d2 100644 --- a/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py +++ b/src/camps/migrations/0040_camp_ticket_type_full_week_adult_and_more.py @@ -1,11 +1,12 @@ # Generated by Django 4.2.21 on 2025-07-01 13:04 +from __future__ import annotations -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations +from django.db import models class Migration(migrations.Migration): - dependencies = [ ("tickets", "0028_alter_prizeticket_comment"), ("camps", "0039_camp_kickoff"), diff --git a/src/camps/models.py b/src/camps/models.py index 1a17c8a47..6c0aa881a 100644 --- a/src/camps/models.py +++ b/src/camps/models.py @@ -2,13 +2,13 @@ import logging from datetime import timedelta -from django.conf import settings from django.apps import apps -from django.contrib.postgres.fields import DateTimeRangeField +from django.conf import settings +from django.contrib.auth.models import Permission as DjangoPermission from django.contrib.contenttypes.models import ContentType +from django.contrib.postgres.fields import DateTimeRangeField from django.core.exceptions import ValidationError -from django.contrib.auth.models import Permission as DjangoPermission from django.db import models from django.urls import reverse from django.utils import timezone @@ -351,19 +351,19 @@ def checked_in_full_week_adults(self) -> int: """Return the count of full week adult tickets checked in""" shop_tickets = ( ShopTicket.objects.filter( - ticket_type=self.ticket_type_full_week_adult + ticket_type=self.ticket_type_full_week_adult, ).exclude(used_at=None) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( - ticket_type=self.ticket_type_full_week_adult + ticket_type=self.ticket_type_full_week_adult, ).exclude(used_at=None) ).count() prize_tickets = ( PrizeTicket.objects.filter( - ticket_type=self.ticket_type_full_week_adult + ticket_type=self.ticket_type_full_week_adult, ).exclude(used_at=None) ).count() @@ -374,19 +374,19 @@ def checked_in_full_week_children(self) -> int: """Return the count of full week children tickets checked in""" shop_tickets = ( ShopTicket.objects.filter( - ticket_type=self.ticket_type_full_week_child + ticket_type=self.ticket_type_full_week_child, ).exclude(used_at=None) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( - ticket_type=self.ticket_type_full_week_child + ticket_type=self.ticket_type_full_week_child, ).exclude(used_at=None) ).count() prize_tickets = ( PrizeTicket.objects.filter( - ticket_type=self.ticket_type_full_week_child + ticket_type=self.ticket_type_full_week_child, ).exclude(used_at=None) ).count() @@ -394,8 +394,7 @@ def checked_in_full_week_children(self) -> int: @property def checked_in_one_day_adults(self) -> int: - """ - Return the count of todays one day adult tickets checked in. + """Return the count of todays one day adult tickets checked in. Count tickets with a checked in timestamp from 0600-0600 next day. Reason being early arriving participants might get checked in before 10. @@ -411,19 +410,19 @@ def checked_in_one_day_adults(self) -> int: shop_tickets = ( ShopTicket.objects.filter( - ticket_type=self.ticket_type_one_day_adult + ticket_type=self.ticket_type_one_day_adult, ).filter(used_at__gte=start, used_at__lt=end) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( - ticket_type=self.ticket_type_one_day_adult + ticket_type=self.ticket_type_one_day_adult, ).filter(used_at__gte=start, used_at__lt=end) ).count() prize_tickets = ( PrizeTicket.objects.filter( - ticket_type=self.ticket_type_one_day_adult + ticket_type=self.ticket_type_one_day_adult, ).filter(used_at__gte=start, used_at__lt=end) ).count() @@ -431,8 +430,7 @@ def checked_in_one_day_adults(self) -> int: @property def checked_in_one_day_children(self) -> int: - """ - Return the count of todays one day children tickets checked in. + """Return the count of todays one day children tickets checked in. Count tickets with a checked in timestamp from 0600-0600 next day. Reason being early arriving participants might get checked in before 10. @@ -448,19 +446,19 @@ def checked_in_one_day_children(self) -> int: shop_tickets = ( ShopTicket.objects.filter( - ticket_type=self.ticket_type_one_day_child + ticket_type=self.ticket_type_one_day_child, ).filter(used_at__gte=start, used_at__lt=end) ).count() sponsor_tickets = ( SponsorTicket.objects.filter( - ticket_type=self.ticket_type_one_day_child + ticket_type=self.ticket_type_one_day_child, ).filter(used_at__gte=start, used_at__lt=end) ).count() prize_tickets = ( PrizeTicket.objects.filter( - ticket_type=self.ticket_type_one_day_child + ticket_type=self.ticket_type_one_day_child, ).filter(used_at__gte=start, used_at__lt=end) ).count() @@ -468,8 +466,7 @@ def checked_in_one_day_children(self) -> int: @property def participant_count(self) -> int: - """ - Retrieve the participant count for all used 'full week' tickets + """Retrieve the participant count for all used 'full week' tickets and todays used 'one day' tickets. """ return ( diff --git a/src/camps/tests.py b/src/camps/tests.py index d96054598..8a1911942 100644 --- a/src/camps/tests.py +++ b/src/camps/tests.py @@ -7,9 +7,9 @@ from django.utils import timezone from sponsors.models import Sponsor +from tickets.models import PrizeTicket from tickets.models import ShopTicket from tickets.models import SponsorTicket -from tickets.models import PrizeTicket from utils.tests import BornhackTestBase @@ -32,33 +32,33 @@ def setUp(self) -> None: self.full_week_adults = { # All tickets are created by bootstrapping "shop_tickets": ( ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( - ticket_type=self.camp.ticket_type_full_week_adult + ticket_type=self.camp.ticket_type_full_week_adult, ) ), "sponsor_tickets": ( SponsorTicket.objects.filter(ticket_type__camp=self.camp).filter( - ticket_type=self.camp.ticket_type_full_week_adult + ticket_type=self.camp.ticket_type_full_week_adult, ) ), "prize_tickets": ( PrizeTicket.objects.filter(ticket_type__camp=self.camp).filter( - ticket_type=self.camp.ticket_type_full_week_adult + ticket_type=self.camp.ticket_type_full_week_adult, ) ), } self.full_week_children = ( # ShopTickets created by bootstrapping ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( - ticket_type=self.camp.ticket_type_full_week_child + ticket_type=self.camp.ticket_type_full_week_child, ) ) self.one_day_adults = ( # ShopTickets created by bootstrapping ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( - ticket_type=self.camp.ticket_type_one_day_adult + ticket_type=self.camp.ticket_type_one_day_adult, ) ) self.one_day_children = ( # ShopTickets created by bootstrapping ShopTicket.objects.filter(ticket_type__camp=self.camp).filter( - ticket_type=self.camp.ticket_type_one_day_child + ticket_type=self.camp.ticket_type_one_day_child, ) ) @@ -83,9 +83,7 @@ def test_checked_in_full_week_children_shop_tickets(self) -> None: assert self.camp.checked_in_full_week_children == 1 def test_checked_in_full_week_children_with_sponsor_ticket(self) -> None: - """ - Test the return value of checked in full week children with sponsor ticket - """ + """Test the return value of checked in full week children with sponsor ticket""" sponsor = Sponsor.objects.all().first() SponsorTicket.objects.create( sponsor=sponsor, @@ -95,9 +93,7 @@ def test_checked_in_full_week_children_with_sponsor_ticket(self) -> None: assert self.camp.checked_in_full_week_children == 1 def test_checked_in_full_week_children_with_prize_ticket(self) -> None: - """ - Test the return value of checked in full week children with prize ticket - """ + """Test the return value of checked in full week children with prize ticket""" PrizeTicket.objects.create( user=self.users[0], ticket_type=self.camp.ticket_type_full_week_child, @@ -115,8 +111,7 @@ def test_checked_in_one_day_adults(self) -> None: assert self.camp.checked_in_one_day_adults == 2 def test_checked_in_one_day_adults_with_sponsor_ticket(self) -> None: - """ - Test the return value of checked in one day adults + """Test the return value of checked in one day adults with sponsor ticket today """ sponsor = Sponsor.objects.all().first() @@ -129,8 +124,7 @@ def test_checked_in_one_day_adults_with_sponsor_ticket(self) -> None: assert self.camp.checked_in_one_day_adults == 1 def test_checked_in_one_day_adults_with_prize_ticket(self) -> None: - """ - Test the return value of checked in one day adults + """Test the return value of checked in one day adults with prize ticket today """ PrizeTicket.objects.create( @@ -163,8 +157,7 @@ def test_checked_in_one_day_children(self) -> None: assert self.camp.checked_in_one_day_children == 2 def test_checked_in_one_day_children_with_sponsor_ticket(self) -> None: - """ - Test the return value of checked in one day children + """Test the return value of checked in one day children with sponsor ticket today """ sponsor = Sponsor.objects.all().first() @@ -177,8 +170,7 @@ def test_checked_in_one_day_children_with_sponsor_ticket(self) -> None: assert self.camp.checked_in_one_day_children == 1 def test_checked_in_one_day_children_with_prize_ticket(self) -> None: - """ - Test the return value of checked in one day children + """Test the return value of checked in one day children with prize ticket today """ PrizeTicket.objects.create( diff --git a/src/utils/bootstrap/base.py b/src/utils/bootstrap/base.py index 11bfef744..2cb76c6e4 100644 --- a/src/utils/bootstrap/base.py +++ b/src/utils/bootstrap/base.py @@ -338,7 +338,10 @@ def create_facilities(self, facility_types: dict) -> dict: return facilities def create_facility_feedbacks( - self, facilities: dict, options: dict, users: dict + self, + facilities: dict, + options: dict, + users: dict, ) -> None: """Create facility feedbacks.""" self.output("Creating facility feedbacks...") @@ -640,7 +643,10 @@ def create_camp_ticket_types(self, camp: Camp) -> dict: return types def create_camp_products( - self, camp: Camp, categories: dict, ticket_types: dict + self, + camp: Camp, + categories: dict, + ticket_types: dict, ) -> dict: """Create camp shop products.""" products = {} @@ -1058,7 +1064,10 @@ def create_camp_news(self, camp: Camp) -> None: ) def create_camp_event_sessions( - self, camp: Camp, event_types: dict, event_locations: dict + self, + camp: Camp, + event_types: dict, + event_locations: dict, ) -> None: """Create camp event sessions.""" self.output(f"Creating EventSessions for {camp}...") @@ -1090,8 +1099,7 @@ def create_camp_event_sessions( event_location=event_locations["bar_area"], when=( datetime(start.year, start.month, start.day, 22, 0, tzinfo=tz), - datetime(start.year, start.month, start.day, 22, 0, tzinfo=tz) - + timedelta(hours=3), + datetime(start.year, start.month, start.day, 22, 0, tzinfo=tz) + timedelta(hours=3), ), ) EventSession.objects.create( @@ -1129,7 +1137,12 @@ def create_camp_event_sessions( event_location=event_locations["speakers_tent"], when=( datetime( - day.lower.year, day.lower.month, day.lower.day, 20, 0, tzinfo=tz + day.lower.year, + day.lower.month, + day.lower.day, + 20, + 0, + tzinfo=tz, ), datetime( day.lower.year, @@ -1254,9 +1267,7 @@ class FakeForm: if not data: continue # 90% chance this speaker is available for any given chunk - form.cleaned_data[data["fieldname"]] = ( - random.randint(1, 100) < 90 - ) # noqa: PLR2004, S311 + form.cleaned_data[data["fieldname"]] = random.randint(1, 100) < 90 # print(f"saving availability for speaker {sp}: {form.cleaned_data}") save_speaker_availability(form, sp) @@ -1287,9 +1298,7 @@ def approve_event_proposals(self, camp: Camp) -> None: break else: # all speakers are approved, approve the event? always approve keynotes! - if ( - random.randint(1, 100) < 90 or ep.event_type.name == "Keynote" - ): # noqa: PLR2004, S311 + if random.randint(1, 100) < 90 or ep.event_type.name == "Keynote": ep.mark_as_approved() else: ep.mark_as_rejected() @@ -1535,7 +1544,10 @@ def create_camp_team_tasks(self, camp: Camp, teams: dict) -> None: ) def create_camp_team_memberships( - self, camp: Camp, teams: dict, users: dict + self, + camp: Camp, + teams: dict, + users: dict, ) -> dict: """Create camp team memberships.""" memberships = {} @@ -1651,7 +1663,10 @@ def create_camp_team_memberships( return memberships def create_camp_team_shifts( - self, camp: Camp, teams: dict, team_memberships: dict + self, + camp: Camp, + teams: dict, + team_memberships: dict, ) -> None: """Create camp team shifts.""" shifts = {} @@ -1902,7 +1917,7 @@ def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: description="Bus Trip", logo_filename="PROSA-logo.png", url="https://www.prosa.dk", - ) + ), ) sponsors.append( Sponsor.objects.create( @@ -1911,7 +1926,7 @@ def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: description="Speakers tent", logo_filename="DKUUGlogo.jpeg", url="http://www.dkuug.dk/", - ) + ), ) sponsors.append( Sponsor.objects.create( @@ -1920,7 +1935,7 @@ def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: description="Shuttle", logo_filename="letsgo.png", url="https://letsgo.dk", - ) + ), ) sponsors.append( Sponsor.objects.create( @@ -1929,7 +1944,7 @@ def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: description="Cash Sponsorship", logo_filename="saxobank.png", url="https://home.saxo", - ) + ), ) sponsors.append( Sponsor.objects.create( @@ -1938,37 +1953,39 @@ def create_camp_sponsors(self, camp: Camp, tiers: dict) -> list: description="Cash Sponsorship", logo_filename="CSIS_PRI_LOGO_TURQUOISE_RGB.jpg", url="https://csis.dk", - ) + ), ) return sponsors def create_camp_sponsor_tickets( - self, camp: Camp, sponsors: list, tiers: dict, ticket_types: dict + self, + camp: Camp, + sponsors: list, + tiers: dict, + ticket_types: dict, ) -> None: """Create tickets for camp sponsors""" year = camp.camp.lower.year self.output(f"Creating sponsor tickets for {year}...") for sponsor in sponsors: - if sponsor.tier == tiers["platinum"]: - for _ in range(10): - SponsorTicket.objects.create( - sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] - ) - elif sponsor.tier == tiers["gold"]: + if sponsor.tier == tiers["platinum"] or sponsor.tier == tiers["gold"]: for _ in range(10): SponsorTicket.objects.create( - sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + sponsor=sponsor, + ticket_type=ticket_types["adult_full_week"], ) elif sponsor.tier == tiers["silver"]: for _ in range(5): SponsorTicket.objects.create( - sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + sponsor=sponsor, + ticket_type=ticket_types["adult_full_week"], ) elif sponsor.tier == tiers["sponsor"]: for _ in range(2): SponsorTicket.objects.create( - sponsor=sponsor, ticket_type=ticket_types["adult_full_week"] + sponsor=sponsor, + ticket_type=ticket_types["adult_full_week"], ) def create_camp_tokens(self, camp: Camp) -> dict[Token]: @@ -2022,7 +2039,10 @@ def create_camp_tokens(self, camp: Camp) -> dict[Token]: return tokens def create_camp_token_finds( - self, camp: Camp, tokens: dict[Token], users: dict[User] + self, + camp: Camp, + tokens: dict[Token], + users: dict[User], ) -> None: """Create the camp token finds.""" year = camp.camp.lower.year @@ -2314,7 +2334,10 @@ def bootstrap_tests(self) -> None: sponsor_tiers = self.create_camp_sponsor_tiers(camp) camp_sponsors = self.create_camp_sponsors(camp, sponsor_tiers) self.create_camp_sponsor_tickets( - camp, camp_sponsors, sponsor_tiers, ticket_types + camp, + camp_sponsors, + sponsor_tiers, + ticket_types, ) self.create_prize_ticket(camp, ticket_types) @@ -2368,7 +2391,9 @@ def bootstrap_camp(self, options: dict) -> None: self.create_camp_team_tasks(camp, teams) team_memberships = self.create_camp_team_memberships( - camp, teams, self.users + camp, + teams, + self.users, ) self.create_camp_team_shifts(camp, teams, team_memberships) @@ -2417,7 +2442,9 @@ def bootstrap_camp(self, options: dict) -> None: facilities = self.create_facilities(facility_types) self.create_facility_feedbacks( - facilities, self.quickfeedback_options, self.users + facilities, + self.quickfeedback_options, + self.users, ) info_categories = self.create_camp_info_categories(camp, teams)