forked from glic3rinu/django-orchestra
-
Notifications
You must be signed in to change notification settings - Fork 1
/
actions.py
174 lines (160 loc) · 6.66 KB
/
actions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
from django.contrib import admin, messages
from django.urls import reverse
from django.db import transaction
from django.utils import timezone
from django.utils.safestring import mark_safe
from django.utils.translation import ungettext, ugettext_lazy as _
from django.shortcuts import render
from orchestra.admin.utils import change_url
from .forms import BillSelectedOptionsForm, BillSelectConfirmationForm, BillSelectRelatedForm
class BillSelectedOrders(object):
""" Form wizard for billing orders admin action """
short_description = _("Bill selected orders")
verbose_name = _("Bill")
template = 'admin/orders/order/bill_selected_options.html'
__name__ = 'bill_selected_orders'
def __call__(self, modeladmin, request, queryset):
""" make this monster behave like a function """
self.modeladmin = modeladmin
self.queryset = queryset
opts = modeladmin.model._meta
app_label = opts.app_label
self.context = {
'opts': opts,
'app_label': app_label,
'queryset': queryset,
'action_checkbox_name': admin.helpers.ACTION_CHECKBOX_NAME,
}
ret = self.set_options(request)
del(self.queryset)
del(self.context)
return ret
def set_options(self, request):
form = BillSelectedOptionsForm()
if request.POST.get('step'):
form = BillSelectedOptionsForm(request.POST)
if form.is_valid():
self.options = dict(
billing_point=form.cleaned_data['billing_point'],
fixed_point=form.cleaned_data['fixed_point'],
proforma=form.cleaned_data['proforma'],
new_open=form.cleaned_data['new_open'],
)
if int(request.POST.get('step')) != 3:
return self.select_related(request)
else:
return self.confirmation(request)
self.context.update({
'title': _("Options for billing selected orders, step 1 / 3"),
'step': 1,
'form': form,
})
return render(request, self.template, self.context)
def select_related(self, request):
# TODO use changelist ?
related = self.queryset.get_related().select_related('account', 'service')
if not related:
return self.confirmation(request)
self.options['related_queryset'] = related
form = BillSelectRelatedForm(initial=self.options)
if int(request.POST.get('step')) >= 2:
form = BillSelectRelatedForm(request.POST, initial=self.options)
if form.is_valid():
select_related = form.cleaned_data['selected_related']
self.queryset = self.queryset | select_related
return self.confirmation(request)
self.context.update({
'title': _("Select related order for billing, step 2 / 3"),
'step': 2,
'form': form,
})
return render(request, self.template, self.context)
@transaction.atomic
def confirmation(self, request):
form = BillSelectConfirmationForm(initial=self.options)
if int(request.POST.get('step')) >= 3:
bills = self.queryset.bill(commit=True, **self.options)
for order in self.queryset:
self.modeladmin.log_change(request, order, _("Billed"))
if not bills:
msg = _("Selected orders do not have pending billing")
self.modeladmin.message_user(request, msg, messages.WARNING)
else:
num = len(bills)
if num == 1:
url = change_url(bills[0])
else:
url = reverse('admin:bills_bill_changelist')
ids = ','.join([str(b.id) for b in bills])
url += '?id__in=%s' % ids
msg = ungettext(
'<a href="{url}">One bill</a> has been created.',
'<a href="{url}">{num} bills</a> have been created.',
num).format(url=url, num=num)
msg = mark_safe(msg)
self.modeladmin.message_user(request, msg, messages.INFO)
return
bills = self.queryset.bill(commit=False, **self.options)
bills_with_total = []
for account, lines in bills:
total = 0
for line in lines:
discount = sum([discount.total for discount in line.discounts])
total += line.subtotal + discount
bills_with_total.append((account, total, lines))
self.context.update({
'title': _("Confirmation for billing selected orders"),
'step': 3,
'form': form,
'bills': sorted(bills_with_total, key=lambda i: -i[1]),
})
return render(request, self.template, self.context)
@transaction.atomic
def mark_as_ignored(modeladmin, request, queryset):
""" Mark orders as ignored """
for order in queryset:
order.mark_as_ignored()
modeladmin.log_change(request, order, 'Marked as ignored')
num = len(queryset)
msg = ungettext(
_("Selected order has been marked as ignored."),
_("%i selected orders have been marked as ignored.") % num,
num)
modeladmin.message_user(request, msg)
@transaction.atomic
def mark_as_not_ignored(modeladmin, request, queryset):
""" Mark orders as ignored """
for order in queryset:
order.mark_as_not_ignored()
modeladmin.log_change(request, order, 'Marked as not ignored')
num = len(queryset)
msg = ungettext(
_("Selected order has been marked as not ignored."),
_("%i selected orders have been marked as not ignored.") % num,
num)
modeladmin.message_user(request, msg)
def report(modeladmin, request, queryset):
services = {}
totals = [0, 0, None, 0]
now = timezone.now().date()
for order in queryset.select_related('service'):
name = order.service.description
active, cancelled = (1, 0) if not order.cancelled_on or order.cancelled_on > now else (0, 1)
try:
info = services[name]
except KeyError:
nominal_price = order.service.nominal_price
info = [active, cancelled, nominal_price, 1]
services[name] = info
else:
info[0] += active
info[1] += cancelled
info[3] += 1
totals[0] += active
totals[1] += cancelled
totals[3] += 1
context = {
'services': sorted(services.items(), key=lambda n: -n[1][0]),
'totals': totals,
}
return render(request, 'admin/orders/order/report.html', context)