1
|
|
|
""" |
2
|
|
|
byceps.services.ticketing.ticket_bundle_service |
3
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
4
|
|
|
|
5
|
|
|
:Copyright: 2006-2020 Jochen Kupperschmidt |
6
|
|
|
:License: Modified BSD, see LICENSE for details. |
7
|
|
|
""" |
8
|
|
|
|
9
|
1 |
|
from typing import Optional, Sequence |
10
|
|
|
|
11
|
1 |
|
from ...database import db, Pagination |
12
|
1 |
|
from ...typing import PartyID, UserID |
13
|
|
|
|
14
|
1 |
|
from ..shop.order.transfer.models import OrderNumber |
15
|
|
|
|
16
|
1 |
|
from .models.category import Category as DbCategory |
17
|
1 |
|
from .models.ticket import Ticket as DbTicket |
18
|
1 |
|
from .models.ticket_bundle import TicketBundle as DbTicketBundle |
19
|
1 |
|
from .ticket_creation_service import build_tickets |
20
|
1 |
|
from .ticket_revocation_service import ( |
21
|
|
|
_build_ticket_revoked_event as build_ticket_revoked_event, |
22
|
|
|
) |
23
|
1 |
|
from .transfer.models import TicketBundleID, TicketCategoryID |
24
|
|
|
|
25
|
|
|
|
26
|
1 |
|
def create_bundle( |
27
|
|
|
category_id: TicketCategoryID, |
28
|
|
|
ticket_quantity: int, |
29
|
|
|
owned_by_id: UserID, |
30
|
|
|
*, |
31
|
|
|
order_number: Optional[OrderNumber] = None, |
32
|
|
|
) -> DbTicketBundle: |
33
|
|
|
"""Create a ticket bundle and the given quantity of tickets.""" |
34
|
1 |
|
if ticket_quantity < 1: |
35
|
|
|
raise ValueError('Ticket quantity must be positive.') |
36
|
|
|
|
37
|
1 |
|
bundle = DbTicketBundle(category_id, ticket_quantity, owned_by_id) |
38
|
1 |
|
db.session.add(bundle) |
39
|
|
|
|
40
|
1 |
|
tickets = list( |
41
|
|
|
build_tickets( |
42
|
|
|
category_id, |
43
|
|
|
owned_by_id, |
44
|
|
|
ticket_quantity, |
45
|
|
|
bundle=bundle, |
46
|
|
|
order_number=order_number, |
47
|
|
|
) |
48
|
|
|
) |
49
|
1 |
|
db.session.add_all(tickets) |
50
|
|
|
|
51
|
1 |
|
db.session.commit() |
52
|
|
|
|
53
|
1 |
|
return bundle |
54
|
|
|
|
55
|
|
|
|
56
|
1 |
|
def revoke_bundle( |
57
|
|
|
bundle_id: TicketBundleID, |
58
|
|
|
initiator_id: UserID, |
59
|
|
|
*, |
60
|
|
|
reason: Optional[str] = None, |
61
|
|
|
) -> None: |
62
|
|
|
"""Revoke the tickets included in this bundle.""" |
63
|
1 |
|
bundle = find_bundle(bundle_id) |
64
|
|
|
|
65
|
1 |
|
if bundle is None: |
66
|
|
|
raise ValueError('Unknown ticket bundle ID.') |
67
|
|
|
|
68
|
1 |
|
for ticket in bundle.tickets: |
69
|
1 |
|
ticket.revoked = True |
70
|
|
|
|
71
|
1 |
|
event = build_ticket_revoked_event(ticket.id, initiator_id, reason) |
72
|
1 |
|
db.session.add(event) |
73
|
|
|
|
74
|
1 |
|
db.session.commit() |
75
|
|
|
|
76
|
|
|
|
77
|
1 |
|
def delete_bundle(bundle_id: TicketBundleID) -> None: |
78
|
|
|
"""Delete a bundle and the tickets assigned to it.""" |
79
|
1 |
|
bundle = find_bundle(bundle_id) |
80
|
|
|
|
81
|
1 |
|
if bundle is None: |
82
|
|
|
raise ValueError('Unknown ticket bundle ID.') |
83
|
|
|
|
84
|
1 |
|
db.session.query(DbTicket) \ |
85
|
|
|
.filter_by(bundle_id=bundle_id) \ |
86
|
|
|
.delete() |
87
|
|
|
|
88
|
1 |
|
db.session.query(DbTicketBundle) \ |
89
|
|
|
.filter_by(id=bundle_id) \ |
90
|
|
|
.delete() |
91
|
|
|
|
92
|
1 |
|
db.session.commit() |
93
|
|
|
|
94
|
|
|
|
95
|
1 |
|
def find_bundle(bundle_id: TicketBundleID) -> Optional[DbTicketBundle]: |
96
|
|
|
"""Return the ticket bundle with that id, or `None` if not found.""" |
97
|
1 |
|
return DbTicketBundle.query.get(bundle_id) |
98
|
|
|
|
99
|
|
|
|
100
|
1 |
|
def find_tickets_for_bundle(bundle_id: TicketBundleID) -> Sequence[DbTicket]: |
101
|
|
|
"""Return all tickets included in this bundle.""" |
102
|
1 |
|
return DbTicket.query \ |
103
|
|
|
.filter(DbTicket.bundle_id == bundle_id) \ |
104
|
|
|
.all() |
105
|
|
|
|
106
|
|
|
|
107
|
1 |
|
def get_bundles_for_party_paginated( |
108
|
|
|
party_id: PartyID, page: int, per_page: int |
109
|
|
|
) -> Pagination: |
110
|
|
|
"""Return the party's ticket bundles to show on the specified page.""" |
111
|
1 |
|
return DbTicketBundle.query \ |
112
|
|
|
.join(DbCategory) \ |
113
|
|
|
.filter(DbCategory.party_id == party_id) \ |
114
|
|
|
.options( |
115
|
|
|
db.joinedload('ticket_category'), |
116
|
|
|
db.joinedload('owned_by'), |
117
|
|
|
) \ |
118
|
|
|
.order_by(DbTicketBundle.created_at.desc()) \ |
119
|
|
|
.paginate(page, per_page) |
120
|
|
|
|