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 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 * backend logs with hal logo

View File

@ -8,6 +8,7 @@ from django.utils.encoding import force_text
def admin_field(method): def admin_field(method):
""" Wraps a function to be used as a ModelAdmin method field """
def admin_field_wrapper(*args, **kwargs): def admin_field_wrapper(*args, **kwargs):
""" utility function for creating admin links """ """ utility function for creating admin links """
kwargs['field'] = args[0] if args else '' 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.apps.accounts.admin import AccountAdminMixin
from orchestra.core import services from orchestra.core import services
from .actions import BillSelectedOrders
from .filters import ActiveOrderListFilter from .filters import ActiveOrderListFilter
from .models import Service, Order, MetricStorage from .models import Service, Order, MetricStorage
@ -81,6 +82,7 @@ class OrderAdmin(AccountAdminMixin, ChangeListDefaultFilter, admin.ModelAdmin):
) )
list_display_link = ('id', 'service') list_display_link = ('id', 'service')
list_filter = (ActiveOrderListFilter, 'service',) list_filter = (ActiveOrderListFilter, 'service',)
actions = (BillSelectedOrders(),)
date_hierarchy = 'registered_on' date_hierarchy = 'registered_on'
default_changelist_filters = ( default_changelist_filters = (
('is_active', 'True'), ('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 %}