We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Venue's Check-In Statuses page crashes
The "Venue's Check-In Statuses" page (Check-Ins -> Rooms' status) is empty, apart from the title element. Opening up devtools shows this error:

![image](https://user-images.githubusercontent.com/10998201/49333465-3ada3780-f5b7-11e8-8108-506d81922565.png)

Which points to this line:

![image](https://user-images.githubusercontent.com/10998201/49333471-57766f80-f5b7-11e8-9749-9fbd278a9d38.png)

This is a fresh installation on our own DigitalOcean server, and every other page works as expected. Running TabbyCat 2.2.7 on Ubuntu 18.04

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `tabbycat/checkins/views.py`
Content:
```
1 import json
2 
3 from asgiref.sync import async_to_sync
4 from channels.layers import get_channel_layer
5 from django.contrib import messages
6 from django.core.exceptions import ObjectDoesNotExist
7 from django.views.generic.base import TemplateView
8 from django.template.response import TemplateResponse
9 from django.utils.translation import gettext as _
10 
11 from actionlog.mixins import LogActionMixin
12 from actionlog.models import ActionLogEntry
13 from options.utils import use_team_code_names
14 from participants.models import Person, Speaker
15 from utils.misc import reverse_tournament
16 from utils.mixins import AdministratorMixin, AssistantMixin
17 from utils.views import PostOnlyRedirectView
18 from tournaments.mixins import PublicTournamentPageMixin, TournamentMixin
19 
20 from .consumers import CheckInEventConsumer
21 from .models import PersonIdentifier, VenueIdentifier
22 from .utils import create_identifiers, get_unexpired_checkins
23 
24 
25 class CheckInPreScanView(TournamentMixin, TemplateView):
26     template_name = 'checkin_scan.html'
27     page_title = _('Scan Identifiers')
28     page_emoji = '📷'
29 
30     def get_context_data(self, **kwargs):
31         kwargs["scan_url"] = self.tournament.slug + '/checkins/'
32         return super().get_context_data(**kwargs)
33 
34 
35 class AdminCheckInPreScanView(AdministratorMixin, CheckInPreScanView):
36     scan_view = 'admin-checkin-scan'
37 
38 
39 class AssistantCheckInPreScanView(AssistantMixin, CheckInPreScanView):
40     scan_view = 'assistant-checkin-scan'
41 
42 
43 class BaseCheckInStatusView(TournamentMixin, TemplateView):
44     template_name = 'checkin_status.html'
45     scan_view = False
46 
47     def get_context_data(self, **kwargs):
48         events = get_unexpired_checkins(self.tournament, self.window_preference)
49         kwargs["events"] = json.dumps([e.serialize() for e in events])
50         if self.scan_view:
51             kwargs["scan_url"] = self.tournament.slug + '/checkins/'
52         return super().get_context_data(**kwargs)
53 
54 
55 class CheckInPeopleStatusView(BaseCheckInStatusView):
56     page_emoji = '⌚️'
57     page_title = _("People's Check-In Statuses")
58     window_preference = 'checkin_window_people'
59 
60     def get_context_data(self, **kwargs):
61 
62         for_admin = True
63         if hasattr(self, '_user_role') and self._user_role == 'public':
64             for_admin = False
65         kwargs["for_admin"] = json.dumps(for_admin)
66 
67         team_codes = use_team_code_names(self.tournament, admin=for_admin)
68         kwargs["team_codes"] = json.dumps(team_codes)
69 
70         adjudicators = []
71         for adj in self.tournament.relevant_adjudicators.all().select_related('institution', 'checkin_identifier'):
72             try:
73                 code = adj.checkin_identifier.barcode
74             except ObjectDoesNotExist:
75                 code = None
76 
77             adjudicators.append({
78                 'id': adj.id, 'name': adj.name, 'type': 'Adjudicator',
79                 'identifier': [code], 'locked': False, 'independent': adj.independent,
80                 'institution': adj.institution.serialize if adj.institution else None,
81             })
82         kwargs["adjudicators"] = json.dumps(adjudicators)
83 
84         speakers = []
85         for speaker in Speaker.objects.filter(team__tournament=self.tournament).select_related('team', 'team__institution', 'checkin_identifier'):
86             try:
87                 code = speaker.checkin_identifier.barcode
88             except ObjectDoesNotExist:
89                 code = None
90 
91             speakers.append({
92                 'id': speaker.id, 'name': speaker.name, 'type': 'Speaker',
93                 'identifier': [code], 'locked': False,
94                 'team': speaker.team.code_name if team_codes else speaker.team.short_name,
95                 'institution': speaker.team.institution.serialize if speaker.team.institution else None,
96             })
97         kwargs["speakers"] = json.dumps(speakers)
98 
99         return super().get_context_data(**kwargs)
100 
101 
102 class AdminCheckInPeopleStatusView(AdministratorMixin, CheckInPeopleStatusView):
103     scan_view = 'admin-checkin-scan'
104 
105 
106 class AssistantCheckInPeopleStatusView(AssistantMixin, CheckInPeopleStatusView):
107     scan_view = 'assistant-checkin-scan'
108 
109 
110 class PublicCheckInPeopleStatusView(PublicTournamentPageMixin, CheckInPeopleStatusView):
111     public_page_preference = 'public_checkins'
112 
113 
114 class CheckInVenuesStatusView(BaseCheckInStatusView):
115     page_emoji = '👜'
116     page_title = _("Venue's Check-In Statuses")
117     window_preference = 'checkin_window_venues'
118 
119     def get_context_data(self, **kwargs):
120         venues = []
121         for venue in self.tournament.relevant_venues.select_related('checkin_identifier').prefetch_related('venuecategory_set').all():
122             item = venue.serialize()
123             item['locked'] = False
124             try:
125                 item['identifier'] = [venue.checkin_identifier.barcode]
126             except ObjectDoesNotExist:
127                 item['identifier'] = [None]
128             venues.append(item)
129         kwargs["venues"] = json.dumps(venues)
130         kwargs["team_codes"] = json.dumps(False)
131 
132         return super().get_context_data(**kwargs)
133 
134 
135 class AdminCheckInVenuesStatusView(AdministratorMixin, CheckInVenuesStatusView):
136     scan_view = 'admin-checkin-scan'
137 
138 
139 class AssistantCheckInVenuesStatusView(AssistantMixin, CheckInVenuesStatusView):
140     scan_view = 'assistant-checkin-scan'
141 
142 
143 class SegregatedCheckinsMixin(TournamentMixin):
144 
145     def t_speakers(self):
146         return Speaker.objects.filter(
147             team__tournament=self.tournament).values_list(
148             'person_ptr_id', flat=True)
149 
150     def speakers_with_barcodes(self):
151         identifiers = PersonIdentifier.objects.all()
152         return identifiers.filter(person_id__in=self.t_speakers())
153 
154     def t_adjs(self):
155         return self.tournament.adjudicator_set.values_list(
156             'person_ptr_id', flat=True)
157 
158     def adjs_with_barcodes(self):
159         identifiers = PersonIdentifier.objects.all()
160         return identifiers.filter(person_id__in=self.t_adjs())
161 
162 
163 class CheckInIdentifiersView(SegregatedCheckinsMixin, TemplateView):
164     template_name = 'checkin_ids.html'
165     page_title = _('Make Identifiers')
166     page_emoji = '📛'
167 
168     def get_context_data(self, **kwargs):
169         t = self.tournament
170         kwargs["check_in_info"] = {
171             "speakers": {
172                 "title": _("Speakers"),
173                 "total": self.t_speakers().count(),
174                 "in":  self.speakers_with_barcodes().count()
175             },
176             "adjudicators": {
177                 "title": _("Adjudicators"),
178                 "total": self.t_adjs().count(),
179                 "in":  self.adjs_with_barcodes().count()
180             },
181             "venues": {
182                 "title": _("Venues"),
183                 "total": t.venue_set.count(),
184                 "in":  VenueIdentifier.objects.filter(venue__tournament=t).count(),
185             }
186         }
187         return super().get_context_data(**kwargs)
188 
189 
190 class AdminCheckInIdentifiersView(AdministratorMixin, CheckInIdentifiersView):
191     pass
192 
193 
194 class AssistantCheckInIdentifiersView(AssistantMixin, CheckInIdentifiersView):
195     pass
196 
197 
198 class AdminCheckInGenerateView(AdministratorMixin, LogActionMixin,
199                                TournamentMixin, PostOnlyRedirectView):
200 
201     def get_action_log_type(self):
202         if self.kwargs["kind"] == "speakers":
203             return ActionLogEntry.ACTION_TYPE_CHECKIN_SPEAK_GENERATE
204         elif self.kwargs["kind"] == "adjudicators":
205             return ActionLogEntry.ACTION_TYPE_CHECKIN_ADJ_GENERATE
206         elif self.kwargs["kind"] == "venues":
207             return ActionLogEntry.ACTION_TYPE_CHECKIN_VENUES_GENERATE
208 
209     # Providing tournament_slug_url_kwarg isn't working for some reason; so use:
210     def get_redirect_url(self, *args, **kwargs):
211         return reverse_tournament('admin-checkin-identifiers', self.tournament)
212 
213     def post(self, request, *args, **kwargs):
214         t = self.tournament
215 
216         if self.kwargs["kind"] == "speakers":
217             create_identifiers(PersonIdentifier, Speaker.objects.filter(team__tournament=t))
218         elif self.kwargs["kind"] == "adjudicators":
219             create_identifiers(PersonIdentifier, t.adjudicator_set.all())
220         elif self.kwargs["kind"] == "venues":
221             create_identifiers(VenueIdentifier, t.venue_set.all())
222 
223         messages.success(request, _("Generated identifiers for %s" % self.kwargs["kind"]))
224         self.log_action()  # Need to call explicitly
225         return super().post(request, *args, **kwargs)
226 
227 
228 class CheckInPrintablesView(SegregatedCheckinsMixin, TemplateView):
229     template_name = 'checkin_printables.html'
230     page_title = _('Identifiers')
231     page_emoji = '📛'
232 
233     def get_context_data(self, **kwargs):
234         if self.kwargs["kind"] == "speakers":
235             kwargs["identifiers"] = self.speakers_with_barcodes().order_by('person__name')
236         elif self.kwargs["kind"] == "adjudicators":
237             kwargs["identifiers"] = self.adjs_with_barcodes().order_by('person__name')
238         elif self.kwargs["kind"] == "venues":
239             venues = self.tournament.relevant_venues
240             kwargs["identifiers"] = VenueIdentifier.objects.filter(venue__in=venues)
241 
242         return super().get_context_data(**kwargs)
243 
244 
245 class AdminCheckInPrintablesView(AdministratorMixin, CheckInPrintablesView):
246     pass
247 
248 
249 class AssistantCheckInPrintablesView(AssistantMixin, CheckInPrintablesView):
250     pass
251 
252 
253 class ParticipantCheckinView(PublicTournamentPageMixin, PostOnlyRedirectView):
254 
255     public_page_preference = 'public_checkins_submit'
256 
257     def post(self, request, *args, **kwargs):
258         t = self.tournament
259 
260         action = request.POST['action']
261 
262         try:
263             person = Person.objects.get(url_key=kwargs['url_key'])
264             identifier = PersonIdentifier.objects.get(person=person)
265         except ObjectDoesNotExist:
266             messages.error(self.request, _("Could not check you in as you do not have an identifying code — your tab director may need to make you an identifier."))
267             return super().post(request, *args, **kwargs)
268 
269         checkins = get_unexpired_checkins(t, 'checkin_window_people')
270         existing_checkin = checkins.filter(identifier=identifier)
271         if action == 'revoke':
272             if existing_checkin.exists():
273                 messages.success(self.request, _("You have revoked your check-in."))
274             else:
275                 messages.error(self.request, _("Whoops! Looks like your check-in was already revoked."))
276         elif action == 'checkin':
277             if existing_checkin.exists():
278                 messages.error(self.request, _("Whoops! Looks like you're already checked in."))
279             else:
280                 messages.success(self.request, _("You are now checked in."))
281         else:
282             return TemplateResponse(request=self.request, template='400.html', status=400)
283 
284         group_name = CheckInEventConsumer.group_prefix + "_" + t.slug
285 
286         # Override permissions check - no user but authenticated through URL
287         async_to_sync(get_channel_layer().group_send)(
288             group_name, {
289                 'type': 'broadcast_checkin',
290                 'content': {
291                     'barcodes': [identifier.barcode],
292                     'status': action == 'checkin',
293                     'type': 'people',
294                     'component_id': None
295                 }
296             }
297         )
298 
299         return super().post(request, *args, **kwargs)
300 
301     def get_redirect_url(self, *args, **kwargs):
302         return reverse_tournament('privateurls-person-index', self.tournament, kwargs={'url_key': kwargs['url_key']})
303
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/tabbycat/checkins/views.py b/tabbycat/checkins/views.py
--- a/tabbycat/checkins/views.py
+++ b/tabbycat/checkins/views.py
@@ -43,8 +43,12 @@
 class BaseCheckInStatusView(TournamentMixin, TemplateView):
     template_name = 'checkin_status.html'
     scan_view = False
+    for_admin = True
 
     def get_context_data(self, **kwargs):
+
+        kwargs["for_admin"] = json.dumps(self.for_admin)
+
         events = get_unexpired_checkins(self.tournament, self.window_preference)
         kwargs["events"] = json.dumps([e.serialize() for e in events])
         if self.scan_view:
@@ -59,12 +63,7 @@
 
     def get_context_data(self, **kwargs):
 
-        for_admin = True
-        if hasattr(self, '_user_role') and self._user_role == 'public':
-            for_admin = False
-        kwargs["for_admin"] = json.dumps(for_admin)
-
-        team_codes = use_team_code_names(self.tournament, admin=for_admin)
+        team_codes = use_team_code_names(self.tournament, admin=self.for_admin)
         kwargs["team_codes"] = json.dumps(team_codes)
 
         adjudicators = []
@@ -108,6 +107,7 @@
 
 
 class PublicCheckInPeopleStatusView(PublicTournamentPageMixin, CheckInPeopleStatusView):
+    for_admin = False
     public_page_preference = 'public_checkins'

{"golden_diff": "diff --git a/tabbycat/checkins/views.py b/tabbycat/checkins/views.py\n--- a/tabbycat/checkins/views.py\n+++ b/tabbycat/checkins/views.py\n@@ -43,8 +43,12 @@\n class BaseCheckInStatusView(TournamentMixin, TemplateView):\n     template_name = 'checkin_status.html'\n     scan_view = False\n+    for_admin = True\n \n     def get_context_data(self, **kwargs):\n+\n+        kwargs[\"for_admin\"] = json.dumps(self.for_admin)\n+\n         events = get_unexpired_checkins(self.tournament, self.window_preference)\n         kwargs[\"events\"] = json.dumps([e.serialize() for e in events])\n         if self.scan_view:\n@@ -59,12 +63,7 @@\n \n     def get_context_data(self, **kwargs):\n \n-        for_admin = True\n-        if hasattr(self, '_user_role') and self._user_role == 'public':\n-            for_admin = False\n-        kwargs[\"for_admin\"] = json.dumps(for_admin)\n-\n-        team_codes = use_team_code_names(self.tournament, admin=for_admin)\n+        team_codes = use_team_code_names(self.tournament, admin=self.for_admin)\n         kwargs[\"team_codes\"] = json.dumps(team_codes)\n \n         adjudicators = []\n@@ -108,6 +107,7 @@\n \n \n class PublicCheckInPeopleStatusView(PublicTournamentPageMixin, CheckInPeopleStatusView):\n+    for_admin = False\n     public_page_preference = 'public_checkins'\n", "issue": "Venue's Check-In Statuses page crashes\nThe \"Venue's Check-In Statuses\" page (Check-Ins -> Rooms' status) is empty, apart from the title element. Opening up devtools shows this error:\r\n\r\n![image](https://user-images.githubusercontent.com/10998201/49333465-3ada3780-f5b7-11e8-8108-506d81922565.png)\r\n\r\nWhich points to this line:\r\n\r\n![image](https://user-images.githubusercontent.com/10998201/49333471-57766f80-f5b7-11e8-9749-9fbd278a9d38.png)\r\n\r\nThis is a fresh installation on our own DigitalOcean server, and every other page works as expected. Running TabbyCat 2.2.7 on Ubuntu 18.04\n", "before_files": [{"content": "import json\n\nfrom asgiref.sync import async_to_sync\nfrom channels.layers import get_channel_layer\nfrom django.contrib import messages\nfrom django.core.exceptions import ObjectDoesNotExist\nfrom django.views.generic.base import TemplateView\nfrom django.template.response import TemplateResponse\nfrom django.utils.translation import gettext as _\n\nfrom actionlog.mixins import LogActionMixin\nfrom actionlog.models import ActionLogEntry\nfrom options.utils import use_team_code_names\nfrom participants.models import Person, Speaker\nfrom utils.misc import reverse_tournament\nfrom utils.mixins import AdministratorMixin, AssistantMixin\nfrom utils.views import PostOnlyRedirectView\nfrom tournaments.mixins import PublicTournamentPageMixin, TournamentMixin\n\nfrom .consumers import CheckInEventConsumer\nfrom .models import PersonIdentifier, VenueIdentifier\nfrom .utils import create_identifiers, get_unexpired_checkins\n\n\nclass CheckInPreScanView(TournamentMixin, TemplateView):\n    template_name = 'checkin_scan.html'\n    page_title = _('Scan Identifiers')\n    page_emoji = '\ud83d\udcf7'\n\n    def get_context_data(self, **kwargs):\n        kwargs[\"scan_url\"] = self.tournament.slug + '/checkins/'\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInPreScanView(AdministratorMixin, CheckInPreScanView):\n    scan_view = 'admin-checkin-scan'\n\n\nclass AssistantCheckInPreScanView(AssistantMixin, CheckInPreScanView):\n    scan_view = 'assistant-checkin-scan'\n\n\nclass BaseCheckInStatusView(TournamentMixin, TemplateView):\n    template_name = 'checkin_status.html'\n    scan_view = False\n\n    def get_context_data(self, **kwargs):\n        events = get_unexpired_checkins(self.tournament, self.window_preference)\n        kwargs[\"events\"] = json.dumps([e.serialize() for e in events])\n        if self.scan_view:\n            kwargs[\"scan_url\"] = self.tournament.slug + '/checkins/'\n        return super().get_context_data(**kwargs)\n\n\nclass CheckInPeopleStatusView(BaseCheckInStatusView):\n    page_emoji = '\u231a\ufe0f'\n    page_title = _(\"People's Check-In Statuses\")\n    window_preference = 'checkin_window_people'\n\n    def get_context_data(self, **kwargs):\n\n        for_admin = True\n        if hasattr(self, '_user_role') and self._user_role == 'public':\n            for_admin = False\n        kwargs[\"for_admin\"] = json.dumps(for_admin)\n\n        team_codes = use_team_code_names(self.tournament, admin=for_admin)\n        kwargs[\"team_codes\"] = json.dumps(team_codes)\n\n        adjudicators = []\n        for adj in self.tournament.relevant_adjudicators.all().select_related('institution', 'checkin_identifier'):\n            try:\n                code = adj.checkin_identifier.barcode\n            except ObjectDoesNotExist:\n                code = None\n\n            adjudicators.append({\n                'id': adj.id, 'name': adj.name, 'type': 'Adjudicator',\n                'identifier': [code], 'locked': False, 'independent': adj.independent,\n                'institution': adj.institution.serialize if adj.institution else None,\n            })\n        kwargs[\"adjudicators\"] = json.dumps(adjudicators)\n\n        speakers = []\n        for speaker in Speaker.objects.filter(team__tournament=self.tournament).select_related('team', 'team__institution', 'checkin_identifier'):\n            try:\n                code = speaker.checkin_identifier.barcode\n            except ObjectDoesNotExist:\n                code = None\n\n            speakers.append({\n                'id': speaker.id, 'name': speaker.name, 'type': 'Speaker',\n                'identifier': [code], 'locked': False,\n                'team': speaker.team.code_name if team_codes else speaker.team.short_name,\n                'institution': speaker.team.institution.serialize if speaker.team.institution else None,\n            })\n        kwargs[\"speakers\"] = json.dumps(speakers)\n\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInPeopleStatusView(AdministratorMixin, CheckInPeopleStatusView):\n    scan_view = 'admin-checkin-scan'\n\n\nclass AssistantCheckInPeopleStatusView(AssistantMixin, CheckInPeopleStatusView):\n    scan_view = 'assistant-checkin-scan'\n\n\nclass PublicCheckInPeopleStatusView(PublicTournamentPageMixin, CheckInPeopleStatusView):\n    public_page_preference = 'public_checkins'\n\n\nclass CheckInVenuesStatusView(BaseCheckInStatusView):\n    page_emoji = '\ud83d\udc5c'\n    page_title = _(\"Venue's Check-In Statuses\")\n    window_preference = 'checkin_window_venues'\n\n    def get_context_data(self, **kwargs):\n        venues = []\n        for venue in self.tournament.relevant_venues.select_related('checkin_identifier').prefetch_related('venuecategory_set').all():\n            item = venue.serialize()\n            item['locked'] = False\n            try:\n                item['identifier'] = [venue.checkin_identifier.barcode]\n            except ObjectDoesNotExist:\n                item['identifier'] = [None]\n            venues.append(item)\n        kwargs[\"venues\"] = json.dumps(venues)\n        kwargs[\"team_codes\"] = json.dumps(False)\n\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInVenuesStatusView(AdministratorMixin, CheckInVenuesStatusView):\n    scan_view = 'admin-checkin-scan'\n\n\nclass AssistantCheckInVenuesStatusView(AssistantMixin, CheckInVenuesStatusView):\n    scan_view = 'assistant-checkin-scan'\n\n\nclass SegregatedCheckinsMixin(TournamentMixin):\n\n    def t_speakers(self):\n        return Speaker.objects.filter(\n            team__tournament=self.tournament).values_list(\n            'person_ptr_id', flat=True)\n\n    def speakers_with_barcodes(self):\n        identifiers = PersonIdentifier.objects.all()\n        return identifiers.filter(person_id__in=self.t_speakers())\n\n    def t_adjs(self):\n        return self.tournament.adjudicator_set.values_list(\n            'person_ptr_id', flat=True)\n\n    def adjs_with_barcodes(self):\n        identifiers = PersonIdentifier.objects.all()\n        return identifiers.filter(person_id__in=self.t_adjs())\n\n\nclass CheckInIdentifiersView(SegregatedCheckinsMixin, TemplateView):\n    template_name = 'checkin_ids.html'\n    page_title = _('Make Identifiers')\n    page_emoji = '\ud83d\udcdb'\n\n    def get_context_data(self, **kwargs):\n        t = self.tournament\n        kwargs[\"check_in_info\"] = {\n            \"speakers\": {\n                \"title\": _(\"Speakers\"),\n                \"total\": self.t_speakers().count(),\n                \"in\":  self.speakers_with_barcodes().count()\n            },\n            \"adjudicators\": {\n                \"title\": _(\"Adjudicators\"),\n                \"total\": self.t_adjs().count(),\n                \"in\":  self.adjs_with_barcodes().count()\n            },\n            \"venues\": {\n                \"title\": _(\"Venues\"),\n                \"total\": t.venue_set.count(),\n                \"in\":  VenueIdentifier.objects.filter(venue__tournament=t).count(),\n            }\n        }\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInIdentifiersView(AdministratorMixin, CheckInIdentifiersView):\n    pass\n\n\nclass AssistantCheckInIdentifiersView(AssistantMixin, CheckInIdentifiersView):\n    pass\n\n\nclass AdminCheckInGenerateView(AdministratorMixin, LogActionMixin,\n                               TournamentMixin, PostOnlyRedirectView):\n\n    def get_action_log_type(self):\n        if self.kwargs[\"kind\"] == \"speakers\":\n            return ActionLogEntry.ACTION_TYPE_CHECKIN_SPEAK_GENERATE\n        elif self.kwargs[\"kind\"] == \"adjudicators\":\n            return ActionLogEntry.ACTION_TYPE_CHECKIN_ADJ_GENERATE\n        elif self.kwargs[\"kind\"] == \"venues\":\n            return ActionLogEntry.ACTION_TYPE_CHECKIN_VENUES_GENERATE\n\n    # Providing tournament_slug_url_kwarg isn't working for some reason; so use:\n    def get_redirect_url(self, *args, **kwargs):\n        return reverse_tournament('admin-checkin-identifiers', self.tournament)\n\n    def post(self, request, *args, **kwargs):\n        t = self.tournament\n\n        if self.kwargs[\"kind\"] == \"speakers\":\n            create_identifiers(PersonIdentifier, Speaker.objects.filter(team__tournament=t))\n        elif self.kwargs[\"kind\"] == \"adjudicators\":\n            create_identifiers(PersonIdentifier, t.adjudicator_set.all())\n        elif self.kwargs[\"kind\"] == \"venues\":\n            create_identifiers(VenueIdentifier, t.venue_set.all())\n\n        messages.success(request, _(\"Generated identifiers for %s\" % self.kwargs[\"kind\"]))\n        self.log_action()  # Need to call explicitly\n        return super().post(request, *args, **kwargs)\n\n\nclass CheckInPrintablesView(SegregatedCheckinsMixin, TemplateView):\n    template_name = 'checkin_printables.html'\n    page_title = _('Identifiers')\n    page_emoji = '\ud83d\udcdb'\n\n    def get_context_data(self, **kwargs):\n        if self.kwargs[\"kind\"] == \"speakers\":\n            kwargs[\"identifiers\"] = self.speakers_with_barcodes().order_by('person__name')\n        elif self.kwargs[\"kind\"] == \"adjudicators\":\n            kwargs[\"identifiers\"] = self.adjs_with_barcodes().order_by('person__name')\n        elif self.kwargs[\"kind\"] == \"venues\":\n            venues = self.tournament.relevant_venues\n            kwargs[\"identifiers\"] = VenueIdentifier.objects.filter(venue__in=venues)\n\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInPrintablesView(AdministratorMixin, CheckInPrintablesView):\n    pass\n\n\nclass AssistantCheckInPrintablesView(AssistantMixin, CheckInPrintablesView):\n    pass\n\n\nclass ParticipantCheckinView(PublicTournamentPageMixin, PostOnlyRedirectView):\n\n    public_page_preference = 'public_checkins_submit'\n\n    def post(self, request, *args, **kwargs):\n        t = self.tournament\n\n        action = request.POST['action']\n\n        try:\n            person = Person.objects.get(url_key=kwargs['url_key'])\n            identifier = PersonIdentifier.objects.get(person=person)\n        except ObjectDoesNotExist:\n            messages.error(self.request, _(\"Could not check you in as you do not have an identifying code \u2014 your tab director may need to make you an identifier.\"))\n            return super().post(request, *args, **kwargs)\n\n        checkins = get_unexpired_checkins(t, 'checkin_window_people')\n        existing_checkin = checkins.filter(identifier=identifier)\n        if action == 'revoke':\n            if existing_checkin.exists():\n                messages.success(self.request, _(\"You have revoked your check-in.\"))\n            else:\n                messages.error(self.request, _(\"Whoops! Looks like your check-in was already revoked.\"))\n        elif action == 'checkin':\n            if existing_checkin.exists():\n                messages.error(self.request, _(\"Whoops! Looks like you're already checked in.\"))\n            else:\n                messages.success(self.request, _(\"You are now checked in.\"))\n        else:\n            return TemplateResponse(request=self.request, template='400.html', status=400)\n\n        group_name = CheckInEventConsumer.group_prefix + \"_\" + t.slug\n\n        # Override permissions check - no user but authenticated through URL\n        async_to_sync(get_channel_layer().group_send)(\n            group_name, {\n                'type': 'broadcast_checkin',\n                'content': {\n                    'barcodes': [identifier.barcode],\n                    'status': action == 'checkin',\n                    'type': 'people',\n                    'component_id': None\n                }\n            }\n        )\n\n        return super().post(request, *args, **kwargs)\n\n    def get_redirect_url(self, *args, **kwargs):\n        return reverse_tournament('privateurls-person-index', self.tournament, kwargs={'url_key': kwargs['url_key']})\n", "path": "tabbycat/checkins/views.py"}], "after_files": [{"content": "import json\n\nfrom asgiref.sync import async_to_sync\nfrom channels.layers import get_channel_layer\nfrom django.contrib import messages\nfrom django.core.exceptions import ObjectDoesNotExist\nfrom django.views.generic.base import TemplateView\nfrom django.template.response import TemplateResponse\nfrom django.utils.translation import gettext as _\n\nfrom actionlog.mixins import LogActionMixin\nfrom actionlog.models import ActionLogEntry\nfrom options.utils import use_team_code_names\nfrom participants.models import Person, Speaker\nfrom utils.misc import reverse_tournament\nfrom utils.mixins import AdministratorMixin, AssistantMixin\nfrom utils.views import PostOnlyRedirectView\nfrom tournaments.mixins import PublicTournamentPageMixin, TournamentMixin\n\nfrom .consumers import CheckInEventConsumer\nfrom .models import PersonIdentifier, VenueIdentifier\nfrom .utils import create_identifiers, get_unexpired_checkins\n\n\nclass CheckInPreScanView(TournamentMixin, TemplateView):\n    template_name = 'checkin_scan.html'\n    page_title = _('Scan Identifiers')\n    page_emoji = '\ud83d\udcf7'\n\n    def get_context_data(self, **kwargs):\n        kwargs[\"scan_url\"] = self.tournament.slug + '/checkins/'\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInPreScanView(AdministratorMixin, CheckInPreScanView):\n    scan_view = 'admin-checkin-scan'\n\n\nclass AssistantCheckInPreScanView(AssistantMixin, CheckInPreScanView):\n    scan_view = 'assistant-checkin-scan'\n\n\nclass BaseCheckInStatusView(TournamentMixin, TemplateView):\n    template_name = 'checkin_status.html'\n    scan_view = False\n    for_admin = True\n\n    def get_context_data(self, **kwargs):\n\n        kwargs[\"for_admin\"] = json.dumps(self.for_admin)\n\n        events = get_unexpired_checkins(self.tournament, self.window_preference)\n        kwargs[\"events\"] = json.dumps([e.serialize() for e in events])\n        if self.scan_view:\n            kwargs[\"scan_url\"] = self.tournament.slug + '/checkins/'\n        return super().get_context_data(**kwargs)\n\n\nclass CheckInPeopleStatusView(BaseCheckInStatusView):\n    page_emoji = '\u231a\ufe0f'\n    page_title = _(\"People's Check-In Statuses\")\n    window_preference = 'checkin_window_people'\n\n    def get_context_data(self, **kwargs):\n\n        team_codes = use_team_code_names(self.tournament, admin=self.for_admin)\n        kwargs[\"team_codes\"] = json.dumps(team_codes)\n\n        adjudicators = []\n        for adj in self.tournament.relevant_adjudicators.all().select_related('institution', 'checkin_identifier'):\n            try:\n                code = adj.checkin_identifier.barcode\n            except ObjectDoesNotExist:\n                code = None\n\n            adjudicators.append({\n                'id': adj.id, 'name': adj.name, 'type': 'Adjudicator',\n                'identifier': [code], 'locked': False, 'independent': adj.independent,\n                'institution': adj.institution.serialize if adj.institution else None,\n            })\n        kwargs[\"adjudicators\"] = json.dumps(adjudicators)\n\n        speakers = []\n        for speaker in Speaker.objects.filter(team__tournament=self.tournament).select_related('team', 'team__institution', 'checkin_identifier'):\n            try:\n                code = speaker.checkin_identifier.barcode\n            except ObjectDoesNotExist:\n                code = None\n\n            speakers.append({\n                'id': speaker.id, 'name': speaker.name, 'type': 'Speaker',\n                'identifier': [code], 'locked': False,\n                'team': speaker.team.code_name if team_codes else speaker.team.short_name,\n                'institution': speaker.team.institution.serialize if speaker.team.institution else None,\n            })\n        kwargs[\"speakers\"] = json.dumps(speakers)\n\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInPeopleStatusView(AdministratorMixin, CheckInPeopleStatusView):\n    scan_view = 'admin-checkin-scan'\n\n\nclass AssistantCheckInPeopleStatusView(AssistantMixin, CheckInPeopleStatusView):\n    scan_view = 'assistant-checkin-scan'\n\n\nclass PublicCheckInPeopleStatusView(PublicTournamentPageMixin, CheckInPeopleStatusView):\n    for_admin = False\n    public_page_preference = 'public_checkins'\n\n\nclass CheckInVenuesStatusView(BaseCheckInStatusView):\n    page_emoji = '\ud83d\udc5c'\n    page_title = _(\"Venue's Check-In Statuses\")\n    window_preference = 'checkin_window_venues'\n\n    def get_context_data(self, **kwargs):\n        venues = []\n        for venue in self.tournament.relevant_venues.select_related('checkin_identifier').prefetch_related('venuecategory_set').all():\n            item = venue.serialize()\n            item['locked'] = False\n            try:\n                item['identifier'] = [venue.checkin_identifier.barcode]\n            except ObjectDoesNotExist:\n                item['identifier'] = [None]\n            venues.append(item)\n        kwargs[\"venues\"] = json.dumps(venues)\n        kwargs[\"team_codes\"] = json.dumps(False)\n\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInVenuesStatusView(AdministratorMixin, CheckInVenuesStatusView):\n    scan_view = 'admin-checkin-scan'\n\n\nclass AssistantCheckInVenuesStatusView(AssistantMixin, CheckInVenuesStatusView):\n    scan_view = 'assistant-checkin-scan'\n\n\nclass SegregatedCheckinsMixin(TournamentMixin):\n\n    def t_speakers(self):\n        return Speaker.objects.filter(\n            team__tournament=self.tournament).values_list(\n            'person_ptr_id', flat=True)\n\n    def speakers_with_barcodes(self):\n        identifiers = PersonIdentifier.objects.all()\n        return identifiers.filter(person_id__in=self.t_speakers())\n\n    def t_adjs(self):\n        return self.tournament.adjudicator_set.values_list(\n            'person_ptr_id', flat=True)\n\n    def adjs_with_barcodes(self):\n        identifiers = PersonIdentifier.objects.all()\n        return identifiers.filter(person_id__in=self.t_adjs())\n\n\nclass CheckInIdentifiersView(SegregatedCheckinsMixin, TemplateView):\n    template_name = 'checkin_ids.html'\n    page_title = _('Make Identifiers')\n    page_emoji = '\ud83d\udcdb'\n\n    def get_context_data(self, **kwargs):\n        t = self.tournament\n        kwargs[\"check_in_info\"] = {\n            \"speakers\": {\n                \"title\": _(\"Speakers\"),\n                \"total\": self.t_speakers().count(),\n                \"in\":  self.speakers_with_barcodes().count()\n            },\n            \"adjudicators\": {\n                \"title\": _(\"Adjudicators\"),\n                \"total\": self.t_adjs().count(),\n                \"in\":  self.adjs_with_barcodes().count()\n            },\n            \"venues\": {\n                \"title\": _(\"Venues\"),\n                \"total\": t.venue_set.count(),\n                \"in\":  VenueIdentifier.objects.filter(venue__tournament=t).count(),\n            }\n        }\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInIdentifiersView(AdministratorMixin, CheckInIdentifiersView):\n    pass\n\n\nclass AssistantCheckInIdentifiersView(AssistantMixin, CheckInIdentifiersView):\n    pass\n\n\nclass AdminCheckInGenerateView(AdministratorMixin, LogActionMixin,\n                               TournamentMixin, PostOnlyRedirectView):\n\n    def get_action_log_type(self):\n        if self.kwargs[\"kind\"] == \"speakers\":\n            return ActionLogEntry.ACTION_TYPE_CHECKIN_SPEAK_GENERATE\n        elif self.kwargs[\"kind\"] == \"adjudicators\":\n            return ActionLogEntry.ACTION_TYPE_CHECKIN_ADJ_GENERATE\n        elif self.kwargs[\"kind\"] == \"venues\":\n            return ActionLogEntry.ACTION_TYPE_CHECKIN_VENUES_GENERATE\n\n    # Providing tournament_slug_url_kwarg isn't working for some reason; so use:\n    def get_redirect_url(self, *args, **kwargs):\n        return reverse_tournament('admin-checkin-identifiers', self.tournament)\n\n    def post(self, request, *args, **kwargs):\n        t = self.tournament\n\n        if self.kwargs[\"kind\"] == \"speakers\":\n            create_identifiers(PersonIdentifier, Speaker.objects.filter(team__tournament=t))\n        elif self.kwargs[\"kind\"] == \"adjudicators\":\n            create_identifiers(PersonIdentifier, t.adjudicator_set.all())\n        elif self.kwargs[\"kind\"] == \"venues\":\n            create_identifiers(VenueIdentifier, t.venue_set.all())\n\n        messages.success(request, _(\"Generated identifiers for %s\" % self.kwargs[\"kind\"]))\n        self.log_action()  # Need to call explicitly\n        return super().post(request, *args, **kwargs)\n\n\nclass CheckInPrintablesView(SegregatedCheckinsMixin, TemplateView):\n    template_name = 'checkin_printables.html'\n    page_title = _('Identifiers')\n    page_emoji = '\ud83d\udcdb'\n\n    def get_context_data(self, **kwargs):\n        if self.kwargs[\"kind\"] == \"speakers\":\n            kwargs[\"identifiers\"] = self.speakers_with_barcodes().order_by('person__name')\n        elif self.kwargs[\"kind\"] == \"adjudicators\":\n            kwargs[\"identifiers\"] = self.adjs_with_barcodes().order_by('person__name')\n        elif self.kwargs[\"kind\"] == \"venues\":\n            venues = self.tournament.relevant_venues\n            kwargs[\"identifiers\"] = VenueIdentifier.objects.filter(venue__in=venues)\n\n        return super().get_context_data(**kwargs)\n\n\nclass AdminCheckInPrintablesView(AdministratorMixin, CheckInPrintablesView):\n    pass\n\n\nclass AssistantCheckInPrintablesView(AssistantMixin, CheckInPrintablesView):\n    pass\n\n\nclass ParticipantCheckinView(PublicTournamentPageMixin, PostOnlyRedirectView):\n\n    public_page_preference = 'public_checkins_submit'\n\n    def post(self, request, *args, **kwargs):\n        t = self.tournament\n\n        action = request.POST['action']\n\n        try:\n            person = Person.objects.get(url_key=kwargs['url_key'])\n            identifier = PersonIdentifier.objects.get(person=person)\n        except ObjectDoesNotExist:\n            messages.error(self.request, _(\"Could not check you in as you do not have an identifying code \u2014 your tab director may need to make you an identifier.\"))\n            return super().post(request, *args, **kwargs)\n\n        checkins = get_unexpired_checkins(t, 'checkin_window_people')\n        existing_checkin = checkins.filter(identifier=identifier)\n        if action == 'revoke':\n            if existing_checkin.exists():\n                messages.success(self.request, _(\"You have revoked your check-in.\"))\n            else:\n                messages.error(self.request, _(\"Whoops! Looks like your check-in was already revoked.\"))\n        elif action == 'checkin':\n            if existing_checkin.exists():\n                messages.error(self.request, _(\"Whoops! Looks like you're already checked in.\"))\n            else:\n                messages.success(self.request, _(\"You are now checked in.\"))\n        else:\n            return TemplateResponse(request=self.request, template='400.html', status=400)\n\n        group_name = CheckInEventConsumer.group_prefix + \"_\" + t.slug\n\n        # Override permissions check - no user but authenticated through URL\n        async_to_sync(get_channel_layer().group_send)(\n            group_name, {\n                'type': 'broadcast_checkin',\n                'content': {\n                    'barcodes': [identifier.barcode],\n                    'status': action == 'checkin',\n                    'type': 'people',\n                    'component_id': None\n                }\n            }\n        )\n\n        return super().post(request, *args, **kwargs)\n\n    def get_redirect_url(self, *args, **kwargs):\n        return reverse_tournament('privateurls-person-index', self.tournament, kwargs={'url_key': kwargs['url_key']})\n", "path": "tabbycat/checkins/views.py"}]}