[UPDT] ATTENDANCE: Add data-action=delete for Actions option in navbar

This commit is contained in:
Horilla
2024-09-10 13:50:54 +05:30
parent 053ed3c641
commit 8e9b6b0e19
12 changed files with 103 additions and 26 deletions

View File

@@ -4,7 +4,6 @@ admin.py
This page is used to register attendance models with admins site.
"""
from django.apps import apps
from django.contrib import admin
from .models import (

View File

@@ -1,7 +1,18 @@
"""
This module defines the configuration for the 'attendance' app within the Horilla HRMS project.
"""
from django.apps import AppConfig
class AttendanceConfig(AppConfig):
"""
Configures the 'attendance' app and performs additional setup during the app's
initialization. This includes appending the 'attendance' URL patterns to the
project's main urlpatterns and dynamically adding the 'AttendanceMiddleware'
to the middleware stack if it's not already present.
"""
default_auto_field = "django.db.models.BigAutoField"
name = "attendance"

View File

@@ -9,8 +9,6 @@ import uuid
import django_filters
from django import forms
from django.apps import apps
from django.db.models import OuterRef, Subquery
from django.forms import DateTimeInput
from django.utils.translation import gettext_lazy as _
@@ -416,6 +414,11 @@ class AttendanceFilters(FilterSet):
)
def filter_pending_hour(self, queryset, name, value):
"""
This method calculates the pending hours for each attendance record in the
queryset and filters the records based on whether the pending hours are less
than or equal to (`pending_hour__lte`) or greater than the specified value.
"""
if value is not None:
value = strtime_seconds(value)
filtered_attendance = []
@@ -484,12 +487,18 @@ class AttendanceFilters(FilterSet):
def filter_by_name(self, queryset, name, value):
# Call the imported function
"""
This method allows filtering by the employee's first and/or last name or by other
fields such as day, shift, work type, department, job position, or company, depending
on the value of `search_field` provided in the request data.
"""
filter_method = {
"day": "attendance_day__day__icontains",
"shift": "shift_id__employee_shift__icontains",
"work_type": "work_type_id__work_type__icontains",
"department": "employee_id__employee_work_info__department_id__department__icontains",
"job_position": "employee_id__employee_work_info__job_position_id__job_position__icontains",
"job_position": "employee_id__employee_work_info__\
job_position_id__job_position__icontains",
"company": "employee_id__employee_work_info__company_id__company__icontains",
}
search_field = self.data.get("search_field")

View File

@@ -45,7 +45,6 @@ from attendance.models import (
AttendanceLateComeEarlyOut,
AttendanceOverTime,
AttendanceRequestComment,
AttendanceRequestFile,
AttendanceValidationCondition,
GraceTime,
WorkRecords,
@@ -53,9 +52,8 @@ from attendance.models import (
strtime_seconds,
validate_time_format,
)
from base.forms import MultipleFileField
from base.methods import get_working_days, reload_queryset
from base.models import Company, EmployeeShift
from base.models import Company
from employee.filters import EmployeeFilter
from employee.models import Employee
from horilla import horilla_middlewares
@@ -129,14 +127,14 @@ class ModelForm(forms.ModelForm):
try:
self.fields["employee_id"].initial = request.user.employee_get
except:
except Exception:
pass
try:
self.fields["company_id"].initial = (
request.user.employee_get.get_company
)
except:
except Exception:
pass
@@ -371,7 +369,7 @@ class AttendanceForm(ModelForm):
if existing_attendance.exists():
raise ValidationError(
{
"employee_id": f"""Already attendance exists for {list(existing_attendance.values_list("employee_id__employee_first_name",flat=True))} employees"""
"employee_id": f"""Already attendance exists for{list(existing_attendance.values_list("employee_id__employee_first_name",flat=True))} employees"""
}
)
@@ -387,8 +385,9 @@ class AttendanceForm(ModelForm):
if attendance is not None:
raise ValidationError(
_(
"Attendance for the date is already exist for %(emp)s"
% {"emp": emp}
("Attendance for the date already exists for {emp}").format(
emp=emp
)
)
)
if employee.first() is None:
@@ -752,6 +751,12 @@ excluded_fields = [
class AttendanceExportForm(forms.Form):
"""
This form allows users to choose which fields of the `Attendance` model
they want to include in the export excel file as column. The fields are
presented as a list of checkboxes, and the user can select multiple fields.
"""
model_fields = Attendance._meta.get_fields()
field_choices = [
(field.name, field.verbose_name)
@@ -778,6 +783,12 @@ class AttendanceExportForm(forms.Form):
class LateComeEarlyOutExportForm(forms.Form):
"""
This form allows users to choose fields from both the `AttendanceLateComeEarlyOut`
model and the related `Attendance` model to include in the export excel file.
The fields are presented as checkboxes, and users can select multiple fields.
"""
model_fields = AttendanceLateComeEarlyOut._meta.get_fields()
field_choices_1 = [
(field.name, field.verbose_name)
@@ -808,6 +819,12 @@ class LateComeEarlyOutExportForm(forms.Form):
class AttendanceActivityExportForm(forms.Form):
"""
This form allows users to choose specific fields from the `AttendanceActivity`
model to include in the export excel file. The fields are presented as checkboxes,
enabling users to select multiple fields.
"""
model_fields = AttendanceActivity._meta.get_fields()
field_choices = [
(field.name, field.verbose_name)
@@ -829,6 +846,12 @@ class AttendanceActivityExportForm(forms.Form):
class AttendanceOverTimeExportForm(forms.Form):
"""
This form allows users to choose specific fields from the `AttendanceOverTime`
model to include in the export. The fields are presented as checkboxes,
enabling users to select multiple fields.
"""
model_fields = AttendanceOverTime._meta.get_fields()
field_choices = [
(field.name, field.verbose_name)
@@ -855,6 +878,10 @@ class GraceTimeForm(ModelForm):
"""
class Meta:
"""
Meta class for additional options
"""
model = GraceTime
fields = "__all__"
widgets = {
@@ -1063,7 +1090,6 @@ class BulkAttendanceRequestForm(ModelForm):
"attendance_date": date,
"attendance_clock_in_date": date,
"attendance_clock_out_date": date,
"attendance_clock_in_date": date,
}
)
form = NewRequestForm(data=initial_data)

View File

@@ -1,3 +1,7 @@
"""
Middleware to automatically trigger employee clock-out based on shift schedules
"""
from datetime import datetime, timedelta
from django.utils import timezone
@@ -7,10 +11,25 @@ from attendance.methods.utils import Request
class AttendanceMiddleware(MiddlewareMixin):
"""
This middleware checks for employees who haven't clocked out by the end of their
scheduled shift and automatically performs the clock-out action if the auto punch-out
is enabled for their shift. It processes this during each request.
"""
def process_request(self, request):
"""
Triggers the `trigger_function` on each request.
"""
self.trigger_function()
def trigger_function(self):
"""
Retrieves shift schedules with auto punch-out enabled and checks if there are
any attendance activities that haven't been clocked out. If the scheduled
auto punch-out time has passed, the function attempts to clock out the employee
automatically by invoking the `clock_out` function.
"""
from attendance.models import Attendance, AttendanceActivity
from attendance.views.clock_in_out import clock_out
from base.models import EmployeeShiftSchedule

View File

@@ -8,15 +8,13 @@ This module is used to register models for recruitment app
import contextlib
import datetime as dt
import json
from collections.abc import Iterable
from datetime import date, datetime, timedelta
import pandas as pd
from django.apps import apps
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import Q
from django.db.models.signals import post_save, pre_delete, pre_save
from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
@@ -29,7 +27,6 @@ from attendance.methods.utils import (
strtime_seconds,
validate_hh_mm_ss_format,
validate_time_format,
validate_time_in_minutes,
)
from base.horilla_company_manager import HorillaCompanyManager
from base.methods import is_company_leave, is_holiday
@@ -264,9 +261,8 @@ class Attendance(HorillaModel):
pending_seconds = minimum_hours - worked_hour
if pending_seconds < 0:
return "00:00"
else:
pending_hours = format_time(pending_seconds)
return pending_hours
pending_hours = format_time(pending_seconds)
return pending_hours
def save(self, *args, **kwargs):
minimum_hour = self.minimum_hour
@@ -300,12 +296,14 @@ class Attendance(HorillaModel):
leaves.append(current_date.strftime("%Y-%m-%d"))
current_date += timedelta(days=1)
# Checking attendance date is in holiday list, if found making the minimum hour to 00:00
# Checking attendance date is in holiday list,
# if found making the minimum hour to 00:00
if is_holiday(self.attendance_date):
self.minimum_hour = "00:00"
self.is_holiday = True
# Checking attendance date is in company leave list, if found making the minimum hour to 00:00
# Checking attendance date is in company leave list,
# if found making the minimum hour to 00:00
if is_company_leave(self.attendance_date):
self.minimum_hour = "00:00"
self.is_holiday = True

View File

@@ -4,7 +4,6 @@ attendance/sidebar.py
from datetime import datetime
from django.apps import apps
from django.urls import reverse
from django.utils.translation import gettext_lazy as trans
@@ -57,27 +56,42 @@ SUBMENUS = [
def attendances_accessibility(request, submenu, user_perms, *args, **kwargs):
"""
Check if the user has permission to view attendance or is a reporting manager.
"""
return request.user.has_perm("attendance.view_attendance") or is_reportingmanager(
request.user
)
def hour_account_accessibility(request, submenu, user_perms, *args, **kwargs):
"""
Modify the submenu redirect URL to include the current year as a query parameter.
"""
submenu["redirect"] = submenu["redirect"] + f"?year={datetime.now().year}"
return True
def work_record_accessibility(request, submenu, user_perms, *args, **kwargs):
"""
Check if the user has permission to view attendance or is a reporting manager.
"""
return request.user.has_perm("attendance.view_attendance") or is_reportingmanager(
request.user
)
def dashboard_accessibility(request, submenu, user_perms, *args, **kwargs):
"""
Check if the user has permission to view attendance or is a reporting manager.
"""
return request.user.has_perm("attendance.view_attendance") or is_reportingmanager(
request.user
)
def tracking_accessibility(request, submenu, user_perms, *args, **kwargs):
"""
Determine if late come/early out tracking is enabled.
"""
return enable_late_come_early_out_tracking(None).get("tracking")

View File

@@ -308,6 +308,7 @@
<a
href="#"
id="bulkDelete"
data-action="delete"
class="oh-dropdown__link oh-dropdown__link--danger"
>{% trans "Delete" %}</a
>

View File

@@ -135,6 +135,7 @@
<a
href="#"
id="hourAccountbulkDelete"
data-action="delete"
class="oh-dropdown__link oh-dropdown__link--danger"
>{% trans "Delete" %}</a
>

View File

@@ -84,7 +84,7 @@
{% endif %}
{% if perms.attendance.delete_attendanceactivity %}
<li class="oh-dropdown__item">
<a href="#" id="attendanceActivityDelete"
<a href="#" id="attendanceActivityDelete" data-action="delete"
class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
</li>
{% endif %}

View File

@@ -76,7 +76,7 @@
{% endif %}
{% if perms.attendance.delete_attendancelatecomeearlyout %}
<li class="oh-dropdown__item">
<a href="#" id="lateComeBulkDelete" class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
<a href="#" id="lateComeBulkDelete" data-action="delete" class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
</li>
{% endif %}
</ul>

View File

@@ -5,7 +5,6 @@ This page is used to map request or url path with function
"""
from django.apps import apps
from django.urls import path
import attendance.views.clock_in_out