diff --git a/attendance/forms.py b/attendance/forms.py old mode 100644 new mode 100755 index 7c41de34b..22fe3a029 --- a/attendance/forms.py +++ b/attendance/forms.py @@ -1,34 +1,87 @@ +""" +forms.py + +This module contains the form classes used in the application. + +Each form represents a specific functionality or data input in the +application. They are responsible for validating +and processing user input data. + +Classes: +- YourForm: Represents a form for handling specific data input. + +Usage: +from django import forms + +class YourForm(forms.Form): + field_name = forms.CharField() + + def clean_field_name(self): + # Custom validation logic goes here + pass +""" +import uuid +from calendar import month_name from django import forms -from .models import Attendance, AttendanceOverTime, AttendanceActivity,AttendanceLateComeEarlyOut,AttendanceValidationCondition from django.utils.translation import gettext_lazy as _ from django.core.exceptions import ValidationError -from django.db import models from django.forms import DateTimeInput from employee.models import Employee -from calendar import month_name -import uuid +from attendance.models import ( + Attendance, + AttendanceOverTime, + AttendanceActivity, + AttendanceLateComeEarlyOut, + AttendanceValidationCondition, +) + class ModelForm(forms.ModelForm): + """ + Overriding django default model form to apply some styles + """ + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for field_name, field in self.fields.items(): widget = field.widget - if isinstance(widget, (forms.NumberInput, forms.EmailInput,forms.TextInput)): - label=_(field.label.title()) - field.widget.attrs.update({'class': 'oh-input w-100','placeholder':label}) - elif isinstance(widget,(forms.Select,)): - label = '' + if isinstance( + widget, (forms.NumberInput, forms.EmailInput, forms.TextInput) + ): + label = _(field.label.title()) + field.widget.attrs.update( + {"class": "oh-input w-100", "placeholder": label} + ) + elif isinstance(widget, (forms.Select,)): + label = "" if field.label is not None: label = _(field.label) field.empty_label = _("---Choose {label}---").format(label=label) - self.fields[field_name].widget.attrs.update({'class':'oh-select oh-select-2 w-100','id': uuid.uuid4(),'style':'height:50px;border-radius:0;'}) - elif isinstance(widget,(forms.Textarea)): + self.fields[field_name].widget.attrs.update( + { + "class": "oh-select oh-select-2 w-100", + "id": uuid.uuid4(), + "style": "height:50px;border-radius:0;", + } + ) + elif isinstance(widget, (forms.Textarea)): label = _(field.label.title()) - field.widget.attrs.update({'class': 'oh-input w-100','placeholder':field.label,'rows':2,'cols':40}) - elif isinstance(widget, (forms.CheckboxInput,forms.CheckboxSelectMultiple,)): - field.widget.attrs.update({'class': 'oh-switch__checkbox'}) - - + field.widget.attrs.update( + { + "class": "oh-input w-100", + "placeholder": field.label, + "rows": 2, + "cols": 40, + } + ) + elif isinstance( + widget, + ( + forms.CheckboxInput, + forms.CheckboxSelectMultiple, + ), + ): + field.widget.attrs.update({"class": "oh-switch__checkbox"}) class AttendanceUpdateForm(ModelForm): @@ -36,79 +89,112 @@ class AttendanceUpdateForm(ModelForm): This model form is used to direct save the validated query dict to attendance model from AttendanceForm. This form can be used to update existing attendance. """ + class Meta: - fields='__all__' - exclude = ['overtime_second','at_work_second','attendance_day','approved_overtime_second'] + """ + Meta class to add the additional info + """ + + fields = "__all__" + exclude = [ + "overtime_second", + "at_work_second", + "attendance_day", + "approved_overtime_second", + ] model = Attendance widgets = { - 'attendance_clock_in': DateTimeInput(attrs={'type': 'time'}), - 'attendance_clock_out': DateTimeInput(attrs={'type': 'time'}), - 'attendance_clock_out_date':DateTimeInput(attrs={'type':'date'}), - 'attendance_date':DateTimeInput(attrs={'type':'date'}), - 'attendance_clock_in_date':DateTimeInput(attrs={'type':'date'}), - } - - def __init__(self, *args, **kwargs): + "attendance_clock_in": DateTimeInput(attrs={"type": "time"}), + "attendance_clock_out": DateTimeInput(attrs={"type": "time"}), + "attendance_clock_out_date": DateTimeInput(attrs={"type": "date"}), + "attendance_date": DateTimeInput(attrs={"type": "date"}), + "attendance_clock_in_date": DateTimeInput(attrs={"type": "date"}), + } - if instance := kwargs.get('instance'): - ''' - django forms not showing value inside the date, time html element. - so here overriding default forms instance method to set initial value - ''' - initial={ - 'attendance_date':instance.attendance_date.strftime('%Y-%m-%d'), - 'attendance_clock_in':instance.attendance_clock_in.strftime('%H:%M'), - 'attendance_clock_in_date':instance.attendance_clock_in_date.strftime('%Y-%m-%d'), + def __init__(self, *args, **kwargs): + if instance := kwargs.get("instance"): + # django forms not showing value inside the date, time html element. + # so here overriding default forms instance method to set initial value + initial = { + "attendance_date": instance.attendance_date.strftime("%Y-%m-%d"), + "attendance_clock_in": instance.attendance_clock_in.strftime("%H:%M"), + "attendance_clock_in_date": instance.attendance_clock_in_date.strftime( + "%Y-%m-%d" + ), } if instance.attendance_clock_out_date is not None: - initial['attendance_clock_out'] = instance.attendance_clock_out.strftime('%H:%M') - initial['attendance_clock_out_date'] = instance.attendance_clock_out_date.strftime('%Y-%m-%d') - kwargs['initial']=initial - super(AttendanceUpdateForm, self).__init__(*args, **kwargs) - + initial[ + "attendance_clock_out" + ] = instance.attendance_clock_out.strftime("%H:%M") + initial[ + "attendance_clock_out_date" + ] = instance.attendance_clock_out_date.strftime("%Y-%m-%d") + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + class AttendanceForm(ModelForm): - employee_id = forms.ModelMultipleChoiceField(queryset=Employee.objects.filter(employee_work_info__isnull=False),) - class Meta: - model=Attendance - fields = '__all__' - exclude = ('attendance_overtime_approve','attendance_overtime_calculation','at_work_second','overtime_second','attendance_day','approved_overtime_second') - widgets = { - 'attendance_clock_in': DateTimeInput(attrs={'type': 'time'}), - 'attendance_clock_out': DateTimeInput(attrs={'type': 'time'}), - 'attendance_clock_out_date':DateTimeInput(attrs={'type':'date'}), - 'attendance_date':DateTimeInput(attrs={'type':'date'}), - 'attendance_clock_in_date':DateTimeInput(attrs={'type':'date'}), - } - - def __init__(self, *args, **kwargs): + """ + Model form for Attendance model + """ - if instance := kwargs.get('instance'): - ''' - django forms not showing value inside the date, time html element. - so here overriding default forms instance method to set initial value - ''' - initial={ - 'attendance_date':instance.attendance_date.strftime('%Y-%m-%d'), - 'attendance_clock_in':instance.attendance_clock_in.strftime('%H:%M'), - 'attendance_clock_in_date':instance.attendance_clock_in_date.strftime('%Y-%m-%d'), + employee_id = forms.ModelMultipleChoiceField( + queryset=Employee.objects.filter(employee_work_info__isnull=False), + ) + + class Meta: + """ + Meta class to add the additional info + """ + + model = Attendance + fields = "__all__" + exclude = ( + "attendance_overtime_approve", + "attendance_overtime_calculation", + "at_work_second", + "overtime_second", + "attendance_day", + "approved_overtime_second", + ) + widgets = { + "attendance_clock_in": DateTimeInput(attrs={"type": "time"}), + "attendance_clock_out": DateTimeInput(attrs={"type": "time"}), + "attendance_clock_out_date": DateTimeInput(attrs={"type": "date"}), + "attendance_date": DateTimeInput(attrs={"type": "date"}), + "attendance_clock_in_date": DateTimeInput(attrs={"type": "date"}), + } + + def __init__(self, *args, **kwargs): + if instance := kwargs.get("instance"): + # django forms not showing value inside the date, time html element. + # so here overriding default forms instance method to set initial value + initial = { + "attendance_date": instance.attendance_date.strftime("%Y-%m-%d"), + "attendance_clock_in": instance.attendance_clock_in.strftime("%H:%M"), + "attendance_clock_in_date": instance.attendance_clock_in_date.strftime( + "%Y-%m-%d" + ), } if instance.attendance_clock_out_date is not None: - initial['attendance_clock_out'] = instance.attendance_clock_out.strftime('%H:%M') - initial['attendance_clock_out_date'] = instance.attendance_clock_out_date.strftime('%Y-%m-%d') - kwargs['initial']=initial - super(AttendanceForm, self).__init__(*args, **kwargs) - self.fields['employee_id'].widget.attrs.update({'id': str(uuid.uuid4())}) - self.fields['shift_id'].widget.attrs.update({'id': str(uuid.uuid4())}) - self.fields['work_type_id'].widget.attrs.update({'id': str(uuid.uuid4())}) - + initial[ + "attendance_clock_out" + ] = instance.attendance_clock_out.strftime("%H:%M") + initial[ + "attendance_clock_out_date" + ] = instance.attendance_clock_out_date.strftime("%Y-%m-%d") + kwargs["initial"] = initial + super().__init__(*args, **kwargs) + self.fields["employee_id"].widget.attrs.update({"id": str(uuid.uuid4())}) + self.fields["shift_id"].widget.attrs.update({"id": str(uuid.uuid4())}) + self.fields["work_type_id"].widget.attrs.update({"id": str(uuid.uuid4())}) def save(self, commit=True): instance = super().save(commit=False) - for emp_id in self.data.getlist('employee_id'): + for emp_id in self.data.getlist("employee_id"): if int(emp_id) != int(instance.employee_id.id): data_copy = self.data.copy() - data_copy.update({'employee_id':str(emp_id)}) + data_copy.update({"employee_id": str(emp_id)}) attendance = AttendanceUpdateForm(data_copy).save(commit=False) attendance.save() if commit: @@ -116,98 +202,137 @@ class AttendanceForm(ModelForm): return instance def clean_employee_id(self): - employee = self.cleaned_data['employee_id'] + """ + Used to validate employee_id field + """ + employee = self.cleaned_data["employee_id"] for emp in employee: - attendance = Attendance.objects.filter(employee_id=emp,attendance_date=self.data['attendance_date']).first() + attendance = Attendance.objects.filter( + employee_id=emp, attendance_date=self.data["attendance_date"] + ).first() if attendance is not None: - raise ValidationError(_('Attendance for the date is already exist for %(emp)s' % {'emp':emp})) + raise ValidationError( + _( + "Attendance for the date is already exist for %(emp)s" + % {"emp": emp} + ) + ) if employee.first() is None: - raise ValidationError(_('Employee not chosen')) + raise ValidationError(_("Employee not chosen")) return employee.first() - + class AttendanceActivityForm(ModelForm): + """ + Model form for AttendanceActivity model + """ + class Meta: - model=AttendanceActivity - fields = '__all__' + """ + Meta class to add the additional info + """ + + model = AttendanceActivity + fields = "__all__" widgets = { - 'clock_in': DateTimeInput(attrs={'type': 'time'}), - 'clock_out': DateTimeInput(attrs={'type': 'time'}), - 'clock_in_date':DateTimeInput(attrs={'type':'date'}), - 'clock_out_date':DateTimeInput(attrs={'type':'date'}) + "clock_in": DateTimeInput(attrs={"type": "time"}), + "clock_out": DateTimeInput(attrs={"type": "time"}), + "clock_in_date": DateTimeInput(attrs={"type": "date"}), + "clock_out_date": DateTimeInput(attrs={"type": "date"}), } def __init__(self, *args, **kwargs): - if instance := kwargs.get('instance'): - ''' - django forms not showing value inside the date, time html element. - so here overriding default forms instance method to set initial value - ''' + if instance := kwargs.get("instance"): + # django forms not showing value inside the date, time html element. + # so here overriding default forms instance method to set initial value + initial = { - 'attendance_date':instance.attendance_date.strftime('%Y-%m-%d'), - 'clock_in_date':instance.clock_in_date.strftime('%Y-%m-%d'), - 'clock_in':instance.clock_in.strftime('%H:%M'), + "attendance_date": instance.attendance_date.strftime("%Y-%m-%d"), + "clock_in_date": instance.clock_in_date.strftime("%Y-%m-%d"), + "clock_in": instance.clock_in.strftime("%H:%M"), } if instance.clock_out is not None: - initial['clock_out'] = instance.clock_out.strftime('%H:%M') - initial['clock_out_date'] = instance.clock_out_date.strftime('%Y-%m-%d') - kwargs['initial']=initial - super(AttendanceActivityForm, self).__init__(*args, **kwargs) - + initial["clock_out"] = instance.clock_out.strftime("%H:%M") + initial["clock_out_date"] = instance.clock_out_date.strftime("%Y-%m-%d") + kwargs["initial"] = initial + super().__init__(*args, **kwargs) class MonthSelectField(forms.ChoiceField): + """ + Generate month choices + """ + def __init__(self, *args, **kwargs): - choices = [(month_name[i].lower(), _(month_name[i].capitalize())) for i in range(1, 13)] - super(MonthSelectField, self).__init__(choices=choices, *args, **kwargs) + choices = [ + (month_name[i].lower(), _(month_name[i].capitalize())) for i in range(1, 13) + ] + super().__init__(choices=choices, *args, **kwargs) class AttendanceOverTimeForm(ModelForm): + """ + Model form for AttendanceOverTime model + """ + month = MonthSelectField(label=_("Month")) class Meta: + """ + Meta class to add the additional info + """ + model = AttendanceOverTime - fields = '__all__' - exclude = ['hour_account_second','overtime_second','month_sequence'] + fields = "__all__" + exclude = ["hour_account_second", "overtime_second", "month_sequence"] labels = { - "employee_id":_("Employee"), - "year":_("Year"), - "hour_account":_("Hour Account"), - "overtime":_("Overtime"), + "employee_id": _("Employee"), + "year": _("Year"), + "hour_account": _("Hour Account"), + "overtime": _("Overtime"), } def __init__(self, *args, **kwargs): - super(AttendanceOverTimeForm, self).__init__(*args, **kwargs) - self.fields['employee_id'].widget.attrs.update({'id': str(uuid.uuid4())}) + super().__init__(*args, **kwargs) + self.fields["employee_id"].widget.attrs.update({"id": str(uuid.uuid4())}) - - - class AttendanceLateComeEarlyOutForm(ModelForm): - class Meta: - model = AttendanceLateComeEarlyOut - fields = '__all__' + """ + Model form for attendance AttendanceLateComeEarlyOut + """ + + class Meta: + """ + Meta class to add the additional info + """ + + model = AttendanceLateComeEarlyOut + fields = "__all__" - def __init__(self, *args, **kwargs): - super(AttendanceLateComeEarlyOutForm, self).__init__(*args, **kwargs) - class AttendanceValidationConditionForm(ModelForm): + """ + Model form for AttendanceValidationCondition + """ + class Meta: + """ + Meta class to add the additional info + """ + model = AttendanceValidationCondition - validation_at_work = forms.DurationField( ) - approve_overtime_after = forms.DurationField( ) - overtime_cutoff = forms.DurationField( ) + validation_at_work = forms.DurationField() + approve_overtime_after = forms.DurationField() + overtime_cutoff = forms.DurationField() labels = { - 'validation_at_work': _('Do not Auto Validate Attendance if an Employee Works More Than this Amount of Duration'), - - 'minimum_overtime_to_approve': _('Minimum Hour to Approve Overtime'), - 'overtime_cutoff': _('Maximum Allowed Overtime Per Day'), + "validation_at_work": _( + "Do not Auto Validate Attendance if an Employee \ + Works More Than this Amount of Duration" + ), + "minimum_overtime_to_approve": _("Minimum Hour to Approve Overtime"), + "overtime_cutoff": _("Maximum Allowed Overtime Per Day"), } - fields = '__all__' - - def __init__(self, *args, **kwargs): - super(AttendanceValidationConditionForm, self).__init__(*args, **kwargs) + fields = "__all__" diff --git a/attendance/urls.py b/attendance/urls.py old mode 100644 new mode 100755 index ee2e66e8d..518e67b7b --- a/attendance/urls.py +++ b/attendance/urls.py @@ -1,69 +1,131 @@ +""" +urls.py + +This page is used to map request or url path with function + +""" from django.urls import path from . import views urlpatterns = [ - path('attendance-create',views.attendance_create,name='attendance-create'), - - path('attendance-view',views.attendance_view,name='attendance-view'), - - path('attendance-search',views.attendance_search,name='attendance-search'), - - path('attendance-update//',views.attendance_update,name='attendance-update'), - - path('attendance-delete//',views.attendance_delete,name='attendance-delete'), - - path('attendance-bulk-delete',views.attendance_bulk_delete,name='attendance-bulk-delete'), - - path('attendance-overtime-create',views.attendance_overtime_create,name='attendance-overtime-create'), - - path('attendance-overtime-view',views.attendance_overtime_view,name='attendance-overtime-view'), - - path('attendance-overtime-search',views.attendance_overtime_search,name='attendance-ot-search'), - - path('attendance-overtime-update//',views.attendance_overtime_update,name='attendance-overtime-update'), - - path('attendance-overtime-delete//',views.attendance_overtime_delete,name='attendance-overtime-delete'), - - path('attendance-activity-view',views.attendance_activity_view,name='attendance-activity-view'), - - path('attendance-activity-search',views.attendance_activity_search,name='attendance-activity-search'), - - path('attendance-activity-delete//',views.attendance_activity_delete,name='attendance-activity-delete'), - - path('view-my-attendance',views.view_my_attendance,name='view-my-attendance'), - - path('filter-own-attendance',views.filter_own_attendance,name='filter-own-attendance'), - - path('own-attendance-filter',views.own_attendance_sort,name='own-attendance-filter'), - - path('clock-in',views.clock_in,name='clock-in'), - - path('clock-out',views.clock_out,name='clock-out'), - - path('late-come-early-out-view',views.late_come_early_out_view,name='late-come-early-out-view'), - - path('late-come-early-out-search',views.late_come_early_out_search,name='late-come-early-out-search'), - - path('late-come-early-out-delete//',views.late_come_early_out_delete,name='late-come-early-out-delete'), - - path('validation-condition-create',views.validation_condition_create,name='validation-condition-create'), - - path('validation-condition-update//',views.validation_condition_update,name='validation-condition-update'), - - path('validation-condition-delete//',views.validation_condition_delete,name='validation-condition-delete'), - - path('validate-bulk-attendance',views.validate_bulk_attendance,name='validate-bulk-attendance'), - - path('validate-this-attendance//',views.validate_this_attendance,name='validate-this-attendance'), - - path('revalidate-this-attendance//',views.revalidate_this_attendance,name='revalidate-this-attendance'), - - path('approve-overtime//',views.approve_overtime,name='approve-overtime'), - - path('approve-bulk-overtime',views.approve_bulk_overtime,name='approve-bulk-overtime'), - - path('dashboard',views.dashboard,name='dashboard'), - - path('dashboard-attendance',views.dashboard_attendance,name='dashboard-attendance'), - + path("attendance-create", views.attendance_create, name="attendance-create"), + path("attendance-view", views.attendance_view, name="attendance-view"), + path("attendance-search", views.attendance_search, name="attendance-search"), + path( + "attendance-update//", views.attendance_update, name="attendance-update" + ), + path( + "attendance-delete//", views.attendance_delete, name="attendance-delete" + ), + path( + "attendance-bulk-delete", + views.attendance_bulk_delete, + name="attendance-bulk-delete", + ), + path( + "attendance-overtime-create", + views.attendance_overtime_create, + name="attendance-overtime-create", + ), + path( + "attendance-overtime-view", + views.attendance_overtime_view, + name="attendance-overtime-view", + ), + path( + "attendance-overtime-search", + views.attendance_overtime_search, + name="attendance-ot-search", + ), + path( + "attendance-overtime-update//", + views.attendance_overtime_update, + name="attendance-overtime-update", + ), + path( + "attendance-overtime-delete//", + views.attendance_overtime_delete, + name="attendance-overtime-delete", + ), + path( + "attendance-activity-view", + views.attendance_activity_view, + name="attendance-activity-view", + ), + path( + "attendance-activity-search", + views.attendance_activity_search, + name="attendance-activity-search", + ), + path( + "attendance-activity-delete//", + views.attendance_activity_delete, + name="attendance-activity-delete", + ), + path("view-my-attendance", views.view_my_attendance, name="view-my-attendance"), + path( + "filter-own-attendance", + views.filter_own_attendance, + name="filter-own-attendance", + ), + path( + "own-attendance-filter", views.own_attendance_sort, name="own-attendance-filter" + ), + path("clock-in", views.clock_in, name="clock-in"), + path("clock-out", views.clock_out, name="clock-out"), + path( + "late-come-early-out-view", + views.late_come_early_out_view, + name="late-come-early-out-view", + ), + path( + "late-come-early-out-search", + views.late_come_early_out_search, + name="late-come-early-out-search", + ), + path( + "late-come-early-out-delete//", + views.late_come_early_out_delete, + name="late-come-early-out-delete", + ), + path( + "validation-condition-create", + views.validation_condition_create, + name="validation-condition-create", + ), + path( + "validation-condition-update//", + views.validation_condition_update, + name="validation-condition-update", + ), + path( + "validation-condition-delete//", + views.validation_condition_delete, + name="validation-condition-delete", + ), + path( + "validate-bulk-attendance", + views.validate_bulk_attendance, + name="validate-bulk-attendance", + ), + path( + "validate-this-attendance//", + views.validate_this_attendance, + name="validate-this-attendance", + ), + path( + "revalidate-this-attendance//", + views.revalidate_this_attendance, + name="revalidate-this-attendance", + ), + path("approve-overtime//", views.approve_overtime, name="approve-overtime"), + path( + "approve-bulk-overtime", + views.approve_bulk_overtime, + name="approve-bulk-overtime", + ), + path("dashboard", views.dashboard, name="dashboard"), + path( + "dashboard-attendance", views.dashboard_attendance, name="dashboard-attendance" + ), ] diff --git a/attendance/views.py b/attendance/views.py old mode 100644 new mode 100755 index 04aa79a4e..7f2ea55ca --- a/attendance/views.py +++ b/attendance/views.py @@ -1,29 +1,67 @@ +""" +views.py + +This module contains the view functions for handling HTTP requests and rendering +responses in your application. + +Each view function corresponds to a specific URL route and performs the necessary +actions to handle the request, process data, and generate a response. + +This module is part of the recruitment project and is intended to +provide the main entry points for interacting with the application's functionality. +""" + + +import contextlib +import json from datetime import date, datetime, timedelta from django.shortcuts import render, redirect -from django.urls import reverse from django.utils.translation import gettext_lazy as _ -from django.utils.translation import get_language,activate -from django.http import HttpResponseRedirect, HttpResponse, JsonResponse -from horilla.decorators import permission_required, login_required, hx_request_required, manager_can_enter -from base.methods import filtersubordinates, choosesubordinates, sortby -from base.models import EmployeeShiftDay, EmployeeShift, EmployeeShiftSchedule, Department -from attendance.forms import AttendanceForm, AttendanceOverTimeForm, AttendanceActivityForm, AttendanceLateComeEarlyOutForm, AttendanceValidationConditionForm, AttendanceUpdateForm -from attendance.models import Attendance, AttendanceActivity, AttendanceOverTime, AttendanceLateComeEarlyOut, AttendanceValidationCondition -from attendance.filters import AttendanceReGroup, AttendanceOvertimeReGroup, LateComeEarlyOutReGroup, AttendanceActivityReGroup -from notifications.signals import notify - from django.db.models import Q -from django.core.paginator import Paginator -from attendance.filters import AttendanceFilters, AttendanceOverTimeFilter, LateComeEarlyOutFilter, AttendanceActivityFilter -from django.views.decorators.http import require_http_methods from django.contrib import messages +from django.core.paginator import Paginator +from django.http import HttpResponseRedirect, HttpResponse, JsonResponse +from django.views.decorators.http import require_http_methods +from horilla.decorators import ( + permission_required, + login_required, + hx_request_required, + manager_can_enter, +) +from base.methods import filtersubordinates, choosesubordinates, sortby +from base.models import EmployeeShiftDay, EmployeeShiftSchedule, Department +from notifications.signals import notify from employee.models import Employee -import json - +from attendance.filters import ( + AttendanceFilters, + AttendanceOverTimeFilter, + LateComeEarlyOutFilter, + AttendanceActivityFilter, +) +from attendance.forms import ( + AttendanceForm, + AttendanceOverTimeForm, + AttendanceValidationConditionForm, + AttendanceUpdateForm, +) +from attendance.models import ( + Attendance, + AttendanceActivity, + AttendanceOverTime, + AttendanceLateComeEarlyOut, + AttendanceValidationCondition, +) +from attendance.filters import ( + AttendanceReGroup, + AttendanceOvertimeReGroup, + LateComeEarlyOutReGroup, + AttendanceActivityReGroup, +) # Create your views here. + def intersection_list(list1, list2): """ This method is used to intersect two list @@ -38,10 +76,10 @@ def format_time(seconds): seconds : seconds """ - hour = int(seconds//3600) - minutes = int((seconds % 3600)//60) + hour = int(seconds // 3600) + minutes = int((seconds % 3600) // 60) seconds = int((seconds % 3600) % 60) - return "%02d:%02d" % (hour, minutes) + return f"{hour:02d}:{minutes:02d}" def strtime_seconds(time): @@ -52,12 +90,13 @@ def strtime_seconds(time): """ ftr = [3600, 60, 1] - return sum(a*b for a, b in zip(ftr, map(int, time.split(':')))) + return sum(a * b for a, b in zip(ftr, map(int, time.split(":")))) def is_reportingmanger(request, instance): """ - if the instance have employee id field then you can use this method to know the request user employee is the reporting manager of the instance + if the instance have employee id field then you can use this method to know the + request user employee is the reporting manager of the instance args : request : request instance : an object or instance of any model contain employee_id foreign key field @@ -65,9 +104,11 @@ def is_reportingmanger(request, instance): manager = request.user.employee_get try: - employee_workinfo_manager = instance.employee_id.employee_work_info.reporting_manager_id + employee_workinfo_manager = ( + instance.employee_id.employee_work_info.reporting_manager_id + ) except Exception: - return HttpResponse('This Employee Dont Have any work information') + return HttpResponse("This Employee Dont Have any work information") return manager == employee_workinfo_manager @@ -78,12 +119,12 @@ def late_come_create(attendance): attendance : attendance object """ - late_come = AttendanceLateComeEarlyOut() - late_come.type = 'late_come' - late_come.attendance_id = attendance - late_come.employee_id = attendance.employee_id - late_come.save() - return + late_come_obj = AttendanceLateComeEarlyOut() + late_come_obj.type = "late_come" + late_come_obj.attendance_id = attendance + late_come_obj.employee_id = attendance.employee_id + late_come_obj.save() + return late_come_obj def late_come(attendance, start_time, end_time): @@ -96,27 +137,19 @@ def late_come(attendance, start_time, end_time): """ - now_sec = strtime_seconds(datetime.now().strftime('%H:%M')) - mid_day_sec = strtime_seconds('12:00') + now_sec = strtime_seconds(datetime.now().strftime("%H:%M")) + mid_day_sec = strtime_seconds("12:00") if start_time > end_time and start_time != end_time: - """ - night shift - """ + # night shift if now_sec < mid_day_sec: - """ - Here attendance or attendance activity for new day night shift - """ - + # Here attendance or attendance activity for new day night shift late_come_create(attendance) elif now_sec > start_time: - """ - Here attendance or attendance activity for previous day night shift - """ - + # Here attendance or attendance activity for previous day night shift late_come_create(attendance) elif start_time < now_sec: late_come_create(attendance) - return + return True def early_out_create(attendance): @@ -126,12 +159,12 @@ def early_out_create(attendance): attendance : attendance obj """ - late_come = AttendanceLateComeEarlyOut() - late_come.type = 'early_out' - late_come.attendance_id = attendance - late_come.employee_id = attendance.employee_id - late_come.save() - return + late_come_obj = AttendanceLateComeEarlyOut() + late_come_obj.type = "early_out" + late_come_obj.attendance_id = attendance + late_come_obj.employee_id = attendance.employee_id + late_come_obj.save() + return late_come_obj def early_out(attendance, start_time, end_time): @@ -143,19 +176,13 @@ def early_out(attendance, start_time, end_time): start_end : attendance day shift end time """ - now_sec = strtime_seconds(datetime.now().strftime('%H:%M')) - mid_day_sec = strtime_seconds('12:00') + now_sec = strtime_seconds(datetime.now().strftime("%H:%M")) + mid_day_sec = strtime_seconds("12:00") if start_time > end_time: - """ - Early out condition for night shift - """ - + # Early out condition for night shift if now_sec < mid_day_sec: if now_sec < end_time: - """ - Early out condition for general shift - """ - + # Early out condition for general shift early_out_create(attendance) else: early_out_create(attendance) @@ -174,40 +201,40 @@ def attendance_validate(attendance): """ conditions = AttendanceValidationCondition.objects.all() - # Set the default condition for 'at work' to 9:00 AM - condition_for_at_work = strtime_seconds('09:00') - + condition_for_at_work = strtime_seconds("09:00") if conditions.exists(): - condition_for_at_work = strtime_seconds( - conditions[0].validation_at_work) + condition_for_at_work = strtime_seconds(conditions[0].validation_at_work) at_work = strtime_seconds(attendance.attendance_worked_hour) return condition_for_at_work >= at_work @login_required -@manager_can_enter('attendance.add_attendance') +@manager_can_enter("attendance.add_attendance") def attendance_create(request): """ This method is used to render attendance create form and save if it is valid """ form = AttendanceForm() - form = choosesubordinates(request, form, 'attendance.add_attendance') - if request.method == 'POST': + form = choosesubordinates(request, form, "attendance.add_attendance") + if request.method == "POST": form = AttendanceForm(request.POST) - form = choosesubordinates(request, form, 'attendance.add_attendance') + form = choosesubordinates(request, form, "attendance.add_attendance") if form.is_valid(): form.save() - messages.success(request, _('Attendance added.')) + messages.success(request, _("Attendance added.")) response = render( - request, 'attendance/attendance/form.html', {'form': form}) - return HttpResponse(response.content.decode('utf-8') + '') - return render(request, 'attendance/attendance/form.html', {'form': form}) + request, "attendance/attendance/form.html", {"form": form} + ) + return HttpResponse( + response.content.decode("utf-8") + "" + ) + return render(request, "attendance/attendance/form.html", {"form": form}) def paginator_qry(qryset, page_number): """ - This method is used to paginate queryset + This method is used to paginate queryset """ paginator = Paginator(qryset, 50) qryset = paginator.get_page(page_number) @@ -215,141 +242,168 @@ def paginator_qry(qryset, page_number): @login_required -@manager_can_enter('attendance.view_attendance') +@manager_can_enter("attendance.view_attendance") def attendance_view(request): - """f + """ This method is used to view attendances. """ - employee = Employee.objects.filter(employee_user_id=request.user).first() - previous_data = request.environ['QUERY_STRING'] + previous_data = request.environ["QUERY_STRING"] form = AttendanceForm() condition = AttendanceValidationCondition.objects.first() - minot = strtime_seconds('00:30') + minot = strtime_seconds("00:30") if condition is not None: minot = strtime_seconds(condition.minimum_overtime_to_approve) - validate_attendances = Attendance.objects.filter( - attendance_validated=False) + validate_attendances = Attendance.objects.filter(attendance_validated=False) attendances = Attendance.objects.filter(attendance_validated=True) ot_attendances = Attendance.objects.filter( - attendance_overtime_approve=False, overtime_second__gte=minot, attendance_validated=True) - f = AttendanceFilters(queryset=Attendance.objects.all()) - - attendances = filtersubordinates( - request, attendances, 'attendance.view_attendance') + attendance_overtime_approve=False, + overtime_second__gte=minot, + attendance_validated=True, + ) + filter_obj = AttendanceFilters(queryset=Attendance.objects.all()) + attendances = filtersubordinates(request, attendances, "attendance.view_attendance") validate_attendances = filtersubordinates( - request, validate_attendances, 'attendance.view_attendance') + request, validate_attendances, "attendance.view_attendance" + ) ot_attendances = filtersubordinates( - request, ot_attendances, 'attendance.view_attendance') + request, ot_attendances, "attendance.view_attendance" + ) - return render(request, 'attendance/attendance/attendance_view.html', { - 'form': form, - 'validate_attendances': paginator_qry(validate_attendances, request.GET.get('vpage')), - 'attendances': paginator_qry(attendances, request.GET.get('page')), - 'overtime_attendances': paginator_qry(ot_attendances, request.GET.get('opage')), - 'f': f, - 'pd': previous_data, - 'gp_fields': AttendanceReGroup.fields - }) + return render( + request, + "attendance/attendance/attendance_view.html", + { + "form": form, + "validate_attendances": paginator_qry( + validate_attendances, request.GET.get("vpage") + ), + "attendances": paginator_qry(attendances, request.GET.get("page")), + "overtime_attendances": paginator_qry( + ot_attendances, request.GET.get("opage") + ), + "f": filter_obj, + "pd": previous_data, + "gp_fields": AttendanceReGroup.fields, + }, + ) @login_required -@manager_can_enter('attendance.view_attendance') +@manager_can_enter("attendance.view_attendance") def attendance_search(request): """ This method is used to search attendance by employee """ - previous_data = request.environ['QUERY_STRING'] - field = request.GET.get('field') - minot = strtime_seconds('00:30') + previous_data = request.environ["QUERY_STRING"] + field = request.GET.get("field") + minot = strtime_seconds("00:30") condition = AttendanceValidationCondition.objects.first() if condition is not None: minot = strtime_seconds(condition.minimum_overtime_to_approve) validate_attendances = Attendance.objects.filter(attendance_validated=False) attendances = Attendance.objects.filter(attendance_validated=True) - ot_attendances = Attendance.objects.filter(attendance_overtime_approve=False, overtime_second__gte=minot, attendance_validated=True,) + ot_attendances = Attendance.objects.filter( + attendance_overtime_approve=False, + overtime_second__gte=minot, + attendance_validated=True, + ) - validate_attendances = AttendanceFilters( - request.GET, validate_attendances).qs + validate_attendances = AttendanceFilters(request.GET, validate_attendances).qs attendances = AttendanceFilters(request.GET, attendances).qs ot_attendances = AttendanceFilters(request.GET, ot_attendances).qs - - template = 'attendance/attendance/tab_content.html' - if field != '' and field is not None: - field_copy = field.replace('.', '__') + + template = "attendance/attendance/tab_content.html" + if field != "" and field is not None: + field_copy = field.replace(".", "__") attendances = attendances.order_by(field_copy) validate_attendances = validate_attendances.order_by(field_copy) ot_attendances = ot_attendances.order_by(field_copy) - template = 'attendance/attendance/group_by.html' + template = "attendance/attendance/group_by.html" - attendances = filtersubordinates( - request, attendances, 'attendance.view_attendance') + attendances = filtersubordinates(request, attendances, "attendance.view_attendance") validate_attendances = filtersubordinates( - request, validate_attendances, 'attendance.view_attendance') + request, validate_attendances, "attendance.view_attendance" + ) ot_attendances = filtersubordinates( - request, ot_attendances, 'attendance.view_attendance') + request, ot_attendances, "attendance.view_attendance" + ) - attendances = sortby(request, attendances, 'sortby') - validate_attendances = sortby(request, validate_attendances, 'sortby') - ot_attendances = sortby(request, ot_attendances, 'sortby') + attendances = sortby(request, attendances, "sortby") + validate_attendances = sortby(request, validate_attendances, "sortby") + ot_attendances = sortby(request, ot_attendances, "sortby") - return render(request, template, { - 'validate_attendances': paginator_qry(validate_attendances, request.GET.get('vpage')), - 'attendances': paginator_qry(attendances, request.GET.get('page')), - 'overtime_attendances': paginator_qry(ot_attendances, request.GET.get('opage')), - 'pd': previous_data, - 'field': field, - }) + return render( + request, + template, + { + "validate_attendances": paginator_qry( + validate_attendances, request.GET.get("vpage") + ), + "attendances": paginator_qry(attendances, request.GET.get("page")), + "overtime_attendances": paginator_qry( + ot_attendances, request.GET.get("opage") + ), + "pd": previous_data, + "field": field, + }, + ) @login_required -@manager_can_enter('attendance.change_attendance') -def attendance_update(request, id): +@manager_can_enter("attendance.change_attendance") +def attendance_update(request, obj_id): """ This method render form to update attendance and save if the form is valid args: - id : attendance id + obj_id : attendance id """ - attendance = Attendance.objects.get(id=id) - form = AttendanceUpdateForm(instance=attendance,) - form = choosesubordinates(request, form, 'attendance.change_attendance') - if request.method == 'POST': + attendance = Attendance.objects.get(id=obj_id) + form = AttendanceUpdateForm( + instance=attendance, + ) + form = choosesubordinates(request, form, "attendance.change_attendance") + if request.method == "POST": form = AttendanceUpdateForm(request.POST, instance=attendance) - form = choosesubordinates( - request, form, 'attendance.change_attendance') + form = choosesubordinates(request, form, "attendance.change_attendance") if form.is_valid(): form.save() - messages.success(request, _('Attendance Updated.')) + messages.success(request, _("Attendance Updated.")) response = render( - request, 'attendance/attendance/update_form.html', {'form': form}) - return HttpResponse(response.content.decode('utf-8') + '') - return render(request, 'attendance/attendance/update_form.html', {'form': form, }) - - + request, "attendance/attendance/update_form.html", {"form": form} + ) + return HttpResponse( + response.content.decode("utf-8") + "" + ) + return render( + request, + "attendance/attendance/update_form.html", + { + "form": form, + }, + ) @login_required -@permission_required('attendance.delete_attendance') -@require_http_methods(['POST']) -def attendance_delete(request, id): +@permission_required("attendance.delete_attendance") +@require_http_methods(["POST"]) +def attendance_delete(request, obj_id): """ This method is used to delete attendance. args: - id : attendance id + obj_id : attendance id """ - attendance = Attendance.objects.get(id=id) + attendance = Attendance.objects.get(id=obj_id) month = attendance.attendance_date - month = month.strftime('%B').lower() - overtime = attendance.employee_id.employee_overtime.filter( - month=month).last() + month = month.strftime("%B").lower() + overtime = attendance.employee_id.employee_overtime.filter(month=month).last() if overtime is not None: if attendance.attendance_overtime_approve: - """ - Subtract overtime of this attendance - """ + # Subtract overtime of this attendance total_overtime = strtime_seconds(overtime.overtime) attendance_overtime_seconds = strtime_seconds( - attendance.attendance_overtime) + attendance.attendance_overtime + ) if total_overtime > attendance_overtime_seconds: total_overtime = total_overtime - attendance_overtime_seconds else: @@ -358,35 +412,35 @@ def attendance_delete(request, id): overtime.save() try: attendance.delete() - messages.success(request, _('Attendance deleted.')) - except Exception as e: - messages.error(request, e) - messages.error(request, _('You cannot delete this attendance')) - return HttpResponseRedirect(request. META. get('HTTP_REFERER', '/')) + messages.success(request, _("Attendance deleted.")) + except Exception as error: + messages.error(request, error) + messages.error(request, _("You cannot delete this attendance")) + return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/")) -@require_http_methods(['POST']) +@require_http_methods(["POST"]) def attendance_bulk_delete(request): """ This method is used to delete bulk of attendances """ - ids = request.POST['ids'] + ids = request.POST["ids"] ids = json.loads(ids) - for id in ids: + for attendance_id in ids: try: - attendance = Attendance.objects.get(id=id) + attendance = Attendance.objects.get(id=attendance_id) month = attendance.attendance_date - month = month.strftime('%B').lower() + month = month.strftime("%B").lower() overtime = attendance.employee_id.employee_overtime.filter( - month=month).last() + month=month + ).last() if overtime is not None: if attendance.attendance_overtime_approve: - """ - Subtract overtime of this attendance - """ + # Subtract overtime of this attendance total_overtime = strtime_seconds(overtime.overtime) attendance_overtime_seconds = strtime_seconds( - attendance.attendance_overtime) + attendance.attendance_overtime + ) if total_overtime > attendance_overtime_seconds: total_overtime = total_overtime - attendance_overtime_seconds else: @@ -395,14 +449,19 @@ def attendance_bulk_delete(request): overtime.save() try: attendance.delete() - messages.success(request, _('Attendance Deleted')) + messages.success(request, _("Attendance Deleted")) except: messages.error( - request, _('You cannot delete this %(attendance)s' % {'attendance':attendance})) + request, + _( + "You cannot delete this %(attendance)s" + % {"attendance": attendance} + ), + ) except: pass - return JsonResponse({'message': 'Success'}) + return JsonResponse({"message": "Success"}) @login_required @@ -414,11 +473,18 @@ def view_my_attendance(request): try: employee = user.employee_get except: - return redirect('/employee/employee-profile') + return redirect("/employee/employee-profile") employee = user.employee_get employee_attendances = employee.employee_attendances.all() filter = AttendanceFilters() - return render(request, 'attendance/own_attendance/view_own_attendances.html', {'attendances': paginator_qry(employee_attendances, request.GET.get('page')), 'f': filter}) + return render( + request, + "attendance/own_attendance/view_own_attendances.html", + { + "attendances": paginator_qry(employee_attendances, request.GET.get("page")), + "f": filter, + }, + ) @login_required @@ -427,10 +493,13 @@ def filter_own_attendance(request): """ This method is used to filter own attendances """ - attendances = Attendance.objects.filter( - employee_id=request.user.employee_get) + attendances = Attendance.objects.filter(employee_id=request.user.employee_get) attendances = AttendanceFilters(request.GET, queryset=attendances).qs - return render(request, 'attendance/own_attendance/attendances.html', {'attendances': paginator_qry(attendances, request.GET.get('page'))}) + return render( + request, + "attendance/own_attendance/attendances.html", + {"attendances": paginator_qry(attendances, request.GET.get("page"))}, + ) @login_required @@ -438,190 +507,219 @@ def own_attendance_sort(request): """ This method is used to sort out attendances """ - attendances = Attendance.objects.filter( - employee_id=request.user.employee_get) - previous_data = request.environ['QUERY_STRING'] - attendances = sortby(request, attendances, 'orderby') - return render(request, 'attendance/own_attendance/attendances.html', {'attendances': paginator_qry(attendances, request.GET.get('page')), 'pd': previous_data}) + attendances = Attendance.objects.filter(employee_id=request.user.employee_get) + previous_data = request.environ["QUERY_STRING"] + attendances = sortby(request, attendances, "orderby") + return render( + request, + "attendance/own_attendance/attendances.html", + { + "attendances": paginator_qry(attendances, request.GET.get("page")), + "pd": previous_data, + }, + ) @login_required -@manager_can_enter('attendance.add_attendanceovertime') +@manager_can_enter("attendance.add_attendanceovertime") def attendance_overtime_create(request): """ This method is used to render overtime creating form and save if the form is valid """ form = AttendanceOverTimeForm() - form = choosesubordinates( - request, form, 'attendance.add_attendanceovertime') - if request.method == 'POST': + form = choosesubordinates(request, form, "attendance.add_attendanceovertime") + if request.method == "POST": form = AttendanceOverTimeForm(request.POST) - form = choosesubordinates( - request, form, 'attendance.add_attendanceovertime') + form = choosesubordinates(request, form, "attendance.add_attendanceovertime") if form.is_valid(): form.save() - messages.success(request, _('Attendance account added.')) + messages.success(request, _("Attendance account added.")) response = render( - request, 'attendance/attendance_account/form.html', {'form': form}) - return HttpResponse(response.content.decode('utf-8') + '') - return render(request, 'attendance/attendance_account/form.html', {'form': form}) + request, "attendance/attendance_account/form.html", {"form": form} + ) + return HttpResponse( + response.content.decode("utf-8") + "" + ) + return render(request, "attendance/attendance_account/form.html", {"form": form}) @login_required -@manager_can_enter('attendance.view_attendanceovertime') +@manager_can_enter("attendance.view_attendanceovertime") def attendance_overtime_view(request): """ This method is used to view attendance account or overtime account. """ - previous_data = request.environ['QUERY_STRING'] + previous_data = request.environ["QUERY_STRING"] accounts = AttendanceOverTime.objects.all() accounts = filtersubordinates( - request, accounts, 'attendance.view_attendanceovertime') + request, accounts, "attendance.view_attendanceovertime" + ) form = AttendanceOverTimeForm() - form = choosesubordinates( - request, form, 'attendance.add_attendanceovertime') - f = AttendanceOverTimeFilter() - return render(request, 'attendance/attendance_account/attendance_overtime_view.html', { - 'accounts': paginator_qry(accounts, request.GET.get('page')), - 'form': form, - 'pd': previous_data, - 'f': f, - 'gp_fields': AttendanceOvertimeReGroup.fields - }) + form = choosesubordinates(request, form, "attendance.add_attendanceovertime") + filter_obj = AttendanceOverTimeFilter() + return render( + request, + "attendance/attendance_account/attendance_overtime_view.html", + { + "accounts": paginator_qry(accounts, request.GET.get("page")), + "form": form, + "pd": previous_data, + "f": filter_obj, + "gp_fields": AttendanceOvertimeReGroup.fields, + }, + ) @login_required -@manager_can_enter('attendance.view_attendanceovertime') +@manager_can_enter("attendance.view_attendanceovertime") def attendance_overtime_search(request): """ This method is used to search attendance overtime account by employee. """ - field = request.GET.get('field') - previous_data = request.environ['QUERY_STRING'] - + field = request.GET.get("field") + previous_data = request.environ["QUERY_STRING"] + accounts = AttendanceOverTimeFilter(request.GET).qs form = AttendanceOverTimeForm() - template = 'attendance/attendance_account/overtime_list.html' - if field != '' and field is not None: - field_copy = field.replace('.', '__') + template = "attendance/attendance_account/overtime_list.html" + if field != "" and field is not None: + field_copy = field.replace(".", "__") accounts = accounts.order_by(field_copy) - template = 'attendance/attendance_account/group_by.html' - accounts = sortby(request, accounts, 'sortby') + template = "attendance/attendance_account/group_by.html" + accounts = sortby(request, accounts, "sortby") accounts = filtersubordinates( - request, accounts, 'attendance.view_attendanceovertime') - return render(request, template, { - 'accounts': paginator_qry(accounts, request.GET.get('page')), - 'form': form, - 'pd': previous_data, - 'field': field, - }) + request, accounts, "attendance.view_attendanceovertime" + ) + return render( + request, + template, + { + "accounts": paginator_qry(accounts, request.GET.get("page")), + "form": form, + "pd": previous_data, + "field": field, + }, + ) @login_required -@manager_can_enter('attendance.change_attendanceovertime') +@manager_can_enter("attendance.change_attendanceovertime") @hx_request_required -def attendance_overtime_update(request, id): +def attendance_overtime_update(request, obj_id): """ This method is used to update attendance overtime and save if the forms is valid args: - id : attendance overtime id + obj_id : attendance overtime id """ - overtime = AttendanceOverTime.objects.get(id=id) + overtime = AttendanceOverTime.objects.get(id=obj_id) form = AttendanceOverTimeForm(instance=overtime) - form = choosesubordinates( - request, form, 'attendance.change_attendanceovertime') - if request.method == 'POST': + form = choosesubordinates(request, form, "attendance.change_attendanceovertime") + if request.method == "POST": form = AttendanceOverTimeForm(request.POST, instance=overtime) - form = choosesubordinates( - request, form, 'attendance.change_attendanceovertime') + form = choosesubordinates(request, form, "attendance.change_attendanceovertime") if form.is_valid(): form.save() - messages.success( - request, _('Attendance account updated successfully.')) + messages.success(request, _("Attendance account updated successfully.")) response = render( - request, 'attendance/attendance_account/update_form.html', {'form': form}) - return HttpResponse(response.content.decode('utf-8') + '') - return render(request, 'attendance/attendance_account/update_form.html', {'form': form}) + request, + "attendance/attendance_account/update_form.html", + {"form": form}, + ) + return HttpResponse( + response.content.decode("utf-8") + "" + ) + return render( + request, "attendance/attendance_account/update_form.html", {"form": form} + ) @login_required -@permission_required('attendance.delete_AttendanceOverTime') -@require_http_methods(['POST']) -def attendance_overtime_delete(request, id): +@permission_required("attendance.delete_AttendanceOverTime") +@require_http_methods(["POST"]) +def attendance_overtime_delete(request, obj_id): """ This method is used to delete attendance overtime args: - id : attendance overtime id + obj_id : attendance overtime id """ try: - overtime = AttendanceOverTime.objects.get(id=id).delete() - messages.success(request, _('OT account deleted.')) + AttendanceOverTime.objects.get(id=obj_id).delete() + messages.success(request, _("OT account deleted.")) except Exception as e: messages.error(request, e) - messages.error(request, _('You cannot delete this attendance OT')) - accounts = AttendanceOverTime.objects.all() - return HttpResponseRedirect(request. META. get('HTTP_REFERER', '/')) + messages.error(request, _("You cannot delete this attendance OT")) + return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/")) @login_required -@permission_required('attendance.view_attendanceactivity') +@permission_required("attendance.view_attendanceactivity") def attendance_activity_view(request): """ This method will render a template to view all attendance activities """ attendance_activities = AttendanceActivity.objects.all() - previous_data = request.environ['QUERY_STRING'] - filter = AttendanceActivityFilter() - return render(request, 'attendance/attendance_activity/attendance_activity_view.html', { - 'data': paginator_qry(attendance_activities, request.GET.get('page')), - 'pd': previous_data, - 'f': filter, - 'gp_fields': AttendanceActivityReGroup.fields} + previous_data = request.environ["QUERY_STRING"] + filter_obj = AttendanceActivityFilter() + return render( + request, + "attendance/attendance_activity/attendance_activity_view.html", + { + "data": paginator_qry(attendance_activities, request.GET.get("page")), + "pd": previous_data, + "f": filter_obj, + "gp_fields": AttendanceActivityReGroup.fields, + }, ) @login_required -@permission_required('attendance.view_attendanceactivity') +@permission_required("attendance.view_attendanceactivity") def attendance_activity_search(request): """ This method is used to search attendance activity """ - previous_data = request.environ['QUERY_STRING'] - field = request.GET.get('field') + previous_data = request.environ["QUERY_STRING"] + field = request.GET.get("field") attendance_activities = AttendanceActivityFilter( - request.GET,).qs - template = 'attendance/attendance_activity/activity_list.html' - if field != '' and field is not None: - field_copy = field.replace('.', '__') + request.GET, + ).qs + template = "attendance/attendance_activity/activity_list.html" + if field != "" and field is not None: + field_copy = field.replace(".", "__") attendance_activities = attendance_activities.order_by(field_copy) - template = 'attendance/attendance_activity/group_by.html' + template = "attendance/attendance_activity/group_by.html" attendance_activities = filtersubordinates( - request, attendance_activities, 'attendance.view_attendanceactivity') + request, attendance_activities, "attendance.view_attendanceactivity" + ) - attendance_activities = sortby(request, attendance_activities, 'orderby') - return render(request, template, { - 'data': paginator_qry(attendance_activities, request.GET.get('page')), - 'pd': previous_data, - 'field': field - }) + attendance_activities = sortby(request, attendance_activities, "orderby") + return render( + request, + template, + { + "data": paginator_qry(attendance_activities, request.GET.get("page")), + "pd": previous_data, + "field": field, + }, + ) @login_required -@permission_required('attendance.delete_attendanceactivity') -@require_http_methods(['POST', 'DELTE']) -def attendance_activity_delete(request, id): +@permission_required("attendance.delete_attendanceactivity") +@require_http_methods(["POST", "DELTE"]) +def attendance_activity_delete(request, obj_id): """ This method is used to delete attendance activity args: - id : attendance activity id + obj_id : attendance activity id """ try: - attendance_activity = AttendanceActivity.objects.get(id=id).delete() - messages.success(request, _('Attendance activity deleted')) + AttendanceActivity.objects.get(id=obj_id).delete() + messages.success(request, _("Attendance activity deleted")) except Exception as e: messages.error(request, e) - messages.error(request, _('You cannot delete this activity')) - return redirect('/attendance/attendance-activity-view') + messages.error(request, _("You cannot delete this activity")) + return redirect("/attendance/attendance-activity-view") def employee_exists(request): @@ -638,28 +736,26 @@ def employee_exists(request): def shift_schedule_today(day, shift): """ - This function is used to find shift schedules for the day, + This function is used to find shift schedules for the day, it will returns min hour,start time seconds end time seconds args: shift : shift instance day : shift day object """ schedule_today = day.day_schedule.filter(shift_id=shift) - start_time_sec, end_time_sec, minimum_hour = 0, 0, '00:00' + start_time_sec, end_time_sec, minimum_hour = 0, 0, "00:00" if schedule_today.exists(): schedule_today = schedule_today[0] minimum_hour = schedule_today.minimum_working_hour - start_time_sec = strtime_seconds( - schedule_today.start_time.strftime('%H:%M')) - end_time_sec = strtime_seconds( - schedule_today.end_time.strftime('%H:%M')) + start_time_sec = strtime_seconds(schedule_today.start_time.strftime("%H:%M")) + end_time_sec = strtime_seconds(schedule_today.end_time.strftime("%H:%M")) return (minimum_hour, start_time_sec, end_time_sec) def overtime_calculation(attendance): """ This method is used to calculate overtime of the attendance, it will - return difference between attendance worked hour and minimum hour if + return difference between attendance worked hour and minimum hour if and only worked hour greater than minimum hour, else return 00:00 args: attendance : attendance instance @@ -671,10 +767,20 @@ def overtime_calculation(attendance): minimum_hour_sec = strtime_seconds(minimum_hour) if at_work_sec > minimum_hour_sec: return format_time((at_work_sec - minimum_hour_sec)) - return '00:00' + return "00:00" -def clock_in_attendance_and_activity(employee, date_today, attendance_date, day, now, shift, minimum_hour, start_time, end_time): +def clock_in_attendance_and_activity( + employee, + date_today, + attendance_date, + day, + now, + shift, + minimum_hour, + start_time, + end_time, +): """ This method is used to create attendance activity or attendance when an employee clocks-in args: @@ -682,7 +788,7 @@ def clock_in_attendance_and_activity(employee, date_today, attendance_date, day, date_today : date attendance_date : the date that attendance for day : shift day - now : current time + now : current time shift : shift object minimum_hour : minimum hour in shift schedule start_time : start time in shift schedule @@ -690,7 +796,7 @@ def clock_in_attendance_and_activity(employee, date_today, attendance_date, day, """ # attendance activity create - attendance_activity = AttendanceActivity( + AttendanceActivity( employee_id=employee, attendance_date=attendance_date, clock_in_date=date_today, @@ -700,7 +806,8 @@ def clock_in_attendance_and_activity(employee, date_today, attendance_date, day, # create attendance if not exist attendance = Attendance.objects.filter( - employee_id=employee, attendance_date=attendance_date) + employee_id=employee, attendance_date=attendance_date + ) if not attendance.exists(): attendance = Attendance() attendance.employee_id = employee @@ -712,26 +819,18 @@ def clock_in_attendance_and_activity(employee, date_today, attendance_date, day, attendance.attendance_clock_in_date = date_today attendance.minimum_hour = minimum_hour attendance.save() - """ - check here late come or not - """ - - late_come(attendance=attendance, - start_time=start_time, end_time=end_time) + # check here late come or not + late_come(attendance=attendance, start_time=start_time, end_time=end_time) else: attendance = attendance[0] attendance.attendance_clock_out = None attendance.attendance_clock_out_date = None attendance.save() - """ - delete if the attendance marked the early out - """ - - early_out_instance = attendance.late_come_early_out.filter( - type='early_out') + # delete if the attendance marked the early out + early_out_instance = attendance.late_come_early_out.filter(type="early_out") if early_out_instance.exists(): early_out_instance[0].delete() - return + return attendance @login_required @@ -744,30 +843,29 @@ def clock_in(request): shift = work_info.shift_id date_today = date.today() attendance_date = date_today - day = date_today.strftime('%A').lower() + day = date_today.strftime("%A").lower() day = EmployeeShiftDay.objects.get(day=day) - now = datetime.now().strftime('%H:%M') + now = datetime.now().strftime("%H:%M") now_sec = strtime_seconds(now) - mid_day_sec = strtime_seconds('12:00') + mid_day_sec = strtime_seconds("12:00") minimum_hour, start_time_sec, end_time_sec = shift_schedule_today( - day=day, shift=shift) + day=day, shift=shift + ) if start_time_sec > end_time_sec: # night shift - """ - Night shift in open hrms consider a 24 hours from noon to next day noon, - the shift day taken today if the attendance clocked in after 12 O clock. - """ + # ------------------ + # Night shift in Horilla consider a 24 hours from noon to next day noon, + # the shift day taken today if the attendance clocked in after 12 O clock. if mid_day_sec > now_sec: - """ - Here you need to create attendance for yesterday - """ + # Here you need to create attendance for yesterday date_yesterday = date_today - timedelta(days=1) - day_yesterday = date_yesterday.strftime('%A').lower() + day_yesterday = date_yesterday.strftime("%A").lower() day_yesterday = EmployeeShiftDay.objects.get(day=day_yesterday) minimum_hour, start_time_sec, end_time_sec = shift_schedule_today( - day=day_yesterday, shift=shift) + day=day_yesterday, shift=shift + ) attendance_date = date_yesterday day = day_yesterday clock_in_attendance_and_activity( @@ -779,17 +877,25 @@ def clock_in(request): shift=shift, minimum_hour=minimum_hour, start_time=start_time_sec, - end_time=end_time_sec + end_time=end_time_sec, ) return HttpResponse( """ - - """.format(check_out=_('Check-Out')) - + """.format( + check_out=_("Check-Out") + ) ) - return HttpResponse("You Don't have work information filled or your employee detail neither entered ") + return HttpResponse( + "You Don't have work information filled or your employee detail neither entered " + ) def activity_datetime(attendance_activity): @@ -797,7 +903,7 @@ def activity_datetime(attendance_activity): This method is used to convert clock-in and clock-out of activity as datetime object args: attendance_activity : attendance activity instance - """ + """ # in in_year = attendance_activity.clock_in_date.year @@ -811,7 +917,9 @@ def activity_datetime(attendance_activity): out_day = attendance_activity.clock_out_date.day out_hour = attendance_activity.clock_out.hour out_minute = attendance_activity.clock_out.minute - return datetime(in_year, in_month, in_day, in_hour, in_minute), datetime(out_year, out_month, out_day, out_hour, out_minute) + return datetime(in_year, in_month, in_day, in_hour, in_minute), datetime( + out_year, out_month, out_day, out_hour, out_minute + ) def clock_out_attendance_and_activity(employee, date_today, now): @@ -824,17 +932,17 @@ def clock_out_attendance_and_activity(employee, date_today, now): """ attendance_activities = AttendanceActivity.objects.filter( - employee_id=employee).order_by('attendance_date', 'id') + employee_id=employee + ).order_by("attendance_date", "id") if attendance_activities.exists(): attendance_activity = attendance_activities.last() attendance_activity.clock_out = now attendance_activity.clock_out_date = date_today attendance_activity.save() attendance_activities = attendance_activities.filter(~Q(clock_out=None)).filter( - attendance_date=attendance_activity.attendance_date) - """ - Here calculate the total durations between the attendance activities - """ + attendance_date=attendance_activity.attendance_date + ) + # Here calculate the total durations between the attendance activities duration = 0 for attendance_activity in attendance_activities: @@ -846,21 +954,17 @@ def clock_out_attendance_and_activity(employee, date_today, now): duration = duration + total_seconds duration = format_time(duration) # update clock out of attendance - attendance = Attendance.objects.filter( - employee_id=employee).order_by('-attendance_date', '-id')[0] + attendance = Attendance.objects.filter(employee_id=employee).order_by( + "-attendance_date", "-id" + )[0] attendance.attendance_clock_out = now attendance.attendance_clock_out_date = date_today attendance.attendance_worked_hour = duration attendance.save() - """ - Overtime calculation - """ - + # Overtime calculation attendance.attendance_overtime = overtime_calculation(attendance) - """ - Validate the attendance as per the condition - """ + # Validate the attendance as per the condition attendance.attendance_validated = attendance_validate(attendance) attendance.save() @@ -875,250 +979,299 @@ def clock_out(request): employee, work_info = employee_exists(request) shift = work_info.shift_id date_today = date.today() - day = date_today.strftime('%A').lower() + day = date_today.strftime("%A").lower() day = EmployeeShiftDay.objects.get(day=day) - attendance = Attendance.objects.filter( - employee_id=employee).order_by('id', 'attendance_date').last() + attendance = ( + Attendance.objects.filter(employee_id=employee) + .order_by("id", "attendance_date") + .last() + ) if attendance is not None: day = attendance.attendance_day - now = datetime.now().strftime('%H:%M') + now = datetime.now().strftime("%H:%M") minimum_hour, start_time_sec, end_time_sec = shift_schedule_today( - day=day, shift=shift) - now_sec = strtime_seconds(now) - mid_day_sec = strtime_seconds('12:00') - if start_time_sec >= end_time_sec and mid_day_sec > now_sec: - # here the shift will be night shift - """ - Night shift in open hrms consider a 24 hours from noon to next day noon, - the shift day taken today if the attendance clocked-in before 12 O clock. - """ - - # here can write night shift conditions - - early_out_instance = attendance.late_come_early_out.filter( - type='early_out') + day=day, shift=shift + ) + early_out_instance = attendance.late_come_early_out.filter(type="early_out") if not early_out_instance.exists(): - early_out(attendance=attendance, - start_time=start_time_sec, end_time=end_time_sec) + early_out( + attendance=attendance, start_time=start_time_sec, end_time=end_time_sec + ) - clock_out_attendance_and_activity( - employee=employee, date_today=date_today, now=now) + clock_out_attendance_and_activity(employee=employee, date_today=date_today, now=now) return HttpResponse( """ - - """.format(check_in=_('Check-In')) - + """.format( + check_in=_("Check-In") + ) ) @login_required -@manager_can_enter('attendance.view_attendancelatecomeearlyout') +@manager_can_enter("attendance.view_attendancelatecomeearlyout") def late_come_early_out_view(request): """ This method render template to view all late come early out entries """ reports = AttendanceLateComeEarlyOut.objects.all() reports = filtersubordinates( - request, reports, 'attendance.view_attendancelatecomeearlyout') - f = LateComeEarlyOutFilter() - return render(request, 'attendance/late_come_early_out/reports.html', { - 'data': paginator_qry(reports, request.GET.get('page')), - 'f': f, - 'gp_fields': LateComeEarlyOutReGroup.fields, - - }) + request, reports, "attendance.view_attendancelatecomeearlyout" + ) + filter_obj = LateComeEarlyOutFilter() + return render( + request, + "attendance/late_come_early_out/reports.html", + { + "data": paginator_qry(reports, request.GET.get("page")), + "f": filter_obj, + "gp_fields": LateComeEarlyOutReGroup.fields, + }, + ) @login_required -@manager_can_enter('attendance.view_attendancelatecomeearlyout') +@manager_can_enter("attendance.view_attendancelatecomeearlyout") def late_come_early_out_search(request): """ - This method is used to search late come early out by employee. Also include filter and pagination. + This method is used to search late come early out by employee. + Also include filter and pagination. """ - field = request.GET.get('field') - previous_data = request.environ['QUERY_STRING'] - - reports = LateComeEarlyOutFilter(request.GET,).qs - template = 'attendance/late_come_early_out/report_list.html' - if field != '' and field is not None: - template = 'design\late_come_early_out\group_by.html' - field_copy = field.replace('.', '__') + field = request.GET.get("field") + previous_data = request.environ["QUERY_STRING"] + + reports = LateComeEarlyOutFilter( + request.GET, + ).qs + template = "attendance/late_come_early_out/report_list.html" + if field != "" and field is not None: + template = "attendance/late_come_early_out/group_by.html" + field_copy = field.replace(".", "__") reports = reports.order_by(field_copy) reports = filtersubordinates( - request, reports, 'attendance.view_attendancelatecomeearlyout') + request, reports, "attendance.view_attendancelatecomeearlyout" + ) + reports = sortby(request, reports, "sortby") - reports = sortby(request, reports, 'sortby') - - return render(request, template, { - 'data': paginator_qry(reports, request.GET.get('page')), - 'pd': previous_data, - 'field': field - }) + return render( + request, + template, + { + "data": paginator_qry(reports, request.GET.get("page")), + "pd": previous_data, + "field": field, + }, + ) @login_required -@permission_required('attendance.delete_attendancelatecomeearlyout') -@require_http_methods(['POST']) -def late_come_early_out_delete(request, id): +@permission_required("attendance.delete_attendancelatecomeearlyout") +@require_http_methods(["POST"]) +def late_come_early_out_delete(request, obj_id): """ This method is used to delete the late come early out instance args: - id : late come early out instance id + obj_id : late come early out instance id """ try: - late_come_early_out = AttendanceLateComeEarlyOut.objects.get( - id=id).delete() + AttendanceLateComeEarlyOut.objects.get(id=obj_id).delete() messages.success(request, _("Late-in early-out deleted")) except Exception as e: messages.error(request, e) - messages.error(request, _('You cannot delete this Late-in early-out')) + messages.error(request, _("You cannot delete this Late-in early-out")) - return redirect('/attendance/late-come-early-out-view') + return redirect("/attendance/late-come-early-out-view") @login_required -@permission_required('attendance.add_attendancevalidationcondition') +@permission_required("attendance.add_attendancevalidationcondition") def validation_condition_create(request): """ - This method render a form to create attendance validation conditions, and create if the form is valid. + This method render a form to create attendance validation conditions, + and create if the form is valid. """ form = AttendanceValidationConditionForm() condition = AttendanceValidationCondition.objects.first() - if request.method == 'POST': + if request.method == "POST": form = AttendanceValidationConditionForm(request.POST) if form.is_valid(): form.save() - return render(request, 'attendance/break_point/condition.html', {'form': form, 'condition': condition}) + return render( + request, + "attendance/break_point/condition.html", + {"form": form, "condition": condition}, + ) @login_required -@permission_required('attendance.change_attendancevalidationcondition') -def validation_condition_update(request, id): +@permission_required("attendance.change_attendancevalidationcondition") +def validation_condition_update(request, obj_id): """ This method is used to update validation condition - args: - id : validation condition instance id + Args: + obj_id : validation condition instance id """ - condition = AttendanceValidationCondition.objects.get(id=id) + condition = AttendanceValidationCondition.objects.get(id=obj_id) form = AttendanceValidationConditionForm(instance=condition) - if request.method == 'POST': - form = AttendanceValidationConditionForm( - request.POST, instance=condition) + if request.method == "POST": + form = AttendanceValidationConditionForm(request.POST, instance=condition) if form.is_valid(): form.save() - return render(request, 'attendance/break_point/condition.html', {'form': form, 'condition': condition}) + return render( + request, + "attendance/break_point/condition.html", + {"form": form, "condition": condition}, + ) @login_required -@permission_required('attendance.change_attendancevalidationcondition') -@require_http_methods(['POST']) -def validation_condition_delete(request, id): +@permission_required("attendance.change_attendancevalidationcondition") +@require_http_methods(["POST"]) +def validation_condition_delete(request, obj_id): """ This method is used to delete created validation condition - args: - id : validation condition id + args: + obj_id : validation condition id """ try: - condition = AttendanceValidationCondition.objects.get(id=id).delete() - messages.success(request, _('validation condition deleted.')) + AttendanceValidationCondition.objects.get(id=obj_id).delete() + messages.success(request, _("validation condition deleted.")) except Exception as e: messages.error(request, e) - messages.error(request, _('You cannot delete this validation condition.')) - return redirect('/attendance/validation-condition-view') + messages.error(request, _("You cannot delete this validation condition.")) + return redirect("/attendance/validation-condition-view") @login_required -@require_http_methods(['POST']) -@manager_can_enter('attendance.change_attendance') +@require_http_methods(["POST"]) +@manager_can_enter("attendance.change_attendance") def validate_bulk_attendance(request): """ This method is used to validate bulk of attendances """ - ids = request.POST['ids'] + ids = request.POST["ids"] ids = json.loads(ids) - for id in ids: - attendance = Attendance.objects.get(id=id) + for attendance_id in ids: + attendance = Attendance.objects.get(id=attendance_id) attendance.attendance_validated = True attendance.save() - messages.success(request, _('Attendance validated.')) - notify.send(request.user.employee_get, recipient=attendance.employee_id.employee_user_id, - verb=f"Your attendance for the date {attendance.attendance_date} is validated", redirect="/attendance/view-my-attendance", icon="checkmark") - return JsonResponse({'message': f'{attendance.employee_id} success'}) + messages.success(request, _("Attendance validated.")) + notify.send( + request.user.employee_get, + recipient=attendance.employee_id.employee_user_id, + verb=f"Your attendance for the date {attendance.attendance_date} is validated", + redirect="/attendance/view-my-attendance", + icon="checkmark", + ) + return JsonResponse({"message": f"{attendance.employee_id} success"}) @login_required -def validate_this_attendance(request, id): +def validate_this_attendance(request, obj_id): """ This method is used to validate attendance args: id : attendance id """ - attendance = Attendance.objects.get(id=id) - if is_reportingmanger(request, attendance) or request.user.has_perm('attendance.change_attendance'): - attendance = Attendance.objects.get(id=id) + attendance = Attendance.objects.get(id=obj_id) + if is_reportingmanger(request, attendance) or request.user.has_perm( + "attendance.change_attendance" + ): + attendance = Attendance.objects.get(id=obj_id) attendance.attendance_validated = True attendance.save() - messages.success(request, _('Attendance validated.')) - notify.send(request.user.employee_get, recipient=attendance.employee_id.employee_user_id, - verb = f"Your attendance for the date {attendance.attendance_date} is validated", redirect="/attendance/view-my-attendance", icon="checkmark") - return HttpResponseRedirect(request. META. get('HTTP_REFERER', '/')) - return HttpResponse('You Dont Have Permission') + messages.success(request, _("Attendance validated.")) + notify.send( + request.user.employee_get, + recipient=attendance.employee_id.employee_user_id, + verb=f"Your attendance for the date {attendance.attendance_date} is validated", + redirect="/attendance/view-my-attendance", + icon="checkmark", + ) + return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/")) + return HttpResponse("You Dont Have Permission") @login_required -def revalidate_this_attendance(request, id): +def revalidate_this_attendance(request, obj_id): """ - This method is used to not validate the attendance. - args: - id : attendance id - """ - - attendance = Attendance.objects.get(id=id) - if is_reportingmanger(request, attendance) or request.user.has_perm('attendance.change_attendance'): - attendance.attendance_validated = False - attendance.save() - try: - notify.send(request.user.employee_get, recipient=attendance.employee_id.employee_work_info.reporting_manager_id.employee_user_id, - verb=f"{attendance.employee_id} requested revalidation for {attendance.attendance_date} attendance", redirect="/attendance/view-my-attendance", icon="refresh") - except Exception: - pass - return HttpResponseRedirect(request. META. get('HTTP_REFERER', '/')) - return HttpResponse('You Cannot Request for others attendance') - - -@login_required -@manager_can_enter('attendance.change_attendance') -def approve_overtime(request, id): - """ - This method is used to approve attendance overtime + This method is used to not validate the attendance. args: id : attendance id """ - attendance = Attendance.objects.get(id=id) - attendance.attendance_overtime_approve = True - attendance.save() - notify.send(request.user.employee_get, recipient=attendance.employee_id.employee_user_id, - verb=f"Your {attendance.attendance_date}'s attendance overtime approved.", redirect="/attendance/attendance-overtime-view", icon="checkmark") - return HttpResponseRedirect(request. META. get('HTTP_REFERER', '/')) + attendance = Attendance.objects.get(id=obj_id) + if is_reportingmanger(request, attendance) or request.user.has_perm( + "attendance.change_attendance" + ): + attendance.attendance_validated = False + attendance.save() + with contextlib.suppress(Exception): + notify.send( + request.user.employee_get, + recipient=( + attendance.employee_id.employee_work_info.reporting_manager_id.employee_user_id + ), + verb=f"{attendance.employee_id} requested revalidation for \ + {attendance.attendance_date} attendance", + redirect="/attendance/view-my-attendance", + icon="refresh", + ) + return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/")) + return HttpResponse("You Cannot Request for others attendance") @login_required -@manager_can_enter('attendance.change_attendance') +@manager_can_enter("attendance.change_attendance") +def approve_overtime(request, obj_id): + """ + This method is used to approve attendance overtime + args: + obj_id : attendance id + """ + attendance = Attendance.objects.get(id=obj_id) + attendance.attendance_overtime_approve = True + attendance.save() + with contextlib.suppress(Exception): + notify.send( + request.user.employee_get, + recipient=attendance.employee_id.employee_user_id, + verb=f"Your {attendance.attendance_date}'s attendance overtime approved.", + redirect="/attendance/attendance-overtime-view", + icon="checkmark", + ) + return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/")) + + +@login_required +@manager_can_enter("attendance.change_attendance") def approve_bulk_overtime(request): - ids = request.POST['ids'] + """ + This method is used to approve bulk of attendance + """ + ids = request.POST["ids"] ids = json.loads(ids) - for id in ids: - attendance = Attendance.objects.get(id=id) + for attendance_id in ids: + attendance = Attendance.objects.get(id=attendance_id) attendance.attendance_overtime_approve = True attendance.save() - messages.success(request, _('Overtime approved')) - notify.send(request.user.employee_get, recipient=attendance.employee_id.employee_user_id, - verb=f"Overtime approved for {attendance.attendance_date}'s attendance", redirect="/attendance/attendance-overtime-view", icon="checkmark") + messages.success(request, _("Overtime approved")) + notify.send( + request.user.employee_get, + recipient=attendance.employee_id.employee_user_id, + verb=f"Overtime approved for {attendance.attendance_date}'s attendance", + redirect="/attendance/attendance-overtime-view", + icon="checkmark", + ) - return JsonResponse({'message': 'Success'}) + return JsonResponse({"message": "Success"}) def find_on_time(request, today, week_day, department=None): @@ -1127,21 +1280,21 @@ def find_on_time(request, today, week_day, department=None): """ on_time = 0 attendances = Attendance.objects.filter(attendance_date=today) - attendances = filtersubordinates( - request, attendances, 'attendance.view_attendance') + attendances = filtersubordinates(request, attendances, "attendance.view_attendance") if department is not None: attendances = attendances.filter( - employee_id__employee_work_info__department_id=department) + employee_id__employee_work_info__department_id=department + ) excepted_attendances = 0 for attendance in attendances: shift = attendance.shift_id - schedules_today = shift.employeeshiftschedule_set.filter( - day__day=week_day) + schedules_today = shift.employeeshiftschedule_set.filter(day__day=week_day) if schedules_today.first() is not None: excepted_attendances = excepted_attendances + 1 - late_come = attendance.late_come_early_out.filter( - type='late_come').first() - if late_come is None: + late_come_obj = attendance.late_come_early_out.filter( + type="late_come" + ).first() + if late_come_obj is None: on_time = on_time + 1 return on_time @@ -1150,12 +1303,14 @@ def find_late_come(today, department=None): """ This method is used to find count of late comers """ - late_come = AttendanceLateComeEarlyOut.objects.filter( - type='late_come', attendance_id__attendance_date=today) + late_come_obj = AttendanceLateComeEarlyOut.objects.filter( + type="late_come", attendance_id__attendance_date=today + ) if department is not None: - late_come = late_come.filter( - employee_id__employee_work_info__department_id=department) - return len(late_come) + late_come_obj = late_come_obj.filter( + employee_id__employee_work_info__department_id=department + ) + return len(late_come_obj) def find_expected_attendances(week_day): @@ -1166,8 +1321,9 @@ def find_expected_attendances(week_day): expected_attendances = 0 for schedule in schedules_today: shift = schedule.shift_id - expected_attendances = expected_attendances + \ - len(shift.employeeworkinformation_set.all()) + expected_attendances = expected_attendances + len( + shift.employeeworkinformation_set.all() + ) return expected_attendances @@ -1176,12 +1332,16 @@ def find_early_out(today, department=None): This method is used to find early out attendances and it returns query set """ if department is not None: - early_out = AttendanceLateComeEarlyOut.objects.filter( - type='early_out', employee_id__employee_work_info__department_id=department, attendance_id__attendance_date=today) + early_out_obj = AttendanceLateComeEarlyOut.objects.filter( + type="early_out", + employee_id__employee_work_info__department_id=department, + attendance_id__attendance_date=today, + ) else: - early_out = AttendanceLateComeEarlyOut.objects.filter( - type='early_out', attendance_id__attendance_date=today) - return early_out + early_out_obj = AttendanceLateComeEarlyOut.objects.filter( + type="early_out", attendance_id__attendance_date=today + ) + return early_out_obj @login_required @@ -1189,41 +1349,48 @@ def dashboard(request): """ This method is used to render individual dashboard for attendance module """ - employees = Employee.objects.filter(is_active=True,).filter( - ~Q(employee_work_info__shift_id=None)) + employees = Employee.objects.filter( + is_active=True, + ).filter(~Q(employee_work_info__shift_id=None)) total_employees = len(employees) today = datetime.today() - week_day = today.strftime('%A').lower() + week_day = today.strftime("%A").lower() on_time = find_on_time(request, today=today, week_day=week_day) - late_come = find_late_come(today=today) + late_come_obj = find_late_come(today=today) - marked_attendances = late_come + on_time + marked_attendances = late_come_obj + on_time expected_attendances = find_expected_attendances(week_day=week_day) on_time_ratio = 0 late_come_ratio = 0 marked_attendances_ratio = 0 if expected_attendances != 0: - on_time_ratio = "%.1f" % ((on_time/expected_attendances)*100) - late_come_ratio = "%.1f" % ((late_come/expected_attendances)*100) - marked_attendances_ratio = "%.1f" % ( - (marked_attendances/expected_attendances)*100) + on_time_ratio = f"{(on_time / expected_attendances) * 100:.1f}" + late_come_ratio = f"{(late_come_obj / expected_attendances) * 100:.1f}" + marked_attendances_ratio = ( + f"{(marked_attendances / expected_attendances) * 100:.1f}" + ) early_outs = AttendanceLateComeEarlyOut.objects.filter( - type='early_out', attendance_id__attendance_date=today) + type="early_out", attendance_id__attendance_date=today + ) - return render(request, 'attendance/dashboard/dashboard.html', { - 'total_employees': total_employees, - 'on_time': on_time, - 'on_time_ratio': on_time_ratio, - 'late_come': late_come, - 'late_come_ratio': late_come_ratio, - 'expected_attendances': expected_attendances, - 'marked_attendances': marked_attendances, - 'marked_attendances_ratio': marked_attendances_ratio, - 'on_break': early_outs, - }) + return render( + request, + "attendance/dashboard/dashboard.html", + { + "total_employees": total_employees, + "on_time": on_time, + "on_time_ratio": on_time_ratio, + "late_come": late_come_obj, + "late_come_ratio": late_come_ratio, + "expected_attendances": expected_attendances, + "marked_attendances": marked_attendances, + "marked_attendances_ratio": marked_attendances_ratio, + "on_break": early_outs, + }, + ) def generate_data_set(request, dept): @@ -1231,28 +1398,41 @@ def generate_data_set(request, dept): This method is used to generate all the dashboard data """ today = datetime.today() - week_day = today.strftime('%A').lower() - # below method will find all the on-time attendance corresponding to the employee shift and shift schedule. - on_time = find_on_time(request, today=today, - week_day=week_day, department=dept) + week_day = today.strftime("%A").lower() + # below method will find all the on-time attendance corresponding to the + # employee shift and shift schedule. + on_time = find_on_time(request, today=today, week_day=week_day, department=dept) - # below method will find all the late-come attendance corresponding to the employee shift and schedule. - late_come = find_late_come(today=today, department=dept) + # below method will find all the late-come attendance corresponding to the + # employee shift and schedule. + late_come_obj = find_late_come(today=today, department=dept) - # below method will find all the early-out attendance corresponding to the employee shift and shift schedule - early_out = find_early_out(department=dept, today=today) + # below method will find all the early-out attendance corresponding to the + # employee shift and shift schedule + early_out_obj = find_early_out(department=dept, today=today) - data = {'label': dept.department, 'data': [ - on_time, late_come, len(early_out)]} + data = { + "label": dept.department, + "data": [on_time, late_come_obj, len(early_out_obj)], + } return data @login_required def dashboard_attendance(request): + """ + This method is used to render json response of dashboard data - labels = ['On Time', 'Late Come', 'On Break', ] + Returns: + JsonResponse: returns data set as json + """ + labels = [ + "On Time", + "Late Come", + "On Break", + ] data_set = [] departments = Department.objects.all() for dept in departments: data_set.append(generate_data_set(request, dept)) - return JsonResponse({'dataSet': data_set, 'labels': labels}) + return JsonResponse({"dataSet": data_set, "labels": labels})