Skip to content

Commit

Permalink
Merge pull request #6 from moshthepitt/issue-3
Browse files Browse the repository at this point in the history
Prevent overlapping overtime and overlapping leave days
  • Loading branch information
moshthepitt authored Jun 19, 2018
2 parents 2c56a68 + 702908a commit 675c1b9
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 0 deletions.
33 changes: 33 additions & 0 deletions small_small_hr/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from datetime import datetime, time

from django import forms
from django.db.models import Q
from django.conf import settings
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
Expand Down Expand Up @@ -102,11 +103,29 @@ def clean(self):
cleaned_data = super().clean()
end = cleaned_data.get('end')
start = cleaned_data.get('start')
date = cleaned_data.get('date')
staff = cleaned_data.get('staff')

# end must be later than start
if end <= start:
self.add_error('end', _("end must be greater than start"))

# must not overlap within the same date
# pylint: disable=no-member
overlap_qs = OverTime.objects.filter(
date=date, staff=staff, status=OverTime.APPROVED).filter(
Q(start__gte=start) | Q(end__lte=end))

if self.instance is not None:
overlap_qs = overlap_qs.exclude(id=self.instance.id)

if overlap_qs.exists():
msg = _('you cannot have overlapping overtime hours on the '
'same day')
self.add_error('start', msg)
self.add_error('end', msg)
self.add_error('date', msg)


class ApplyOverTimeForm(OverTimeForm):
"""
Expand Down Expand Up @@ -253,6 +272,20 @@ def clean(self):
self.add_error('start', msg)
self.add_error('end', msg)

# must not overlap
# pylint: disable=no-member
overlap_qs = Leave.objects.filter(
staff=staff, status=Leave.APPROVED, leave_type=leave_type).filter(
Q(start__gte=start) | Q(end__lte=end))

if self.instance is not None:
overlap_qs = overlap_qs.exclude(id=self.instance.id)

if overlap_qs.exists():
msg = _('you cannot have overlapping leave days')
self.add_error('start', msg)
self.add_error('end', msg)


class ApplyLeaveForm(LeaveForm):
"""
Expand Down
92 changes: 92 additions & 0 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,51 @@ def test_overtime_form_apply(self):
self.assertEqual(OverTime.PENDING, overtime.status)
self.assertEqual('', overtime.comments)

def test_overtime_form_apply_no_overlap(self):
"""
Test no overlaps on OverTime
"""
user = mommy.make('auth.User', first_name='Bob', last_name='Ndoe')
staffprofile = mommy.make('small_small_hr.StaffProfile', user=user)

request = self.factory.get('/')
request.session = {}
request.user = AnonymousUser()

# 6 hours of overtime
start = datetime(
2017, 6, 5, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
end = datetime(
2017, 6, 5, 6, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))

mommy.make(
'small_small_hr.OverTime', start=start.time(), end=end.time(),
status=OverTime.APPROVED, date=start.date, staff=staffprofile)

data = {
'staff': staffprofile.id,
'date': start.date(),
'start': start.time(),
'end': end.time(),
'reason': 'Extra work',
}

form = ApplyOverTimeForm(data=data)
self.assertFalse(form.is_valid())
self.assertEqual(3, len(form.errors.keys()))
self.assertEqual(
'you cannot have overlapping overtime hours on the same day',
form.errors['start'][0]
)
self.assertEqual(
'you cannot have overlapping overtime hours on the same day',
form.errors['date'][0]
)
self.assertEqual(
'you cannot have overlapping overtime hours on the same day',
form.errors['end'][0]
)

def test_overtime_form_process(self):
"""
Test OverTimeForm
Expand Down Expand Up @@ -208,6 +253,53 @@ def test_leaveform_apply(self):
self.assertEqual(Leave.PENDING, leave.status)
self.assertEqual('', leave.comments)

def test_leaveform_no_overlap(self):
"""
Test LeaveForm no overlap
"""
user = mommy.make('auth.User', first_name='Bob', last_name='Ndoe')
staffprofile = mommy.make('small_small_hr.StaffProfile', user=user)
staffprofile.leave_days = 21
staffprofile.sick_days = 10
staffprofile.save()

request = self.factory.get('/')
request.session = {}
request.user = AnonymousUser()

# 6 days of leave
start = datetime(
2017, 6, 5, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
end = datetime(
2017, 6, 10, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))

mommy.make('small_small_hr.AnnualLeave', staff=staffprofile, year=2017,
leave_type=Leave.REGULAR, carried_over_days=12)

mommy.make('small_small_hr.Leave', leave_type=Leave.REGULAR,
start=start, end=end, status=Leave.APPROVED,
staff=staffprofile)

data = {
'staff': staffprofile.id,
'leave_type': Leave.REGULAR,
'start': start,
'end': end,
'reason': 'Need a break',
}

form = ApplyLeaveForm(data=data)
self.assertFalse(form.is_valid())
self.assertEqual(2, len(form.errors.keys()))
self.assertEqual(
'you cannot have overlapping leave days',
form.errors['start'][0]
)
self.assertEqual(
'you cannot have overlapping leave days',
form.errors['end'][0]
)

def test_leaveform_admin(self):
"""
Test LeaveForm apply for leave
Expand Down

0 comments on commit 675c1b9

Please sign in to comment.