[UPDT] ATTENDANCE: Updated attendance app by adding htmx function in attendance dashboard cards
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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 %}
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user