Skip to content

Commit cecfe4f

Browse files
authored
Merge pull request #41 from moshthepitt/day-count
Implement better leave day count
2 parents 21b410b + c9a4efc commit cecfe4f

9 files changed

+94
-13
lines changed

small_small_hr/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Main init file for small_small_hr."""
2-
VERSION = (0, 3, 0)
2+
VERSION = (0, 4, 0)
33
__version__ = ".".join(str(v) for v in VERSION)
44
# pylint: disable=invalid-name
55
default_app_config = "small_small_hr.apps.SmallSmallHrConfig" # noqa

small_small_hr/models.py

+27
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,15 @@ def duration(self):
347347
"""Get duration as a property."""
348348
return self.get_duration()
349349

350+
@cached_property
351+
def day_count(self):
352+
"""
353+
Get the number of leave days as a property.
354+
355+
This takes into account holidays and weekend policy.
356+
"""
357+
return get_real_leave_duration(leave_obj=self)
358+
350359

351360
class OverTime(BaseStaffRequest):
352361
"""Overtime model class."""
@@ -507,6 +516,24 @@ def get_days(start: object, end: object):
507516
yield local_start.date() + timedelta(days=i)
508517

509518

519+
def get_real_leave_duration(leave_obj: Leave) -> Decimal:
520+
"""
521+
Get the real leave duration.
522+
523+
Takes into account public holidays, weekends and weekend policy
524+
"""
525+
count = Decimal(0)
526+
free_days = FreeDay.objects.filter(
527+
date__gte=leave_obj.start.date(), date__lte=leave_obj.end.date()
528+
).values_list("date", flat=True)
529+
days = get_days(start=leave_obj.start, end=leave_obj.end)
530+
for day in days:
531+
if day not in free_days:
532+
day_value = settings.SSHR_DAY_LEAVE_VALUES[day.isoweekday()]
533+
count = count + Decimal(day_value)
534+
return count
535+
536+
510537
def get_taken_leave_days(
511538
staffprofile: object, status: str, leave_type: str, start_year: int, end_year: int
512539
):

small_small_hr/templates/small_small_hr/email/leave_application_email_body.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{{ object.content_object.staff.get_name }} requested time off:<br /><br />
2-
{{ object.content_object.duration.days }} days of {{ object.content_object.get_leave_type_display}}<br />
2+
{{ object.content_object.day_count }} days of {{ object.content_object.get_leave_type_display}}<br />
33
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}<br />
44
Available Balance: {{ object.content_object.staff.get_available_leave_days|floatformat:2 }} days<br /><br />
55
Please log in to process the above: http://{{SITE.domain}}/reviews/{{ object.pk }}

small_small_hr/templates/small_small_hr/email/leave_application_email_body.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{ object.content_object.staff.get_name }} requested time off:
22

3-
{{ object.content_object.duration.days }} days of {{ object.content_object.get_leave_type_display}}
3+
{{ object.content_object.day_count }} days of {{ object.content_object.get_leave_type_display}}
44
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}
55
Available Balance: {{ object.content_object.staff.get_available_leave_days|floatformat:2 }} days
66

small_small_hr/templates/small_small_hr/email/leave_completed_email_body.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{{ object.content_object.staff.get_name }},<br /><br />
2-
Your time off request for {{ object.content_object.duration.days }} days of {{ object.content_object.get_leave_type_display }} from {{ object.content_object.start|date:"d M" }} - {{ object.content_object.end|date:"d M" }} has been {{ object.content_object.get_review_status_display|lower }}.<br /><br />
2+
Your time off request for {{ object.content_object.day_count }} days of {{ object.content_object.get_leave_type_display }} from {{ object.content_object.start|date:"d M" }} - {{ object.content_object.end|date:"d M" }} has been {{ object.content_object.get_review_status_display|lower }}.<br /><br />
33
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}<br />
44
{{ object.content_object.get_leave_type_display}}<br />
5-
{{ object.content_object.duration.days }} days<br />
5+
{{ object.content_object.day_count }} days<br />
66
Status: {{ object.content_object.get_review_status_display }}
77
<br/><br/>
88
Thank you,<br/>

small_small_hr/templates/small_small_hr/email/leave_completed_email_body.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
{{ object.content_object.staff.get_name }},
22

3-
Your time off request for {{ object.content_object.duration.days }} days of {{ object.content_object.get_leave_type_display }} from {{ object.content_object.start|date:"d M" }} - {{ object.content_object.end|date:"d M" }} has been {{ object.content_object.get_review_status_display|lower }}.
3+
Your time off request for {{ object.content_object.day_count }} days of {{ object.content_object.get_leave_type_display }} from {{ object.content_object.start|date:"d M" }} - {{ object.content_object.end|date:"d M" }} has been {{ object.content_object.get_review_status_display|lower }}.
44

55
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}
66
{{ object.content_object.get_leave_type_display}}
7-
{{ object.content_object.duration.days }} days
7+
{{ object.content_object.day_count }} days
88
Status: {{ object.content_object.get_review_status_display }}
99

1010
Thank you,

tests/test_emails.py

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
"""Module to test small_small_hr Emails."""
2+
# pylint: disable=hard-coded-auth-user
23
from datetime import datetime
34

45
from django.conf import settings

tests/test_forms.py

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Module to test small_small_hr models."""
2-
# pylint: disable=too-many-lines
2+
# pylint: disable=too-many-lines,hard-coded-auth-user
33
import os
44
from datetime import date, datetime, timedelta
55

@@ -11,6 +11,7 @@
1111

1212
import pytz
1313
from model_mommy import mommy
14+
from model_mommy.recipe import Recipe
1415
from model_reviews.models import ModelReview
1516

1617
from small_small_hr.forms import (
@@ -39,6 +40,17 @@ class TestForms(TestCase): # pylint: disable=too-many-public-methods
3940
def setUp(self):
4041
"""Set up test class."""
4142
self.factory = RequestFactory()
43+
StaffProfile.objects.rebuild()
44+
self.manager = mommy.make(
45+
"auth.User", first_name="Jane", last_name="Ndoe", email="[email protected]"
46+
)
47+
self.user = mommy.make(
48+
"auth.User", first_name="Bob", last_name="Ndoe", email="[email protected]"
49+
)
50+
manager_mommy = Recipe(StaffProfile, lft=None, rght=None, user=self.manager)
51+
staff_mommy = Recipe(StaffProfile, lft=None, rght=None, user=self.user)
52+
self.manager_profile = manager_mommy.make()
53+
self.staffprofile = staff_mommy.make()
4254

4355
def test_annual_leave_form(self):
4456
"""Test AnnualLeaveForm."""
@@ -1266,11 +1278,9 @@ def test_staff_profile_admin_create_form(self):
12661278

12671279
def test_staff_profile_admin_form(self):
12681280
"""Test StaffProfileAdminForm."""
1269-
manager = mommy.make("auth.User", username="manager")
1270-
managerprofile = mommy.make("small_small_hr.StaffProfile", user=manager)
1271-
1272-
user = mommy.make("auth.User")
1273-
staffprofile = mommy.make("small_small_hr.StaffProfile", user=user)
1281+
managerprofile = self.manager_profile
1282+
user = self.user
1283+
staffprofile = self.staffprofile
12741284

12751285
request = self.factory.get("/")
12761286
request.session = {}

tests/test_models.py

+43
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from small_small_hr.models import FreeDay, Leave, get_taken_leave_days
1212
from small_small_hr.utils import create_free_days
1313

14+
# pylint: disable=hard-coded-auth-user
15+
1416

1517
class TestModels(TestCase):
1618
"""Test class for models."""
@@ -41,6 +43,47 @@ def test_freedays_str(self):
4143
).__str__(),
4244
)
4345

46+
@override_settings(
47+
SSHR_DAY_LEAVE_VALUES={
48+
1: 1, # Monday
49+
2: 1, # Tuesday
50+
3: 1, # Wednesday
51+
4: 1, # Thursday
52+
5: 1, # Friday
53+
6: 0.5, # Saturday
54+
7: 0, # Sunday
55+
}
56+
)
57+
def test_leave_day_count(self):
58+
"""Test leave object day_count."""
59+
user = mommy.make("auth.User", first_name="Mosh", last_name="Pitt")
60+
staff = mommy.make("small_small_hr.StaffProfile", user=user)
61+
mommy.make(
62+
"small_small_hr.AnnualLeave",
63+
staff=staff,
64+
year=2017,
65+
leave_type=Leave.REGULAR,
66+
allowed_days=21,
67+
)
68+
mommy.make(
69+
"small_small_hr.FreeDay",
70+
name="RANDOM HOLIDAY",
71+
date=date(day=15, month=6, year=2017),
72+
)
73+
# 9.5 days of leave ==> Sun not counted, Sat = 0.5 and 15/6/2017 is holiday
74+
start = datetime(2017, 6, 5, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
75+
end = datetime(2017, 6, 16, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
76+
leave_obj = mommy.make(
77+
"small_small_hr.Leave",
78+
staff=staff,
79+
start=start,
80+
end=end,
81+
leave_type=Leave.REGULAR,
82+
review_status=Leave.APPROVED,
83+
)
84+
85+
self.assertEqual(9.5, leave_obj.day_count)
86+
4487
@override_settings(
4588
SSHR_DAY_LEAVE_VALUES={
4689
1: 1, # Monday

0 commit comments

Comments
 (0)