Commit bf1dcce6 authored by Michal Čihař's avatar Michal Čihař

Add interval validation and tests for it

Signed-off-by: default avatarMichal Čihař <michal@cihar.com>
parent 7352a459
...@@ -23,7 +23,9 @@ from __future__ import unicode_literals ...@@ -23,7 +23,9 @@ from __future__ import unicode_literals
from datetime import timedelta from datetime import timedelta
from django.db import models from django.db import models
from django.db.models import Q
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from django.utils import timezone from django.utils import timezone
...@@ -161,3 +163,15 @@ class Invoice(models.Model): ...@@ -161,3 +163,15 @@ class Invoice(models.Model):
def __str__(self): def __str__(self):
return '{0} - {1}: {2}'.format(self.start, self.end, self.billing) return '{0} - {1}: {2}'.format(self.start, self.end, self.billing)
def clean(self):
if self.end <= self.start:
raise ValidationError('Start has be to before end!')
overlapping = Invoice.objects.filter(
(Q(start__lte=self.end) & Q(end__gte=self.end)) |
(Q(start__lte=self.start) & Q(end__gte=self.start))
).filter(billing=self.billing)
if overlapping.exists():
raise ValidationError(
'Overlapping invoices exist: {0}'.format(overlapping)
)
...@@ -24,6 +24,7 @@ from six import StringIO ...@@ -24,6 +24,7 @@ from six import StringIO
from django.test import TestCase from django.test import TestCase
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.core.management import call_command from django.core.management import call_command
from django.utils import timezone from django.utils import timezone
...@@ -38,8 +39,8 @@ class BillingTest(TestCase): ...@@ -38,8 +39,8 @@ class BillingTest(TestCase):
self.billing = Billing.objects.create(user=self.user, plan=self.plan) self.billing = Billing.objects.create(user=self.user, plan=self.plan)
self.invoice = Invoice.objects.create( self.invoice = Invoice.objects.create(
billing=self.billing, billing=self.billing,
start=timezone.now() - timedelta(days=2), start=timezone.now().date() - timedelta(days=2),
end=timezone.now() + timedelta(days=2), end=timezone.now().date() + timedelta(days=2),
payment=10, payment=10,
) )
self.projectnum = 0 self.projectnum = 0
...@@ -78,3 +79,46 @@ class BillingTest(TestCase): ...@@ -78,3 +79,46 @@ class BillingTest(TestCase):
'Following billings are over limit:\n * bill (test)\n' 'Following billings are over limit:\n * bill (test)\n'
'Following billings are past due date:\n * bill (test)\n' 'Following billings are past due date:\n * bill (test)\n'
) )
def test_invoice_validation(self):
invoice = Invoice(
billing=self.billing,
start=self.invoice.start,
end=self.invoice.end,
payment=30
)
# Full overlap
self.assertRaises(
ValidationError,
invoice.clean
)
# Start overlap
invoice.start = self.invoice.end + timedelta(days=1)
self.assertRaises(
ValidationError,
invoice.clean
)
# Zero interval
invoice.end = self.invoice.end + timedelta(days=1)
self.assertRaises(
ValidationError,
invoice.clean
)
# Valid after existing
invoice.end = self.invoice.end + timedelta(days=2)
invoice.clean()
# End overlap
invoice.start = self.invoice.start - timedelta(days=4)
invoice.end = self.invoice.end
self.assertRaises(
ValidationError,
invoice.clean
)
# Valid before existing
invoice.end = self.invoice.start - timedelta(days=1)
invoice.clean()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment