Passed
Push — master ( d0d419...634080 )
by Jochen
02:24
created

index_for_shop()   B

Complexity

Conditions 1

Size

Total Lines 54
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 38
nop 2
dl 0
loc 54
rs 8.968
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.admin.shop.order.views
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4
5
:Copyright: 2006-2019 Jochen Kupperschmidt
6
:License: Modified BSD, see LICENSE for details.
7
"""
8
9
from flask import abort, g, request, Response
10
11
from .....services.shop.order import service as order_service
12
from .....services.shop.order.email import service as order_email_service
13
from .....services.shop.order.export import service as order_export_service
14
from .....services.shop.order.transfer.models import PaymentMethod, PaymentState
15
from .....services.shop.sequence import service as sequence_service
16
from .....services.shop.shop import service as shop_service
17
from .....services.ticketing import ticket_service
18
from .....services.user import service as user_service
19
from .....util.framework.blueprint import create_blueprint
20
from .....util.framework.flash import flash_error, flash_notice, flash_success
21
from .....util.framework.templating import templated
22
from .....util.views import redirect_to, respond_no_content
23
24
from ....authorization.decorators import permission_required
25
from ....authorization.registry import permission_registry
26
from ....shop.order.signals import order_canceled, order_paid
27
28
from .authorization import ShopOrderPermission
29
from .forms import CancelForm, MarkAsPaidForm
30
from .models import OrderStateFilter
31
from . import service
32
33
34
blueprint = create_blueprint('shop_order_admin', __name__)
35
36
37
permission_registry.register_enum(ShopOrderPermission)
38
39
40
@blueprint.route('/parties/<shop_id>', defaults={'page': 1})
41
@blueprint.route('/parties/<shop_id>/pages/<int:page>')
42
@permission_required(ShopOrderPermission.view)
43
@templated
44
def index_for_shop(shop_id, page):
45
    """List orders for that shop."""
46
    shop = _get_shop_or_404(shop_id)
47
48
    order_number_sequence = sequence_service.find_order_number_sequence(shop.id)
49
    order_number_prefix = order_number_sequence.prefix
50
51
    per_page = request.args.get('per_page', type=int, default=15)
52
53
    search_term = request.args.get('search_term', default='').strip()
54
55
    only_payment_state = request.args.get(
56
        'only_payment_state', type=PaymentState.__members__.get
57
    )
58
59
    def _str_to_bool(value):
60
        valid_values = {
61
            'true': True,
62
            'false': False,
63
        }
64
        return valid_values.get(value, False)
65
66
    only_shipped = request.args.get('only_shipped', type=_str_to_bool)
67
68
    order_state_filter = OrderStateFilter.find(only_payment_state, only_shipped)
69
70
    orders = order_service.get_orders_for_shop_paginated(
71
        shop.id,
72
        page,
73
        per_page,
74
        search_term=search_term,
75
        only_payment_state=only_payment_state,
76
        only_shipped=only_shipped,
77
    )
78
79
    # Replace order objects in pagination object with order tuples.
80
    orders.items = [order.to_transfer_object() for order in orders.items]
81
82
    orders.items = list(service.extend_order_tuples_with_orderer(orders.items))
83
84
    return {
85
        'shop': shop,
86
        'order_number_prefix': order_number_prefix,
87
        'search_term': search_term,
88
        'PaymentState': PaymentState,
89
        'only_payment_state': only_payment_state,
90
        'only_shipped': only_shipped,
91
        'OrderStateFilter': OrderStateFilter,
92
        'order_state_filter': order_state_filter,
93
        'orders': orders,
94
    }
95
96
97
@blueprint.route('/<uuid:order_id>')
98
@permission_required(ShopOrderPermission.view)
99
@templated
100
def view(order_id):
101
    """Show a single order."""
102
    order = order_service.find_order_with_details(order_id)
103
    if order is None:
104
        abort(404)
105
106
    placed_by = user_service.find_user(order.placed_by_id, include_avatar=True)
107
108
    shop = shop_service.get_shop(order.shop_id)
109
110
    articles_by_item_number = service.get_articles_by_item_number(order)
111
112
    events = service.get_events(order.id)
113
114
    tickets = ticket_service.find_tickets_created_by_order(order.order_number)
115
116
    return {
117
        'shop': shop,
118
        'order': order,
119
        'placed_by': placed_by,
120
        'articles_by_item_number': articles_by_item_number,
121
        'events': events,
122
        'PaymentMethod': PaymentMethod,
123
        'PaymentState': PaymentState,
124
        'tickets': tickets,
125
    }
126
127
128
@blueprint.route('/<uuid:order_id>/export')
129
@permission_required(ShopOrderPermission.view)
130
def export(order_id):
131
    """Export the order as an XML document."""
132
    xml_export = order_export_service.export_order_as_xml(order_id)
133
134
    if xml_export is None:
135
        abort(404)
136
137
    return Response(
138
        xml_export['content'], content_type=xml_export['content_type']
139
    )
140
141
142
@blueprint.route('/<uuid:order_id>/flags/invoiced', methods=['POST'])
143
@permission_required(ShopOrderPermission.update)
144
@respond_no_content
145
def set_invoiced_flag(order_id):
146
    """Mark the order as invoiced."""
147
    order = _get_order_or_404(order_id)
148
    initiator_id = g.current_user.id
149
150
    order_service.set_invoiced_flag(order, initiator_id)
151
152
    flash_success(
153
        'Bestellung {} wurde als in Rechnung gestellt markiert.',
154
        order.order_number,
155
    )
156
157
158
@blueprint.route('/<uuid:order_id>/flags/invoiced', methods=['DELETE'])
159
@permission_required(ShopOrderPermission.update)
160
@respond_no_content
161
def unset_invoiced_flag(order_id):
162
    """Mark the order as not invoiced."""
163
    order = _get_order_or_404(order_id)
164
    initiator_id = g.current_user.id
165
166
    order_service.unset_invoiced_flag(order, initiator_id)
167
168
    flash_success(
169
        'Bestellung {} wurde als nicht in Rechnung gestellt markiert.',
170
        order.order_number,
171
    )
172
173
174
@blueprint.route('/<uuid:order_id>/flags/shipped', methods=['POST'])
175
@permission_required(ShopOrderPermission.update)
176
@respond_no_content
177
def set_shipped_flag(order_id):
178
    """Mark the order as shipped."""
179
    order = _get_order_or_404(order_id)
180
    initiator_id = g.current_user.id
181
182
    order_service.set_shipped_flag(order, initiator_id)
183
184
    flash_success(
185
        'Bestellung {} wurde als verschickt markiert.', order.order_number
186
    )
187
188
189
@blueprint.route('/<uuid:order_id>/flags/shipped', methods=['DELETE'])
190
@permission_required(ShopOrderPermission.update)
191
@respond_no_content
192
def unset_shipped_flag(order_id):
193
    """Mark the order as not shipped."""
194
    order = _get_order_or_404(order_id)
195
    initiator_id = g.current_user.id
196
197
    order_service.unset_shipped_flag(order, initiator_id)
198
199
    flash_success(
200
        'Bestellung {} wurde als nicht verschickt markiert.', order.order_number
201
    )
202
203
204
@blueprint.route('/<uuid:order_id>/cancel')
205
@permission_required(ShopOrderPermission.cancel)
206
@templated
207
def cancel_form(order_id, erroneous_form=None):
208
    """Show form to cancel an order."""
209
    order = _get_order_or_404(order_id)
210
211
    if order.is_canceled:
212
        flash_error(
213
            'Die Bestellung ist bereits storniert worden; '
214
            'der Bezahlstatus kann nicht mehr geändert werden.'
215
        )
216
        return redirect_to('.view', order_id=order.id)
217
218
    shop = shop_service.get_shop(order.shop_id)
219
220
    form = erroneous_form if erroneous_form else CancelForm()
221
222
    return {
223
        'shop': shop,
224
        'order': order,
225
        'form': form,
226
    }
227
228
229
@blueprint.route('/<uuid:order_id>/cancel', methods=['POST'])
230
@permission_required(ShopOrderPermission.cancel)
231
def cancel(order_id):
232
    """Set the payment status of a single order to 'canceled' and
233
    release the respective article quantities.
234
    """
235
    order = _get_order_or_404(order_id)
236
237
    form = CancelForm(request.form)
238
    if not form.validate():
239
        return cancel_form(order_id, form)
240
241
    reason = form.reason.data.strip()
242
    send_email = form.send_email.data
243
244
    try:
245
        order_service.cancel_order(order.id, g.current_user.id, reason)
246
    except order_service.OrderAlreadyCanceled:
247
        flash_error(
248
            'Die Bestellung ist bereits storniert worden; '
249
            'der Bezahlstatus kann nicht mehr geändert werden.'
250
        )
251
        return redirect_to('.view', order_id=order.id)
252
253
    flash_success(
254
        'Die Bestellung wurde als storniert markiert und die betroffenen '
255
        'Artikel in den entsprechenden Stückzahlen wieder zur Bestellung '
256
        'freigegeben.'
257
    )
258
259
    if send_email:
260
        order_email_service.send_email_for_canceled_order_to_orderer(order.id)
261
    else:
262
        flash_notice(
263
            'Es wurde keine E-Mail an den/die Auftraggeber/in versendet.'
264
        )
265
266
    order_canceled.send(None, order_id=order.id)
267
268
    return redirect_to('.view', order_id=order.id)
269
270
271
@blueprint.route('/<uuid:order_id>/mark_as_paid')
272
@permission_required(ShopOrderPermission.mark_as_paid)
273
@templated
274
def mark_as_paid_form(order_id, erroneous_form=None):
275
    """Show form to mark an order as paid."""
276
    order = _get_order_or_404(order_id)
277
278
    if order.is_paid:
279
        flash_error('Die Bestellung ist bereits als bezahlt markiert worden.')
280
        return redirect_to('.view', order_id=order.id)
281
282
    shop = shop_service.get_shop(order.shop_id)
283
284
    form = erroneous_form if erroneous_form else MarkAsPaidForm()
285
286
    return {
287
        'shop': shop,
288
        'order': order,
289
        'form': form,
290
    }
291
292
293
@blueprint.route('/<uuid:order_id>/mark_as_paid', methods=['POST'])
294
@permission_required(ShopOrderPermission.mark_as_paid)
295
def mark_as_paid(order_id):
296
    """Set the payment status of a single order to 'paid'."""
297
    order = _get_order_or_404(order_id)
298
299
    form = MarkAsPaidForm(request.form)
300
    if not form.validate():
301
        return mark_as_paid_form(order_id, form)
302
303
    payment_method = PaymentMethod[form.payment_method.data]
304
    updated_by_id = g.current_user.id
305
306
    try:
307
        order_service.mark_order_as_paid(
308
            order.id, payment_method, updated_by_id
309
        )
310
    except order_service.OrderAlreadyMarkedAsPaid:
311
        flash_error('Die Bestellung ist bereits als bezahlt markiert worden.')
312
        return redirect_to('.view', order_id=order.id)
313
314
    flash_success('Die Bestellung wurde als bezahlt markiert.')
315
316
    order_email_service.send_email_for_paid_order_to_orderer(order.id)
317
318
    order_paid.send(None, order_id=order.id)
319
320
    return redirect_to('.view', order_id=order.id)
321
322
323
@blueprint.route(
324
    '/<uuid:order_id>/resend_incoming_order_email', methods=['POST']
325
)
326
@permission_required(ShopOrderPermission.update)
327
@respond_no_content
328
def resend_email_for_incoming_order_to_orderer(order_id):
329
    """Resend the e-mail to the orderer to confirm that the order was placed."""
330
    order = _get_order_or_404(order_id)
331
332
    order_email_service.send_email_for_incoming_order_to_orderer(order.id)
333
334
    flash_success('Die E-Mail-Eingangsbestätigung wurde erneut versendet.')
335
336
337
def _get_shop_or_404(shop_id):
338
    shop = shop_service.find_shop(shop_id)
339
340
    if shop is None:
341
        abort(404)
342
343
    return shop
344
345
346
def _get_order_or_404(order_id):
347
    order = order_service.find_order(order_id)
348
349
    if order is None:
350
        abort(404)
351
352
    return order
353