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')
|
||||
|
||||
|
||||
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):
|
||||
"""
|
||||
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.end, 'end')
|
||||
validate_duration(self)
|
||||
validate_unique_period(Feeding.objects.filter(child=self.child), self)
|
||||
|
||||
# "Formula" Type may only be associated with "Bottle" Method.
|
||||
if self.type == 'formula'and self.method != 'bottle':
|
||||
|
@ -216,6 +233,7 @@ class Sleep(models.Model):
|
|||
validate_time(self.start, 'start')
|
||||
validate_time(self.end, 'end')
|
||||
validate_duration(self)
|
||||
validate_unique_period(Sleep.objects.filter(child=self.child), self)
|
||||
|
||||
|
||||
class Timer(models.Model):
|
||||
|
@ -304,3 +322,4 @@ class TummyTime(models.Model):
|
|||
validate_time(self.start, 'start')
|
||||
validate_time(self.end, 'end')
|
||||
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)
|
||||
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)
|
||||
self.assertEqual(page.status_code, 302)
|
||||
|
||||
|
@ -107,7 +110,7 @@ class FormsTestCase(TestCase):
|
|||
page, 'form', 'method',
|
||||
'Only "Bottle" method is allowed with "Formula" type.')
|
||||
|
||||
def test_sleeping_forms(self):
|
||||
def test_sleep_forms(self):
|
||||
params = {
|
||||
'child': 1,
|
||||
'start': '2000-01-01 1:01',
|
||||
|
@ -119,6 +122,9 @@ class FormsTestCase(TestCase):
|
|||
page = self.c.post('/sleep/add/?timer={}'.format(timer.id), params)
|
||||
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()
|
||||
page = self.c.post('/sleep/{}/'.format(entry.id), params)
|
||||
self.assertEqual(page.status_code, 302)
|
||||
|
@ -167,11 +173,14 @@ class FormsTestCase(TestCase):
|
|||
'/tummy-time/add/?timer={}'.format(timer.id), params)
|
||||
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()
|
||||
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
|
||||
self.assertEqual(page.status_code, 302)
|
||||
|
||||
def test_validators(self):
|
||||
def test_validate_duration(self):
|
||||
params = {
|
||||
'child': 1,
|
||||
'start': '2001-01-01 1:01',
|
||||
|
@ -190,9 +199,43 @@ class FormsTestCase(TestCase):
|
|||
self.assertEqual(page.status_code, 200)
|
||||
self.assertFormError(page, 'form', None, 'Duration too long.')
|
||||
|
||||
tomorrow = (timezone.localtime() + timezone.timedelta(days=1))
|
||||
params['end'] = tomorrow.strftime('%Y-%m-%d %H:%M:%S')
|
||||
def test_validate_time(self):
|
||||
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)
|
||||
self.assertEqual(page.status_code, 200)
|
||||
self.assertFormError(page, 'form', 'end',
|
||||
'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