Use freezegun for test time mockup

This commit is contained in:
Marc 2014-09-24 20:09:41 +00:00
parent c0e8e9f85d
commit 0de534f4e2
13 changed files with 183 additions and 90 deletions

View File

@ -109,3 +109,4 @@ at + clock time, midnight, noon- At 3:30 p.m., At 4:01, At noon
* latest by 'id' *always* * latest by 'id' *always*
* replace add_now by default=lambda: timezone.now()

View File

@ -35,17 +35,21 @@ class Bill(models.Model):
(PENDING, _("Pending")), (PENDING, _("Pending")),
(BAD_DEBT, _("Bad debt")), (BAD_DEBT, _("Bad debt")),
) )
BILL = 'BILL'
INVOICE = 'INVOICE'
AMENDMENTINVOICE = 'AMENDMENTINVOICE'
FEE = 'FEE'
AMENDMENTFEE = 'AMENDMENTFEE'
PROFORMA = 'PROFORMA'
TYPES = ( TYPES = (
('INVOICE', _("Invoice")), (INVOICE, _("Invoice")),
('AMENDMENTINVOICE', _("Amendment invoice")), (AMENDMENTINVOICE, _("Amendment invoice")),
('FEE', _("Fee")), (FEE, _("Fee")),
('AMENDMENTFEE', _("Amendment Fee")), (AMENDMENTFEE, _("Amendment Fee")),
('PROFORMA', _("Pro forma")), (PROFORMA, _("Pro forma")),
) )
number = models.CharField(_("number"), max_length=16, unique=True, number = models.CharField(_("number"), max_length=16, unique=True, blank=True)
blank=True)
account = models.ForeignKey('accounts.Account', verbose_name=_("account"), account = models.ForeignKey('accounts.Account', verbose_name=_("account"),
related_name='%(class)s') related_name='%(class)s')
type = models.CharField(_("type"), max_length=16, choices=TYPES) type = models.CharField(_("type"), max_length=16, choices=TYPES)
@ -63,7 +67,7 @@ class Bill(models.Model):
objects = BillManager() objects = BillManager()
class Meta: class Meta:
get_latest_by = 'created_on' get_latest_by = 'id'
def __unicode__(self): def __unicode__(self):
return self.number return self.number
@ -101,8 +105,8 @@ class Bill(models.Model):
def set_number(self): def set_number(self):
cls = type(self) cls = type(self)
bill_type = self.get_type() bill_type = self.get_type()
if bill_type == 'BILL': if bill_type == self.BILL:
raise TypeError("get_new_number() can not be used on a Bill class") raise TypeError('This method can not be used on BILL instances')
prefix = getattr(settings, 'BILLS_%s_NUMBER_PREFIX' % bill_type) prefix = getattr(settings, 'BILLS_%s_NUMBER_PREFIX' % bill_type)
if self.is_open: if self.is_open:
prefix = 'O{}'.format(prefix) prefix = 'O{}'.format(prefix)
@ -117,8 +121,7 @@ class Bill(models.Model):
number_length = settings.BILLS_NUMBER_LENGTH number_length = settings.BILLS_NUMBER_LENGTH
zeros = (number_length - len(str(number))) * '0' zeros = (number_length - len(str(number))) * '0'
number = zeros + str(number) number = zeros + str(number)
self.number = '{prefix}{year}{number}'.format( self.number = '{prefix}{year}{number}'.format(prefix=prefix, year=year, number=number)
prefix=prefix, year=year, number=number)
def get_due_date(self, payment=None): def get_due_date(self, payment=None):
now = timezone.now() now = timezone.now()
@ -134,7 +137,7 @@ class Bill(models.Model):
self.due_on = self.get_due_date(payment=payment) self.due_on = self.get_due_date(payment=payment)
self.total = self.get_total() self.total = self.get_total()
self.html = self.render(payment=payment) self.html = self.render(payment=payment)
if self.get_type() != 'PROFORMA': if self.get_type() != self.PROFORMA:
self.transactions.create(bill=self, source=payment, amount=self.total) self.transactions.create(bill=self, source=payment, amount=self.total)
self.closed_on = timezone.now() self.closed_on = timezone.now()
self.is_open = False self.is_open = False
@ -175,8 +178,8 @@ class Bill(models.Model):
'default_due_date': self.get_due_date(payment=payment), 'default_due_date': self.get_due_date(payment=payment),
'now': timezone.now(), 'now': timezone.now(),
}) })
template = getattr(settings, 'BILLS_%s_TEMPLATE' % self.get_type(), template_name = 'BILLS_%s_TEMPLATE' % self.get_type()
settings.BILLS_DEFAULT_TEMPLATE) template = getattr(settings, template_name, settings.BILLS_DEFAULT_TEMPLATE)
bill_template = loader.get_template(template) bill_template = loader.get_template(template)
html = bill_template.render(context) html = bill_template.render(context)
html = html.replace('-pageskip-', '<pdf:nextpage />') html = html.replace('-pageskip-', '<pdf:nextpage />')
@ -234,8 +237,7 @@ class BillLine(models.Model):
""" Base model for bill item representation """ """ Base model for bill item representation """
bill = models.ForeignKey(Bill, verbose_name=_("bill"), related_name='lines') bill = models.ForeignKey(Bill, verbose_name=_("bill"), related_name='lines')
description = models.CharField(_("description"), max_length=256) description = models.CharField(_("description"), max_length=256)
rate = models.DecimalField(_("rate"), blank=True, null=True, rate = models.DecimalField(_("rate"), blank=True, null=True, max_digits=12, decimal_places=2)
max_digits=12, decimal_places=2)
quantity = models.DecimalField(_("quantity"), max_digits=12, decimal_places=2) quantity = models.DecimalField(_("quantity"), max_digits=12, decimal_places=2)
subtotal = models.DecimalField(_("subtotal"), max_digits=12, decimal_places=2) subtotal = models.DecimalField(_("subtotal"), max_digits=12, decimal_places=2)
tax = models.PositiveIntegerField(_("tax")) tax = models.PositiveIntegerField(_("tax"))
@ -261,7 +263,7 @@ class BillLine(models.Model):
return total return total
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# TODO cost of this shit # TODO cost and consistency of this shit
super(BillLine, self).save(*args, **kwargs) super(BillLine, self).save(*args, **kwargs)
if self.bill.is_open: if self.bill.is_open:
self.bill.total = self.bill.get_total() self.bill.total = self.bill.get_total()
@ -270,8 +272,7 @@ class BillLine(models.Model):
class BillSubline(models.Model): class BillSubline(models.Model):
""" Subline used for describing an item discount """ """ Subline used for describing an item discount """
line = models.ForeignKey(BillLine, verbose_name=_("bill line"), line = models.ForeignKey(BillLine, verbose_name=_("bill line"), related_name='sublines')
related_name='sublines')
description = models.CharField(_("description"), max_length=256) description = models.CharField(_("description"), max_length=256)
total = models.DecimalField(max_digits=12, decimal_places=2) total = models.DecimalField(max_digits=12, decimal_places=2)
# TODO type ? Volume and Compensation # TODO type ? Volume and Compensation

View File

@ -57,7 +57,9 @@ class DomainAdmin(ChangeListDefaultFilter, AccountAdminMixin, ExtendedModelAdmin
list_filter = [TopDomainListFilter] list_filter = [TopDomainListFilter]
change_readonly_fields = ('name',) change_readonly_fields = ('name',)
search_fields = ['name', 'account__user__username'] search_fields = ['name', 'account__user__username']
default_changelist_filters = (('top_domain', 'True'),) default_changelist_filters = (
('top_domain', 'True'),
)
form = DomainAdminForm form = DomainAdminForm
def structured_name(self, domain): def structured_name(self, domain):

View File

@ -74,7 +74,9 @@ class Bind9MasterDomainBackend(ServiceController):
class Bind9SlaveDomainBackend(Bind9MasterDomainBackend): class Bind9SlaveDomainBackend(Bind9MasterDomainBackend):
verbose_name = _("Bind9 slave domain") verbose_name = _("Bind9 slave domain")
related_models = (('domains.Domain', 'origin'),) related_models = (
('domains.Domain', 'origin'),
)
def save(self, domain): def save(self, domain):
context = self.get_context(domain) context = self.get_context(domain)

View File

@ -161,7 +161,7 @@ class Message(models.Model):
created_on = models.DateTimeField(_("created on"), auto_now_add=True) created_on = models.DateTimeField(_("created on"), auto_now_add=True)
class Meta: class Meta:
get_latest_by = "created_on" get_latest_by = 'id'
def __unicode__(self): def __unicode__(self):
return u"#%i" % self.id return u"#%i" % self.id
@ -188,4 +188,6 @@ class TicketTracker(models.Model):
related_name='ticket_trackers') related_name='ticket_trackers')
class Meta: class Meta:
unique_together = (('ticket', 'user'),) unique_together = (
('ticket', 'user'),
)

View File

@ -66,7 +66,7 @@ class BackendLog(models.Model):
last_update = models.DateTimeField(_("last update"), auto_now=True) last_update = models.DateTimeField(_("last update"), auto_now=True)
class Meta: class Meta:
get_latest_by = 'created' get_latest_by = 'id'
@property @property
def execution_time(self): def execution_time(self):

View File

@ -81,9 +81,9 @@ class Order(models.Model):
related_name='orders') related_name='orders')
content_type = models.ForeignKey(ContentType) content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField(null=True) object_id = models.PositiveIntegerField(null=True)
service = models.ForeignKey(settings.ORDERS_SERVICE_MODEL, service = models.ForeignKey(settings.ORDERS_SERVICE_MODEL, verbose_name=_("service"),
verbose_name=_("service"), related_name='orders') related_name='orders')
registered_on = models.DateField(_("registered"), auto_now_add=True) # TODO datetime field? registered_on = models.DateField(_("registered"), default=lambda: timezone.now())
cancelled_on = models.DateField(_("cancelled"), null=True, blank=True) cancelled_on = models.DateField(_("cancelled"), null=True, blank=True)
billed_on = models.DateField(_("billed on"), null=True, blank=True) billed_on = models.DateField(_("billed on"), null=True, blank=True)
billed_until = models.DateField(_("billed until"), null=True, blank=True) billed_until = models.DateField(_("billed until"), null=True, blank=True)
@ -93,6 +93,9 @@ class Order(models.Model):
content_object = generic.GenericForeignKey() content_object = generic.GenericForeignKey()
objects = OrderQuerySet.as_manager() objects = OrderQuerySet.as_manager()
class Meta:
get_latest_by = 'id'
def __unicode__(self): def __unicode__(self):
return str(self.service) return str(self.service)
@ -180,6 +183,7 @@ class MetricStorage(models.Model):
order = models.ForeignKey(Order, verbose_name=_("order"), related_name='metrics') order = models.ForeignKey(Order, verbose_name=_("order"), related_name='metrics')
value = models.DecimalField(_("value"), max_digits=16, decimal_places=2) value = models.DecimalField(_("value"), max_digits=16, decimal_places=2)
created_on = models.DateField(_("created"), auto_now_add=True) created_on = models.DateField(_("created"), auto_now_add=True)
# default=lambda: timezone.now())
updated_on = models.DateTimeField(_("updated")) updated_on = models.DateTimeField(_("updated"))
class Meta: class Meta:
@ -203,9 +207,11 @@ class MetricStorage(models.Model):
metric.save() metric.save()
_excluded_models = (MetricStorage, LogEntry, Order, ContentType, MigrationRecorder.Migration) accounts.register(Order)
_excluded_models = (MetricStorage, LogEntry, Order, ContentType, MigrationRecorder.Migration)
@receiver(post_delete, dispatch_uid="orders.cancel_orders") @receiver(post_delete, dispatch_uid="orders.cancel_orders")
def cancel_orders(sender, **kwargs): def cancel_orders(sender, **kwargs):
if sender not in _excluded_models: if sender not in _excluded_models:
@ -218,7 +224,6 @@ def cancel_orders(sender, **kwargs):
if related and related != instance: if related and related != instance:
Order.update_orders(related) Order.update_orders(related)
@receiver(post_save, dispatch_uid="orders.update_orders") @receiver(post_save, dispatch_uid="orders.update_orders")
def update_orders(sender, **kwargs): def update_orders(sender, **kwargs):
if sender not in _excluded_models: if sender not in _excluded_models:
@ -229,7 +234,3 @@ def update_orders(sender, **kwargs):
related = helpers.get_related_objects(instance) related = helpers.get_related_objects(instance)
if related and related != instance: if related and related != instance:
Order.update_orders(related) Order.update_orders(related)
accounts.register(Order)

View File

@ -2,10 +2,11 @@ import datetime
import decimal import decimal
import sys import sys
from dateutil import relativedelta from dateutil.relativedelta import relativedelta
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models import F from django.db.models import F
from django.utils import timezone from django.utils import timezone
from freezegun import freeze_time
from orchestra.apps.accounts.models import Account from orchestra.apps.accounts.models import Account
from orchestra.apps.mails.models import Mailbox from orchestra.apps.mails.models import Mailbox
@ -56,21 +57,21 @@ class FTPBillingTest(BaseBillingTest):
def test_ftp_account_1_year_fiexed(self): def test_ftp_account_1_year_fiexed(self):
service = self.create_ftp_service() service = self.create_ftp_service()
user = self.create_ftp() user = self.create_ftp()
bp = timezone.now().date() + relativedelta.relativedelta(years=1) bp = timezone.now().date() + relativedelta(years=1)
bills = service.orders.bill(billing_point=bp, fixed_point=True) bills = service.orders.bill(billing_point=bp, fixed_point=True)
self.assertEqual(10, bills[0].get_total()) self.assertEqual(10, bills[0].get_total())
def test_ftp_account_2_year_fiexed(self): def test_ftp_account_2_year_fiexed(self):
service = self.create_ftp_service() service = self.create_ftp_service()
user = self.create_ftp() user = self.create_ftp()
bp = timezone.now().date() + relativedelta.relativedelta(years=2) bp = timezone.now().date() + relativedelta(years=2)
bills = service.orders.bill(billing_point=bp, fixed_point=True) bills = service.orders.bill(billing_point=bp, fixed_point=True)
self.assertEqual(20, bills[0].get_total()) self.assertEqual(20, bills[0].get_total())
def test_ftp_account_6_month_fixed(self): def test_ftp_account_6_month_fixed(self):
service = self.create_ftp_service() service = self.create_ftp_service()
self.create_ftp() self.create_ftp()
bp = timezone.now().date() + relativedelta.relativedelta(months=6) bp = timezone.now().date() + relativedelta(months=6)
bills = service.orders.bill(billing_point=bp, fixed_point=True) bills = service.orders.bill(billing_point=bp, fixed_point=True)
self.assertEqual(5, bills[0].get_total()) self.assertEqual(5, bills[0].get_total())
@ -95,7 +96,7 @@ class FTPBillingTest(BaseBillingTest):
account = self.create_account() account = self.create_account()
service = self.create_ftp_service() service = self.create_ftp_service()
user = self.create_ftp(account=account) user = self.create_ftp(account=account)
first_bp = timezone.now().date() + relativedelta.relativedelta(years=2) first_bp = timezone.now().date() + relativedelta(years=2)
bills = service.orders.bill(billing_point=first_bp, fixed_point=True) bills = service.orders.bill(billing_point=first_bp, fixed_point=True)
self.assertEqual(1, service.orders.active().count()) self.assertEqual(1, service.orders.active().count())
user.delete() user.delete()
@ -103,7 +104,7 @@ class FTPBillingTest(BaseBillingTest):
user = self.create_ftp(account=account) user = self.create_ftp(account=account)
self.assertEqual(1, service.orders.active().count()) self.assertEqual(1, service.orders.active().count())
self.assertEqual(2, service.orders.count()) self.assertEqual(2, service.orders.count())
bp = timezone.now().date() + relativedelta.relativedelta(years=1) bp = timezone.now().date() + relativedelta(years=1)
bills = service.orders.bill(billing_point=bp, fixed_point=True, new_open=True) bills = service.orders.bill(billing_point=bp, fixed_point=True, new_open=True)
discount = bills[0].lines.order_by('id')[0].sublines.get() discount = bills[0].lines.order_by('id')[0].sublines.get()
self.assertEqual(decimal.Decimal(-20), discount.total) self.assertEqual(decimal.Decimal(-20), discount.total)
@ -246,7 +247,9 @@ class DomainBillingTest(BaseBillingTest):
self.assertEqual(6, bills[0].get_total()) self.assertEqual(6, bills[0].get_total())
class TrafficBillingTest(BaseBillingTest): class BaseTrafficBillingTest(BaseBillingTest):
METRIC = 'account.resources.traffic.used'
def create_traffic_service(self): def create_traffic_service(self):
service = Service.objects.create( service = Service.objects.create(
description="Traffic", description="Traffic",
@ -255,7 +258,7 @@ class TrafficBillingTest(BaseBillingTest):
billing_period=Service.MONTHLY, billing_period=Service.MONTHLY,
billing_point=Service.FIXED_DATE, billing_point=Service.FIXED_DATE,
is_fee=False, is_fee=False,
metric='account.resources.traffic.used', metric=self.METRIC,
pricing_period=Service.BILLING_PERIOD, pricing_period=Service.BILLING_PERIOD,
rate_algorithm=Service.STEP_PRICE, rate_algorithm=Service.STEP_PRICE,
on_cancel=Service.NOTHING, on_cancel=Service.NOTHING,
@ -287,7 +290,9 @@ class TrafficBillingTest(BaseBillingTest):
MonitorData.objects.create(monitor='FTPTraffic', content_object=account.user, value=value, date=date) MonitorData.objects.create(monitor='FTPTraffic', content_object=account.user, value=value, date=date)
data = ResourceData.get_or_create(account, self.resource) data = ResourceData.get_or_create(account, self.resource)
data.update() data.update()
class TrafficBillingTest(BaseTrafficBillingTest):
def test_traffic(self): def test_traffic(self):
service = self.create_traffic_service() service = self.create_traffic_service()
resource = self.create_traffic_resource() resource = self.create_traffic_resource()
@ -297,7 +302,7 @@ class TrafficBillingTest(BaseBillingTest):
bills = service.orders.bill(commit=False) bills = service.orders.bill(commit=False)
self.assertEqual([(account, [])], bills) self.assertEqual([(account, [])], bills)
# Prepay # move into the past
delta = datetime.timedelta(days=60) delta = datetime.timedelta(days=60)
date = (timezone.now()-delta).date() date = (timezone.now()-delta).date()
order = service.orders.get() order = service.orders.get()
@ -322,10 +327,71 @@ class TrafficBillingTest(BaseBillingTest):
account1 = self.create_account() account1 = self.create_account()
account2 = self.create_account() account2 = self.create_account()
# TODO # TODO
class TrafficPrepayBillingTest(BaseTrafficBillingTest):
METRIC = "max((account.resources.traffic.used or 0) - getattr(account.miscellaneous.filter(service__name='traffic prepay').last(), 'amount', 0), 0)"
def create_prepay_service(self):
service = Service.objects.create(
description="Traffic prepay",
content_type=ContentType.objects.get_for_model(Miscellaneous),
match="miscellaneous.is_active and miscellaneous.service.name.lower() == 'traffic prepay'",
billing_period=Service.ANUAL,
billing_point=Service.FIXED_DATE,
is_fee=False,
metric="miscellaneous.amount",
pricing_period=Service.BILLING_PERIOD,
rate_algorithm=Service.STEP_PRICE,
on_cancel=Service.NOTHING, # TODO on_register == NOTHING or make on_cancel generic
payment_style=Service.PREPAY,
tax=0,
nominal_price=5
)
return service
def create_prepay(self, amount, account=None):
if not account:
account = self.create_account()
name = 'traffic prepay'
service, __ = MiscService.objects.get_or_create(name='traffic prepay', description='Traffic prepay', has_amount=True)
return Miscellaneous.objects.create(service=service, description=name, account=account, amount=amount)
def test_traffic_prepay(self): def test_traffic_prepay(self):
pass service = self.create_traffic_service()
# TODO prepay_service = self.create_prepay_service()
account = self.create_account()
self.create_traffic_resource()
prepay = self.create_prepay(10, account=account)
self.report_traffic(account, timezone.now(), 10**9)
print prepay_service.orders.all()
# TODO metric on the current day! how to solve it consistently?
# TODO prepay doesnt allow for discount
# move into the past
# TODO with patch.object(timezone, 'now', return_value=now+relativedelta(years=1)):
delta = datetime.timedelta(days=60)
date = (timezone.now()-delta).date()
order = service.orders.get()
order.registered_on = date
order.save()
metric = order.metrics.latest()
metric.updated_on -= delta
metric.save()
bills = service.orders.bill(proforma=True)
self.assertEqual(0, bills[0].get_total())
self.report_traffic(account, date, 10**10*9)
metric = order.metrics.latest()
metric.updated_on -= delta
metric.save()
bills = service.orders.bill(proforma=True)
self.assertEqual((90-10-10)*10, bills[0].get_total())
class MailboxBillingTest(BaseBillingTest): class MailboxBillingTest(BaseBillingTest):
@ -403,7 +469,7 @@ class MailboxBillingTest(BaseBillingTest):
self.allocate_disk(mailbox, 10) self.allocate_disk(mailbox, 10)
bill = service.orders.bill()[0] bill = service.orders.bill()[0]
self.assertEqual(0, bill.get_total()) self.assertEqual(0, bill.get_total())
bp = timezone.now().date() + relativedelta.relativedelta(years=1) bp = timezone.now().date() + relativedelta(years=1)
bill = disk_service.orders.bill(billing_point=bp, fixed_point=True)[0] bill = disk_service.orders.bill(billing_point=bp, fixed_point=True)[0]
self.assertEqual(90, bill.get_total()) self.assertEqual(90, bill.get_total())
mailbox = self.create_mailbox(account=account) mailbox = self.create_mailbox(account=account)
@ -421,38 +487,30 @@ class MailboxBillingTest(BaseBillingTest):
account = self.create_account() account = self.create_account()
mailbox = self.create_mailbox(account=account) mailbox = self.create_mailbox(account=account)
now = timezone.now() now = timezone.now()
bp = now.date() + relativedelta.relativedelta(years=1) bp = now.date() + relativedelta(years=1)
options = dict(billing_point=bp, fixed_point=True, proforma=True, new_open=True)
self.allocate_disk(mailbox, 10) self.allocate_disk(mailbox, 10)
bill = service.orders.bill(billing_point=bp, fixed_point=True, proforma=True, new_open=True)[0] bill = service.orders.bill(**options).pop()
self.assertEqual(9*10, bill.get_total()) self.assertEqual(9*10, bill.get_total())
self.allocate_disk(mailbox, 20) with freeze_time(now+relativedelta(months=6)):
created_on = now+relativedelta.relativedelta(months=6) self.allocate_disk(mailbox, 20)
order = service.orders.get() bill = service.orders.bill(**options).pop()
metric = order.metrics.latest('id') total = 9*10*0.5 + 19*10*0.5
metric.created_on = created_on self.assertEqual(total, bill.get_total())
metric.save()
bill = service.orders.bill(billing_point=bp, fixed_point=True, proforma=True, new_open=True)[0]
self.assertEqual(9*10*0.5 + 19*10*0.5, bill.get_total())
self.allocate_disk(mailbox, 30) with freeze_time(now+relativedelta(months=9)):
created_on = now+relativedelta.relativedelta(months=9) self.allocate_disk(mailbox, 30)
order = service.orders.get() bill = service.orders.bill(**options).pop()
metric = order.metrics.latest('id') total = 9*10*0.5 + 19*10*0.25 + 29*10*0.25
metric.created_on = created_on self.assertEqual(total, bill.get_total())
metric.save()
bill = service.orders.bill(billing_point=bp, fixed_point=True, proforma=True, new_open=True)[0]
self.assertEqual(9*10*0.5 + 19*10*0.25 + 29*10*0.25, bill.get_total())
self.allocate_disk(mailbox, 10) with freeze_time(now+relativedelta(years=1)):
created_on = now+relativedelta.relativedelta(years=1) self.allocate_disk(mailbox, 10)
order = service.orders.get() bill = service.orders.bill(**options).pop()
metric = order.metrics.latest('id') total = 9*10*0.5 + 19*10*0.25 + 29*10*0.25
metric.created_on = created_on self.assertEqual(total, bill.get_total())
metric.save()
bill = service.orders.bill(billing_point=bp, fixed_point=True, proforma=True, new_open=True)[0]
self.assertEqual(9*10*0.5 + 19*10*0.25 + 29*10*0.25, bill.get_total())
class JobBillingTest(BaseBillingTest): class JobBillingTest(BaseBillingTest):
@ -480,9 +538,9 @@ class JobBillingTest(BaseBillingTest):
def create_job(self, amount, account=None): def create_job(self, amount, account=None):
if not account: if not account:
account = self.create_account() account = self.create_account()
job_name = '%s.es' % random_ascii(10) description = 'Random Job %s' % random_ascii(10)
job_service, __ = MiscService.objects.get_or_create(name='job', description='Random job', has_amount=True) service, __ = MiscService.objects.get_or_create(name='job', description=description, has_amount=True)
return Miscellaneous.objects.create(service=job_service, description=job_name, account=account, amount=amount) return Miscellaneous.objects.create(service=service, description=description, account=account, amount=amount)
def test_job(self): def test_job(self):
service = self.create_job_service() service = self.create_job_service()
@ -499,7 +557,22 @@ class JobBillingTest(BaseBillingTest):
class PlanBillingTest(BaseBillingTest): class PlanBillingTest(BaseBillingTest):
def create_plan_service(self): def create_plan_service(self):
pass service = Service.objects.create(
description="Association membership fee",
content_type=ContentType.objects.get_for_model(Miscellaneous),
match="account.is_active and account.type == 'ASSOCIATION'",
billing_period=Service.ANUAL,
billing_point=Service.FIXED_DATE,
is_fee=True,
metric='',
pricing_period=Service.BILLING_PERIOD,
rate_algorithm=Service.STEP_PRICE,
on_cancel=Service.DISCOUNT,
payment_style=Service.PREPAY,
tax=0,
nominal_price=20
)
return service
def create_plan(self): def create_plan(self):
if not account: if not account:

View File

@ -161,7 +161,7 @@ class MonitorData(models.Model):
content_object = GenericForeignKey() content_object = GenericForeignKey()
class Meta: class Meta:
get_latest_by = 'date' get_latest_by = 'id'
verbose_name_plural = _("monitor data") verbose_name_plural = _("monitor data")
def __unicode__(self): def __unicode__(self):

View File

@ -288,7 +288,9 @@ class ServiceHandler(plugins.Plugin):
dsize, new_end = self.apply_compensations(order, only_beyond=True) dsize, new_end = self.apply_compensations(order, only_beyond=True)
cprice += dsize*price cprice += dsize*price
if cprice: if cprice:
discounts = (('compensation', -cprice),) discounts = (
('compensation', -cprice),
)
if new_end: if new_end:
size = self.get_price_size(order.new_billed_until, new_end) size = self.get_price_size(order.new_billed_until, new_end)
price += price*size price += price*size
@ -386,7 +388,9 @@ class ServiceHandler(plugins.Plugin):
discounts = () discounts = ()
dsize, new_end = self.apply_compensations(order) dsize, new_end = self.apply_compensations(order)
if dsize: if dsize:
discounts=(('compensation', -dsize*price),) discounts=(
('compensation', -dsize*price),
)
if new_end: if new_end:
order.new_billed_until = new_end order.new_billed_until = new_end
end = new_end end = new_end

View File

@ -326,7 +326,7 @@ class HandlerTests(BaseTestCase):
rates = [ rates = [
{'price': decimal.Decimal('0.00'), 'quantity': 2}, {'price': decimal.Decimal('0.00'), 'quantity': 2},
{'price': decimal.Decimal('9.00'), 'quantity': 28}, {'price': decimal.Decimal('9.00'), 'quantity': 28},
] ]
for rate, result in zip(rates, results): for rate, result in zip(rates, results):
self.assertEqual(rate['price'], result.price) self.assertEqual(rate['price'], result.price)
self.assertEqual(rate['quantity'], result.quantity) self.assertEqual(rate['quantity'], result.quantity)
@ -337,7 +337,7 @@ class HandlerTests(BaseTestCase):
rates = [ rates = [
{'price': decimal.Decimal('0.00'), 'quantity': 4}, {'price': decimal.Decimal('0.00'), 'quantity': 4},
{'price': decimal.Decimal('9.00'), 'quantity': 26}, {'price': decimal.Decimal('9.00'), 'quantity': 26},
] ]
for rate, result in zip(rates, results): for rate, result in zip(rates, results):
self.assertEqual(rate['price'], result.price) self.assertEqual(rate['price'], result.price)
self.assertEqual(rate['quantity'], result.quantity) self.assertEqual(rate['quantity'], result.quantity)
@ -348,7 +348,7 @@ class HandlerTests(BaseTestCase):
rates = [ rates = [
{'price': decimal.Decimal('0.00'), 'quantity': 6}, {'price': decimal.Decimal('0.00'), 'quantity': 6},
{'price': decimal.Decimal('9.00'), 'quantity': 24}, {'price': decimal.Decimal('9.00'), 'quantity': 24},
] ]
for rate, result in zip(rates, results): for rate, result in zip(rates, results):
self.assertEqual(rate['price'], result.price) self.assertEqual(rate['price'], result.price)
self.assertEqual(rate['quantity'], result.quantity) self.assertEqual(rate['quantity'], result.quantity)
@ -366,3 +366,6 @@ class HandlerTests(BaseTestCase):
lines = service.handler.generate_bill_lines(orders, account, commit=False) lines = service.handler.generate_bill_lines(orders, account, commit=False)
print lines print lines
print len(lines) print len(lines)
# TODO
# TODO test incomplete rate 1 -> nominal_price 10 -> rate

View File

@ -13,7 +13,9 @@ from .. import settings
class Apache2Backend(ServiceController): class Apache2Backend(ServiceController):
model = 'websites.Website' model = 'websites.Website'
related_models = (('websites.Content', 'website'),) related_models = (
('websites.Content', 'website'),
)
verbose_name = _("Apache 2") verbose_name = _("Apache 2")
def save(self, site): def save(self, site):

View File

@ -82,7 +82,7 @@ export -f get_orchestra_dir
function print_install_requirements_help () { function print_install_requirements_help () {
cat <<- EOF cat <<- EOF
${bold}NAME${normal} ${bold}NAME${normal}
${bold}orchetsra-admin install_requirements${normal} - Installs all Orchestra requirements using apt-get and pip ${bold}orchetsra-admin install_requirements${normal} - Installs all Orchestra requirements using apt-get and pip
@ -157,7 +157,8 @@ function install_requirements () {
iceweasel" iceweasel"
PIP="${PIP} \ PIP="${PIP} \
selenium \ selenium \
xvfbwrapper" xvfbwrapper \
freezegun"
fi fi
# Make sure locales are in place before installing postgres # Make sure locales are in place before installing postgres
@ -253,6 +254,7 @@ function print_install_certificate_help () {
EOF EOF
} }
function install_certificate () { function install_certificate () {
opts=$(getopt -o h -l help -- "$@") || exit 1 opts=$(getopt -o h -l help -- "$@") || exit 1
set -- $opts set -- $opts
@ -311,7 +313,6 @@ function uninstall_certificate () {
export -f uninstall_certificate export -f uninstall_certificate
function print_install_postfix_help () { function print_install_postfix_help () {
cat <<- EOF cat <<- EOF
@ -329,7 +330,7 @@ function print_install_postfix_help () {
function install_postfix () { function install_postfix () {
opts=$(getopt -o h -l help -- "$@") || exit 1 opts=$(getopt -o h -l help -- "$@") || exit 1
set -- $opts set -- $opts
while [ $# -gt 0 ]; do while [ $# -gt 0 ]; do
case $1 in case $1 in
-h|--help) print_deploy_help; exit 0 ;; -h|--help) print_deploy_help; exit 0 ;;
@ -364,6 +365,7 @@ function install_postfix () {
} }
export -f install_postfix export -f install_postfix
function print_uninstall_postfix_help () { function print_uninstall_postfix_help () {
cat <<- EOF cat <<- EOF