release_seat()   B
last analyzed

Complexity

Conditions 6

Size

Total Lines 51
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 28.6671

Importance

Changes 0
Metric Value
cc 6
eloc 35
nop 1
dl 0
loc 51
ccs 3
cts 21
cp 0.1429
crap 28.6671
rs 8.1066
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
"""
2
byceps.blueprints.site.seating.views
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2021 Jochen Kupperschmidt
6
:License: Revised BSD (see `LICENSE` file for details)
7
"""
8
9 1
from flask import abort, g, request
10 1
from flask_babel import gettext
11
12 1
from ....services.party import service as party_service
13 1
from ....services.seating import area_service as seating_area_service
14 1
from ....services.seating import seat_service
15 1
from ....services.seating.transfer.models import Seat, SeatID
16 1
from ....services.ticketing.dbmodels.ticket import Ticket as DbTicket
17 1
from ....services.ticketing import (
18
    exceptions as ticket_exceptions,
19
    ticket_seat_management_service,
20
    ticket_service,
21
)
22 1
from ....services.ticketing.transfer.models import TicketID
23 1
from ....util.authorization import has_current_user_permission
24 1
from ....util.framework.blueprint import create_blueprint
25 1
from ....util.framework.flash import flash_error, flash_success
26 1
from ....util.framework.templating import templated
27 1
from ....util.views import login_required, redirect_to, respond_no_content
28
29 1
from . import service
30
31
32 1
blueprint = create_blueprint('seating', __name__)
33
34
35 1
@blueprint.get('/')
36 1
@templated
37
def index():
38
    """List areas."""
39
    if g.party_id is None:
40
        # No party is configured for the current site.
41
        abort(404)
42
43
    areas = seating_area_service.get_areas_for_party(g.party_id)
44
45
    return {
46
        'areas': areas,
47
    }
48
49
50 1
@blueprint.get('/areas/<slug>')
51 1
@templated
52
def view_area(slug):
53
    """View area."""
54
    if g.party_id is None:
55
        # No party is configured for the current site.
56
        abort(404)
57
58
    area = seating_area_service.find_area_for_party_by_slug(g.party_id, slug)
59
    if area is None:
60
        abort(404)
61
62
    seat_management_enabled = _is_seat_management_enabled()
63
64
    seats_with_tickets = seat_service.get_seats_with_tickets_for_area(area.id)
65
66
    users_by_id = service.get_users(seats_with_tickets, [])
67
68
    seats_and_tickets = service.get_seats_and_tickets(
69
        seats_with_tickets, users_by_id
70
    )
71
72
    return {
73
        'area': area,
74
        'seat_management_enabled': seat_management_enabled,
75
        'seats_and_tickets': seats_and_tickets,
76
        'manage_mode': False,
77
    }
78
79
80 1
@blueprint.get('/areas/<slug>/manage_seats')
81 1
@login_required
82 1
@templated('site/seating/view_area')
83
def manage_seats_in_area(slug):
84
    """Manage seats for assigned tickets in area."""
85
    if not _is_seat_management_enabled():
86
        flash_error(
87
            gettext('Seat reservations cannot be changed at this time.')
88
        )
89
        return redirect_to('.view_area', slug=slug)
90
91
    area = seating_area_service.find_area_for_party_by_slug(g.party_id, slug)
92
    if area is None:
93
        abort(404)
94
95
    seat_management_enabled = _is_seat_management_enabled()
96
97
    seat_manager_id = None
98
    selected_ticket_id = None
99
    selected_ticket = None
100
101
    if _is_current_user_seating_admin():
102
        selected_ticket = _get_selected_ticket()
103
        if selected_ticket is not None:
104
            seat_manager_id = selected_ticket.get_seat_manager().id
105
            selected_ticket_id = selected_ticket.id
106
        elif seat_management_enabled:
107
            seat_manager_id = g.user.id
108
109
    elif seat_management_enabled:
110
        seat_manager_id = g.user.id
111
112
    seats_with_tickets = seat_service.get_seats_with_tickets_for_area(area.id)
113
114
    if seat_manager_id is not None:
115
        tickets = ticket_service.find_tickets_for_seat_manager(
116
            seat_manager_id, g.party_id
117
        )
118
    else:
119
        tickets = []
120
121
    users_by_id = service.get_users(seats_with_tickets, tickets)
122
123
    seats_and_tickets = service.get_seats_and_tickets(
124
        seats_with_tickets, users_by_id
125
    )
126
127
    if seat_management_enabled:
128
        managed_tickets = list(
129
            service.get_managed_tickets(tickets, users_by_id)
130
        )
131
    else:
132
        managed_tickets = []
133
134
    return {
135
        'area': area,
136
        'seats_and_tickets': seats_and_tickets,
137
        'manage_mode': True,
138
        'seat_management_enabled': seat_management_enabled,
139
        'managed_tickets': managed_tickets,
140
        'selected_ticket_id': selected_ticket_id,
141
    }
142
143
144 1
def _get_selected_ticket():
145
    selected_ticket = None
146
147
    selected_ticket_id_arg = request.args.get('ticket_id')
148
    if selected_ticket_id_arg:
149
        selected_ticket = ticket_service.find_ticket(selected_ticket_id_arg)
150
        if selected_ticket is None:
151
            flash_error(
152
                gettext(
153
                    'Ticket ID "%(selected_ticket_id_arg)s" not found.',
154
                    selected_ticket_id_arg=selected_ticket_id_arg,
155
                )
156
            )
157
158
    if (selected_ticket is not None) and selected_ticket.revoked:
159
        flash_error(
160
            gettext(
161
                'Ticket "%(selected_ticket_code)s" is revoked.',
162
                selected_ticket_code=selected_ticket.code,
163
            )
164
        )
165
        selected_ticket = None
166
167
    return selected_ticket
168
169
170 1
@blueprint.post('/ticket/<uuid:ticket_id>/seat/<uuid:seat_id>')
171 1
@login_required
172 1
@respond_no_content
173
def occupy_seat(ticket_id, seat_id):
174
    """Use ticket to occupy seat."""
175
    if not _is_seat_management_enabled():
176
        flash_error(
177
            gettext('Seat reservations cannot be changed at this time.')
178
        )
179
        return
180
181
    ticket = _get_ticket_or_404(ticket_id)
182
183
    manager = g.user
184
185
    if (
186
        not ticket.is_seat_managed_by(manager.id)
187
        and not _is_current_user_seating_admin()
188
    ):
189
        flash_error(
190
            gettext(
191
                'You are not authorized to manage the seat for ticket %(ticket_code)s.',
192
                ticket_code=ticket.code,
193
            )
194
        )
195
        return
196
197
    seat = _get_seat_or_404(seat_id)
198
199
    if ticket_service.find_ticket_occupying_seat(seat.id) is not None:
200
        flash_error(
201
            gettext(
202
                '%(seat_label)s is already occupied.', seat_label=seat.label
203
            )
204
        )
205
        return
206
207
    try:
208
        ticket_seat_management_service.occupy_seat(
209
            ticket.id, seat.id, manager.id
210
        )
211
    except ticket_exceptions.SeatChangeDeniedForBundledTicket:
212
        flash_error(
213
            gettext(
214
                'Ticket %(ticket_code)s belongs to a bundle and cannot be managed separately.',
215
                ticket_code=ticket.code,
216
            )
217
        )
218
        return
219
    except ticket_exceptions.TicketCategoryMismatch:
220
        flash_error(
221
            gettext(
222
                'Ticket %(ticket_code)s and seat "%(seat_label)s" belong to different categories.',
223
                ticket_code=ticket.code,
224
                seat_label=seat.label,
225
            )
226
        )
227
        return
228
    except ValueError:
229
        abort(404)
230
231
    flash_success(
232
        gettext(
233
            '%(seat_label)s has been occupied with ticket %(ticket_code)s.',
234
            seat_label=seat.label,
235
            ticket_code=ticket.code,
236
        )
237
    )
238
239
240 1
@blueprint.delete('/ticket/<uuid:ticket_id>/seat')
241 1
@login_required
242 1
@respond_no_content
243
def release_seat(ticket_id):
244
    """Release the seat."""
245
    if not _is_seat_management_enabled():
246
        flash_error(
247
            gettext('Seat reservations cannot be changed at this time.')
248
        )
249
        return
250
251
    ticket = _get_ticket_or_404(ticket_id)
252
253
    if not ticket.occupied_seat:
254
        flash_error(
255
            gettext(
256
                'Ticket %(ticket_code)s occupies no seat.',
257
                ticket_code=ticket.code,
258
            )
259
        )
260
        return
261
262
    manager = g.user
263
264
    if (
265
        not ticket.is_seat_managed_by(manager.id)
266
        and not _is_current_user_seating_admin()
267
    ):
268
        flash_error(
269
            gettext(
270
                'You are not authorized to manage the seat for ticket %(ticket_code)s.',
271
                ticket_code=ticket.code,
272
            )
273
        )
274
        return
275
276
    seat = ticket.occupied_seat
277
278
    try:
279
        ticket_seat_management_service.release_seat(ticket.id, manager.id)
280
    except ticket_exceptions.SeatChangeDeniedForBundledTicket:
281
        flash_error(
282
            gettext(
283
                'Ticket %(ticket_code)s belongs to a bundle and cannot be managed separately.',
284
                ticket_code=ticket.code,
285
            )
286
        )
287
        return
288
289
    flash_success(
290
        gettext('%(seat_label)s has been released.', seat_label=seat.label)
291
    )
292
293
294 1
def _is_seat_management_enabled():
295
    if not g.user.authenticated:
296
        return False
297
298
    if g.party_id is None:
299
        return False
300
301
    if _is_current_user_seating_admin():
302
        return True
303
304
    party = party_service.get_party(g.party_id)
305
    return party.seat_management_enabled
306
307
308 1
def _is_current_user_seating_admin() -> bool:
309
    return has_current_user_permission('seating.administrate')
310
311
312 1
def _get_ticket_or_404(ticket_id: TicketID) -> DbTicket:
313
    ticket = ticket_service.find_ticket(ticket_id)
314
315
    if (ticket is None) or ticket.revoked:
316
        abort(404)
317
318
    return ticket
319
320
321 1
def _get_seat_or_404(seat_id: SeatID) -> Seat:
322
    seat = seat_service.find_seat(seat_id)
323
324
    if seat is None:
325
        abort(404)
326
327
    return seat
328