Fixes on billing and mailman traffic backend
This commit is contained in:
parent
8753b94b8c
commit
332ad49b64
18
TODO.md
18
TODO.md
|
@ -156,7 +156,6 @@ require_once(‘/etc/moodles/’.$moodle_host.‘config.php’);``` moodle/drupl
|
||||||
# * add ini, end dates on bill lines and breakup quanity into size(defaut:1) and metric
|
# * add ini, end dates on bill lines and breakup quanity into size(defaut:1) and metric
|
||||||
# * threshold for significative metric accountancy on services.handler
|
# * threshold for significative metric accountancy on services.handler
|
||||||
# * http://orchestra.pangea.org/admin/orders/order/6418/
|
# * http://orchestra.pangea.org/admin/orders/order/6418/
|
||||||
# * http://orchestra.pangea.org/admin/orders/order/6495/bill_selected_orders/
|
|
||||||
|
|
||||||
* move normurlpath to orchestra.utils from websites.utils
|
* move normurlpath to orchestra.utils from websites.utils
|
||||||
|
|
||||||
|
@ -183,22 +182,11 @@ ugettext("Description")
|
||||||
|
|
||||||
* saas validate_creation generic approach, for all backends. standard output
|
* saas validate_creation generic approach, for all backends. standard output
|
||||||
|
|
||||||
* html code x: × for bill line verbose quantity
|
* periodic task to cleanup metricstorage
|
||||||
|
# create orchestrate databases.Database pk=1 -n --dry-run | --noinput --action save (default)|delete --backend name (limit to this backend) --help
|
||||||
* periodic task to cleanup backendlogs, monitor data and metricstorage
|
|
||||||
* create orchestrate databases.Database pk=1 -n --dry-run | --noinput --action save (default)|delete --backend name (limit to this backend) --help
|
|
||||||
|
|
||||||
* uwsgi --max-requests=5000 \ # respawn processes after serving 5000 requests and
|
|
||||||
celery max-tasks-per-child
|
|
||||||
|
|
||||||
* generate settings.py more like django (installed_apps, middlewares, etc,,,)
|
|
||||||
|
|
||||||
* postupgradeorchestra send signals in order to hook custom stuff
|
* postupgradeorchestra send signals in order to hook custom stuff
|
||||||
|
|
||||||
* autoscale celery workers http://docs.celeryproject.org/en/latest/userguide/workers.html#autoscaling
|
|
||||||
|
|
||||||
|
|
||||||
glic3rinu's django-fluent-dashboard
|
|
||||||
* gevent is not ported to python3 :'(
|
* gevent is not ported to python3 :'(
|
||||||
|
|
||||||
# FIXME account deletion generates an integrity error
|
# FIXME account deletion generates an integrity error
|
||||||
|
@ -248,8 +236,6 @@ https://code.djangoproject.com/ticket/24576
|
||||||
# Determine the difference between data serializer used for validation and used for the rest API!
|
# Determine the difference between data serializer used for validation and used for the rest API!
|
||||||
# Make PluginApiView that fills metadata and other stuff like modeladmin plugin support
|
# Make PluginApiView that fills metadata and other stuff like modeladmin plugin support
|
||||||
|
|
||||||
# TODO orchestra related services code reload: celery/uwsgi reloading find aonther way without root and implement reload
|
|
||||||
|
|
||||||
# reset setting button
|
# reset setting button
|
||||||
|
|
||||||
# admin edit relevant djanog settings
|
# admin edit relevant djanog settings
|
||||||
|
|
|
@ -271,6 +271,7 @@ class MailmanTraffic(ServiceMonitor):
|
||||||
'Nov': '11',
|
'Nov': '11',
|
||||||
'Dec': '12',
|
'Dec': '12',
|
||||||
}}
|
}}
|
||||||
|
mailman_addr = re.compile(r'.*-(admin|bounces|confirm|join|leave|owner|request|subscribe|unsubscribe)@.*')
|
||||||
|
|
||||||
def prepare(object_id, list_name, ini_date):
|
def prepare(object_id, list_name, ini_date):
|
||||||
global lists
|
global lists
|
||||||
|
@ -283,12 +284,15 @@ class MailmanTraffic(ServiceMonitor):
|
||||||
try:
|
try:
|
||||||
with open(postlog, 'r') as postlog:
|
with open(postlog, 'r') as postlog:
|
||||||
for line in postlog.readlines():
|
for line in postlog.readlines():
|
||||||
month, day, time, year, __, __, __, list_name, __, __, size = line.split()[:11]
|
month, day, time, year, __, __, __, list_name, __, addr, size = line.split()[:11]
|
||||||
try:
|
try:
|
||||||
list = lists[list_name]
|
list = lists[list_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
|
# discard mailman messages because of inconsistent POST logging
|
||||||
|
if mailman_addr.match(addr):
|
||||||
|
continue
|
||||||
date = year + months[month] + day + time.replace(':', '')
|
date = year + months[month] + day + time.replace(':', '')
|
||||||
if list[0] < int(date) < end_date:
|
if list[0] < int(date) < end_date:
|
||||||
size = size[5:-1]
|
size = size[5:-1]
|
||||||
|
|
|
@ -202,6 +202,7 @@ class MonitorDataAdmin(ExtendedModelAdmin):
|
||||||
change_readonly_fields = fields
|
change_readonly_fields = fields
|
||||||
list_select_related = ('content_type',)
|
list_select_related = ('content_type',)
|
||||||
search_fields = ('content_object_repr',)
|
search_fields = ('content_object_repr',)
|
||||||
|
date_hierarchy = 'created_at'
|
||||||
|
|
||||||
display_created = admin_date('created_at', short_description=_("Created"))
|
display_created = admin_date('created_at', short_description=_("Created"))
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,11 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
||||||
|
|
||||||
def get_price_size(self, ini, end):
|
def get_price_size(self, ini, end):
|
||||||
rdelta = relativedelta.relativedelta(end, ini)
|
rdelta = relativedelta.relativedelta(end, ini)
|
||||||
if self.billing_period == self.MONTHLY:
|
anual_prepay_of_monthly_pricing = bool(
|
||||||
|
self.billing_period == self.ANUAL and
|
||||||
|
self.payment_style == self.PREPAY and
|
||||||
|
self.get_pricing_period() == self.MONTHLY)
|
||||||
|
if self.billing_period == self.MONTHLY or anual_prepay_of_monthly_pricing:
|
||||||
size = rdelta.years * 12
|
size = rdelta.years * 12
|
||||||
size += rdelta.months
|
size += rdelta.months
|
||||||
days = calendar.monthrange(end.year, end.month)[1]
|
days = calendar.monthrange(end.year, end.month)[1]
|
||||||
|
@ -508,7 +512,9 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
||||||
recharges = []
|
recharges = []
|
||||||
rini = order.billed_on
|
rini = order.billed_on
|
||||||
rend = min(bp, order.billed_until)
|
rend = min(bp, order.billed_until)
|
||||||
bmetric = order.billed_metric or 0
|
bmetric = order.billed_metric
|
||||||
|
if bmetric is None:
|
||||||
|
bmetric = order.get_metric(order.billed_on)
|
||||||
bsize = self.get_price_size(rini, order.billed_until)
|
bsize = self.get_price_size(rini, order.billed_until)
|
||||||
prepay_discount = self.get_price(account, bmetric) * bsize
|
prepay_discount = self.get_price(account, bmetric) * bsize
|
||||||
prepay_discount = round(prepay_discount, 2)
|
prepay_discount = round(prepay_discount, 2)
|
||||||
|
@ -580,6 +586,17 @@ class ServiceHandler(plugins.Plugin, metaclass=plugins.PluginMount):
|
||||||
line = self.generate_line(order, price, cini, cend, metric=metric,
|
line = self.generate_line(order, price, cini, cend, metric=metric,
|
||||||
discounts=discounts)
|
discounts=discounts)
|
||||||
lines.append(line)
|
lines.append(line)
|
||||||
|
elif self.get_pricing_period() in (self.MONTHLY, self.ANUAL):
|
||||||
|
if self.payment_style == self.PREPAY:
|
||||||
|
# Traffic Prepay
|
||||||
|
metric = order.get_metric(timezone.now().date())
|
||||||
|
if metric > 0:
|
||||||
|
price = self.get_price(account, metric)
|
||||||
|
for cini, cend in self.get_pricing_slots(ini, bp):
|
||||||
|
line = self.generate_line(order, price, cini, cend, metric=metric)
|
||||||
|
lines.append(line)
|
||||||
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import calendar
|
||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
|
@ -70,9 +71,8 @@ class Service(models.Model):
|
||||||
"<tt> contractedplan.plan.name == 'association_fee''</tt><br>"
|
"<tt> contractedplan.plan.name == 'association_fee''</tt><br>"
|
||||||
"<tt> instance.active</tt>"))
|
"<tt> instance.active</tt>"))
|
||||||
handler_type = models.CharField(_("handler"), max_length=256, blank=True,
|
handler_type = models.CharField(_("handler"), max_length=256, blank=True,
|
||||||
help_text=_("Handler used for processing this Service. A handler "
|
help_text=_("Handler used for processing this Service. A handler enables customized "
|
||||||
"enables customized behaviour far beyond what options "
|
"behaviour far beyond what options here allow to."),
|
||||||
"here allow to."),
|
|
||||||
choices=ServiceHandler.get_choices())
|
choices=ServiceHandler.get_choices())
|
||||||
is_active = models.BooleanField(_("active"), default=True)
|
is_active = models.BooleanField(_("active"), default=True)
|
||||||
ignore_superusers = models.BooleanField(_("ignore %s") % _ignore_types, default=True,
|
ignore_superusers = models.BooleanField(_("ignore %s") % _ignore_types, default=True,
|
||||||
|
@ -87,16 +87,16 @@ class Service(models.Model):
|
||||||
),
|
),
|
||||||
default=ANUAL, blank=True)
|
default=ANUAL, blank=True)
|
||||||
billing_point = models.CharField(_("billing point"), max_length=16,
|
billing_point = models.CharField(_("billing point"), max_length=16,
|
||||||
help_text=_("Reference point for calculating the renewal date "
|
help_text=_("Reference point for calculating the renewal date on recurring invoices"),
|
||||||
"on recurring invoices"),
|
|
||||||
choices=(
|
choices=(
|
||||||
(ON_REGISTER, _("Registration date")),
|
(ON_REGISTER, _("Registration date")),
|
||||||
(FIXED_DATE, _("Fixed billing date")),
|
(FIXED_DATE, _("Every %(month)s") % {
|
||||||
|
'month': calendar.month_name[settings.SERVICES_SERVICE_ANUAL_BILLING_MONTH]
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
default=FIXED_DATE)
|
default=FIXED_DATE)
|
||||||
is_fee = models.BooleanField(_("fee"), default=False,
|
is_fee = models.BooleanField(_("fee"), default=False,
|
||||||
help_text=_("Designates whether this service should be billed as "
|
help_text=_("Designates whether this service should be billed as membership fee or not"))
|
||||||
" membership fee or not"))
|
|
||||||
order_description = models.CharField(_("Order description"), max_length=128, blank=True,
|
order_description = models.CharField(_("Order description"), max_length=128, blank=True,
|
||||||
help_text=_(
|
help_text=_(
|
||||||
"Python <a href='https://docs.python.org/2/library/functions.html#eval'>expression</a> "
|
"Python <a href='https://docs.python.org/2/library/functions.html#eval'>expression</a> "
|
||||||
|
|
Loading…
Reference in a new issue