from django import forms
from django.db import models
from django.contrib import admin
from django.core.urlresolvers import reverse
from django.utils import timezone
from django.utils.html import escape
from django.utils.translation import ugettext_lazy as _
from orchestra.admin import ChangeListDefaultFilter
from orchestra.admin.filters import UsedContentTypeFilter
from orchestra.admin.utils import admin_link, admin_date
from orchestra.apps.accounts.admin import AccountAdminMixin
from orchestra.core import services
from orchestra.utils.humanize import naturaldate
from .actions import BillSelectedOrders
from .filters import ActiveOrderListFilter, BilledOrderListFilter
from .models import Plan, Rate, Service, Order, MetricStorage
class PlanAdmin(AccountAdminMixin, admin.ModelAdmin):
list_display = ('name', 'account_link')
list_filter = ('name',)
class RateInline(admin.TabularInline):
model = Rate
ordering = ('plan', 'quantity')
class ServiceAdmin(admin.ModelAdmin):
list_display = (
'description', 'content_type', 'handler_type', 'num_orders', 'is_active'
)
list_filter = ('is_active', 'handler_type', UsedContentTypeFilter)
fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('description', 'content_type', 'match', 'handler_type',
'is_active')
}),
(_("Billing options"), {
'classes': ('wide',),
'fields': ('billing_period', 'billing_point', 'delayed_billing',
'is_fee')
}),
(_("Pricing options"), {
'classes': ('wide',),
'fields': ('metric', 'pricing_period', 'rate_algorithm',
'orders_effect', 'on_cancel', 'payment_style',
'trial_period', 'refound_period', 'tax', 'nominal_price')
}),
)
inlines = [RateInline]
def formfield_for_dbfield(self, db_field, **kwargs):
""" Improve performance of account field and filter by account """
if db_field.name == 'content_type':
models = [model._meta.model_name for model in services.get()]
queryset = db_field.rel.to.objects
kwargs['queryset'] = queryset.filter(model__in=models)
if db_field.name in ['match', 'metric']:
kwargs['widget'] = forms.TextInput(attrs={'size':'160'})
return super(ServiceAdmin, self).formfield_for_dbfield(db_field, **kwargs)
def num_orders(self, service):
num = service.orders__count
url = reverse('admin:orders_order_changelist')
url += '?service=%i&is_active=True' % service.pk
return '%d' % (url, num)
num_orders.short_description = _("Orders")
num_orders.admin_order_field = 'orders__count'
num_orders.allow_tags = True
def get_queryset(self, request):
qs = super(ServiceAdmin, self).get_queryset(request)
# Count active orders
qs = qs.extra(select={
'orders__count': (
"SELECT COUNT(*) "
"FROM orders_order "
"WHERE orders_order.service_id = orders_service.id AND ("
" orders_order.cancelled_on IS NULL OR"
" orders_order.cancelled_on > '%s' "
")" % timezone.now()
)
})
return qs
class OrderAdmin(AccountAdminMixin, ChangeListDefaultFilter, admin.ModelAdmin):
list_display = (
'id', 'service', 'account_link', 'content_object_link',
'display_registered_on', 'display_billed_until', 'display_cancelled_on'
)
list_display_links = ('id', 'service')
list_filter = (ActiveOrderListFilter, BilledOrderListFilter, 'service',)
actions = (BillSelectedOrders(),)
date_hierarchy = 'registered_on'
default_changelist_filters = (
('is_active', 'True'),
)
content_object_link = admin_link('content_object', order=False)
display_registered_on = admin_date('registered_on')
display_cancelled_on = admin_date('cancelled_on')
def display_billed_until(self, order):
value = order.billed_until
color = ''
if value and value < timezone.now():
color = 'style="color:red;"'
return '{human}'.format(
raw=escape(str(value)), color=color, human=escape(naturaldate(value)),
)
display_billed_until.short_description = _("billed until")
display_billed_until.allow_tags = True
display_billed_until.admin_order_field = 'billed_until'
def get_queryset(self, request):
qs = super(OrderAdmin, self).get_queryset(request)
return qs.select_related('service').prefetch_related('content_object')
class MetricStorageAdmin(admin.ModelAdmin):
list_display = ('order', 'value', 'created_on', 'updated_on')
list_filter = ('order__service',)
admin.site.register(Plan, PlanAdmin)
admin.site.register(Service, ServiceAdmin)
admin.site.register(Order, OrderAdmin)
admin.site.register(MetricStorage, MetricStorageAdmin)