mirror of https://github.com/snachodog/mybuddy.git
Add date intersection validation for models with start and end dates.
This commit is contained in:
parent
08d6efa98b
commit
e6acfe4e75
|
@ -26,6 +26,22 @@ def validate_duration(model, max_duration=timedelta(hours=24)):
|
||||||
raise ValidationError('Duration too long.', code='max_duration')
|
raise ValidationError('Duration too long.', code='max_duration')
|
||||||
|
|
||||||
|
|
||||||
|
def validate_unique_period(queryset, model):
|
||||||
|
"""
|
||||||
|
Confirm that model's start and end date do not intersect with other
|
||||||
|
instances.
|
||||||
|
:param queryset: a queryset of instances to check against.
|
||||||
|
:param model: a model instance with 'start' and 'end' attributes
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
if model.id:
|
||||||
|
queryset = queryset.exclude(id=model.id)
|
||||||
|
if queryset.filter(start__lte=model.end, end__gte=model.start):
|
||||||
|
raise ValidationError(
|
||||||
|
'Another entry already exists within the specified time period.',
|
||||||
|
code='period_intersection')
|
||||||
|
|
||||||
|
|
||||||
def validate_time(time, field_name):
|
def validate_time(time, field_name):
|
||||||
"""
|
"""
|
||||||
Confirm that a time is not in the future.
|
Confirm that a time is not in the future.
|
||||||
|
@ -149,6 +165,7 @@ class Feeding(models.Model):
|
||||||
validate_time(self.start, 'start')
|
validate_time(self.start, 'start')
|
||||||
validate_time(self.end, 'end')
|
validate_time(self.end, 'end')
|
||||||
validate_duration(self)
|
validate_duration(self)
|
||||||
|
validate_unique_period(Feeding.objects.filter(child=self.child), self)
|
||||||
|
|
||||||
# "Formula" Type may only be associated with "Bottle" Method.
|
# "Formula" Type may only be associated with "Bottle" Method.
|
||||||
if self.type == 'formula'and self.method != 'bottle':
|
if self.type == 'formula'and self.method != 'bottle':
|
||||||
|
@ -216,6 +233,7 @@ class Sleep(models.Model):
|
||||||
validate_time(self.start, 'start')
|
validate_time(self.start, 'start')
|
||||||
validate_time(self.end, 'end')
|
validate_time(self.end, 'end')
|
||||||
validate_duration(self)
|
validate_duration(self)
|
||||||
|
validate_unique_period(Sleep.objects.filter(child=self.child), self)
|
||||||
|
|
||||||
|
|
||||||
class Timer(models.Model):
|
class Timer(models.Model):
|
||||||
|
@ -304,3 +322,4 @@ class TummyTime(models.Model):
|
||||||
validate_time(self.start, 'start')
|
validate_time(self.start, 'start')
|
||||||
validate_time(self.end, 'end')
|
validate_time(self.end, 'end')
|
||||||
validate_duration(self)
|
validate_duration(self)
|
||||||
|
validate_unique_period(TummyTime.objects.filter(child=self.child), self)
|
||||||
|
|
|
@ -97,6 +97,9 @@ class FormsTestCase(TestCase):
|
||||||
page = self.c.post('/feedings/add/?timer={}'.format(timer.id), params)
|
page = self.c.post('/feedings/add/?timer={}'.format(timer.id), params)
|
||||||
self.assertEqual(page.status_code, 302)
|
self.assertEqual(page.status_code, 302)
|
||||||
|
|
||||||
|
# Change start and end to prevent intersection validation errors.
|
||||||
|
params['start'] = '2000-01-01 2:01'
|
||||||
|
params['end'] = '2000-01-01 2:31'
|
||||||
page = self.c.post('/feedings/{}/'.format(entry.id), params)
|
page = self.c.post('/feedings/{}/'.format(entry.id), params)
|
||||||
self.assertEqual(page.status_code, 302)
|
self.assertEqual(page.status_code, 302)
|
||||||
|
|
||||||
|
@ -107,7 +110,7 @@ class FormsTestCase(TestCase):
|
||||||
page, 'form', 'method',
|
page, 'form', 'method',
|
||||||
'Only "Bottle" method is allowed with "Formula" type.')
|
'Only "Bottle" method is allowed with "Formula" type.')
|
||||||
|
|
||||||
def test_sleeping_forms(self):
|
def test_sleep_forms(self):
|
||||||
params = {
|
params = {
|
||||||
'child': 1,
|
'child': 1,
|
||||||
'start': '2000-01-01 1:01',
|
'start': '2000-01-01 1:01',
|
||||||
|
@ -119,6 +122,9 @@ class FormsTestCase(TestCase):
|
||||||
page = self.c.post('/sleep/add/?timer={}'.format(timer.id), params)
|
page = self.c.post('/sleep/add/?timer={}'.format(timer.id), params)
|
||||||
self.assertEqual(page.status_code, 302)
|
self.assertEqual(page.status_code, 302)
|
||||||
|
|
||||||
|
# Change start and end to prevent intersection validation errors.
|
||||||
|
params['start'] = '2000-01-01 4:01'
|
||||||
|
params['end'] = '2000-01-01 6:01'
|
||||||
entry = models.Sleep.objects.first()
|
entry = models.Sleep.objects.first()
|
||||||
page = self.c.post('/sleep/{}/'.format(entry.id), params)
|
page = self.c.post('/sleep/{}/'.format(entry.id), params)
|
||||||
self.assertEqual(page.status_code, 302)
|
self.assertEqual(page.status_code, 302)
|
||||||
|
@ -167,11 +173,14 @@ class FormsTestCase(TestCase):
|
||||||
'/tummy-time/add/?timer={}'.format(timer.id), params)
|
'/tummy-time/add/?timer={}'.format(timer.id), params)
|
||||||
self.assertEqual(page.status_code, 302)
|
self.assertEqual(page.status_code, 302)
|
||||||
|
|
||||||
|
# Change start and end to prevent intersection validation errors.
|
||||||
|
params['start'] = '2000-01-01 2:01'
|
||||||
|
params['end'] = '2000-01-01 2:11'
|
||||||
entry = models.TummyTime.objects.first()
|
entry = models.TummyTime.objects.first()
|
||||||
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
|
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
|
||||||
self.assertEqual(page.status_code, 302)
|
self.assertEqual(page.status_code, 302)
|
||||||
|
|
||||||
def test_validators(self):
|
def test_validate_duration(self):
|
||||||
params = {
|
params = {
|
||||||
'child': 1,
|
'child': 1,
|
||||||
'start': '2001-01-01 1:01',
|
'start': '2001-01-01 1:01',
|
||||||
|
@ -190,9 +199,43 @@ class FormsTestCase(TestCase):
|
||||||
self.assertEqual(page.status_code, 200)
|
self.assertEqual(page.status_code, 200)
|
||||||
self.assertFormError(page, 'form', None, 'Duration too long.')
|
self.assertFormError(page, 'form', None, 'Duration too long.')
|
||||||
|
|
||||||
tomorrow = (timezone.localtime() + timezone.timedelta(days=1))
|
def test_validate_time(self):
|
||||||
params['end'] = tomorrow.strftime('%Y-%m-%d %H:%M:%S')
|
future = (timezone.localtime() + timezone.timedelta(hours=1))
|
||||||
|
params = {
|
||||||
|
'child': 1,
|
||||||
|
'start': timezone.localtime().strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
'end': future.strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
|
'milestone': ''
|
||||||
|
}
|
||||||
|
entry = models.TummyTime.objects.first()
|
||||||
|
|
||||||
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
|
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
|
||||||
self.assertEqual(page.status_code, 200)
|
self.assertEqual(page.status_code, 200)
|
||||||
self.assertFormError(page, 'form', 'end',
|
self.assertFormError(page, 'form', 'end',
|
||||||
'Date/time can not be in the future.')
|
'Date/time can not be in the future.')
|
||||||
|
|
||||||
|
def test_validate_unique_period(self):
|
||||||
|
entry = models.TummyTime.objects.first()
|
||||||
|
base_time = timezone.localtime()
|
||||||
|
new_entry = models.TummyTime.objects.create(
|
||||||
|
child=entry.child,
|
||||||
|
start=base_time - timezone.timedelta(minutes=45),
|
||||||
|
end=base_time - timezone.timedelta(minutes=15),
|
||||||
|
)
|
||||||
|
new_entry.save()
|
||||||
|
|
||||||
|
params = {
|
||||||
|
'child': 1,
|
||||||
|
'start': (base_time - timezone.timedelta(minutes=35)).strftime(
|
||||||
|
'%Y-%m-%d %H:%M'),
|
||||||
|
'end': (base_time - timezone.timedelta(minutes=5)).strftime(
|
||||||
|
'%Y-%m-%d %H:%M'),
|
||||||
|
'milestone': ''
|
||||||
|
}
|
||||||
|
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
|
||||||
|
self.assertEqual(page.status_code, 200)
|
||||||
|
self.assertFormError(
|
||||||
|
page,
|
||||||
|
'form',
|
||||||
|
None,
|
||||||
|
'Another entry already exists within the specified time period.')
|
||||||
|
|
Loading…
Reference in New Issue