[ADD] ATTENDANCE: Work record date filter
This commit is contained in:
@@ -1,6 +1,61 @@
|
||||
{% extends 'index.html' %} {% block content %} {% load i18n %}
|
||||
|
||||
<style>
|
||||
.date-filter-form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1rem 2rem;
|
||||
align-items: flex-end;
|
||||
background-color: #f9f9f9;
|
||||
padding: 1rem 1.5rem;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
|
||||
max-width: 700px;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Stack label and input vertically */
|
||||
.input-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.3rem;
|
||||
}
|
||||
|
||||
/* Button aligns right */
|
||||
.button-group {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Input style */
|
||||
.oh-input {
|
||||
padding: 0.5rem 0.75rem;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
font-size: 0.95rem;
|
||||
width: 180px;
|
||||
}
|
||||
|
||||
/* Button style */
|
||||
.oh-btn-filter {
|
||||
padding: 0.5rem 1.25rem;
|
||||
background-color: hsl(8, 77%, 56%);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 0.95rem;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.oh-btn-filter:hover {
|
||||
background-color: hsl(8, 77%, 56%);
|
||||
}
|
||||
|
||||
/* Label style */
|
||||
.date-filter-form label {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -48,12 +103,12 @@
|
||||
<div class="col-12 mt-4 mb-4">
|
||||
<div class="oh-card d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<h4>{% trans "Work Records" %}</h4>
|
||||
<h4>{% trans "Work Record Status" %}</h4>
|
||||
</div>
|
||||
<div class="me-3" >
|
||||
<h6 class="mb-2 fw-bold">{% trans "Date:" %} {{ current_date }}</h6>
|
||||
<h6>
|
||||
<div style = "cursor: pointer;display:flex;align-items:center">
|
||||
{% comment %} <div style = "cursor: pointer;display:flex;align-items:center">
|
||||
<label for="monthYearField" class="text-danger fw-bold" style = "cursor: pointer;">{% trans "Month" %}</label>
|
||||
<input class="oh-select p-2 w-75 m-1"
|
||||
type="month"
|
||||
@@ -64,7 +119,27 @@
|
||||
hx-target="#workRecordTable"
|
||||
hx-trigger="change"
|
||||
>
|
||||
</div>
|
||||
</div> {% endcomment %}
|
||||
<form
|
||||
id="dateFilterForm"
|
||||
hx-get="{% url 'work-records-change-month' %}"
|
||||
hx-target="#workRecordTable"
|
||||
class="date-filter-form"
|
||||
>
|
||||
<div class="input-group">
|
||||
<label for="startDate">Start Date:</label>
|
||||
<input type="date" name="start_date" id="startDate" class="oh-input">
|
||||
</div>
|
||||
|
||||
<div class="input-group">
|
||||
<label for="endDate">End Date:</label>
|
||||
<input type="date" name="end_date" id="endDate" class="oh-input" max="{{ today|date:'Y-m-d' }}">
|
||||
</div>
|
||||
|
||||
<div class="button-group">
|
||||
<button type="submit" class="oh-btn-filter">Filter</button>
|
||||
</div>
|
||||
</form>
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% if perms.attendance.delete_attendanceactivity %}
|
||||
<div class="detail-view" style="width: 100%;" onclick="event.stopPropagation()">
|
||||
<button class="oh-btn oh-btn-group oh-btn--secondary"
|
||||
hx-confirm="{% trans 'Are you sure you want to delete ?' %}"
|
||||
hx-post="{% url 'attendance-activity-delete' instance.id %}?instances_ids={{request.GET.instance_ids}}"
|
||||
hx-target="#genericModalBody" style="width:100%;"
|
||||
title="{% trans 'Delete' %}"
|
||||
data-toggle="oh-modal-toggle">
|
||||
<ion-icon class="me-1" name="trash-outline"></ion-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="detail-view" style="width: 100%" onclick="event.stopPropagation()">
|
||||
<button
|
||||
class="oh-btn oh-btn-group oh-btn--secondary"
|
||||
hx-confirm="{% trans 'Are you sure you want to delete ?' %}"
|
||||
hx-post="{% url 'attendance-activity-delete' instance.id %}?instances_ids={{request.GET.instance_ids}}"
|
||||
hx-target="#genericModalBody"
|
||||
style="width: 100%"
|
||||
title="{% trans 'Delete' %}"
|
||||
data-toggle="oh-modal-toggle"
|
||||
>
|
||||
<ion-icon class="me-1" name="trash-outline"></ion-icon>
|
||||
{% trans 'Delete' %}
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if request.GET.deleted %}
|
||||
<script>
|
||||
$("#reloadMessagesButton").click()
|
||||
$('.reload-record').click();
|
||||
</script>
|
||||
<script>
|
||||
$("#reloadMessagesButton").click();
|
||||
$(".reload-record").click();
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
@@ -2471,12 +2471,48 @@ def work_records_change_month(request):
|
||||
|
||||
employees = [request.user.employee_get] + list(page_emp.object_list)
|
||||
|
||||
month_dates = [
|
||||
datetime(year, month, day).date()
|
||||
for week in calendar.monthcalendar(year, month)
|
||||
for day in week
|
||||
if day
|
||||
]
|
||||
start_date_str = request.GET.get("start_date")
|
||||
end_date_str = request.GET.get("end_date")
|
||||
|
||||
# Initialize as None
|
||||
start_date = None
|
||||
end_date = None
|
||||
|
||||
# Try parsing the start date
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
start_date = None
|
||||
|
||||
# Try parsing the end date
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
end_date = None
|
||||
|
||||
# Default end_date to today if missing or invalid
|
||||
if not end_date:
|
||||
today = date.today()
|
||||
last_day = calendar.monthrange(today.year, today.month)[1]
|
||||
end_date = date(today.year, today.month, last_day)
|
||||
|
||||
# Default start_date to first day of end_date's month if missing or invalid
|
||||
if not start_date:
|
||||
start_date = date(year=end_date.year, month=end_date.month, day=1)
|
||||
|
||||
# Ensure start_date is not after end_date
|
||||
if start_date > end_date:
|
||||
# Optional: raise error or swap, depending on your use case
|
||||
start_date = date(year=end_date.year, month=end_date.month, day=1)
|
||||
|
||||
# Generate list of dates between start_date and end_date (inclusive)
|
||||
month_dates = []
|
||||
current_date = start_date
|
||||
while current_date <= end_date:
|
||||
month_dates.append(current_date)
|
||||
current_date += timedelta(days=1)
|
||||
|
||||
work_records = WorkRecords.objects.filter(
|
||||
date__in=month_dates, employee_id__in=page_emp.object_list
|
||||
@@ -2512,6 +2548,7 @@ def work_records_change_month(request):
|
||||
@login_required
|
||||
@permission_required("attendance.view_workrecords")
|
||||
def work_record_export(request):
|
||||
|
||||
try:
|
||||
month_str = request.GET.get("month")
|
||||
if month_str:
|
||||
@@ -2524,8 +2561,48 @@ def work_record_export(request):
|
||||
|
||||
employees = EmployeeFilter(request.GET).qs
|
||||
records = WorkRecords.objects.filter(date__month=month, date__year=year)
|
||||
num_days = calendar.monthrange(year, month)[1]
|
||||
all_date_objects = [date(year, month, day) for day in range(1, num_days + 1)]
|
||||
# all_date_objects = [date(year, month, day) for day in range(1, num_days + 1)]
|
||||
|
||||
start_date_str = request.GET.get("start_date")
|
||||
end_date_str = request.GET.get("end_date")
|
||||
|
||||
# Initialize as None
|
||||
start_date = None
|
||||
end_date = None
|
||||
|
||||
# Try parsing the start date
|
||||
if start_date_str:
|
||||
try:
|
||||
start_date = datetime.strptime(start_date_str, "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
start_date = None
|
||||
|
||||
# Try parsing the end date
|
||||
if end_date_str:
|
||||
try:
|
||||
end_date = datetime.strptime(end_date_str, "%Y-%m-%d").date()
|
||||
except ValueError:
|
||||
end_date = None
|
||||
|
||||
# Default end_date to today if missing or invalid
|
||||
if not end_date:
|
||||
end_date = date.today()
|
||||
|
||||
# Default start_date to first day of end_date's month if missing or invalid
|
||||
if not start_date:
|
||||
start_date = date(year=end_date.year, month=end_date.month, day=1)
|
||||
|
||||
# Ensure start_date is not after end_date
|
||||
if start_date > end_date:
|
||||
# Optional: raise error or swap, depending on your use case
|
||||
start_date = date(year=end_date.year, month=end_date.month, day=1)
|
||||
|
||||
# Generate list of dates between start_date and end_date (inclusive)
|
||||
all_date_objects = []
|
||||
current_date = start_date
|
||||
while current_date <= end_date:
|
||||
all_date_objects.append(current_date)
|
||||
current_date += timedelta(days=1)
|
||||
leave_dates = set(monthly_leave_days(month, year))
|
||||
|
||||
record_lookup = defaultdict(lambda: "ABS")
|
||||
|
||||
Reference in New Issue
Block a user