[UPDT] ATTENDANCE: Updated get_diff_dict function for improved performance and readability by reducing redundant operations

This commit is contained in:
Horilla
2024-12-03 17:21:00 +05:30
parent 4b3de79298
commit 684b6a2971
2 changed files with 237 additions and 310 deletions

View File

@@ -98,53 +98,63 @@ def get_diff_dict(first_dict, other_dict, model=None):
Args:
first_dict: The first dictionary to compare.
other_dict: The second dictionary to compare.
model: The model class
model: The model class (optional, for verbose names and type-specific formatting)
Returns:
A dictionary of differing keys with their old and new values.
"""
# model is passed as argument if any need of verbose name instead of field name
difference = {}
if model is None:
for key in first_dict:
if first_dict[key] != other_dict[key]:
# get the verbose name of the field
difference[key] = (first_dict[key], other_dict[key])
return difference
for key in first_dict:
if first_dict[key] != other_dict[key]:
# get the verbose name of the field
field = model._meta.get_field(key)
verb_key = field.verbose_name
value = first_dict[key]
other_value = other_dict[key]
if isinstance(field, models.DateField):
if value is not None and value != "None":
value = datetime.strptime(value, "%Y-%m-%d").strftime("%d %b %Y")
if other_value is not None and other_value != "None":
other_value = datetime.strptime(other_value, "%Y-%m-%d").strftime(
"%d %b %Y"
)
elif isinstance(field, models.TimeField):
if value is not None and value != "None":
if len(value.split(":")) == 2:
value = value + ":00"
value = datetime.strptime(value, "%H:%M:%S").strftime("%I:%M %p")
if other_value is not None and value != "None":
if len(other_value.split(":")) == 2:
other_value = other_value + ":00"
if other_value != "None":
other_value = datetime.strptime(
other_value, "%H:%M:%S"
).strftime("%I:%M %p")
else:
other_value = "None"
elif isinstance(field, models.ForeignKey):
if value is not None and len(str(value)):
value = field.related_model.objects.get(id=value)
if other_value is not None and len(str(other_value)):
other_value = field.related_model.objects.get(id=other_value)
difference[verb_key] = (value, other_value)
for key, value in first_dict.items():
other_value = other_dict.get(key)
if value == other_value:
continue # Skip if values are the same
if not model:
difference[key] = (value, other_value)
continue
# Fetch the model field metadata
field = model._meta.get_field(key)
verbose_key = field.verbose_name
# Handle specific field types
if isinstance(field, models.DateField):
value = (
datetime.strptime(value, "%Y-%m-%d").strftime("%d %b %Y")
if value and value != "None"
else value
)
other_value = (
datetime.strptime(other_value, "%Y-%m-%d").strftime("%d %b %Y")
if other_value and other_value != "None"
else other_value
)
elif isinstance(field, models.TimeField):
def format_time(val):
if val and val != "None":
val += ":00" if len(val.split(":")) == 2 else ""
return datetime.strptime(val, "%H:%M:%S").strftime("%I:%M %p")
return val
value = format_time(value)
other_value = format_time(other_value)
elif isinstance(field, models.ForeignKey):
value = (
field.related_model.objects.get(id=value)
if value and str(value).isdigit()
else value
)
other_value = (
field.related_model.objects.get(id=other_value)
if other_value and str(other_value).isdigit()
else other_value
)
# Add the difference
difference[verbose_key] = (value, other_value)
return difference

View File

@@ -5,7 +5,7 @@
position: sticky;
right: 0;
background-color: #fff;
}
}
</style>
<div class="oh-wrapper">
<div class="oh-dashboard__left col-12 col-sm-12 col-md-12 col-lg-12 pb-5">
@@ -14,89 +14,191 @@
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
<div class="oh-card-dashboard oh-card-dashboard--neutral">
<div class="oh-card-dashboard__header">
<span class="oh-card-dashboard__title"
>{% trans "Today's Attendances" %}</span
>
<span class="oh-card-dashboard__title">{% trans "Today's Attendances" %}</span>
</div>
<div class="oh-card-dashboard__body">
<div class="oh-card-dashboard__counts">
<span class="oh-card-dashboard__count"
>{{marked_attendances_ratio}}%</span
>
<span class="oh-card-dashboard__count">{{marked_attendances_ratio}}%</span>
</div>
{% comment %} <span class="oh-badge oh-card-dashboard__badge"
>{{marked_attendances}}/{{expected_attendances}}</span
> {% endcomment %}
{% comment %}
<span class="oh-badge oh-card-dashboard__badge">{{marked_attendances}}/{{expected_attendances}}</span>
{% endcomment %}
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
<div
class="oh-card-dashboard oh-card-dashboard oh-card-dashboard--success"
>
<div class="oh-card-dashboard oh-card-dashboard oh-card-dashboard--success">
<div class="oh-card-dashboard__header">
<span class="oh-card-dashboard__title"
>{% trans "On Time" %}</span
>
<span class="oh-card-dashboard__title">{% trans "On Time" %}</span>
</div>
<div class="oh-card-dashboard__body">
<div class="oh-card-dashboard__counts">
<span class="oh-card-dashboard__count"
>{{on_time}}</span
>
<span class="oh-card-dashboard__count">{{on_time}}</span>
</div>
{% comment %} <span class="oh-badge oh-card-dashboard__badge"
>{{on_time_ratio}}%</span
> {% endcomment %}
{% comment %}
<span class="oh-badge oh-card-dashboard__badge">{{on_time_ratio}}%</span>
{% endcomment %}
</div>
</div>
</div>
{% if late_come_early_out_tracking %}
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
<div class="oh-card-dashboard oh-card-dashboard--danger">
<div class="oh-card-dashboard__header">
<span class="oh-card-dashboard__title"
>{% trans "Late Come" %}</span
>
</div>
<div class="oh-card-dashboard__body">
<div class="oh-card-dashboard__counts">
<span class="oh-card-dashboard__count"
>{{late_come}}</span
>
{% if late_come_early_out_tracking %}
<div class="col-12 col-sm-12 col-md-6 col-lg-4">
<div class="oh-card-dashboard oh-card-dashboard--danger">
<div class="oh-card-dashboard__header">
<span class="oh-card-dashboard__title">{% trans "Late Come" %}</span>
</div>
<div class="oh-card-dashboard__body">
<div class="oh-card-dashboard__counts">
<span class="oh-card-dashboard__count">{{late_come}}</span>
</div>
</div>
</div>
{% endif %}
{% endif %}
</div>
</div>
</div>
<div class="oh-dashboard row pt-3">
<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"
>
<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">
{% trans "Attendance Analytic" %}
</div>
<div class="d-flex justify-content-between mb-2">
<select
id="type"
class="oh-select"
name="type"
onchange="changeView(this)"
style="
<div class="oh-dashboard row pt-3">
<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;"
>
<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">
{% trans "Attendance Analytic" %}
</div>
<div class="d-flex justify-content-between mb-2">
<select id="type" class="oh-select" name="type" onchange="changeView(this)" style="
width: 150px;
padding: 3px;
color: #5e5c5c;
"
>
">
<option value="day">
{% trans "Day" %}
</option>
<option value="weekly">
{% trans "Weekly" %}
</option>
<option value="monthly">
{% trans "Monthly" %}
</option>
<option value="date_range">
{% trans "Date range" %}
</option>
</select>
<span id="day_input">
<input type="date" class="mb-2 float-end pointer oh-select"
id="attendance_month" onchange="changeMonth()"
style="width: 100px; color: #5e5c5c" />
</span>
</div>
<div class="oh-card-dashboard__body">
<canvas id="dailyAnalytic" style="cursor: pointer"></canvas>
</div>
</div>
</div>
</div>
<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">
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider">
<span class="oh-card-dashboard__title">{% trans 'Offline Employees' %}
</span>
</div>
<div class="oh-card-dashboard__body" hx-get="{% url 'not-in-yet' %}" hx-trigger="load"
id="notInYetIdCardBody" style="height: 310px;">
<div class="animated-background"></div>
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-12 col-lg-4 " id="pendingHours">
<div class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent"
style="min-height: 423px;">
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider"
id="pendingHoursHeader">
<div class="d-flex justify-content-between">
<div class="oh-card-dashboard__title mb-2">
{% trans "Hours Chart" %}
</div>
<div class="d-flex justify-content-between mb-2">
<input type="month" class="mb-2 float-end pointer oh-select"
id="hourAccountMonth" onchange="dynamicMonth($(this))"
style="width: 100px; color: #5e5c5c" />
</div>
</div>
<div class="oh-card-dashboard__body" style="height:275px">
<canvas id="pendingHoursCanvas" style="cursor: pointer"></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="oh-dashboard row pt-3">
<div class="col-12 col-sm-12 col-md-12 col-lg-3 ">
<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 "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>
</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>
</div>
<div class="oh-card-dashboard__body" style="height:400px">
{% include "attendance/dashboard/overtime_table.html" %}
</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>
<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">
<div class="oh-card-dashboard__header oh-card-dashboard__header--divider"
id="departmentChartHeader">
<div class="oh-card-dashboard__title mb-2">
{% trans "Department Overtime Chart" %}
</div>
<div class="d-flex justify-content-between mb-2">
<select id="department_date_type" class="oh-select" name="type" style="
width: 150px;
padding: 3px;
color: #5e5c5c;
">
<option value="day">
{% trans "Day" %}
</option>
@@ -110,221 +212,36 @@
{% trans "Date range" %}
</option>
</select>
<span id="day_input">
<input
type="date"
class="mb-2 float-end pointer oh-select"
id="attendance_month"
onchange="changeMonth()"
style="width: 100px; color: #5e5c5c"
/>
<span id="department_day_input">
<input type="date" class="mb-2 float-end pointer oh-select" id="department_month"
style="width: 100px; color: #5e5c5c" />
</span>
</div>
<div class="oh-card-dashboard__body">
<canvas
id="dailyAnalytic"
style="cursor: pointer"
></canvas>
<div class="oh-card-dashboard__body" style="height:400px">
<canvas id="departmentOverChart" style="cursor: pointer"></canvas>
</div>
</div>
</div>
</div>
<div class="col-12 col-sm-12 col-md-12 col-lg-4"
id="notInYetId"
hx-get="{% url "not-in-yet" %}" hx-trigger="load" >
{% include "dashboard/not_in_yet.html" %}
</div>
<div
class="col-12 col-sm-12 col-md-12 col-lg-4 "
id="pendingHours"
>
<div
class="oh-card-dashboard oh-card-dashboard--no-scale oh-card-dashboard--transparent" style="min-height: 423px;"
>
<div
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
id="pendingHoursHeader"
>
<div class="d-flex justify-content-between">
<div class="oh-card-dashboard__title mb-2">
{% trans "Hours Chart" %}
</div>
<div class="d-flex justify-content-between mb-2">
<input
type="month"
class="mb-2 float-end pointer oh-select"
id="hourAccountMonth"
onchange="dynamicMonth($(this))"
style="width: 100px; color: #5e5c5c"
/>
</div>
</div>
<div class="oh-card-dashboard__body" style="height:275px">
<canvas
id="pendingHoursCanvas"
style="cursor: pointer"
></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="oh-dashboard row pt-3">
<div
class="col-12 col-sm-12 col-md-12 col-lg-3 "
>
<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 "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 on break...." %}</h3>
</div>
</div>
{% endif %}
</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
>
</div>
<div class="oh-card-dashboard__body" style="height:400px">
{% include "attendance/dashboard/overtime_table.html" %}
</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>
<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"
>
<div
class="oh-card-dashboard__header oh-card-dashboard__header--divider"
id="departmentChartHeader"
>
<div class="oh-card-dashboard__title mb-2">
{% trans "Department Overtime Chart" %}
</div>
<div class="d-flex justify-content-between mb-2">
<select
id="department_date_type"
class="oh-select"
name="type"
style="
width: 150px;
padding: 3px;
color: #5e5c5c;
"
>
<option value="day">
{% trans "Day" %}
</option>
<option value="weekly">
{% trans "Weekly" %}
</option>
<option value="monthly">
{% trans "Monthly" %}
</option>
<option value="date_range">
{% trans "Date range" %}
</option>
</select>
<span id="department_day_input">
<input
type="date"
class="mb-2 float-end pointer oh-select"
id="department_month"
style="width: 100px; color: #5e5c5c"
/>
</span>
</div>
<div class="oh-card-dashboard__body" style="height:400px">
<canvas
id="departmentOverChart"
style="cursor: pointer"
></canvas>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="oh-modal"
id="sendMailModal"
role="dialog"
aria-labelledby="sendMailModal"
aria-hidden="true"
>
<div class="oh-modal__dialog">
<div class="oh-modal__dialog-header">
<h5 class="oh-modal__dialog-title" id="sendMailModalLabel">
{% trans "Send Mail" %}
</h5>
<button class="oh-modal__close" aria-label="Close">
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
<div class="oh-modal__dialog-body" id="mail-content"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div class="oh-modal" id="sendMailModal" role="dialog" aria-labelledby="sendMailModal" aria-hidden="true">
<div class="oh-modal__dialog">
<div class="oh-modal__dialog-header">
<h5 class="oh-modal__dialog-title" id="sendMailModalLabel">
{% trans "Send Mail" %}
</h5>
<button class="oh-modal__close" aria-label="Close">
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
<div class="oh-modal__dialog-body" id="mail-content"></div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="{% static 'dashboard/attendanceChart.js' %}"></script>
<script src="{% static 'dashboard/attendanceChart.js' %}"></script>
{% endblock content %}
{% endblock content %}