Added preliminar implementation of admin billing

This commit is contained in:
Marc 2014-07-24 15:43:23 +00:00
parent 06db4cd346
commit b88689864f
7 changed files with 196 additions and 1 deletions

View file

@ -64,6 +64,11 @@ Remember that, as always with QuerySets, any subsequent chained methods which im
dependency collector with max_recursion that matches the number of dots on service.match and service.metric
* Be consistent with dates: name_on, created ?
* Be consistent with dates:
* created_on date
* created_at datetime
at + clock time, midnight, noon- At 3:30 p.m., At 4:01, At noon
* backend logs with hal logo

View file

@ -8,6 +8,7 @@ from django.utils.encoding import force_text
def admin_field(method):
""" Wraps a function to be used as a ModelAdmin method field """
def admin_field_wrapper(*args, **kwargs):
""" utility function for creating admin links """
kwargs['field'] = args[0] if args else ''

18
orchestra/admin/forms.py Normal file
View file

@ -0,0 +1,18 @@
from django.template import Template, Context
from django.contrib.admin.helpers import AdminForm
class AdminFormMixin(object):
""" Provides a method for rendering a form just like in Django Admin """
def as_admin(self):
prepopulated_fields = {}
fieldsets = [
(None, {'fields': self.fields.keys()})
]
adminform = AdminForm(self, fieldsets, prepopulated_fields)
template = Template(
'{% for fieldset in adminform %}'
'{% include "admin/includes/fieldset.html" %}'
'{% endfor %}'
)
return template.render(Context({'adminform': adminform}))

View file

@ -0,0 +1,90 @@
from django.contrib import admin, messages
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render
from .forms import (BillSelectedOptionsForm, BillSelectConfirmationForm,
BillSelectRelatedForm)
class BillSelectedOrders(object):
""" Form wizard for billing orders admin action """
short_description = _("Bill selected orders")
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,
}
return self.set_options(request)
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'],
create_new_open=form.cleaned_data['create_new_open'],
)
return self.select_related(request)
self.context.update({
'title': _("Options for billing selected orders, step 1 / 3"),
'step': 'one',
'form': form,
})
return render(request, self.template, self.context)
def select_related(self, request):
self.options['related_queryset'] = self.queryset.all() #get_related(**options)
form = BillSelectRelatedForm(initial=self.options)
if request.POST.get('step') == 'two':
form = BillSelectRelatedForm(request.POST, initial=self.options)
if form.is_valid():
select_related = form.cleaned_data['selected_related']
self.options['selected_related'] = select_related
return self.confirmation(request)
self.context.update({
'title': _("Select related order for billing, step 2 / 3"),
'step': 'two',
'form': form,
})
return render(request, self.template, self.context)
def confirmation(self, request):
form = BillSelectConfirmationForm(initial=self.options)
if request.POST:
bills = Order.bill(queryset, commit=True, **self.options)
if not bills:
msg = _("Selected orders do not have pending billing")
self.modeladmin.message_user(request, msg, messages.WARNING)
else:
ids = ','.join([bill.id for bill in bills])
url = reverse('admin:bills_bill_changelist')
context = {
'url': url + '?id=%s' % ids,
'num': len(bills),
'bills': _("bills"),
'msg': _("have been generated"),
}
msg = '<a href="%(url)s">%(num)s %(bills)s</a> %(msg)s' % context
msg = mark_safe(msg)
self.modeladmin.message_user(request, msg, messages.INFO)
return
self.context.update({
'title': _("Confirmation for billing selected orders"),
'step': 'three',
'form': form,
})
return render(request, self.template, self.context)

View file

@ -11,6 +11,7 @@ from orchestra.admin.utils import admin_link, admin_date
from orchestra.apps.accounts.admin import AccountAdminMixin
from orchestra.core import services
from .actions import BillSelectedOrders
from .filters import ActiveOrderListFilter
from .models import Service, Order, MetricStorage
@ -81,6 +82,7 @@ class OrderAdmin(AccountAdminMixin, ChangeListDefaultFilter, admin.ModelAdmin):
)
list_display_link = ('id', 'service')
list_filter = (ActiveOrderListFilter, 'service',)
actions = (BillSelectedOrders(),)
date_hierarchy = 'registered_on'
default_changelist_filters = (
('is_active', 'True'),

View file

@ -0,0 +1,43 @@
from django import forms
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from orchestra.admin.forms import AdminFormMixin
from .models import Order
class BillSelectedOptionsForm(AdminFormMixin, forms.Form):
billing_point = forms.DateField(initial=timezone.now,
label=_("Billing point"),
help_text=_("Date you want to bill selected orders"))
fixed_point = forms.BooleanField(initial=False, required=False,
label=_("fixed point"),
help_text=_("Deisgnates whether you want the billing point to be an "
"exact date, or adapt it to the billing period."))
create_new_open = forms.BooleanField(initial=False, required=False,
label=_("Create a new open bill"),
help_text=_("Deisgnates whether you want to put this orders on a new "
"open bill, or allow to reuse an existing one."))
class BillSelectRelatedForm(AdminFormMixin, forms.Form):
selected_related = forms.ModelMultipleChoiceField(queryset=Order.objects.none(),
required=False)
billing_point = forms.DateField(widget=forms.HiddenInput())
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)
def __init__(self, *args, **kwargs):
super(BillSelectRelatedForm, self).__init__(*args, **kwargs)
queryset = kwargs['initial'].get('related_queryset', None)
if queryset:
self.fields['selected_related'].queryset = queryset
class BillSelectConfirmationForm(forms.Form):
selected_related = forms.ModelMultipleChoiceField(queryset=Order.objects.none(),
widget=forms.HiddenInput(), required=False)
billing_point = forms.DateField(widget=forms.HiddenInput())
fixed_point = forms.BooleanField(widget=forms.HiddenInput(), required=False)
create_new_open = forms.BooleanField(widget=forms.HiddenInput(), required=False)

View file

@ -0,0 +1,36 @@
{% extends "admin/base_site.html" %}
{% load i18n l10n staticfiles admin_urls %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static "admin/css/forms.css" %}" />
{% endblock %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
&rsaquo; <a href="{% url 'admin:app_list' app_label='orders' %}">Slices</a>
&rsaquo; <a href="{% url 'admin:orders_order_changelist' %}">Slices</a>
&rsaquo; {{ title }}
</div>
{% endblock %}
{% block content %}
<form action="" method="post">{% csrf_token %}
<div>
<div style="margin:20px;">
{{ form.as_admin }}
</div>
{% for obj in queryset %}
<input type="hidden" name="{{ action_checkbox_name }}" value="{{ obj.pk|unlocalize }}" />
{% endfor %}
<input type="hidden" name="action" value="bill_selected_orders" />
<input type="hidden" name="step" value="{{ step }}" />
<input type="submit" value="{% trans "Yes, create slivers" %}" />
</div>
</form>
{% endblock %}