[UPDT] ATTENDANCE: Updated attendance app by adding htmx function in attendance dashboard cards

This commit is contained in:
Horilla
2024-12-04 14:46:55 +05:30
parent 078471a282
commit d2476619c9
12 changed files with 340 additions and 511 deletions

View File

@@ -5,18 +5,18 @@
reloadMessage()
</script>
{% if previous_url %}
<span hx-on-htmx-after-request="setTimeout(() => {$('#dynamicCreateBatchAttendanceSpan').removeAttr('hx-vals');$(this).parents().closest('.oh-modal--show').toggleClass('oh-modal--show');}, 500);"
<span hx-on-htmx-after-request="setTimeout(() => {$('#dynamicCreateBatchAttendanceSpan').removeAttr('hx-vals');$(this).parents().closest('.oh-modal--show').toggleClass('oh-modal--show');}, 500);"
hx-target="{{hx_target}}" hx-trigger="load"
hx-get="{{previous_url}}&{{previous_form_data}}"></span>
{% endif %}
{% endif %}
<div class="oh-modal__dialog">
<div class="oh-modal__dialog-header">
<button
type="button"
class="oh-modal_close--custom"
onclick="$(this).parents().closest('.oh-modal--show').toggleClass('oh-modal--show');$('#dynamicCreateBatchAttendanceSpan').removeAttr('hx-vals');"
onclick="$(this).parents().closest('.oh-modal--show').toggleClass('oh-modal--show');$('#dynamicCreateBatchAttendanceSpan').removeAttr('hx-vals');"
>
<ion-icon
name="close-outline"
@@ -27,9 +27,9 @@
</button>
</div>
<div class="oh-modal__dialog-body" id="addBatchModalBody">
<form hx-post="{% url 'create-batch-attendance' %}?{{previous_form_data}}" hx-target="#dynamicCreateModalTarget" id="attendanceBatchForm"
<form hx-post="{% url 'create-batch-attendance' %}?{{previous_form_data}}" hx-target="#dynamicCreateModalTarget" id="attendanceBatchForm"
data-url="objective-creation/?data=">
{{form.as_p}}
</form>
</div>
</div>
</div>

View File

@@ -48,7 +48,7 @@
>
<div class="oh-sticky-table__sd">
{% if batch.created_by == request.user %}
<input name="title" value="{{batch.title}}"
<input name="title" value="{{batch.title}}"
data-id = "{{batch.id}}"
style = "width: -webkit-fill-available;"
onchange = "batchTitleChange(this)"
@@ -61,8 +61,8 @@
<div class="oh-sticky-table__td">
<div class="oh-btn-group" onclick="event.stopPropagation()">
{% if perms.attendance.delete_batchattendance %}
<form
{% if perms.attendance.delete_batchattendance %}
<form
hx-post="{% url 'delete-batch' batch.id %}"
hx-confirm="{%trans "Are you sure want to delete this batch?" %}"
hx-target="#objectDetailsModalTarget" class='w-100'>
@@ -105,4 +105,4 @@
</div>
</div>
{% endif %}
</div>
</div>

View File

@@ -60,8 +60,7 @@
<div class="oh-dashboard__movable-cards row mt-4">
<div class="col-12 col-sm-12 col-md-12 col-lg-4 ">
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
style="min-height: 423px;"
>
style="min-height: 423px;">
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider"
style="margin-bottom:2.25rem;" id="attendance_header">
<div class="oh-card-dashboard__title mb-2">
@@ -143,48 +142,38 @@
<span class="oh-card-dashboard__title">{% trans "On Break" %}</span>
</div>
<div class="oh-card-dashboard__body" style="height:400px">
{% if on_break %}
<ul class="oh-card-dashboard__user-list">
{% for emp in on_break %}
<li class="oh-card-dashboard__user-item">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img src="https://ui-avatars.com/api/?name={{emp.employee_id}}&background=random"
class="oh-profile__image" alt="Amy Winehouse" />
</div>
<span class="oh-profile__name oh-text--dark">{{emp.employee_id}}</span>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<div style="height: 380px; display:flex;align-items: center;justify-content: center;"
class="">
<div style="" class="">
<img style=" display: block;width: 70px;margin: 20px auto ;" src="{% static '/images/ui/coffee-break.png' %}" class="" alt="" />
<h3 style="font-size:16px" class="oh-404__subtitle">{% trans "No employees are currently taking a break." %}</h3>
</div>
</div>
{% endif %}
<div class="oh-card-dashboard__body" hx-get="{% url 'on-break-employees' %}" hx-trigger="load"
id="onBreakEmployeesCard" style="height:400px">
<div class="animated-background h-100"></div>
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-12 col-lg-9">
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent">
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider">
<span class="oh-card-dashboard__title">{% trans "Overtime To Validate" %}</span>
<span class="oh-card-dashboard__title">{% trans "Overtime To Approve" %}</span>
</div>
<div class="oh-card-dashboard__body" style="height:400px">
{% include "attendance/dashboard/overtime_table.html" %}
<div class="oh-card-dashboard__body pb-4" style="height:400px"
hx-get="{% url 'dashboard-approve-overtimes' %}" hx-trigger="load"
hx-on-htmx-after-request="$('#department_date_type').change();"
id="OTApproveBody">
<div class="animated-background h-100"></div>
</div>
</div>
</div>
</div>
<div class="oh-dashboard row pt-3">
<div class="col-12 col-sm-12 col-md-12 col-lg-8" id="validateTableCard">
{% include "attendance/dashboard/to_validate_table.html" %}
<div class="oh-dashboard row pt-3">
<div class="col-12 col-sm-12 col-md-12 col-lg-8">
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent h-100">
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider">
<span class="oh-card-dashboard__title">{% trans "Attendance To Validate" %}</span>
</div>
<div class="oh-card-dashboard__body" style="height:400px" id="attendanceValidateCardBody"
hx-get="{% url 'dashboard-validate-attendances' %}" hx-trigger="load">
<div class="animated-background h-100"></div>
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-12 col-lg-4 " id="departmentChartCard">
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent">
@@ -241,7 +230,6 @@
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="{% static 'dashboard/attendanceChart.js' %}"></script>
{% endblock content %}
</div>
{% endblock content %}

View File

@@ -0,0 +1,27 @@
{% load static %}
{% load i18n %}
{% if on_break %}
<ul class="oh-card-dashboard__user-list">
{% for emp in on_break %}
<li class="oh-card-dashboard__user-item">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img src="https://ui-avatars.com/api/?name={{emp.employee_id}}&background=random"
class="oh-profile__image" alt="Amy Winehouse" />
</div>
<span class="oh-profile__name oh-text--dark">{{emp.employee_id}}</span>
</div>
</li>
{% endfor %}
</ul>
{% else %}
<div style="height: 380px; display:flex;align-items: center;justify-content: center;"
class="">
<div style="" class="">
<img style="display: block;width: 70px;margin: 20px auto ;"
src="{% static '/images/ui/coffee-break.png' %}" class="" alt="" />
<h3 style="font-size:16px" class="oh-404__subtitle">
{% trans "No employees are currently taking a break." %}</h3>
</div>
</div>
{% endif %}

View File

@@ -1,92 +1,104 @@
{% load i18n static %}
{% if overtime_attendances %}
<div class="oh-sticky-table h-100">
<div class="oh-sticky-table__table oh-table--sortable">
<div class="oh-sticky-table__thead">
<div class="oh-sticky-table__tr">
<div
class="oh-sticky-table__th"
>
{% trans "Employee" %}
<div class="oh-sticky-table h-100">
<div class="oh-sticky-table__table oh-table--sortable">
<div class="oh-sticky-table__thead">
<div class="oh-sticky-table__tr">
<div class="oh-sticky-table__th">
{% trans "Employee" %}
</div>
{% if not main_dashboard %}
<div class="oh-sticky-table__th">{% trans "Check-In" %}</div>
<div class="oh-sticky-table__th">
{% trans "In Date" %}
</div>
<div class="oh-sticky-table__th">{% trans "Check-Out" %}</div>
<div class="oh-sticky-table__th">
{% trans "Out Date" %}
</div>
{% endif %}
<div class="oh-sticky-table__th">
{% trans "Overtime" %}
</div>
<div class="oh-sticky-table__th">{% trans "Actions" %}</div>
</div>
<div class="oh-sticky-table__th">{% trans "Check-In" %}</div>
<div
class="oh-sticky-table__th"
>
{% trans "In Date" %}
</div>
<div class="oh-sticky-table__th">{% trans "Check-Out" %}</div>
<div
class="oh-sticky-table__th"
>
{% trans "Out Date" %}
</div>
<div
class="oh-sticky-table__th"
>
{% trans "Overtime" %}
</div>
<div class="oh-sticky-table__th">{% trans "Actions" %}</div>
</div>
</div>
{% for attendance in overtime_attendances %}
<div class="oh-sticky-table__tbody">
<div
class="oh-sticky-table__tr"
draggable="false"
data-toggle="oh-modal-toggle"
data-target="#objectDetailsModalW25"
hx-target="#objectDetailsModalW25Target"
hx-get="{% url 'user-request-one-view' attendance.id %}?ot=true&instances_ids={{ot_attendances_ids}}"
>
<div class="oh-sticky-table__sd">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img
src="{{attendance.employee_id.get_avatar}}"
class="oh-profile__image"
alt=""
/>
{% for attendance in overtime_attendances %}
<div class="oh-sticky-table__tbody">
<div class="oh-sticky-table__tr" draggable="false" data-toggle="oh-modal-toggle"
data-target="#objectDetailsModalW25" hx-target="#objectDetailsModalW25Target"
hx-get="{% url 'user-request-one-view' attendance.id %}?ot=true&instances_ids={{ot_attendances_ids}}">
<div class="oh-sticky-table__sd">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img src="{{attendance.employee_id.get_avatar}}" class="oh-profile__image" alt="" />
</div>
<span class="oh-profile__name oh-text--dark">{{attendance.employee_id}}</span>
</div>
<span class="oh-profile__name oh-text--dark"
>{{attendance.employee_id}}</span
>
</div>
{% if not main_dashboard %}
<div class="oh-sticky-table__td timeformat_changer">
{{attendance.attendance_clock_in}}
</div>
<div class="oh-sticky-table__td dateformat_changer">
{{attendance.attendance_clock_in_date}}
</div>
<div class="oh-sticky-table__td timeformat_changer">
{{attendance.attendance_clock_out}}
</div>
<div class="oh-sticky-table__td dateformat_changer">
{{attendance.attendance_clock_out_date}}
</div>
{% endif %}
<div class="oh-sticky-table__td">
{{attendance.attendance_overtime}}
</div>
<div class="oh-sticky-table__td">
<a href="{% url 'approve-overtime' attendance.id %}" onclick="event.stopPropagation()"
class="oh-btn oh-btn oh-btn--success w-100" title="{% trans 'Approve Overtime' %}">
<ion-icon class="me-1 md hydrated" name="checkmark-outline" role="img" aria-label="checkmark outline"></ion-icon>
</a>
</div>
</div>
<div class="oh-sticky-table__td timeformat_changer">
{{attendance.attendance_clock_in}}
</div>
<div class="oh-sticky-table__td dateformat_changer">
{{attendance.attendance_clock_in_date}}
</div>
<div class="oh-sticky-table__td timeformat_changer">
{{attendance.attendance_clock_out}}
</div>
<div class="oh-sticky-table__td dateformat_changer">
{{attendance.attendance_clock_out_date}}
</div>
<div class="oh-sticky-table__td">
{{attendance.attendance_overtime}}
</div>
<div class="oh-sticky-table__td">
<a
href="{% url 'approve-overtime' attendance.id %}"
onclick="event.stopPropagation()"
class="oh-btn oh-btn--info"
>
{% trans "Approve" %}
</a>
</div>
</div>
</div>
{% endfor %}
{% endfor %}
</div>
</div>
</div>
{% else %}
<div style="height: 380px; display:flex;align-items: center;justify-content: center;" class="">
<div style="" class="">
<img style="display: block;width: 70px;margin: 20px auto ;" src="{% static "/images/ui/overtime-icon.png" %}" class="" alt=""/>
<h3 style="font-size:16px" class="oh-404__subtitle">{% trans "No Overtime to Validate...." %}</h3>
</div>
</div>
<div style="height: 380px; display:flex;align-items: center;justify-content: center;" class="">
<div style="" class="">
<img style="display: block;width: 70px;margin: 20px auto ;" src="{% static '/images/ui/overtime-icon.png' %}"
class="" alt="" />
<h3 style="font-size:16px" class="oh-404__subtitle">{% trans "No Overtime to Validate...." %}</h3>
</div>
</div>
{% endif %}
{% if overtime_attendances.has_previous or overtime_attendances.has_next %}
<div class="float-end mt-2">
{% if overtime_attendances.has_previous %}
<span class="oh-card-dashboard__title" style="cursor: pointer"
hx-target="#OTApproveBody"
hx-get="{% url 'dashboard-approve-overtimes' %}?page={{ overtime_attendances.previous_page_number }}"
hx-trigger="click delay:0.3s">
<ion-icon name="caret-back-outline" role="img" class="md hydrated" aria-label="caret back outline"></ion-icon>
</span>
{% endif %}
{% if overtime_attendances.has_next %}
<span class="oh-card-dashboard__title ms-2 float-end" style="cursor: pointer"
hx-target="#OTApproveBody"
hx-get="{% url 'dashboard-approve-overtimes' %}?page={{ overtime_attendances.next_page_number }}"
hx-trigger="click delay:0.3s">
<ion-icon name="caret-forward-outline" role="img" class="md hydrated"
aria-label="caret back outline"></ion-icon>
</span>
{% endif %}
{% if overtime_attendances.has_previous or overtime_attendances.has_next %}
<span class="oh-pagination__page mt-1 fw-bold">
{% trans "Page" %} {{ overtime_attendances.number }} {%trans "of" %}
{{overtime_attendances.paginator.num_pages }}
</span>
{% endif %}
</div>
{% endif %}

View File

@@ -1,142 +1,122 @@
{% load i18n static basefilters %}
<div
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
>
<div
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
>
{% if validate_attendances.has_previous %}
<span class="oh-card-dashboard__title" id="department-previous" style="cursor: pointer;" hx-target="#validateTableCard"
hx-get="{% url 'attendance-validate-table' %}?{{pd}}&page={{ validate_attendances.previous_page_number }}">
<ion-icon name="caret-back-outline" role="img" class="md hydrated" aria-label="caret back outline"></ion-icon>
</span>
{% endif %}
<span class="oh-card-dashboard__title">{% trans 'Attendance To Validate' %} </span>
{% if validate_attendances.has_next %}
<span class="oh-card-dashboard__title float-end" id="department-previous" style="cursor: pointer;" hx-target="#validateTableCard"
hx-get="{% url 'attendance-validate-table' %}?{{pd}}&page={{ validate_attendances.next_page_number }}">
<ion-icon name="caret-forward-outline" role="img" class="md hydrated" aria-label="caret back outline"></ion-icon>
</span>
{% endif %}
</div>
<div class="oh-card-dashboard__body" style="height:450px">
{% if validate_attendances %}
<div class="oh-sticky-table h-100">
<div class="oh-sticky-table__table oh-table--sortable">
<div class="oh-sticky-table__thead">
<div class="oh-sticky-table__tr">
<div
class="oh-sticky-table__th"
>
{% if validate_attendances %}
<div class="oh-sticky-table h-100">
<div class="oh-sticky-table__table oh-table--sortable">
<div class="oh-sticky-table__thead">
<div class="oh-sticky-table__tr">
<div class="oh-sticky-table__th">
{% trans "Employee" %}
</div>
<div
class="oh-sticky-table__th"
>
{% trans "Date" %}
</div>
{% if not main_dashboard %}
<div class="oh-sticky-table__th">
{% trans "Date" %}
</div>
<div class="oh-sticky-table__th">{% trans "Check-In" %}</div>
<div
class="oh-sticky-table__th"
>
{% trans "In Date" %}
<div class="oh-sticky-table__th">
{% trans "In Date" %}
</div>
<div class="oh-sticky-table__th">{% trans "Check-Out" %}</div>
<div
class="oh-sticky-table__th"
>
{% trans "Out Date" %}
<div class="oh-sticky-table__th">
{% trans "Out Date" %}
</div>
<div class="oh-sticky-table__th">{% trans "Shift" %}</div>
<div class="oh-sticky-table__th">{% trans "Work Type" %}</div>
<div class="oh-sticky-table__th">{% trans "Min Hour" %}</div>
<div
class="oh-sticky-table__th"
>
<div class="oh-sticky-table__th">
{% trans "Pending Hour" %}
</div>
{% endif %}
<div class="oh-sticky-table__th">
{% trans "At Work" %}
</div>
<div
class="oh-sticky-table__th"
>
{% trans "Pending Hour" %}
</div>
<div class="oh-sticky-table__th oh-sticky-table__right">{% trans "Actions" %}</div>
</div>
<div class="oh-sticky-table__th oh-sticky-table__right">{% trans "Actions" %}</div>
</div>
{% for attendance in validate_attendances %}
<div class="oh-sticky-table__tbody">
<div
class="oh-sticky-table__tr"
draggable="false"
data-toggle="oh-modal-toggle"
data-target="#objectDetailsModalW25"
hx-target="#objectDetailsModalW25Target"
hx-get="{% url 'user-request-one-view' attendance.id %}?validate=true&instances_ids={{validate_attendances_ids}}"
>
</div>
{% for attendance in validate_attendances %}
<div class="oh-sticky-table__tbody">
<div class="oh-sticky-table__tr" draggable="false" data-toggle="oh-modal-toggle"
data-target="#objectDetailsModalW25" hx-target="#objectDetailsModalW25Target"
hx-get="{% url 'user-request-one-view' attendance.id %}?validate=true&instances_ids={{validate_attendances_ids}}">
<div class="oh-sticky-table__sd">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img
src="{{attendance.employee_id.get_avatar}}"
class="oh-profile__image"
alt="Mary Magdalene"
/>
</div>
<span class="oh-profile__name oh-text--dark"
>{{attendance.employee_id}}</span
>
<div class="oh-sticky-table__sd">
<div class="oh-profile oh-profile--md">
<div class="oh-profile__avatar mr-1">
<img src="{{attendance.employee_id.get_avatar}}" class="oh-profile__image"
alt="Mary Magdalene" />
</div>
<span class="oh-profile__name oh-text--dark">{{attendance.employee_id}}</span>
</div>
</div>
{% if not main_dashboard %}
<div class="oh-sticky-table__td dateformat_changer">{{attendance.attendance_date}}</div>
<div class="oh-sticky-table__td timeformat_changer">
{{attendance.attendance_clock_in}}
{{attendance.attendance_clock_in}}
</div>
<div class="oh-sticky-table__td dateformat_changer">
{{attendance.attendance_clock_in_date}}
{{attendance.attendance_clock_in_date}}
</div>
<div class="oh-sticky-table__td timeformat_changer">
{{attendance.attendance_clock_out}}
{{attendance.attendance_clock_out}}
</div>
<div class="oh-sticky-table__td dateformat_changer">
{{attendance.attendance_clock_out_date}}
{{attendance.attendance_clock_out_date}}
</div>
<div class="oh-sticky-table__td">{{attendance.shift_id}}</div>
<div class="oh-sticky-table__td">{{attendance.work_type_id}}</div>
<div class="oh-sticky-table__td">{{attendance.minimum_hour}}</div>
<div class="oh-sticky-table__td">
{{attendance.attendance_worked_hour}}
</div>
<div class="oh-sticky-table__td">{{attendance.hours_pending}}</div>
<div class="oh-sticky-table__td oh-sticky-table__right">
{% if perms.attendance.change_attendance or request.user|is_reportingmanager %}
<a
href='{% url "validate-this-attendance" attendance.id %}'
hx-target="#updateAttendanceBody"
{% endif %}
<div class="oh-sticky-table__td">
{{attendance.attendance_worked_hour}}
</div>
<div class="oh-sticky-table__td oh-sticky-table__right">
{% if perms.attendance.change_attendance or request.user|is_reportingmanager %}
<a href='{% url "validate-this-attendance" attendance.id %}' hx-target="#updateAttendanceBody"
data-req="/attendance/request-attendance-view/?id={{attendance.id}}"
onclick="event.stopPropagation(); {% if attendance.is_validate_request %} event.preventDefault(); showSweetAlert($(this).data('req')); {% endif %}"
class="oh-btn oh-btn--info"
>
class="oh-btn oh-btn--info">
{% trans "Validate" %}
</a>
{% endif %}
</div>
</a>
{% endif %}
</div>
</div>
{% endfor %}
</div>
</div>
{% else %}
<div style="height: 380px; display:flex;align-items: center;justify-content: center;" class="">
<div style="" class="">
<img style="display: block;width: 70px;margin: 20px auto ;" src="{% static "/images/ui/attendance-validate.png" %}" class="" alt=""/>
</div>
</div>
{% endfor %}
</div>
</div>
{% else %}
<div style="height: 380px; display:flex;align-items: center;justify-content: center;" class="">
<div style="" class="">
<img style="display: block;width: 70px;margin: 20px auto ;" src="{% static '/images/ui/attendance-validate.png' %}" class="" alt="" />
<h3 style="font-size:16px" class="oh-404__subtitle">{% trans "All Attendance Validated." %}</h3>
</div>
</div>
</div>
</div>
{% endif %}
{% if validate_attendances.has_previous or validate_attendances.has_next %}
<div class="float-end mt-2">
{% if validate_attendances.has_previous %}
<span class="oh-card-dashboard__title" style="cursor: pointer"
hx-target="#attendanceValidateCardBody"
hx-get="{% url 'dashboard-validate-attendances' %}?page={{ validate_attendances.previous_page_number }}"
hx-trigger="click delay:0.3s">
<ion-icon name="caret-back-outline" role="img" class="md hydrated" aria-label="caret back outline"></ion-icon>
</span>
{% endif %}
{% if validate_attendances.has_next %}
<span class="oh-card-dashboard__title ms-2 float-end" style="cursor: pointer"
hx-target="#attendanceValidateCardBody"
hx-get="{% url 'dashboard-validate-attendances' %}?page={{ validate_attendances.next_page_number }}"
hx-trigger="click delay:0.3s">
<ion-icon name="caret-forward-outline" role="img" class="md hydrated"
aria-label="caret back outline"></ion-icon>
</span>
{% endif %}
{% if validate_attendances.has_previous or validate_attendances.has_next %}
<span class="oh-pagination__page mt-1 fw-bold">
{% trans "Page" %} {{ validate_attendances.number }} {%trans "of" %}
{{validate_attendances.paginator.num_pages }}
</span>
{% endif %}
</div>
</div>
{% endif %}

View File

@@ -225,16 +225,26 @@ urlpatterns = [
path(
"dashboard", attendance.views.dashboard.dashboard, name="attendance-dashboard"
),
path(
"on-break-employees",
attendance.views.dashboard.on_break_employees,
name="on-break-employees",
),
path(
"dashboard-approve-overtimes",
attendance.views.dashboard.dashboard_approve_overtimes,
name="dashboard-approve-overtimes",
),
path(
"dashboard-validate-attendances",
attendance.views.dashboard.dashboard_validate_attendances,
name="dashboard-validate-attendances",
),
path(
"department-overtime-chart",
attendance.views.dashboard.department_overtime_chart,
name="department-overtime-chart",
),
path(
"attendance-validate-table/",
attendance.views.dashboard.validated_attendances_table,
name="attendance-validate-table",
),
path(
"dashboard-attendance/",
attendance.views.dashboard.dashboard_attendance,
@@ -440,16 +450,6 @@ urlpatterns = [
attendance.views.penalty.cut_available_leave,
name="cut-penalty",
),
path(
"dashboard-overtime-approve",
attendance.views.dashboard.dashboard_overtime_approve,
name="dashboard-overtime-approve",
),
path(
"dashboard-attendance-validate",
attendance.views.dashboard.dashboard_attendance_validate,
name="dashboard-attendance-validate",
),
path(
"attendance-settings-view/",
views.validation_condition_view,

View File

@@ -8,7 +8,6 @@ import json
from datetime import date, datetime
from django.apps import apps
from django.db.models import Q
from django.http import JsonResponse
from django.shortcuts import render
from django.utils.translation import gettext_lazy as _
@@ -75,12 +74,6 @@ def dashboard(request):
"""
This method is used to render individual dashboard for attendance module
"""
page_number = request.GET.get("page")
previous_data = request.GET.urlencode()
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()
@@ -101,10 +94,61 @@ def dashboard(request):
marked_attendances_ratio = (
f"{(marked_attendances / expected_attendances) * 100:.2f}"
)
return render(
request,
"attendance/dashboard/dashboard.html",
{
"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,
},
)
@login_required
@hx_request_required
def on_break_employees(request):
"""
Fetches and displays employees who left early (early outs) for the current day.
This view retrieves all records from the `AttendanceLateComeEarlyOut` model
where the type is "early_out" and the associated attendance date matches the current date.
The results are passed to the template `on_break_employees.html` for rendering
"""
today = datetime.today()
early_outs = AttendanceLateComeEarlyOut.objects.filter(
type="early_out", attendance_id__attendance_date=today
)
context = {
"on_break": early_outs,
}
return render(request, "attendance/dashboard/on_break_employees.html", context)
@login_required
@hx_request_required
def dashboard_approve_overtimes(request):
"""
Displays and validates employee overtime records for the dashboard.
This view retrieves a paginated list of employee attendance records with
overtime that meets or exceeds a specified minimum threshold, which is defined
in the `AttendanceValidationCondition` model. Only records that are validated
but not yet approved are included, and the results are filtered based on the
user's subordinate permissions.
"""
main_dashboard = None
referer = request.META.get("HTTP_REFERER", "/")
referer = "/" + "/".join(referer.split("/")[3:])
if referer == "/":
main_dashboard = True
page_number = request.GET.get("page")
condition = AttendanceValidationCondition.objects.first()
min_ot = strtime_seconds("00:00")
if condition is not None and condition.minimum_overtime_to_approve is not None:
@@ -121,6 +165,33 @@ def dashboard(request):
queryset=ot_attendances,
)
id_list = [ot.id for ot in ot_attendances]
ot_attendances_ids = json.dumps(list(id_list))
ot_attendances = paginator_qry(ot_attendances, page_number)
context = {
"overtime_attendances": ot_attendances,
"ot_attendances_ids": ot_attendances_ids,
"main_dashboard": main_dashboard,
}
return render(request, "attendance/dashboard/overtime_table.html", context)
@login_required
@hx_request_required
def dashboard_validate_attendances(request):
"""
Displays and validates employee attendance records for the dashboard.
This view retrieves a paginated list of attendance records that have not yet
been validated. Only records belonging to active employees and accessible
subordinates, as determined by the user's permissions, are included in the results.
"""
main_dashboard = None
referer = request.META.get("HTTP_REFERER", "/")
referer = "/" + "/".join(referer.split("/")[3:])
if referer == "/":
main_dashboard = True
page_number = request.GET.get("page")
validate_attendances = Attendance.objects.filter(
attendance_validated=False, employee_id__is_active=True
)
@@ -130,52 +201,16 @@ def dashboard(request):
perm="attendance.change_overtime",
queryset=validate_attendances,
)
validate_attendances = paginator_qry(validate_attendances, page_number)
id_list = [ot.id for ot in ot_attendances]
validate_id_list = [val.id for val in validate_attendances]
ot_attendances_ids = json.dumps(list(id_list))
validate_attendances_ids = json.dumps(list(validate_id_list))
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,
"overtime_attendances": ot_attendances,
"validate_attendances": validate_attendances,
"pd": previous_data,
"ot_attendances_ids": ot_attendances_ids,
"validate_attendances_ids": validate_attendances_ids,
},
)
@login_required
@hx_request_required
def validated_attendances_table(request):
page_number = request.GET.get("page")
previous_data = request.GET.urlencode()
validate_attendances = Attendance.objects.filter(
attendance_validated=False, employee_id__is_active=True
)
validate_attendances = filtersubordinates(
request=request,
perm="attendance.change_attendance",
queryset=validate_attendances,
)
validate_attendances = paginator_qry(validate_attendances, page_number)
context = {
"validate_attendances": paginator_qry(validate_attendances, page_number),
"pd": previous_data,
"validate_attendances": validate_attendances,
"validate_attendances_ids": validate_attendances_ids,
"main_dashboard": main_dashboard,
}
return render(request, "attendance/dashboard/to_validate_table.html", context)
@@ -417,63 +452,3 @@ def department_overtime_chart(request):
}
return JsonResponse(response)
@login_required
def dashboard_overtime_approve(request):
previous_data = request.GET.urlencode()
page_number = request.GET.get("page")
min_ot = strtime_seconds("00:00")
if apps.is_installed("attendance"):
from attendance.models import Attendance, AttendanceValidationCondition
condition = AttendanceValidationCondition.objects.first()
if condition is not None and condition.minimum_overtime_to_approve is not None:
min_ot = strtime_seconds(condition.minimum_overtime_to_approve)
ot_attendances = Attendance.objects.filter(
overtime_second__gte=min_ot,
attendance_validated=True,
employee_id__is_active=True,
attendance_overtime_approve=False,
)
else:
ot_attendances = None
ot_attendances = filtersubordinates(
request, ot_attendances, "attendance.change_attendance"
)
ot_attendances = paginator_qry(ot_attendances, page_number)
ot_attendances_ids = json.dumps([instance.id for instance in ot_attendances])
return render(
request,
"request_and_approve/overtime_approve.html",
{
"overtime_attendances": ot_attendances,
"ot_attendances_ids": ot_attendances_ids,
"pd": previous_data,
},
)
@login_required
def dashboard_attendance_validate(request):
previous_data = request.GET.urlencode()
page_number = request.GET.get("page")
validate_attendances = Attendance.objects.filter(
attendance_validated=False, employee_id__is_active=True
)
validate_attendances = filtersubordinates(
request, validate_attendances, "attendance.change_attendance"
)
validate_attendances = paginator_qry(validate_attendances, page_number)
validate_attendances_ids = json.dumps(
[instance.id for instance in validate_attendances]
)
return render(
request,
"request_and_approve/attendance_validate.html",
{
"validate_attendances": validate_attendances,
"validate_attendances_ids": validate_attendances_ids,
"pd": previous_data,
},
)