diff --git a/small_small_hr/__init__.py b/small_small_hr/__init__.py
index 97e6b04..513c17e 100644
--- a/small_small_hr/__init__.py
+++ b/small_small_hr/__init__.py
@@ -1,5 +1,5 @@
"""Main init file for small_small_hr."""
-VERSION = (0, 3, 0)
+VERSION = (0, 4, 0)
__version__ = ".".join(str(v) for v in VERSION)
# pylint: disable=invalid-name
default_app_config = "small_small_hr.apps.SmallSmallHrConfig" # noqa
diff --git a/small_small_hr/models.py b/small_small_hr/models.py
index 3e97c25..e17ee61 100644
--- a/small_small_hr/models.py
+++ b/small_small_hr/models.py
@@ -347,6 +347,15 @@ def duration(self):
"""Get duration as a property."""
return self.get_duration()
+ @cached_property
+ def day_count(self):
+ """
+ Get the number of leave days as a property.
+
+ This takes into account holidays and weekend policy.
+ """
+ return get_real_leave_duration(leave_obj=self)
+
class OverTime(BaseStaffRequest):
"""Overtime model class."""
@@ -507,6 +516,24 @@ def get_days(start: object, end: object):
yield local_start.date() + timedelta(days=i)
+def get_real_leave_duration(leave_obj: Leave) -> Decimal:
+ """
+ Get the real leave duration.
+
+ Takes into account public holidays, weekends and weekend policy
+ """
+ count = Decimal(0)
+ free_days = FreeDay.objects.filter(
+ date__gte=leave_obj.start.date(), date__lte=leave_obj.end.date()
+ ).values_list("date", flat=True)
+ days = get_days(start=leave_obj.start, end=leave_obj.end)
+ for day in days:
+ if day not in free_days:
+ day_value = settings.SSHR_DAY_LEAVE_VALUES[day.isoweekday()]
+ count = count + Decimal(day_value)
+ return count
+
+
def get_taken_leave_days(
staffprofile: object, status: str, leave_type: str, start_year: int, end_year: int
):
diff --git a/small_small_hr/templates/small_small_hr/email/leave_application_email_body.html b/small_small_hr/templates/small_small_hr/email/leave_application_email_body.html
index c4ce072..0bca4c7 100644
--- a/small_small_hr/templates/small_small_hr/email/leave_application_email_body.html
+++ b/small_small_hr/templates/small_small_hr/email/leave_application_email_body.html
@@ -1,5 +1,5 @@
{{ object.content_object.staff.get_name }} requested time off:
-{{ object.content_object.duration.days }} days of {{ object.content_object.get_leave_type_display}}
+{{ object.content_object.day_count }} days of {{ object.content_object.get_leave_type_display}}
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}
Available Balance: {{ object.content_object.staff.get_available_leave_days|floatformat:2 }} days
Please log in to process the above: http://{{SITE.domain}}/reviews/{{ object.pk }}
diff --git a/small_small_hr/templates/small_small_hr/email/leave_application_email_body.txt b/small_small_hr/templates/small_small_hr/email/leave_application_email_body.txt
index c1f3028..33c7311 100644
--- a/small_small_hr/templates/small_small_hr/email/leave_application_email_body.txt
+++ b/small_small_hr/templates/small_small_hr/email/leave_application_email_body.txt
@@ -1,6 +1,6 @@
{{ object.content_object.staff.get_name }} requested time off:
-{{ object.content_object.duration.days }} days of {{ object.content_object.get_leave_type_display}}
+{{ object.content_object.day_count }} days of {{ object.content_object.get_leave_type_display}}
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}
Available Balance: {{ object.content_object.staff.get_available_leave_days|floatformat:2 }} days
diff --git a/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.html b/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.html
index a2e32b4..5c8ae5d 100644
--- a/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.html
+++ b/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.html
@@ -1,8 +1,8 @@
{{ object.content_object.staff.get_name }},
-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 }}.
+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 }}.
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}
{{ object.content_object.get_leave_type_display}}
-{{ object.content_object.duration.days }} days
+{{ object.content_object.day_count }} days
Status: {{ object.content_object.get_review_status_display }}
Thank you,
diff --git a/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.txt b/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.txt
index 955f22f..12bb225 100644
--- a/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.txt
+++ b/small_small_hr/templates/small_small_hr/email/leave_completed_email_body.txt
@@ -1,10 +1,10 @@
{{ object.content_object.staff.get_name }},
-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 }}.
+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 }}.
{{ object.content_object.start|date:"D, d M Y" }} - {{ object.content_object.end|date:"D, d M Y" }}
{{ object.content_object.get_leave_type_display}}
-{{ object.content_object.duration.days }} days
+{{ object.content_object.day_count }} days
Status: {{ object.content_object.get_review_status_display }}
Thank you,
diff --git a/tests/test_emails.py b/tests/test_emails.py
index e5026e7..8c15a3c 100644
--- a/tests/test_emails.py
+++ b/tests/test_emails.py
@@ -1,4 +1,5 @@
"""Module to test small_small_hr Emails."""
+# pylint: disable=hard-coded-auth-user
from datetime import datetime
from django.conf import settings
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 51d94eb..649be1d 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -1,5 +1,5 @@
"""Module to test small_small_hr models."""
-# pylint: disable=too-many-lines
+# pylint: disable=too-many-lines,hard-coded-auth-user
import os
from datetime import date, datetime, timedelta
@@ -11,6 +11,7 @@
import pytz
from model_mommy import mommy
+from model_mommy.recipe import Recipe
from model_reviews.models import ModelReview
from small_small_hr.forms import (
@@ -39,6 +40,17 @@ class TestForms(TestCase): # pylint: disable=too-many-public-methods
def setUp(self):
"""Set up test class."""
self.factory = RequestFactory()
+ StaffProfile.objects.rebuild()
+ self.manager = mommy.make(
+ "auth.User", first_name="Jane", last_name="Ndoe", email="jane@example.com"
+ )
+ self.user = mommy.make(
+ "auth.User", first_name="Bob", last_name="Ndoe", email="bob@example.com"
+ )
+ manager_mommy = Recipe(StaffProfile, lft=None, rght=None, user=self.manager)
+ staff_mommy = Recipe(StaffProfile, lft=None, rght=None, user=self.user)
+ self.manager_profile = manager_mommy.make()
+ self.staffprofile = staff_mommy.make()
def test_annual_leave_form(self):
"""Test AnnualLeaveForm."""
@@ -1266,11 +1278,9 @@ def test_staff_profile_admin_create_form(self):
def test_staff_profile_admin_form(self):
"""Test StaffProfileAdminForm."""
- manager = mommy.make("auth.User", username="manager")
- managerprofile = mommy.make("small_small_hr.StaffProfile", user=manager)
-
- user = mommy.make("auth.User")
- staffprofile = mommy.make("small_small_hr.StaffProfile", user=user)
+ managerprofile = self.manager_profile
+ user = self.user
+ staffprofile = self.staffprofile
request = self.factory.get("/")
request.session = {}
diff --git a/tests/test_models.py b/tests/test_models.py
index bc0b04f..9a319c5 100644
--- a/tests/test_models.py
+++ b/tests/test_models.py
@@ -11,6 +11,8 @@
from small_small_hr.models import FreeDay, Leave, get_taken_leave_days
from small_small_hr.utils import create_free_days
+# pylint: disable=hard-coded-auth-user
+
class TestModels(TestCase):
"""Test class for models."""
@@ -41,6 +43,47 @@ def test_freedays_str(self):
).__str__(),
)
+ @override_settings(
+ SSHR_DAY_LEAVE_VALUES={
+ 1: 1, # Monday
+ 2: 1, # Tuesday
+ 3: 1, # Wednesday
+ 4: 1, # Thursday
+ 5: 1, # Friday
+ 6: 0.5, # Saturday
+ 7: 0, # Sunday
+ }
+ )
+ def test_leave_day_count(self):
+ """Test leave object day_count."""
+ user = mommy.make("auth.User", first_name="Mosh", last_name="Pitt")
+ staff = mommy.make("small_small_hr.StaffProfile", user=user)
+ mommy.make(
+ "small_small_hr.AnnualLeave",
+ staff=staff,
+ year=2017,
+ leave_type=Leave.REGULAR,
+ allowed_days=21,
+ )
+ mommy.make(
+ "small_small_hr.FreeDay",
+ name="RANDOM HOLIDAY",
+ date=date(day=15, month=6, year=2017),
+ )
+ # 9.5 days of leave ==> Sun not counted, Sat = 0.5 and 15/6/2017 is holiday
+ start = datetime(2017, 6, 5, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
+ end = datetime(2017, 6, 16, 0, 0, 0, tzinfo=pytz.timezone(settings.TIME_ZONE))
+ leave_obj = mommy.make(
+ "small_small_hr.Leave",
+ staff=staff,
+ start=start,
+ end=end,
+ leave_type=Leave.REGULAR,
+ review_status=Leave.APPROVED,
+ )
+
+ self.assertEqual(9.5, leave_obj.day_count)
+
@override_settings(
SSHR_DAY_LEAVE_VALUES={
1: 1, # Monday