2021-05-17 12:15:12 +00:00
|
|
|
from datetime import datetime
|
2016-02-23 11:49:10 +00:00
|
|
|
from django import forms
|
2014-05-27 15:55:09 +00:00
|
|
|
from django.contrib import admin
|
2021-04-21 12:27:18 +00:00
|
|
|
from django.urls import reverse, NoReverseMatch
|
2015-04-05 22:34:47 +00:00
|
|
|
from django.db.models import Prefetch
|
2014-07-22 21:47:01 +00:00
|
|
|
from django.utils import timezone
|
2021-05-17 12:15:12 +00:00
|
|
|
from django.utils.html import escape, format_html
|
2015-03-27 19:50:54 +00:00
|
|
|
from django.utils.safestring import mark_safe
|
2023-10-24 16:59:02 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2014-05-27 15:55:09 +00:00
|
|
|
|
2021-04-21 12:27:18 +00:00
|
|
|
from orchestra.admin import ExtendedModelAdmin
|
2015-07-15 12:13:03 +00:00
|
|
|
from orchestra.admin.utils import admin_link, admin_date, change_url
|
2015-07-21 10:44:32 +00:00
|
|
|
from orchestra.contrib.accounts.actions import list_accounts
|
2015-04-05 10:46:24 +00:00
|
|
|
from orchestra.contrib.accounts.admin import AccountAdminMixin
|
2014-09-03 14:51:07 +00:00
|
|
|
from orchestra.utils.humanize import naturaldate
|
2014-07-16 15:20:16 +00:00
|
|
|
|
2015-07-10 13:00:51 +00:00
|
|
|
from .actions import BillSelectedOrders, mark_as_ignored, mark_as_not_ignored, report
|
2014-10-16 17:14:21 +00:00
|
|
|
from .filters import IgnoreOrderListFilter, ActiveOrderListFilter, BilledOrderListFilter
|
2014-09-17 10:32:29 +00:00
|
|
|
from .models import Order, MetricStorage
|
2014-05-27 15:55:09 +00:00
|
|
|
|
|
|
|
|
2015-03-27 19:50:54 +00:00
|
|
|
class MetricStorageInline(admin.TabularInline):
|
|
|
|
model = MetricStorage
|
2015-04-05 22:34:47 +00:00
|
|
|
readonly_fields = ('value', 'created_on', 'updated_on')
|
2015-03-27 19:50:54 +00:00
|
|
|
extra = 0
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2015-03-27 19:50:54 +00:00
|
|
|
def has_add_permission(self, request, obj=None):
|
|
|
|
return False
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2015-03-27 19:50:54 +00:00
|
|
|
def get_fieldsets(self, request, obj=None):
|
|
|
|
if obj:
|
|
|
|
url = reverse('admin:orders_metricstorage_changelist')
|
|
|
|
url += '?order=%i' % obj.pk
|
|
|
|
title = _('Metric storage, last 10 entries, <a href="%s">(See all)</a>')
|
|
|
|
self.verbose_name_plural = mark_safe(title % url)
|
|
|
|
return super(MetricStorageInline, self).get_fieldsets(request, obj)
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2015-03-27 19:50:54 +00:00
|
|
|
def get_queryset(self, request):
|
|
|
|
qs = super(MetricStorageInline, self).get_queryset(request)
|
2015-04-05 22:34:47 +00:00
|
|
|
change_view = bool(self.parent_object and self.parent_object.pk)
|
|
|
|
if change_view:
|
|
|
|
qs = qs.order_by('-id')
|
2016-02-23 11:49:10 +00:00
|
|
|
parent_id = self.parent_object.pk
|
2015-03-27 19:50:54 +00:00
|
|
|
try:
|
2016-02-23 11:49:10 +00:00
|
|
|
tenth_id = qs.filter(order_id=parent_id).values_list('id', flat=True)[9]
|
2015-03-27 19:50:54 +00:00
|
|
|
except IndexError:
|
|
|
|
pass
|
|
|
|
else:
|
2015-09-23 12:22:32 +00:00
|
|
|
return qs.filter(pk__gte=tenth_id)
|
2015-03-27 19:50:54 +00:00
|
|
|
return qs
|
|
|
|
|
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.register(Order)
|
2015-03-27 19:50:54 +00:00
|
|
|
class OrderAdmin(AccountAdminMixin, ExtendedModelAdmin):
|
2014-07-21 15:43:36 +00:00
|
|
|
list_display = (
|
2015-09-30 13:22:17 +00:00
|
|
|
'display_description', 'service_link', 'account_link', 'content_object_link',
|
2015-07-21 10:44:32 +00:00
|
|
|
'display_registered_on', 'display_billed_until', 'display_cancelled_on',
|
|
|
|
'display_metric'
|
|
|
|
)
|
|
|
|
list_filter = (
|
2016-05-13 08:42:58 +00:00
|
|
|
ActiveOrderListFilter, IgnoreOrderListFilter, BilledOrderListFilter, 'account__type',
|
|
|
|
'service',
|
2014-07-21 15:43:36 +00:00
|
|
|
)
|
2014-10-16 17:14:21 +00:00
|
|
|
default_changelist_filters = (
|
|
|
|
('ignore', '0'),
|
|
|
|
)
|
2015-07-21 10:44:32 +00:00
|
|
|
actions = (
|
|
|
|
BillSelectedOrders(), mark_as_ignored, mark_as_not_ignored, report, list_accounts
|
|
|
|
)
|
2015-03-27 19:50:54 +00:00
|
|
|
change_view_actions = (BillSelectedOrders(), mark_as_ignored, mark_as_not_ignored)
|
2014-07-22 21:47:01 +00:00
|
|
|
date_hierarchy = 'registered_on'
|
2015-03-27 19:50:54 +00:00
|
|
|
inlines = (MetricStorageInline,)
|
|
|
|
add_inlines = ()
|
2015-07-15 12:13:03 +00:00
|
|
|
search_fields = ('account__username', 'content_object_repr', 'description',)
|
2015-04-05 22:34:47 +00:00
|
|
|
list_prefetch_related = (
|
|
|
|
'content_object',
|
|
|
|
Prefetch('metrics', queryset=MetricStorage.objects.order_by('-id')),
|
|
|
|
)
|
2015-04-01 15:49:21 +00:00
|
|
|
list_select_related = ('account', 'service')
|
2016-02-23 11:49:10 +00:00
|
|
|
add_fieldsets = (
|
|
|
|
(None, {
|
|
|
|
'fields': ('account', 'service')
|
|
|
|
}),
|
|
|
|
(_("Object"), {
|
|
|
|
'fields': ('content_type', 'object_id',),
|
|
|
|
}),
|
|
|
|
(_("State"), {
|
|
|
|
'fields': ('registered_on', 'cancelled_on', 'billed_on', 'billed_metric',
|
|
|
|
'billed_until' )
|
|
|
|
}),
|
|
|
|
(None, {
|
|
|
|
'fields': ('description', 'ignore',),
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
fieldsets = (
|
|
|
|
(None, {
|
|
|
|
'fields': ('account_link', 'service_link', 'content_object_link'),
|
|
|
|
}),
|
|
|
|
(_("State"), {
|
|
|
|
'fields': ('registered_on', 'cancelled_on', 'billed_on', 'billed_metric',
|
|
|
|
'billed_until' )
|
|
|
|
}),
|
|
|
|
(None, {
|
|
|
|
'fields': ('description', 'ignore', 'bills_links'),
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
readonly_fields = (
|
|
|
|
'content_object_repr', 'content_object_link', 'bills_links', 'account_link',
|
|
|
|
'service_link'
|
|
|
|
)
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2014-10-21 15:29:36 +00:00
|
|
|
service_link = admin_link('service')
|
2014-07-22 21:47:01 +00:00
|
|
|
display_registered_on = admin_date('registered_on')
|
|
|
|
display_cancelled_on = admin_date('cancelled_on')
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.display(
|
|
|
|
description=_("Description"),
|
|
|
|
ordering='description',
|
|
|
|
)
|
2015-09-30 13:22:17 +00:00
|
|
|
def display_description(self, order):
|
2021-05-17 12:15:12 +00:00
|
|
|
return format_html(order.description[:64])
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.display(
|
|
|
|
description=_("Content object"),
|
|
|
|
ordering='content_object_repr',
|
|
|
|
)
|
2015-07-15 12:13:03 +00:00
|
|
|
def content_object_link(self, order):
|
|
|
|
if order.content_object:
|
|
|
|
try:
|
|
|
|
url = change_url(order.content_object)
|
|
|
|
except NoReverseMatch:
|
|
|
|
# Does not has admin
|
|
|
|
return order.content_object_repr
|
|
|
|
description = str(order.content_object)
|
2021-05-17 12:15:12 +00:00
|
|
|
return format_html('<a href="{url}">{description}</a>',
|
2015-07-15 12:13:03 +00:00
|
|
|
url=url, description=description)
|
|
|
|
return order.content_object_repr
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.display(
|
|
|
|
description=_("Bills")
|
|
|
|
)
|
2021-05-17 12:15:12 +00:00
|
|
|
@mark_safe
|
2016-02-23 11:49:10 +00:00
|
|
|
def bills_links(self, order):
|
|
|
|
bills = []
|
|
|
|
make_link = admin_link()
|
|
|
|
for line in order.lines.select_related('bill').distinct('bill'):
|
|
|
|
bills.append(make_link(line.bill))
|
2016-04-06 19:00:16 +00:00
|
|
|
return '<br>'.join(bills)
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.display(
|
|
|
|
description=_("billed until"),
|
|
|
|
ordering='billed_until',
|
|
|
|
)
|
2014-09-03 14:51:07 +00:00
|
|
|
def display_billed_until(self, order):
|
2015-05-27 14:05:25 +00:00
|
|
|
billed_until = order.billed_until
|
|
|
|
red = False
|
2015-06-16 11:34:46 +00:00
|
|
|
human = escape(naturaldate(billed_until))
|
2015-05-27 14:05:25 +00:00
|
|
|
if billed_until:
|
2015-07-09 13:04:26 +00:00
|
|
|
if order.cancelled_on and order.cancelled_on <= billed_until:
|
|
|
|
pass
|
|
|
|
elif order.service.billing_period == order.service.NEVER:
|
2015-06-16 11:34:46 +00:00
|
|
|
human = _("Forever")
|
|
|
|
elif order.service.payment_style == order.service.POSTPAY:
|
2015-05-27 14:05:25 +00:00
|
|
|
boundary = order.service.handler.get_billing_point(order)
|
|
|
|
if billed_until < boundary:
|
|
|
|
red = True
|
|
|
|
elif billed_until < timezone.now().date():
|
|
|
|
red = True
|
2021-05-17 12:15:12 +00:00
|
|
|
color = mark_safe('style="color:red;"') if red else ''
|
|
|
|
return format_html(
|
|
|
|
'<span title="{raw}" {color}>{human}</span>',
|
2015-06-16 11:34:46 +00:00
|
|
|
raw=escape(str(billed_until)), color=color, human=human,
|
2014-09-03 14:51:07 +00:00
|
|
|
)
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.display(
|
|
|
|
description=_("Metric")
|
|
|
|
)
|
2015-03-27 19:50:54 +00:00
|
|
|
def display_metric(self, order):
|
2015-07-21 10:44:32 +00:00
|
|
|
"""
|
|
|
|
dispalys latest metric value, don't uses latest() because not loosing prefetch_related
|
|
|
|
"""
|
2015-04-01 15:49:21 +00:00
|
|
|
try:
|
|
|
|
metric = order.metrics.all()[0]
|
|
|
|
except IndexError:
|
|
|
|
return ''
|
|
|
|
return metric.value
|
2021-04-21 12:27:18 +00:00
|
|
|
|
2016-02-23 11:49:10 +00:00
|
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
|
|
""" Make value input widget bigger """
|
|
|
|
if db_field.name == 'description':
|
|
|
|
kwargs['widget'] = forms.Textarea(attrs={'cols': 70, 'rows': 2})
|
|
|
|
return super().formfield_for_dbfield(db_field, **kwargs)
|
2014-08-22 15:31:44 +00:00
|
|
|
|
2015-04-28 15:23:57 +00:00
|
|
|
# def get_changelist(self, request, **kwargs):
|
|
|
|
# ChangeList = super(OrderAdmin, self).get_changelist(request, **kwargs)
|
|
|
|
# class OrderFilterChangeList(ChangeList):
|
|
|
|
# def get_filters(self, request):
|
|
|
|
# filters = super(OrderFilterChangeList, self).get_filters(request)
|
|
|
|
# tail = []
|
|
|
|
# filters_copy = []
|
|
|
|
# for list_filter in filters[0]:
|
|
|
|
# if getattr(list_filter, 'apply_last', False):
|
|
|
|
# tail.append(list_filter)
|
|
|
|
# else:
|
|
|
|
# filters_copy.append(list_filter)
|
|
|
|
# filters = ((filters_copy+tail),) + filters[1:]
|
|
|
|
# return filters
|
|
|
|
# return OrderFilterChangeList
|
|
|
|
|
2014-07-22 21:47:01 +00:00
|
|
|
|
2024-01-26 13:05:02 +00:00
|
|
|
@admin.register(MetricStorage)
|
2014-07-16 15:20:16 +00:00
|
|
|
class MetricStorageAdmin(admin.ModelAdmin):
|
2014-07-21 12:20:04 +00:00
|
|
|
list_display = ('order', 'value', 'created_on', 'updated_on')
|
2014-07-18 16:02:05 +00:00
|
|
|
list_filter = ('order__service',)
|
2016-04-06 19:00:16 +00:00
|
|
|
raw_id_fields = ('order',)
|
2014-05-27 15:55:09 +00:00
|
|
|
|
|
|
|
|