Skip to content

Commit

Permalink
Allow rejecting leave/overtime even when an overlapping approved obje…
Browse files Browse the repository at this point in the history
…ct exists
  • Loading branch information
moshthepitt committed Feb 12, 2019
1 parent c6771fc commit 6d53033
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = "pypi"
python_version = "3.6"

[packages]
"e1839a8" = {editable = true, path = "."}
e1839a8 = {editable = true,path = "."}

[dev-packages]
"flake8" = "*"
Expand Down
10 changes: 6 additions & 4 deletions small_small_hr/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,13 @@ def clean(self):
start = cleaned_data.get('start')
date = cleaned_data.get('date')
staff = cleaned_data.get('staff')
status = cleaned_data.get('status')

# 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
# must not overlap within the same date unless being rejected
# pylint: disable=no-member
overlap_qs = OverTime.objects.filter(
date=date, staff=staff, status=OverTime.APPROVED).filter(
Expand All @@ -196,7 +197,7 @@ def clean(self):
if self.instance is not None:
overlap_qs = overlap_qs.exclude(id=self.instance.id)

if overlap_qs.exists():
if overlap_qs.exists() and status != OverTime.REJECTED:
msg = _('you cannot have overlapping overtime hours on the '
'same day')
self.add_error('start', msg)
Expand Down Expand Up @@ -337,6 +338,7 @@ def clean(self):
staff = cleaned_data.get('staff')
end = cleaned_data.get('end')
start = cleaned_data.get('start')
status = cleaned_data.get('status')

if all([staff, leave_type, start, end]):
# end year and start year must be the same
Expand Down Expand Up @@ -369,7 +371,7 @@ def clean(self):
self.add_error('start', msg)
self.add_error('end', msg)

# must not overlap
# must not overlap unless it is being rejected
# pylint: disable=no-member
overlap_qs = Leave.objects.filter(
staff=staff,
Expand All @@ -380,7 +382,7 @@ def clean(self):
if self.instance is not None:
overlap_qs = overlap_qs.exclude(id=self.instance.id)

if overlap_qs.exists():
if overlap_qs.exists() and status != Leave.REJECTED:
msg = _('you cannot have overlapping leave days')
self.add_error('start', msg)
self.add_error('end', msg)
Expand Down
99 changes: 99 additions & 0 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,52 @@ def test_overtime_form_process(self):
self.assertEqual(OverTime.APPROVED, overtime.status)
self.assertEqual('Cool', overtime.comments)

def test_overtime_form_process_with_overlap(self):
"""
Test OverTimeForm with overlap for existing objects
"""
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, 18, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
end = datetime(
2017, 6, 5, 19, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))

# make sure object already exists
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',
'status': OverTime.REJECTED,
'comments': 'Already there'
}

form = OverTimeForm(data=data)
self.assertTrue(form.is_valid())
overtime = form.save()
self.assertEqual(staffprofile, overtime.staff)
self.assertEqual(start.date(), overtime.date)
self.assertEqual(start.time(), overtime.start)
self.assertEqual(end.time(), overtime.end)
self.assertEqual(
timedelta(seconds=3600).seconds,
overtime.get_duration().seconds)
self.assertEqual('Extra work', overtime.reason)
self.assertEqual(OverTime.REJECTED, overtime.status)
self.assertEqual('Already there', overtime.comments)

def test_overtime_form_start_end(self):
"""
Test OverTimeForm start end fields
Expand Down Expand Up @@ -657,6 +703,59 @@ def test_leaveform_process(self):
self.assertEqual(Leave.REJECTED, leave.status)
self.assertEqual('Just no', leave.comments)

@override_settings(SSHR_DEFAULT_TIME=7)
def test_leaveform_process_with_overlap(self):
"""
Test LeaveForm process works even if leave object exists
"""
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, 7, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
end = datetime(
2017, 6, 10, 7, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))

# make sure leave obj already exists for said dates
mommy.make(
'small_small_hr.Leave', staff=staffprofile, start=start,
end=end, leave_type=Leave.REGULAR,
status=Leave.APPROVED)

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

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

form = LeaveForm(data=data)
self.assertTrue(form.is_valid())
leave = form.save()
self.assertEqual(staffprofile, leave.staff)
self.assertEqual(Leave.REGULAR, leave.leave_type)
self.assertEqual(start, leave.start)
self.assertEqual(end, leave.end)
self.assertEqual(
timedelta(days=5).days, (leave.end - leave.start).days)
self.assertEqual('Need a break', leave.reason)
self.assertEqual(Leave.REJECTED, leave.status)
self.assertEqual('Already exists', leave.comments)

@override_settings(SSHR_DEFAULT_TIME=7)
def test_sickleave_apply(self):
"""
Expand Down

0 comments on commit 6d53033

Please sign in to comment.