[FIX]leave reset carryforward

This commit is contained in:
Horilla
2023-08-14 14:47:15 +05:30
parent b337ba49b7
commit 63da64282d
13 changed files with 445 additions and 360 deletions

View File

@@ -1,7 +1,8 @@
from employee.models import Employee
from django.utils.translation import gettext as _
def filtersubordinates(request,queryset,perm=None):
def filtersubordinates(request, queryset, perm=None):
"""
This method is used to filter out subordinates queryset element.
"""
@@ -9,11 +10,13 @@ def filtersubordinates(request,queryset,perm=None):
if user.has_perm(perm):
return queryset
manager = Employee.objects.filter(employee_user_id=user).first()
queryset = queryset.filter(employee_id__employee_work_info__reporting_manager_id=manager)
queryset = queryset.filter(
employee_id__employee_work_info__reporting_manager_id=manager
)
return queryset
def filtersubordinatesemployeemodel(request,queryset,perm=None):
def filtersubordinatesemployeemodel(request, queryset, perm=None):
"""
This method is used to filter out subordinates queryset element.
"""
@@ -25,7 +28,6 @@ def filtersubordinatesemployeemodel(request,queryset,perm=None):
return queryset
def is_reportingmanager(request):
"""
This method is used to check weather the employee is reporting manager or not.
@@ -37,63 +39,68 @@ def is_reportingmanager(request):
return False
def choosesubordinates(request,form,perm,):
def choosesubordinates(
request,
form,
perm,
):
user = request.user
if user.has_perm(perm):
return form
manager = Employee.objects.filter(employee_user_id=user).first()
queryset = Employee.objects.filter(employee_work_info__reporting_manager_id=manager)
form.fields['employee_id'].queryset = queryset
form.fields["employee_id"].queryset = queryset
return form
def choosesubordinatesemployeemodel(request,form,perm):
def choosesubordinatesemployeemodel(request, form, perm):
user = request.user
if user.has_perm(perm):
return form
manager = Employee.objects.filter(employee_user_id=user).first()
queryset = Employee.objects.filter(employee_work_info__reporting_manager_id=manager)
form.fields['employee_id'].queryset = queryset
form.fields["employee_id"].queryset = queryset
return form
orderingList = [
{
"id": "",
"field": "",
"ordering": "",
}
]
orderingList = [{
'id':'',
'field':'',
'ordering':'',
}]
def sortby(request,queryset,key):
def sortby(request, queryset, key):
"""
This method is used to sort query set by asc or desc
"""
global orderingList
id = request.user.id
# here will create dictionary object to the global orderingList if not exists,
id = request.user.id
# here will create dictionary object to the global orderingList if not exists,
# if exists then method will switch corresponding object ordering.
filtered_list = [x for x in orderingList if x['id'] ==id]
filtered_list = [x for x in orderingList if x["id"] == id]
ordering = filtered_list[0] if filtered_list else None
if ordering is None:
ordering = {
'id':id,
'field':None,
'ordering':'-',
"id": id,
"field": None,
"ordering": "-",
}
orderingList.append(ordering)
sortby = request.GET.get(key)
if sortby is not None and sortby != '':
if sortby is not None and sortby != "":
# here will update the orderingList
ordering['field']=sortby
ordering["field"] = sortby
if queryset.query.order_by == queryset.query.order_by:
queryset = queryset.order_by(f'{ordering["ordering"]}{sortby}')
if ordering['ordering']=='-':
ordering['ordering']=''
if ordering["ordering"] == "-":
ordering["ordering"] = ""
else:
ordering["ordering"]='-'
ordering["ordering"] = "-"
orderingList = [item for item in orderingList if item["id"] != id]
orderingList.append(ordering)
return queryset
return queryset

View File

@@ -254,7 +254,7 @@ class EmployeeShiftDay(models.Model):
def __str__(self) -> str:
return str(_(self.day))
from django.utils.translation import gettext_lazy as _
class EmployeeShift(models.Model):
"""
EmployeeShift model

View File

@@ -1,17 +1,17 @@
from django.utils.translation import gettext as _
from django.utils.translation import gettext as _
_('monday'),
_('tuesday'),
_('wednesday'),
_('thursday'),
_('friday'),
_('saturday'),
_('sunday'),
_('after'),
_('weekly'),
_('monthly'),
_('Employee First Name'),
_('Employee Last Name'),
_("monday"),
_("tuesday"),
_("wednesday"),
_("thursday"),
_("friday"),
_("saturday"),
_("sunday"),
_("after"),
_("weekly"),
_("monthly"),
_("Employee First Name"),
_("Employee Last Name"),
_("Bank Code #1"),
_("Bank Code #2"),
_("RECRUITMENT"),
@@ -21,28 +21,28 @@ _("PAYROLL"),
_("ATTENDANCE"),
_("LEAVE"),
_("ASSET"),
_('Your asset request approved!.'),
_('Your asset request rejected!.'),
_('You are added to rotating work type'),
_("Your asset request approved!."),
_("Your asset request rejected!."),
_("You are added to rotating work type"),
_("You are added to rotating shift"),
_('Your work type request has been canceled.'),
_('Your work type request has been approved.'),
_('Your work type request has been deleted.'),
_('Your shift request has been canceled.'),
_('Your shift request has been approved.'),
_('Your shift request has been deleted.'),
_('Your work details has been updated.'),
_("Your work type request has been canceled."),
_("Your work type request has been approved."),
_("Your work type request has been deleted."),
_("Your shift request has been canceled."),
_("Your shift request has been approved."),
_("Your shift request has been deleted."),
_("Your work details has been updated."),
_("You have a new leave request to validate."),
_("New leave type is assigned to you"),
_("Your Leave request has been cancelled"),
_("Your Leave request has been approved"),
_("You are chosen as onboarding stage manager"),
_("You are chosen as onboarding task manager"),
_('You got an OKR!.'),
_('You have received feedback!'),
_('You have been assigned as a manager in a feedback!'),
_('You have been assigned as a subordinate in a feedback!'),
_('You have been assigned as a colleague in a feedback!'),
_("You got an OKR!."),
_("You have received feedback!"),
_("You have been assigned as a manager in a feedback!"),
_("You have been assigned as a subordinate in a feedback!"),
_("You have been assigned as a colleague in a feedback!"),
_("You are chosen as one of recruitment manager"),
_("Your attendance for the date "),
_(" is validated"),
@@ -96,4 +96,10 @@ _("Divorced"),
_("Description"),
_("Rotate every weekend"),
_("Rotate every"),
_(),
_("Request description"),
_("Attendance validated"),
_("Is validate request"),
_("Is validate request approved"),
_("Reporting Manager"),
_("Employment Type"),
_("Regular Shift"),

View File

@@ -1,6 +1,9 @@
"""
Module for registering LeaveType, LeaveRequest, AvailableLeave, Holiday, and CompanyLeave
models with the Django admin site.
"""
from django.contrib import admin
from .models import *
from .models import LeaveType, LeaveRequest, AvailableLeave, Holiday, CompanyLeave
# Register your models here.
@@ -9,4 +12,3 @@ admin.site.register(LeaveRequest)
admin.site.register(AvailableLeave)
admin.site.register(Holiday)
admin.site.register(CompanyLeave)

View File

@@ -1,6 +1,6 @@
from django.apps import AppConfig
class LeaveConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'leave'
class LeaveConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "leave"

View File

@@ -1,171 +1,254 @@
from .models import *
"""
This module contains custom filter classes used for filtering
various models in the Leave Management System app.
The filters are designed to provide flexible search and filtering
capabilities for LeaveType, LeaveRequest,AvailableLeave, Holiday, and CompanyLeave models.
"""
from django import forms
from django_filters import FilterSet, DateFilter, filters
from .models import LeaveType, LeaveRequest, AvailableLeave, Holiday, CompanyLeave
class FilterSet(FilterSet):
"""
Custom FilterSet class for styling filter widgets.
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
for field_name, field in self.filters.items():
filter_widget = self.filters[field_name]
widget = filter_widget.field.widget
if isinstance(widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)):
filter_widget.field.widget.attrs.update(
{'class': 'oh-input w-100'})
if isinstance(
widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)
):
filter_widget.field.widget.attrs.update({"class": "oh-input w-100"})
elif isinstance(widget, (forms.Select,)):
filter_widget.field.widget.attrs.update(
{'class': 'oh-select oh-select-2 select2-hidden-accessible', })
{
"class": "oh-select oh-select-2 select2-hidden-accessible",
}
)
elif isinstance(widget, (forms.Textarea)):
filter_widget.field.widget.attrs.update({"class": "oh-input w-100"})
elif isinstance(
widget,
(
forms.CheckboxInput,
forms.CheckboxSelectMultiple,
),
):
filter_widget.field.widget.attrs.update(
{'class': 'oh-input w-100'})
elif isinstance(widget, (forms.CheckboxInput, forms.CheckboxSelectMultiple,)):
filter_widget.field.widget.attrs.update(
{'class': 'oh-switch__checkbox'})
{"class": "oh-switch__checkbox"}
)
elif isinstance(widget, (forms.ModelChoiceField)):
filter_widget.field.widget.attrs.update(
{'class': 'oh-select oh-select-2 select2-hidden-accessible', })
{
"class": "oh-select oh-select-2 select2-hidden-accessible",
}
)
class LeaveTypeFilter(FilterSet):
name = filters.CharFilter(field_name='name', lookup_expr='icontains')
"""
Filter class for LeaveType model.
This filter allows searching LeaveType objects based on their name and payment attributes.
"""
name = filters.CharFilter(field_name="name", lookup_expr="icontains")
class Meta:
""" "
Meta class defines the model and fields to filter
"""
model = LeaveType
fields = {
'payment': ['exact'],
"payment": ["exact"],
}
class AssignedLeavefilter(FilterSet):
class AssignedLeaveFilter(FilterSet):
"""
Filter class for AvailableLeave model.
This filter allows searching AvailableLeave objects based on leave type,
employee, assigned date and payment attributes.
"""
leave_type = filters.CharFilter(
field_name='leave_type_id__name', lookup_expr='icontains')
field_name="leave_type_id__name", lookup_expr="icontains"
)
employee_id = filters.CharFilter(
field_name='employee_id__employee_first_name', lookup_expr='icontains')
field_name="employee_id__employee_first_name", lookup_expr="icontains"
)
assigned_date = DateFilter(
field_name='assigned_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="assigned_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
class Meta:
""" "
Meta class defines the model and fields to filter
"""
model = AvailableLeave
fields = {
'leave_type_id': ['exact'],
"leave_type_id": ["exact"],
}
class LeaveRequestFilter(FilterSet):
"""
Filter class for LeaveRequest model.
This filter allows searching LeaveRequest objects based on employee,
date range, leave type, and status.
"""
employee_id = filters.CharFilter(
field_name='employee_id__employee_first_name', lookup_expr='icontains')
field_name="employee_id__employee_first_name", lookup_expr="icontains"
)
from_date = DateFilter(
field_name='start_date',
lookup_expr='gte',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="start_date",
lookup_expr="gte",
widget=forms.DateInput(attrs={"type": "date"}),
)
to_date = DateFilter(
field_name='end_date',
lookup_expr='lte',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="end_date",
lookup_expr="lte",
widget=forms.DateInput(attrs={"type": "date"}),
)
start_date = DateFilter(
field_name='start_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="start_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
end_date = DateFilter(
field_name='end_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="end_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
class Meta:
""" "
Meta class defines the model and fields to filter
"""
model = LeaveRequest
fields = {
'leave_type_id': ['exact'],
'status' : ['exact'],
"leave_type_id": ["exact"],
"status": ["exact"],
}
class HolidayFilter(FilterSet):
name = filters.CharFilter(
field_name='name', lookup_expr='icontains')
"""
Filter class for Holiday model.
This filter allows searching Holiday objects based on name and date range.
"""
name = filters.CharFilter(field_name="name", lookup_expr="icontains")
from_date = DateFilter(
field_name='start_date',
lookup_expr='gte',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="start_date",
lookup_expr="gte",
widget=forms.DateInput(attrs={"type": "date"}),
)
to_date = DateFilter(
field_name='end_date',
lookup_expr='lte',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="end_date",
lookup_expr="lte",
widget=forms.DateInput(attrs={"type": "date"}),
)
start_date = DateFilter(
field_name='start_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="start_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
end_date = DateFilter(
field_name='end_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="end_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
class Meta:
""" "
Meta class defines the model and fields to filter
"""
model = Holiday
fields = {
'recurring': ['exact'],
"recurring": ["exact"],
}
class CompanyLeavefilter(FilterSet):
name = filters.CharFilter(
field_name='based_on_week_day', lookup_expr='icontains')
class CompanyLeaveFilter(FilterSet):
"""
Filter class for CompanyLeave model.
This filter allows searching CompanyLeave objects based on
name, week day and based_on_week choices.
"""
name = filters.CharFilter(field_name="based_on_week_day", lookup_expr="icontains")
class Meta:
""" "
Meta class defines the model and fields to filter
"""
model = CompanyLeave
fields = {
'based_on_week': ['exact'],
'based_on_week_day': ['exact'],
"based_on_week": ["exact"],
"based_on_week_day": ["exact"],
}
class userLeaveRequestFilter(FilterSet):
class UserLeaveRequestFilter(FilterSet):
"""
Filter class for LeaveRequest model specific to user leave requests.
This filter allows searching user-specific LeaveRequest objects
based on leave type, date range, and status.
"""
leave_type = filters.CharFilter(
field_name='leave_type_id__name', lookup_expr='icontains')
field_name="leave_type_id__name", lookup_expr="icontains"
)
from_date = DateFilter(
field_name='start_date',
lookup_expr='gte',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="start_date",
lookup_expr="gte",
widget=forms.DateInput(attrs={"type": "date"}),
)
to_date = DateFilter(
field_name='end_date',
lookup_expr='lte',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="end_date",
lookup_expr="lte",
widget=forms.DateInput(attrs={"type": "date"}),
)
start_date = DateFilter(
field_name='start_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="start_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
end_date = DateFilter(
field_name='end_date',
lookup_expr='exact',
widget=forms.DateInput(attrs={'type': 'date'})
field_name="end_date",
lookup_expr="exact",
widget=forms.DateInput(attrs={"type": "date"}),
)
class Meta:
""" "
Meta class defines the model and fields to filter
"""
model = LeaveRequest
fields = {
'leave_type_id': ['exact'],
'status' : ['exact'],
}
"leave_type_id": ["exact"],
"status": ["exact"],
}

View File

@@ -1,20 +1,17 @@
from typing import Any
from django.forms import ModelForm
from django.template.loader import render_to_string
from .models import *
from django.forms import DateInput
from django.forms.widgets import TextInput
import re
from django import forms
from django.forms import ModelForm
from django.forms.widgets import TextInput
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from employee.models import Employee
from .models import LeaveType, LeaveRequest, AvailableLeave, Holiday, CompanyLeave
from .methods import (
calculate_requested_days,
leave_requested_dates,
holiday_dates_list,
company_leave_dates_list,
)
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
import re
CHOICES = [("yes", _("Yes")), ("no", _("No"))]
@@ -30,21 +27,19 @@ class ModelForm(forms.ModelForm):
field.widget.attrs.update({"class": "oh-input oh-calendar-input w-100"})
elif isinstance(
widget, (forms.NumberInput, forms.EmailInput, forms.TextInput)
):
placeholder = _(field.label)
):
field.widget.attrs.update(
{"class": "oh-input w-100", "placeholder": placeholder}
{"class": "oh-input w-100", "placeholder": field.label}
)
elif isinstance(widget, (forms.Select,)):
field.widget.attrs.update(
{"class": "oh-select oh-select-2 select2-hidden-accessible"}
)
elif isinstance(widget, (forms.Textarea)):
placeholder = _(field.label)
field.widget.attrs.update(
{
"class": "oh-input w-100",
"placeholder": placeholder,
"placeholder": field.label,
"rows": 2,
"cols": 40,
}
@@ -363,7 +358,6 @@ class HolidayForm(ModelForm):
widget=forms.DateInput(attrs={"type": "date"}),
)
end_date = forms.DateField(
required=False,
widget=forms.DateInput(attrs={"type": "date"}),
)

View File

@@ -1,9 +1,10 @@
from datetime import datetime, timedelta
import calendar
from django.utils import timezone
from datetime import datetime, timedelta
def calculate_requested_days(start_date, end_date, start_date_breakdown, end_date_breakdown):
def calculate_requested_days(
start_date, end_date, start_date_breakdown, end_date_breakdown
):
if start_date == end_date:
if start_date_breakdown == "full_day" and end_date_breakdown == "full_day":
requested_days = 1
@@ -21,14 +22,17 @@ def calculate_requested_days(start_date, end_date, start_date_breakdown, end_dat
if start_date_breakdown == "full_day" and end_date_breakdown == "full_day":
requested_days = (end_date - start_date).days + start_days + end_days + 1
else:
if start_date_breakdown == 'full_day' or end_date_breakdown == 'full_day':
if start_date_breakdown == "full_day" or end_date_breakdown == "full_day":
requested_days = (end_date - start_date).days + start_days + end_days
else:
requested_days = (end_date - start_date).days + start_days + end_days - 1
requested_days = (
(end_date - start_date).days + start_days + end_days - 1
)
return requested_days
def leave_requested_dates(start_date,end_date):
def leave_requested_dates(start_date, end_date):
"""
:return: this functions returns a list of dates from start date to end date.
"""
@@ -43,46 +47,58 @@ def leave_requested_dates(start_date,end_date):
requested_dates.append(date)
return requested_dates
def holiday_dates_list(holidays):
"""
:return: this functions returns a list of all holiday dates.
"""
holiday_dates = []
for holiday in holidays:
holiday_start_date = holiday.start_date
holiday_end_date = holiday.end_date
if holiday_end_date is None:
holiday_end_date = holiday_start_date
holiday_days = holiday_end_date - holiday_start_date
for i in range(holiday_days.days + 1):
date = holiday_start_date + timedelta(i)
holiday_dates.append(date)
return holiday_dates
def company_leave_dates_list(company_leaves,start_date):
"""
:return: This function returns a list of all company leave dates"""
company_leave_dates = []
for company_leave in company_leaves:
year = start_date.year
based_on_week = company_leave.based_on_week
based_on_week_day = company_leave.based_on_week_day
for month in range(1, 13):
if based_on_week != None:
# Set Sunday as the first day of the week
calendar.setfirstweekday(6)
month_calendar = calendar.monthcalendar(year, 7)
weeks = month_calendar[based_on_week]
day = weeks[based_on_week_day]
company_leave_dates.append(date(year=year, month=7, day=day))
else:
# Set Monday as the first day of the week
calendar.setfirstweekday(0)
month_calendar = calendar.monthcalendar(year, month)
for week in month_calendar:
if week[int(based_on_week_day)-1] != 0:
date = datetime.strptime(
f"{year}-{month:02}-{week[int(based_on_week_day)-1]:02}", '%Y-%m-%d').date()
if date not in company_leave_dates:
company_leave_dates.append(date)
return list(set(company_leave_dates))
def holiday_dates_list(holidays):
"""
:return: this functions returns a list of all holiday dates.
"""
holiday_dates = []
for holiday in holidays:
holiday_start_date = holiday.start_date
holiday_end_date = holiday.end_date
if holiday_end_date is None:
holiday_end_date = holiday_start_date
holiday_days = holiday_end_date - holiday_start_date
for i in range(holiday_days.days + 1):
date = holiday_start_date + timedelta(i)
holiday_dates.append(date)
return holiday_dates
def company_leave_dates_list(company_leaves, start_date):
"""
:return: This function returns a list of all company leave dates"""
company_leave_dates = []
for company_leave in company_leaves:
year = start_date.year
based_on_week = company_leave.based_on_week
based_on_week_day = company_leave.based_on_week_day
for month in range(1, 13):
if based_on_week != None:
# Set Sunday as the first day of the week
calendar.setfirstweekday(6)
month_calendar = calendar.monthcalendar(year, month)
weeks = month_calendar[int(based_on_week)]
weekdays_in_weeks = [day for day in weeks if day != 0]
for day in weekdays_in_weeks:
date = datetime.strptime(
f"{year}-{month:02}-{day:02}", "%Y-%m-%d"
).date()
if (
date.weekday() == int(based_on_week_day)
and date not in company_leave_dates
):
company_leave_dates.append(date)
else:
# Set Monday as the first day of the week
calendar.setfirstweekday(0)
month_calendar = calendar.monthcalendar(year, month)
for week in month_calendar:
if week[int(based_on_week_day)] != 0:
date = datetime.strptime(
f"{year}-{month:02}-{week[int(based_on_week_day)]:02}",
"%Y-%m-%d",
).date()
if date not in company_leave_dates:
company_leave_dates.append(date)
return company_leave_dates

View File

@@ -1,16 +1,11 @@
"""
models.py
This module is used to regster models for the leave app
"""
import calendar
from datetime import datetime, timedelta
from django.db import models
from django.utils import timezone
from dateutil.relativedelta import relativedelta
from django.utils.translation import gettext_lazy as _
from django.utils import timezone
from django.db import models
from employee.models import Employee
from leave.methods import calculate_requested_days
from .methods import calculate_requested_days
# Create your models here.
@@ -102,18 +97,18 @@ WEEKS = [
("1", _("Second Week")),
("2", _("Third Week")),
("3", _("Fourth Week")),
("5", _("Fifth Week")),
("4", _("Fifth Week")),
]
WEEK_DAYS = [
("1", _("Monday")),
("2", _("Tuesday")),
("3", _("Wednesday")),
("4", _("Thursday")),
("5", _("Friday")),
("6", _("Saturday")),
("7", _("Sunday")),
("0", _("Monday")),
("1", _("Tuesday")),
("2", _("Wednesday")),
("3", _("Thursday")),
("4", _("Friday")),
("5", _("Saturday")),
("6", _("Sunday")),
]
@@ -150,6 +145,7 @@ class LeaveType(models.Model):
)
exclude_company_leave = models.CharField(max_length=30, choices=CHOICES)
exclude_holiday = models.CharField(max_length=30, choices=CHOICES)
objects = models.Manager()
def __str__(self):
return self.name
@@ -197,6 +193,7 @@ class AvailableLeave(models.Model):
assigned_date = models.DateField(default=timezone.now)
reset_date = models.DateField(blank=True, null=True)
expired_date = models.DateField(blank=True, null=True)
objects = models.Manager()
class Meta:
unique_together = ("leave_type_id", "employee_id")
@@ -221,45 +218,61 @@ class AvailableLeave(models.Model):
available_leave.save()
# Setting the reset date for carryforward leaves
def set_reset_date(self,assigned_date,available_leave):
if available_leave.leave_type_id.reset_based == 'monthly':
reset_day = available_leave.leave_type_id.reset_day
if reset_day == 'last day' :
target_reset_date = assigned_date + relativedelta(months=0,day=31)
if assigned_date < target_reset_date:
reset_date = target_reset_date
else:
reset_date = assigned_date + relativedelta(months=1,day=31)
else:
target_reset_date = assigned_date + relativedelta(months=0,day=int(reset_day))
if assigned_date < target_reset_date:
reset_date = target_reset_date
else:
reset_date = assigned_date + relativedelta(months=1,day=int(reset_day))
elif available_leave.leave_type_id.reset_based == 'weekly':
target_reset_date = 7 - (assigned_date.isoweekday() - int(available_leave.leave_type_id.reset_weekend))
if target_reset_date != 7 :
reset_date = assigned_date + relativedelta(days=(target_reset_date % 7))
def set_reset_date(self, assigned_date, available_leave):
if available_leave.leave_type_id.reset_based == "monthly":
reset_day = available_leave.leave_type_id.reset_day
if reset_day == "last day":
temp_date = assigned_date + relativedelta(months=0, day=31)
if assigned_date < temp_date:
reset_date = temp_date
else:
reset_date = assigned_date + relativedelta(months=1, day=31)
else:
temp_date = assigned_date + relativedelta(months=0, day=int(reset_day))
if assigned_date < temp_date:
reset_date = temp_date
else:
reset_date = assigned_date + relativedelta(
months=1, day=int(reset_day)
)
elif available_leave.leave_type_id.reset_based == "weekly":
temp = 7 - (
assigned_date.isoweekday()
- int(available_leave.leave_type_id.reset_weekend)
- 1
)
if temp != 7:
reset_date = assigned_date + relativedelta(days=(temp % 7))
else:
reset_date = assigned_date + relativedelta(days=7)
else:
reset_month = int(available_leave.leave_type_id.reset_month)
reset_day = available_leave.leave_type_id.reset_day
reset_day = available_leave.leave_type_id.reset_day
if reset_day == 'last day' :
target_reset_date = assigned_date + relativedelta(years=0,month = reset_month,day=31)
if assigned_date < target_reset_date:
reset_date = target_reset_date
else:
reset_date = assigned_date + relativedelta(years=1,month = reset_month,day=31)
else:
target_reset_date = assigned_date + relativedelta(years=0,month = reset_month,day=int(reset_day))
if assigned_date < target_reset_date:
reset_date = target_reset_date
if reset_day == "last day":
temp_date = assigned_date + relativedelta(
years=0, month=reset_month, day=31
)
if assigned_date < temp_date:
reset_date = temp_date
else:
# nth_day = int(reset_day)
reset_date = assigned_date + relativedelta(years=1,month=reset_month,day=int(reset_day))
reset_date = assigned_date + relativedelta(
years=1, month=reset_month, day=31
)
else:
temp_date = assigned_date + relativedelta(
years=0, month=reset_month, day=int(reset_day)
)
if assigned_date < temp_date:
reset_date = temp_date
else:
# nth_day = int(reset_day)
reset_date = assigned_date + relativedelta(
years=1, month=reset_month, day=int(reset_day)
)
return reset_date
# Setting the expiration date for carryforward leaves
@@ -324,6 +337,7 @@ class LeaveRequest(models.Model):
approved_available_days = models.FloatField(default=0)
approved_carryforward_days = models.FloatField(default=0)
created_at = models.DateTimeField(auto_now="True")
objects = models.Manager()
def __str__(self):
return f"{self.employee_id} | {self.leave_type_id} | {self.status}"
@@ -373,23 +387,31 @@ class LeaveRequest(models.Model):
if based_on_week != None:
# Set Sunday as the first day of the week
calendar.setfirstweekday(6)
month_calendar = calendar.monthcalendar(year, 7)
weeks = month_calendar[based_on_week]
day = weeks[based_on_week_day]
company_leave_dates.append(date(year=year, month=7, day=day))
month_calendar = calendar.monthcalendar(year, month)
weeks = month_calendar[int(based_on_week)]
weekdays_in_weeks = [day for day in weeks if day != 0]
for day in weekdays_in_weeks:
date = datetime.strptime(
f"{year}-{month:02}-{day:02}", "%Y-%m-%d"
).date()
if (
date.weekday() == int(based_on_week_day)
and date not in company_leave_dates
):
company_leave_dates.append(date)
else:
# Set Monday as the first day of the week
calendar.setfirstweekday(0)
month_calendar = calendar.monthcalendar(year, month)
for week in month_calendar:
if week[int(based_on_week_day) - 1] != 0:
if week[int(based_on_week_day)] != 0:
date = datetime.strptime(
f"{year}-{month:02}-{week[int(based_on_week_day) - 1]:02}",
f"{year}-{month:02}-{week[int(based_on_week_day)]:02}",
"%Y-%m-%d",
).date()
if date not in company_leave_dates:
company_leave_dates.append(date)
return list(set(company_leave_dates))
return company_leave_dates
def save(self, *args, **kwargs):
self.requested_days = calculate_requested_days(

View File

@@ -1,7 +1,12 @@
"""
Module for Import-Export Resources
This module defines resources for exporting and importing data using the django-import-export library.
"""
from import_export import resources
from .models import Holiday
class HolidayResource(resources.ModelResource):
class Meta:
model = Holiday
model = Holiday

View File

@@ -1,9 +1,3 @@
"""
scheduler.py
Used to register the scheduled tasks.
"""
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
@@ -25,7 +19,6 @@ def leave_reset():
for available_leave in available_leaves:
reset_date = available_leave.reset_date
expired_date = available_leave.expired_date
if reset_date == today_date:
available_leave.update_carryforward(available_leave=available_leave)
# new_reset_date = available_leave.set_reset_date(assigned_date=today_date,available_leave = available_leave)

View File

@@ -80,12 +80,12 @@
</div>
<div class="oh-sticky-table__td">
<div class="oh-btn-group">
<button class="oh-btn oh-btn--light-bkg w-100" title="{% trans 'Edit' %}" data-toggle="oh-modal-toggle"
<button onclick="event.stopPropagation()" class="oh-btn oh-btn--light-bkg w-100" title="{% trans 'Edit' %}" data-toggle="oh-modal-toggle"
data-target="#editModal2" hx-get="{% url 'request-update' leave_request.id %}"
hx-target="#updateForm"><ion-icon name="create-outline"></ion-icon></button>
<a class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100" id="delete-link"
href="{% url 'request-delete' leave_request.id %}" title="{% trans 'Delete' %}"><ion-icon
href="{% url 'request-delete' leave_request.id %}" onclick="event.stopPropagation()" title="{% trans 'Delete' %}"><ion-icon
name="trash-outline"></ion-icon></a>
</div>

View File

@@ -1,69 +1,30 @@
# Standard library imports
import contextlib
from datetime import datetime, timedelta, date
# Third-party imports
from django.shortcuts import render, redirect
from horilla.decorators import login_required, hx_request_required
from .forms import *
from .models import *
from django.http import JsonResponse, HttpResponse
from employee.models import Employee
from .filters import *
from django.contrib import messages
from django.db.models import Q
from django.core.paginator import Paginator
from django.db.models.functions import TruncYear
from django.utils.translation import gettext_lazy as _
from notifications.signals import notify
from django.shortcuts import render, redirect
# Django imports (grouped together)
from django.utils.translation import gettext_lazy as _
# Local imports (grouped together)
from horilla.decorators import (
login_required,
hx_request_required,
permission_required,
manager_can_enter,
)
from base.models import Department
from base.methods import filtersubordinates, choosesubordinates
from employee.models import Employee
from .forms import (
LeaveTypeForm,
UpdateLeaveTypeForm,
LeaveRequestCreationForm,
LeaveRequestUpdationForm,
LeaveOneAssignForm,
AvailableLeaveForm,
AvailableLeaveUpdateForm,
HolidayForm,
CompanyLeaveForm,
UserLeaveRequestForm,
)
from .models import (
LeaveType,
AvailableLeave,
LeaveRequest,
Holiday,
CompanyLeave,
WEEKS,
WEEK_DAYS,
)
from .filters import (
LeaveTypeFilter,
AssignedLeavefilter,
LeaveRequestFilter,
HolidayFilter,
userLeaveRequestFilter,
CompanyLeavefilter,
)
from datetime import datetime, timedelta, date
from django.utils import timezone
from base.models import *
from .methods import (
calculate_requested_days,
leave_requested_dates,
holiday_dates_list,
company_leave_dates_list,
)
import random
from django.core.paginator import Paginator
from django.db.models.functions import TruncYear
from horilla.decorators import permission_required
from horilla.decorators import manager_can_enter
from base.methods import filtersubordinates, choosesubordinates
from django.utils.translation import gettext_lazy as _
from notifications.signals import notify
@login_required
@@ -247,7 +208,7 @@ def leave_request_creation(request):
recipient=leave_request.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
verb=f"New leave request created for {leave_request.employee_id}.",
verb_ar=f"تم إنشاء طلب إجازة جديد لـ {leave_request.employee_id}.",
verb_de=f"Neuer Urlaubsantrag für {leave_request.employee_id} erstellt.",
verb_de=f"Neuer Urlaubsantrag erstellt für {leave_request.employee_id}.",
verb_es=f"Nueva solicitud de permiso creada para {leave_request.employee_id}.",
verb_fr=f"Nouvelle demande de congé créée pour {leave_request.employee_id}.",
icon="people-circle",
@@ -353,7 +314,7 @@ def leave_request_update(request, id):
recipient=leave_request.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
verb=f"Leave request updated for {leave_request.employee_id}.",
verb_ar=f"تم تحديث طلب الإجازة لـ {leave_request.employee_id}.",
verb_de=f"Urlaubsantrag für {leave_request.employee_id} aktualisiert.",
verb_de=f"Urlaubsantrag aktualisiert für {leave_request.employee_id}.",
verb_es=f"Solicitud de permiso actualizada para {leave_request.employee_id}.",
verb_fr=f"Demande de congé mise à jour pour {leave_request.employee_id}.",
icon="people-circle",
@@ -418,10 +379,8 @@ def leave_request_approve(request, id):
)
leave_request.approved_carryforward_days = leave
else:
available_days = available_leave.available_days
available_leave.available_days = (
available_days - leave_request.requested_days
)
temp = available_leave.available_days
available_leave.available_days = temp - leave_request.requested_days
leave_request.approved_available_days = leave_request.requested_days
leave_request.status = "approved"
available_leave.save()
@@ -432,10 +391,10 @@ def leave_request_approve(request, id):
request.user.employee_get,
recipient=leave_request.employee_id.employee_user_id,
verb="Your Leave request has been approved",
verb_ar="تمت الموافقة على طلب الإجازة الخاص بك.",
verb_de="Ihr Urlaubsantrag wurde genehmigt.",
verb_es="Se ha aprobado su solicitud de permiso.",
verb_fr="Votre demande de congé a été approuvée.",
verb_ar="تمت الموافقة على طلب الإجازة الخاص بك",
verb_de="Ihr Urlaubsantrag wurde genehmigt",
verb_es="Se ha aprobado su solicitud de permiso",
verb_fr="Votre demande de congé a été approuvée",
icon="people-circle",
redirect="/leave/user-request-view",
)
@@ -480,10 +439,10 @@ def leave_request_cancel(request, id):
request.user.employee_get,
recipient=leave_request.employee_id.employee_user_id,
verb="Your Leave request has been cancelled",
verb_ar="تم إلغاء طلب الإجازة الخاص بك.",
verb_de="Ihr Urlaubsantrag wurde storniert.",
verb_es="Se ha cancelado su solicitud de permiso.",
verb_fr="Votre demande de congé a été annulée.",
verb_ar="تم إلغاء طلب الإجازة الخاص بك",
verb_de="Ihr Urlaubsantrag wurde storniert",
verb_es="Se ha cancelado su solicitud de permiso",
verb_fr="Votre demande de congé a été annulée",
icon="people-circle",
redirect="/leave/user-request-view",
)
@@ -544,10 +503,10 @@ def leave_assign_one(request, id):
request.user.employee_get,
recipient=employee.employee_user_id,
verb="New leave type is assigned to you",
verb_ar="تم تعيين نوع إجازة جديد لك.",
verb_de="Ihnen wurde ein neuer Urlaubstyp zugewiesen.",
verb_es="Se le ha asignado un nuevo tipo de permiso.",
verb_fr="Un nouveau type de congé vous a été attribué.",
verb_ar="تم تعيين نوع إجازة جديد لك",
verb_de="Ihnen wurde ein neuer Urlaubstyp zugewiesen",
verb_es="Se le ha asignado un nuevo tipo de permiso",
verb_fr="Un nouveau type de congé vous a été attribué",
icon="people-circle",
redirect="/leave/user-leave",
)
@@ -581,7 +540,7 @@ def leave_assign_view(request):
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
assigned_leave_filter = AssignedLeavefilter()
assigned_leave_filter = AssignedLeaveFilter()
return render(
request,
"leave/assign-view.html",
@@ -608,7 +567,7 @@ def leave_assign_filter(request):
"""
queryset = AvailableLeave.objects.all()
queryset = filtersubordinates(request, queryset, "leave.view_availableleave")
assigned_leave_filter = AssignedLeavefilter(request.GET, queryset).qs
assigned_leave_filter = AssignedLeaveFilter(request.GET, queryset).qs
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
page_obj = paginator_qry(assigned_leave_filter, page_number)
@@ -661,10 +620,10 @@ def leave_assign(request):
request.user.employee_get,
recipient=employee.employee_user_id,
verb="New leave type is assigned to you",
verb_ar="تم تعيين نوع إجازة جديد لك.",
verb_de="Ihnen wurde ein neuer Urlaubstyp zugewiesen.",
verb_es="Se te ha asignado un nuevo tipo de permiso.",
verb_fr="Un nouveau type de congé vous a été attribué.",
verb_ar="تم تعيين نوع إجازة جديد لك",
verb_de="Ihnen wurde ein neuer Urlaubstyp zugewiesen",
verb_es="Se le ha asignado un nuevo tipo de permiso",
verb_fr="Un nouveau type de congé vous a été attribué",
icon="people-circle",
redirect="/leave/user-leave",
)
@@ -709,7 +668,7 @@ def available_leave_update(request, id):
request.user.employee_get,
recipient=available_leave.employee_id.employee_user_id,
verb=f"Your {available_leave.leave_type_id} leave type updated.",
verb_ar=f"تم تحديث نوع إجازتك {available_leave.leave_type_id}.",
verb_ar=f"تم تحديث نوع الإجازة {available_leave.leave_type_id} الخاص بك.",
verb_de=f"Ihr Urlaubstyp {available_leave.leave_type_id} wurde aktualisiert.",
verb_es=f"Se ha actualizado su tipo de permiso {available_leave.leave_type_id}.",
verb_fr=f"Votre type de congé {available_leave.leave_type_id} a été mis à jour.",
@@ -916,7 +875,7 @@ def company_leave_view(request):
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
company_leave_filter = CompanyLeavefilter()
company_leave_filter = CompanyLeaveFilter()
return render(
request,
"leave/company-leave-view.html",
@@ -946,7 +905,7 @@ def company_leave_filter(request):
queryset = CompanyLeave.objects.all()
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
company_leave_filter = CompanyLeavefilter(request.GET, queryset).qs
company_leave_filter = CompanyLeaveFilter(request.GET, queryset).qs
page_obj = paginator_qry(company_leave_filter, page_number)
return render(
request,
@@ -1087,12 +1046,10 @@ def user_leave_request(request, id):
leave_request = form.save(commit=False)
leave_request.leave_type_id = leave_type
leave_request.employee_id = employee
leave_request.requested_days = requested_days
leave_request.end_date_breakdown = end_date_breakdown
leave_request.save()
if leave_request.leave_type_id.require_approval == "no":
employee_id = leave_request.employee_id
leave_type_id = leave_request.leave_type_id
leave_request.requested_days = requested_days
available_leave = AvailableLeave.objects.get(
leave_type_id=leave_type_id, employee_id=employee_id
)
@@ -1127,9 +1084,9 @@ def user_leave_request(request, id):
request.user.employee_get,
recipient=leave_request.employee_id.employee_work_info.reporting_manager_id.employee_user_id,
verb="You have a new leave request to validate.",
verb_ar="لديك طلب إجازة جديد يحتاج إلى التحقق منه.",
verb_ar="لديك طلب إجازة جديد يجب التحقق منه.",
verb_de="Sie haben eine neue Urlaubsanfrage zur Validierung.",
verb_es="Tiene una nueva solicitud de permiso para validar.",
verb_es="Tiene una nueva solicitud de permiso que debe validar.",
verb_fr="Vous avez une nouvelle demande de congé à valider.",
icon="people-circle",
redirect="/leave/user-request-view",
@@ -1284,7 +1241,7 @@ def user_leave_view(request):
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
assigned_leave_filter = AssignedLeavefilter()
assigned_leave_filter = AssignedLeaveFilter()
return render(
request,
"leave/user-leave-view.html",
@@ -1316,7 +1273,7 @@ def user_leave_filter(request):
queryset = employee.available_leave.all()
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
assigned_leave_filter = AssignedLeavefilter(request.GET, queryset).qs
assigned_leave_filter = AssignedLeaveFilter(request.GET, queryset).qs
page_obj = paginator_qry(assigned_leave_filter, page_number)
return render(
request,
@@ -1345,7 +1302,7 @@ def user_request_view(request):
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
user_request_filter = userLeaveRequestFilter()
user_request_filter = UserLeaveRequestFilter()
return render(
request,
"leave/user-request-view.html",
@@ -1377,7 +1334,7 @@ def user_request_filter(request):
queryset = user.leaverequest_set.all()
previous_data = request.environ["QUERY_STRING"]
page_number = request.GET.get("page")
user_request_filter = userLeaveRequestFilter(request.GET, queryset).qs
user_request_filter = UserLeaveRequestFilter(request.GET, queryset).qs
page_obj = paginator_qry(user_request_filter, page_number)
return render(
request,