Added update orders confirmation page

This commit is contained in:
Marc 2014-10-20 19:22:18 +00:00
parent 0e65c65433
commit e669dcf926
10 changed files with 124 additions and 15 deletions

View File

@ -154,3 +154,7 @@ textwrap.dedent( \\)
* parmiko write to a channel instead of transfering files? http://sysadmin.circularvale.com/programming/paramiko-channel-hangs/
* strip leading and trailing whitre spaces of most input fields
* Examples of service.match and service.metric

View File

@ -16,6 +16,7 @@ def admin_field(method):
kwargs['field'] = args[0] if args else ''
kwargs['order'] = kwargs.get('order', kwargs['field'])
kwargs['popup'] = kwargs.get('popup', False)
# TODO get field verbose name
kwargs['short_description'] = kwargs.get('short_description',
kwargs['field'].split('__')[-1].replace('_', ' ').capitalize())
admin_method = partial(method, **kwargs)

View File

@ -13,7 +13,7 @@ def create_account_creation_form():
for model, key, kwargs, help_text in settings.ACCOUNTS_CREATE_RELATED:
model = get_model(model)
field_name = 'create_%s' % model._meta.model_name
label = _("Create related %s") % model._meta.verbose_name
label = _("Create %s") % model._meta.verbose_name
fields[field_name] = forms.BooleanField(initial=True, required=False, label=label,
help_text=help_text)

View File

@ -4,6 +4,7 @@ import zipfile
from django.contrib import messages
from django.contrib.admin import helpers
from django.core.urlresolvers import reverse
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import render
from django.utils.safestring import mark_safe
@ -45,6 +46,7 @@ view_bill.verbose_name = _("View")
view_bill.url_name = 'view'
@transaction.atomic
def close_bills(modeladmin, request, queryset):
queryset = queryset.filter(is_open=True)
if not queryset:

View File

@ -59,6 +59,7 @@ class OrderQuerySet(models.QuerySet):
return self.filter(**qs)
def get_related(self, **options):
""" returns related orders that could have a pricing effect """
Service = get_model(settings.ORDERS_SERVICE_MODEL)
conflictive = self.filter(service__metric='')
conflictive = conflictive.exclude(service__billing_period=Service.NEVER)
@ -66,6 +67,8 @@ class OrderQuerySet(models.QuerySet):
qs = Q()
for account_id, services in conflictive.iteritems():
for service, orders in services.iteritems():
if not service.rates.exists():
continue
end = datetime.date.min
bp = None
for order in orders:
@ -107,7 +110,7 @@ class Order(models.Model):
related_name='orders')
registered_on = models.DateField(_("registered"), default=lambda: timezone.now())
cancelled_on = models.DateField(_("cancelled"), null=True, blank=True)
billed_on = models.DateField(_("billed on"), null=True, blank=True)
billed_on = models.DateField(_("billed"), null=True, blank=True)
billed_until = models.DateField(_("billed until"), null=True, blank=True)
ignore = models.BooleanField(_("ignore"), default=False)
description = models.TextField(_("description"), blank=True)
@ -122,7 +125,8 @@ class Order(models.Model):
return str(self.service)
@classmethod
def update_orders(cls, instance, service=None):
def update_orders(cls, instance, service=None, commit=True):
updates = []
if service is None:
Service = get_model(settings.ORDERS_SERVICE_MODEL)
services = Service.get_services(instance)
@ -140,14 +144,23 @@ class Order(models.Model):
account = getattr(instance, 'account', instance)
if account.is_superuser:
ignore = service.ignore_superusers
order = cls.objects.create(content_object=instance, service=service,
order = cls(content_object=instance, service=service,
account_id=account_id, ignore=ignore)
if commit:
order.save()
updates.append((order, 'created'))
logger.info("CREATED new order id: {id}".format(id=order.id))
else:
order = orders.get()
order.update()
updates.append((order, 'updated'))
if commit:
order.update()
elif orders:
orders.get().cancel()
order = orders.get()
if commit:
order.cancel()
updates.append((order, 'cancelled'))
return updates
@classmethod
def get_bill_backend(cls):

View File

@ -41,7 +41,7 @@
{% for line in lines %}
<tr class="form-row {% if forloop.counter|divisibleby:2 %}row2{% else %}row1{% endif %}">
<td>
<a href="{{ line.order | admin_link }}">{{ line.order.description }}</a>
<a href="{{ line.order | admin_url }}">{{ line.order.description }}</a>
{% for discount in line.discounts %}
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Discount per {{ discount.type }}
{% endfor %}

View File

@ -1,15 +1,50 @@
from django.contrib.admin import helpers
from django.core.urlresolvers import reverse
from django.db import transaction
from django.shortcuts import render
from django.template.response import TemplateResponse
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from orchestra.admin.utils import get_object_from_url
@transaction.atomic
def update_orders(modeladmin, request, queryset):
def update_orders(modeladmin, request, queryset, extra_context=None):
if not queryset:
return
if request.POST.get('post') == 'confirmation':
num = 0
services = []
for service in queryset:
updates = service.update_orders()
num += len(updates)
services.append(str(service.pk))
modeladmin.log_change(request, service, _("Orders updated"))
if num == 1:
url = reverse('admin:orders_order_change', args=(updates[0][0].pk,))
msg = _('<a href="%s">One related order</a> has benn updated') % url
else:
url = reverse('admin:orders_order_changelist')
url += '?service__in=%s' % ','.join(services)
msg = _('<a href="%s">%s related orders</a> have been updated') % (url, num)
modeladmin.message_user(request, mark_safe(msg))
return
updates = []
for service in queryset:
service.update_orders()
modeladmin.log_change(request, service, 'Update orders')
msg = _("Orders for %s selected services have been updated.") % queryset.count()
modeladmin.message_user(request, msg)
updates += service.update_orders(commit=False)
opts = modeladmin.model._meta
context = {
'title': _("Update orders will cause the following."),
'action_name': 'Update orders',
'action_value': 'update_orders',
'updates': updates,
'queryset': queryset,
'opts': opts,
'app_label': opts.app_label,
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
'obj': get_object_from_url(modeladmin, request),
}
return render(request, 'admin/services/service/update_orders.html', context)
update_orders.url_name = 'update-orders'
update_orders.verbose_name = _("Update orders")

View File

@ -272,11 +272,13 @@ class Service(models.Model):
def rate_method(self):
return self.RATE_METHODS[self.rate_algorithm]
def update_orders(self):
def update_orders(self, commit=True):
order_model = get_model(settings.SERVICES_ORDER_MODEL)
related_model = self.content_type.model_class()
updates = []
for instance in related_model.objects.all().select_related('account'):
order_model.update_orders(instance, service=self)
updates += order_model.update_orders(instance, service=self, commit=commit)
return updates
accounts.register(ContractedPlan)

View File

@ -0,0 +1,52 @@
{% extends "admin/orchestra/generic_confirmation.html" %}
{% load i18n l10n %}
{% load url from future %}
{% load admin_urls static utils %}
{% block content %}
<div class="inline-group" id="rates-group">
<div class="tabular inline-related last-related">
<fieldset class="module">
<table id="result_list">
<thead>
<tr>
<th scope="col"><div class="text"><span>Action</span</div></th>
<th scope="col"><div class="text"><span>ID</span</div></th>
<th scope="col"><div class="text"><span>Service</span</div></th>
<th scope="col"><div class="text"><span>Account</span</div></th>
<th scope="col"><div class="text"><span>Content object</span</div></th>
<th scope="col"><div class="text"><span>Registered on</span</div></th>
<th scope="col"><div class="text"><span>Billed until</span</div></th>
<th scope="col"><div class="text"><span>Cancelled on</span</div>
</th>
</tr>
</thead>
<tbody>
{% for order, action in updates %}
<tr class="{% if forloop.counter|divisibleby:2 %}row2{% else %}row1{% endif %}">
<th>{{ action }}</th>
<td>{% if order.pk %}<a href="{{ order | admin_url }}">{{ order.id }}</a>{% endif %}</td>
<td><a href="{{ order.service | admin_url }}">{{ order.service }}</a></td>
<td><a href="{{ order.account | admin_url }}">{{ order.account }}</a></td>
<td><a href="{{ order.content_object | admin_url }}">{{ order.content_object }}</a></td>
<td><span title="{{ order.registered_on }}">{{ order.registered_on }}</span></td>
<td><span title="{{ order.billed_unitl }}">{{ order.billed_unitl }}</span></td>
<td>{{ order.canncelled_on }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</ul>
<form action="" method="post">{% csrf_token %}
{% for obj in queryset %}
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
{% endfor %}
<input type="hidden" name="action" value="{{ action_value }}" />
<input type="hidden" name="post" value="confirmation" />
<input type="submit" value="{% trans "Yes, I'm sure" %}" />
</form>
{% endblock %}

View File

@ -54,5 +54,5 @@ def is_checkbox(field):
@register.filter
def admin_link(obj):
def admin_url(obj):
return change_url(obj)