1 | """ |
||
2 | byceps.blueprints.admin.shop.order.service |
||
3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
||
4 | |||
5 | :Copyright: 2006-2020 Jochen Kupperschmidt |
||
6 | :License: Modified BSD, see LICENSE for details. |
||
7 | """ |
||
8 | |||
9 | from dataclasses import dataclass |
||
10 | from typing import Dict, Iterator, Sequence |
||
11 | |||
12 | from .....services.shop.article.models.article import Article |
||
13 | from .....services.shop.article import service as article_service |
||
14 | from .....services.shop.article.transfer.models import ArticleNumber |
||
15 | from .....services.shop.order.models.order_event import ( |
||
16 | OrderEvent, |
||
17 | OrderEventData, |
||
18 | ) |
||
19 | from .....services.shop.order import event_service as order_event_service |
||
20 | from .....services.shop.order import service as order_service |
||
21 | from .....services.shop.order.transfer.models import Order, OrderID |
||
22 | from .....services.ticketing import category_service as ticket_category_service |
||
23 | from .....services.user.models.user import User as DbUser |
||
24 | from .....services.user import service as user_service |
||
25 | from .....services.user.transfer.models import User |
||
26 | from .....services.user_badge import service as user_badge_service |
||
27 | from .....typing import UserID |
||
28 | |||
29 | |||
30 | @dataclass(frozen=True) |
||
31 | class OrderWithOrderer(Order): |
||
32 | placed_by: DbUser |
||
33 | |||
34 | |||
35 | def extend_order_tuples_with_orderer( |
||
36 | orders: Sequence[Order] |
||
37 | ) -> Iterator[OrderWithOrderer]: |
||
38 | orderer_ids = {order.placed_by_id for order in orders} |
||
39 | orderers = user_service.find_users(orderer_ids, include_avatars=True) |
||
40 | orderers_by_id = user_service.index_users_by_id(orderers) |
||
41 | |||
42 | for order in orders: |
||
43 | orderer = orderers_by_id[order.placed_by_id] |
||
44 | values = attr.astuple(order, recurse=False) + (orderer,) |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Loading history...
|
|||
45 | yield OrderWithOrderer(*values) |
||
46 | |||
47 | |||
48 | def get_articles_by_item_number(order: Order) -> Dict[ArticleNumber, Article]: |
||
49 | numbers = {item.article_number for item in order.items} |
||
50 | |||
51 | articles = article_service.get_articles_by_numbers(numbers) |
||
52 | |||
53 | return {article.item_number: article for article in articles} |
||
54 | |||
55 | |||
56 | def get_events(order_id: OrderID) -> Iterator[OrderEventData]: |
||
57 | events = order_event_service.get_events_for_order(order_id) |
||
58 | events.insert(0, _fake_order_placement_event(order_id)) |
||
59 | |||
60 | user_ids = { |
||
61 | event.data['initiator_id'] |
||
62 | for event in events |
||
63 | if 'initiator_id' in event.data |
||
64 | } |
||
65 | users = user_service.find_users(user_ids, include_avatars=True) |
||
66 | users_by_id = {str(user.id): user for user in users} |
||
67 | |||
68 | for event in events: |
||
69 | data = { |
||
70 | 'event': event.event_type, |
||
71 | 'occurred_at': event.occurred_at, |
||
72 | 'data': event.data, |
||
73 | } |
||
74 | |||
75 | additional_data = _get_additional_data(event, users_by_id) |
||
76 | data.update(additional_data) |
||
77 | |||
78 | yield data |
||
79 | |||
80 | |||
81 | def _fake_order_placement_event(order_id: OrderID) -> OrderEvent: |
||
82 | order = order_service.find_order_with_details(order_id) |
||
83 | if order is None: |
||
84 | raise ValueError('Unknown order ID') |
||
85 | |||
86 | data = { |
||
87 | 'initiator_id': str(order.placed_by_id), |
||
88 | } |
||
89 | |||
90 | return OrderEvent(order.created_at, 'order-placed', order.id, data) |
||
91 | |||
92 | |||
93 | def _get_additional_data( |
||
94 | event: OrderEvent, users_by_id: Dict[UserID, User] |
||
95 | ) -> OrderEventData: |
||
96 | if event.event_type == 'badge-awarded': |
||
97 | return _get_additional_data_for_badge_awarded(event) |
||
98 | elif event.event_type == 'ticket-bundle-created': |
||
99 | return _get_additional_data_for_ticket_bundle_created(event) |
||
100 | elif event.event_type == 'ticket-bundle-revoked': |
||
101 | return _get_additional_data_for_ticket_bundle_revoked( |
||
102 | event, users_by_id |
||
103 | ) |
||
104 | elif event.event_type == 'ticket-created': |
||
105 | return _get_additional_data_for_ticket_created(event) |
||
106 | elif event.event_type == 'ticket-revoked': |
||
107 | return _get_additional_data_for_ticket_revoked(event, users_by_id) |
||
108 | else: |
||
109 | return _get_additional_data_for_standard_event(event, users_by_id) |
||
110 | |||
111 | |||
112 | def _get_additional_data_for_standard_event( |
||
113 | event: OrderEvent, users_by_id: Dict[UserID, User] |
||
114 | ) -> OrderEventData: |
||
115 | initiator_id = event.data['initiator_id'] |
||
116 | |||
117 | return { |
||
118 | 'initiator': users_by_id[initiator_id], |
||
119 | } |
||
120 | |||
121 | |||
122 | def _get_additional_data_for_badge_awarded(event: OrderEvent) -> OrderEventData: |
||
123 | badge_id = event.data['badge_id'] |
||
124 | badge = user_badge_service.find_badge(badge_id) |
||
125 | |||
126 | recipient_id = event.data['recipient_id'] |
||
127 | recipient = user_service.find_user(recipient_id) |
||
128 | recipient = _to_user_dto(recipient) |
||
129 | |||
130 | return { |
||
131 | 'badge_label': badge.label, |
||
132 | 'recipient': recipient, |
||
133 | } |
||
134 | |||
135 | |||
136 | def _get_additional_data_for_ticket_bundle_created( |
||
137 | event: OrderEvent |
||
138 | ) -> OrderEventData: |
||
139 | bundle_id = event.data['ticket_bundle_id'] |
||
140 | category_id = event.data['ticket_bundle_category_id'] |
||
141 | ticket_quantity = event.data['ticket_bundle_ticket_quantity'] |
||
142 | owner_id = event.data['ticket_bundle_owner_id'] |
||
143 | |||
144 | category = ticket_category_service.find_category(category_id) |
||
145 | category_title = category.title if (category is not None) else None |
||
146 | |||
147 | return { |
||
148 | 'bundle_id': bundle_id, |
||
149 | 'ticket_category_title': category_title, |
||
150 | 'ticket_quantity': ticket_quantity, |
||
151 | } |
||
152 | |||
153 | |||
154 | def _get_additional_data_for_ticket_bundle_revoked( |
||
155 | event: OrderEvent, users_by_id: Dict[UserID, User] |
||
156 | ) -> OrderEventData: |
||
157 | bundle_id = event.data['ticket_bundle_id'] |
||
158 | |||
159 | data = { |
||
160 | 'bundle_id': bundle_id, |
||
161 | } |
||
162 | |||
163 | initiator_id = event.data.get('initiator_id') |
||
164 | if initiator_id: |
||
165 | data['initiator'] = users_by_id[initiator_id] |
||
166 | |||
167 | return data |
||
168 | |||
169 | |||
170 | def _get_additional_data_for_ticket_created( |
||
171 | event: OrderEvent |
||
172 | ) -> OrderEventData: |
||
173 | ticket_id = event.data['ticket_id'] |
||
174 | ticket_code = event.data['ticket_code'] |
||
175 | category_id = event.data['ticket_category_id'] |
||
176 | owner_id = event.data['ticket_owner_id'] |
||
177 | |||
178 | return { |
||
179 | 'ticket_id': ticket_id, |
||
180 | 'ticket_code': ticket_code, |
||
181 | } |
||
182 | |||
183 | |||
184 | def _get_additional_data_for_ticket_revoked( |
||
185 | event: OrderEvent, users_by_id: Dict[UserID, User] |
||
186 | ) -> OrderEventData: |
||
187 | ticket_id = event.data['ticket_id'] |
||
188 | ticket_code = event.data['ticket_code'] |
||
189 | |||
190 | data = { |
||
191 | 'ticket_code': ticket_code, |
||
192 | } |
||
193 | |||
194 | initiator_id = event.data.get('initiator_id') |
||
195 | if initiator_id: |
||
196 | data['initiator'] = users_by_id[initiator_id] |
||
197 | |||
198 | return data |
||
199 | |||
200 | |||
201 | def _to_user_dto(user: DbUser) -> User: |
||
202 | """Create an immutable user object with selected values from user entity.""" |
||
203 | avatar = getattr(user, 'avatar', None) |
||
204 | avatar_url = avatar.url if avatar else None |
||
205 | is_orga = False |
||
206 | |||
207 | return User( |
||
208 | user.id, |
||
209 | user.screen_name, |
||
210 | user.suspended, |
||
211 | user.deleted, |
||
212 | avatar_url, |
||
213 | is_orga, |
||
214 | ) |
||
215 |