Skip to content

Commit

Permalink
Merge pull request #7 from moshthepitt/issue-1
Browse files Browse the repository at this point in the history
Add utils to create annual leave objects
  • Loading branch information
moshthepitt authored Jun 19, 2018
2 parents 675c1b9 + e9dc29e commit 75b112f
Show file tree
Hide file tree
Showing 9 changed files with 258 additions and 10 deletions.
42 changes: 41 additions & 1 deletion small_small_hr/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,47 @@
from phonenumber_field.formfields import PhoneNumberField

from small_small_hr.models import (TWOPLACES, Leave, OverTime, Role,
StaffDocument, StaffProfile)
StaffDocument, StaffProfile, AnnualLeave)


class AnnualLeaveForm(forms.ModelForm):
"""
Form used when managing AnnualLeave
"""

class Meta: # pylint: disable=too-few-public-methods
"""
Class meta options
"""
model = AnnualLeave
fields = [
'staff',
'year',
'leave_type',
'allowed_days',
'carried_over_days'
]

def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = True
self.helper.form_method = 'post'
self.helper.render_required_fields = True
self.helper.form_show_labels = True
self.helper.html5_required = True
self.helper.form_id = 'annual-leave-form'
self.helper.layout = Layout(
Field('staff',),
Field('year',),
Field('leave_type',),
Field('allowed_days',),
Field('carried_over_days'),
FormActions(
Submit('submitBtn', _('Submit'), css_class='btn-primary'),
)
)


class RoleForm(forms.ModelForm):
Expand Down
4 changes: 2 additions & 2 deletions small_small_hr/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 2.0.6 on 2018-06-17 09:21
# Generated by Django 2.0.6 on 2018-06-19 19:22

from django.conf import settings
import django.contrib.postgres.fields.jsonb
Expand Down Expand Up @@ -57,7 +57,7 @@ class Migration(migrations.Migration):
default=0,
help_text=
'Number of leave days carried over into this year.',
verbose_name='Carried Leave days')),
verbose_name='Carried Over Leave days')),
],
options={
'verbose_name': 'Annual Leave',
Expand Down
2 changes: 1 addition & 1 deletion small_small_hr/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ class AnnualLeave(TimeStampedModel, models.Model):
_('Allowed Leave days'), default=21, blank=True,
help_text=_('Number of leave days allowed in a year.'))
carried_over_days = models.PositiveIntegerField(
_('Carried Leave days'), default=0, blank=True,
_('Carried Over Leave days'), default=0, blank=True,
help_text=_('Number of leave days carried over into this year.'))

class Meta(object): # pylint: disable=too-few-public-methods
Expand Down
57 changes: 57 additions & 0 deletions small_small_hr/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"""
Utils module for small small hr
"""
from django.conf import settings

from small_small_hr.models import AnnualLeave, Leave

MAX_CARRY_OVER = getattr(settings, 'SSHR_MAX_CARRY_OVER', 10)


def get_carry_over(staffprofile: object, year: int, leave_type: str):
"""
Get carried over leave days
"""
# pylint: disable=no-member
if leave_type == Leave.REGULAR:
previous_obj = AnnualLeave.objects.filter(
staff=staffprofile, year=year-1, leave_type=leave_type).first()
if previous_obj:
remaining = previous_obj.get_available_leave_days()
max_carry_over = MAX_CARRY_OVER
if remaining > max_carry_over:
carry_over = max_carry_over
else:
carry_over = remaining

return carry_over

return 0


def create_annual_leave(staffprofile: object, year: int, leave_type: str):
"""
Creates an annuall leave object for the staff member
"""
# pylint: disable=no-member
try:
annual_leave = AnnualLeave.objects.get(
staff=staffprofile, year=year, leave_type=leave_type)
except AnnualLeave.DoesNotExist:
carry_over = get_carry_over(staffprofile, year, leave_type)

if leave_type == Leave.REGULAR:
allowed_days = staffprofile.leave_days
elif leave_type == Leave.SICK:
allowed_days = staffprofile.sick_days

annual_leave = AnnualLeave(
staff=staffprofile,
year=year,
leave_type=leave_type,
allowed_days=allowed_days,
carried_over_days=carry_over
)
annual_leave.save()

return annual_leave
53 changes: 50 additions & 3 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
import pytz
from model_mommy import mommy

from small_small_hr.forms import (ApplyLeaveForm, ApplyOverTimeForm, LeaveForm,
OverTimeForm, RoleForm, StaffDocumentForm,
from small_small_hr.forms import (AnnualLeaveForm, ApplyLeaveForm,
ApplyOverTimeForm, LeaveForm, OverTimeForm,
RoleForm, StaffDocumentForm,
StaffProfileAdminCreateForm,
StaffProfileAdminForm, StaffProfileUserForm)
from small_small_hr.models import Leave, OverTime, StaffProfile
Expand All @@ -24,7 +25,7 @@

class TestForms(TestCase):
"""
Test class for Scam models
Test class for forms
"""

def setUp(self):
Expand All @@ -33,6 +34,52 @@ def setUp(self):
"""
self.factory = RequestFactory()

def test_annual_leave_form(self):
"""
Test AnnualLeaveForm
"""
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()

data = {
'staff': staffprofile.id,
'year': 2018,
'leave_type': Leave.REGULAR,
'allowed_days': 21,
'carried_over_days': 10
}

form = AnnualLeaveForm(data=data)
self.assertTrue(form.is_valid())
annual_leave = form.save()
self.assertEqual(staffprofile, annual_leave.staff)
self.assertEqual(2018, annual_leave.year)
self.assertEqual(21, annual_leave.allowed_days)
self.assertEqual(10, annual_leave.carried_over_days)
self.assertEqual(Leave.REGULAR, annual_leave.leave_type)

data2 = {
'staff': staffprofile.id,
'year': 2017,
'leave_type': Leave.REGULAR,
'allowed_days': 21,
'carried_over_days': 5
}

form = AnnualLeaveForm(data=data2, instance=annual_leave)
self.assertTrue(form.is_valid())
form.save()
annual_leave.refresh_from_db()
self.assertEqual(staffprofile, annual_leave.staff)
self.assertEqual(2017, annual_leave.year)
self.assertEqual(21, annual_leave.allowed_days)
self.assertEqual(5, annual_leave.carried_over_days)
self.assertEqual(Leave.REGULAR, annual_leave.leave_type)

def test_role_form(self):
"""
Test RoleForm
Expand Down
2 changes: 1 addition & 1 deletion tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

class TestModels(TestCase):
"""
Test class for Scam models
Test class for models
"""

def test_annualleave_str(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class TestSerializers(TestCase):
"""
Test class for Scam models
Test class for serializers
"""

def test_staffprofileserializer_fields(self):
Expand Down
2 changes: 1 addition & 1 deletion tests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

class TestSignals(TestCase):
"""
Test class for Scam models
Test class for signals
"""

def setUp(self):
Expand Down
104 changes: 104 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""
Module to test small_small_hr Signals
"""
from datetime import datetime

from django.conf import settings
from django.test import TestCase

import pytz
from model_mommy import mommy

from small_small_hr.models import Leave, StaffProfile
from small_small_hr.utils import create_annual_leave, get_carry_over


class TestUtils(TestCase):
"""
Test class for utils
"""

def test_get_carry_over(self):
"""
Test get_carry_over
"""
user = mommy.make('auth.User', id=23)
StaffProfile.objects.all().delete()
staffprofile = mommy.make('small_small_hr.StaffProfile', user=user)

self.assertEqual(
0,
get_carry_over(staffprofile, 2017, Leave.REGULAR)
)

create_annual_leave(staffprofile, 2016, Leave.REGULAR)

# carry over should be 10 because the balance is 21
self.assertEqual(
10,
get_carry_over(staffprofile, 2017, Leave.REGULAR)
)

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

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

# carry over should be 9 => 21-12
self.assertEqual(
9,
get_carry_over(staffprofile, 2017, Leave.REGULAR)
)

# no sick leave carry over
create_annual_leave(staffprofile, 2016, Leave.SICK)

self.assertEqual(
0,
get_carry_over(staffprofile, 2017, Leave.SICK)
)

def test_create_annual_leave(self):
"""
Test create_annual_leave
"""
user = mommy.make('auth.User', id=56)
StaffProfile.objects.all().delete()
staffprofile = mommy.make('small_small_hr.StaffProfile', user=user)

obj = create_annual_leave(staffprofile, 2016, Leave.REGULAR)

self.assertEqual(staffprofile, obj.staff)
self.assertEqual(2016, obj.year)
self.assertEqual(0, obj.carried_over_days)
self.assertEqual(21, obj.allowed_days)
self.assertEqual(Leave.REGULAR, obj.leave_type)

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

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

obj2 = create_annual_leave(staffprofile, 2017, Leave.REGULAR)
self.assertEqual(staffprofile, obj2.staff)
self.assertEqual(2017, obj2.year)
self.assertEqual(9, obj2.carried_over_days)
self.assertEqual(21, obj2.allowed_days)
self.assertEqual(Leave.REGULAR, obj2.leave_type)

obj3 = create_annual_leave(staffprofile, 2018, Leave.SICK)
self.assertEqual(staffprofile, obj3.staff)
self.assertEqual(2018, obj3.year)
self.assertEqual(0, obj3.carried_over_days)
self.assertEqual(10, obj3.allowed_days)
self.assertEqual(Leave.SICK, obj3.leave_type)

0 comments on commit 75b112f

Please sign in to comment.