diff --git a/attendance/forms.py b/attendance/forms.py index f1a538836..fd104c701 100644 --- a/attendance/forms.py +++ b/attendance/forms.py @@ -204,7 +204,10 @@ class AttendanceUpdateForm(ModelForm): self.fields["shift_id"].widget.attrs.update( { "id": str(uuid.uuid4()), - "onchange": "shiftChange($(this))", + "hx-include": "#attendanceUpdateForm", + "hx-target": "#attendanceUpdateForm", + "hx-trigger": "change", + "hx-get": "/attendance/update-fields-based-shift", } ) self.fields["attendance_date"].widget.attrs.update( @@ -278,22 +281,30 @@ class AttendanceForm(ModelForm): } def __init__(self, *args, **kwargs): + # Get the initial data passed from the view + view_initial = kwargs.pop("initial", {}) + + # Default initial values initial = { "attendance_clock_out_date": datetime.datetime.today() .date() .strftime("%Y-%m-%d"), "attendance_clock_out": datetime.datetime.today().time().strftime("%H:%M"), } + + # If an instance is provided, override the default initial values if instance := kwargs.get("instance"): - # django forms not showing value inside the date, time html element. - # so here overriding default forms instance method to set initial value - initial = { - "attendance_date": instance.attendance_date.strftime("%Y-%m-%d"), - "attendance_clock_in": instance.attendance_clock_in.strftime("%H:%M"), - "attendance_clock_in_date": instance.attendance_clock_in_date.strftime( - "%Y-%m-%d" - ), - } + initial.update( + { + "attendance_date": instance.attendance_date.strftime("%Y-%m-%d"), + "attendance_clock_in": instance.attendance_clock_in.strftime( + "%H:%M" + ), + "attendance_clock_in_date": instance.attendance_clock_in_date.strftime( + "%Y-%m-%d" + ), + } + ) if instance.attendance_clock_out_date is not None: initial["attendance_clock_out"] = ( instance.attendance_clock_out.strftime("%H:%M") @@ -301,14 +312,21 @@ class AttendanceForm(ModelForm): initial["attendance_clock_out_date"] = ( instance.attendance_clock_out_date.strftime("%Y-%m-%d") ) + + # Merge with initial values passed from the view + initial.update(view_initial) kwargs["initial"] = initial + super().__init__(*args, **kwargs) reload_queryset(self.fields) self.fields["employee_id"].widget.attrs.update({"id": str(uuid.uuid4())}) self.fields["shift_id"].widget.attrs.update( { "id": str(uuid.uuid4()), - "onchange": "shiftChange($(this))", + "hx-include": "#attendanceCreateForm", + "hx-target": "#attendanceCreateForm", + "hx-trigger": "change", + "hx-get": "/attendance/update-fields-based-shift", } ) self.fields["attendance_date"].widget.attrs.update( @@ -560,7 +578,11 @@ class AttendanceRequestForm(ModelForm): self.fields["shift_id"].widget.attrs.update( { "id": str(uuid.uuid4()), - "onchange": "shiftChange($(this))", + "hx-include": "#attendanceRequestForm", + "hx-target": "#attendanceRequestDiv", + "hx-trigger": "change", + "hx-swap": "outerHTML", + "hx-get": "/attendance/update-fields-based-shift", } ) self.fields["attendance_date"].widget.attrs.update( @@ -609,7 +631,8 @@ class NewRequestForm(AttendanceRequestForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - + # Get the initial data passes from views.py file + view_initial = kwargs.pop("initial", {}) # Add the new model choice field to the form at the beginning old_dict = self.fields new_dict = { @@ -624,6 +647,7 @@ class NewRequestForm(AttendanceRequestForm): "hx-trigger": "change", } ), + initial=view_initial.get("employee_id"), ), "create_bulk": forms.BooleanField( required=False, @@ -642,6 +666,8 @@ class NewRequestForm(AttendanceRequestForm): new_dict.update(old_dict) self.fields = new_dict + kwargs["initial"] = view_initial + def as_p(self, *args, **kwargs): """ Render the form fields as HTML table rows with Bootstrap styling. diff --git a/attendance/templates/attendance/attendance/attendance_view.html b/attendance/templates/attendance/attendance/attendance_view.html index d1860f212..dfa8a0200 100644 --- a/attendance/templates/attendance/attendance/attendance_view.html +++ b/attendance/templates/attendance/attendance/attendance_view.html @@ -1,132 +1,77 @@ -{% extends 'index.html' %} {% block content %} {% load static %} {% load i18n %} -{% load basefilters %} {% include 'attendance/attendance/attendance_nav.html' %} +{% extends 'index.html' %} +{% block content %} +{% load i18n %} +{% load static %} +{% load basefilters %} +{% include 'attendance/attendance/attendance_nav.html' %}
-
- -
- {% include 'attendance/attendance/tab_content.html' %}
-
{% endblock content %} diff --git a/attendance/templates/attendance/attendance/form.html b/attendance/templates/attendance/attendance/form.html index d8133ee7a..d1736a2ae 100644 --- a/attendance/templates/attendance/attendance/form.html +++ b/attendance/templates/attendance/attendance/form.html @@ -1,8 +1,11 @@ {% load i18n %} -
- {{form.as_p}} + + {{form.as_p}}
+ diff --git a/attendance/templates/attendance/attendance/update_form.html b/attendance/templates/attendance/attendance/update_form.html index dad39b8f0..59ddcacad 100644 --- a/attendance/templates/attendance/attendance/update_form.html +++ b/attendance/templates/attendance/attendance/update_form.html @@ -1,11 +1,11 @@ {% load i18n %} -
- {{form.as_p}} - - + + {{form.as_p}} +
diff --git a/attendance/templates/attendance/attendance/update_hx_form.html b/attendance/templates/attendance/attendance/update_hx_form.html new file mode 100644 index 000000000..b03a008c1 --- /dev/null +++ b/attendance/templates/attendance/attendance/update_hx_form.html @@ -0,0 +1,8 @@ +{{form.as_p}} + \ No newline at end of file diff --git a/attendance/templates/requests/attendance/form_field.html b/attendance/templates/requests/attendance/form_field.html index 56f1d79e0..54472f80b 100644 --- a/attendance/templates/requests/attendance/form_field.html +++ b/attendance/templates/requests/attendance/form_field.html @@ -1,12 +1,12 @@ - {% load i18n %} - + {{field}} diff --git a/attendance/templates/requests/attendance/request_new_form.html b/attendance/templates/requests/attendance/request_new_form.html index 73a54907d..4384f783d 100644 --- a/attendance/templates/requests/attendance/request_new_form.html +++ b/attendance/templates/requests/attendance/request_new_form.html @@ -1,72 +1,61 @@ -{% load i18n %}{% load widget_tweaks %} {% load attendancefilters %} -
-

- {% trans "New Attendances Request" %} -

- -
-
-
-
- {% csrf_token %} -
-
-
{{form.non_field_errors}}
- {% for field in form.visible_fields %} - {% if field.field.widget|is_select_multiple or field.field.widget|is_text_area %} - -
- - {{ field|add_class:"form-control" }} -
- - {% else %} -
- - {% if field.field.widget.input_type == "checkbox" %} -
- {{ field|add_class:"oh-switch__checkbox" }} - -
- {% else %} - {{ field|add_class:"form-control" }} - {% endif %} - {{field.errors}} -
- {% endif %} - {% endfor %} - -
- -
- - -
-
+
+
+
+ {% csrf_token %} +
+
+
{{form.non_field_errors}}
+ {% for field in form.visible_fields %} + {% if field.field.widget|is_select_multiple or field.field.widget|is_text_area %} + +
+ + {{ field|add_class:"form-control" }} +
+ {% else %} +
+ + {% if field.field.widget.input_type == "checkbox" %} +
+ {{ field|add_class:"oh-switch__checkbox" }} + +
+ {% else %} + {{ field|add_class:"form-control" }} + {% endif %} + {{field.errors}} +
+ {% endif %} + {% endfor %} +
+ +
+ +
+
+
+
+
+
- diff --git a/attendance/urls.py b/attendance/urls.py index c20abb753..94c03dfe8 100644 --- a/attendance/urls.py +++ b/attendance/urls.py @@ -302,9 +302,9 @@ urlpatterns = [ name="attendance-widget-filter", ), path( - "update-shift-details", - views.form_shift_dynamic_data, - name="update-shift-details", + "update-fields-based-shift", + views.update_fields_based_shift, + name="update-fields-based-shift", ), path( "update-date-details", diff --git a/attendance/views/views.py b/attendance/views/views.py index 02ee3369f..d5be5e5bd 100644 --- a/attendance/views/views.py +++ b/attendance/views/views.py @@ -60,6 +60,7 @@ from attendance.forms import ( AttendanceValidationConditionForm, GraceTimeForm, LateComeEarlyOutExportForm, + NewRequestForm, ) from attendance.methods.utils import ( Request, @@ -103,6 +104,7 @@ from base.models import ( AttendanceAllowedIP, EmployeeShiftSchedule, TrackLateComeEarlyOut, + WorkType, ) from employee.filters import EmployeeFilter from employee.models import Employee, EmployeeWorkInformation @@ -1407,62 +1409,90 @@ def approve_bulk_overtime(request): return JsonResponse({"message": "Success"}) -def form_shift_dynamic_data(request): - """ - This method is used to update the shift details to the form - """ - work_type = None - if "employee_id" in request.POST and request.POST["employee_id"]: - shift_id = request.POST["shift_id"] - # Check if 'employee_id' is present in POST request and not empty - if "employee_id" in request.POST and request.POST["employee_id"]: - employee_id = request.POST["employee_id"] - try: - employee = Employee.objects.get(id=employee_id) - # Use getattr to get the work type - work_type = employee.get_work_type() - if work_type: - work_type = work_type.id - except Employee.DoesNotExist: - pass - attendance_date_str = request.POST.get("attendance_date") - today = datetime.now() - attendance_date = date(day=today.day, month=today.month, year=today.year) - if attendance_date_str is not None and attendance_date_str != "": - attendance_date = datetime.strptime(attendance_date_str, "%Y-%m-%d").date() +@login_required +@hx_request_required +def update_fields_based_shift(request): + shift_id = request.GET.get("shift_id") + hx_target = request.META.get("HTTP_HX_TARGET") + + employee_ids = ( + request.GET.get("employee_id") + if hx_target == "attendanceUpdateForm" or hx_target == "attendanceRequestDiv" + else request.GET.getlist("employee_id") + ) + employee_queryset = ( + ( + Employee.objects.get(id=employee_ids) + if hx_target == "attendanceUpdateForm" + or hx_target == "attendanceRequestDiv" + else Employee.objects.filter(id__in=employee_ids) + ) + if employee_ids + else None + ) + attendance_date_str = request.GET.get("attendance_date") + + attendance_date = ( + datetime.strptime(attendance_date_str, "%Y-%m-%d").date() + if attendance_date_str + else datetime.today().date() + ) day = attendance_date.strftime("%A").lower() - schedule_today = None - if shift_id: - schedule_today = EmployeeShiftSchedule.objects.filter( - shift_id__id=shift_id, day__day=day - ).first() - shift_start_time = "" - shift_end_time = "" - minimum_hour = "00:00" - attendance_clock_out_date = attendance_date - if schedule_today is not None: - shift_start_time = schedule_today.start_time - shift_end_time = schedule_today.end_time - minimum_hour = schedule_today.minimum_working_hour - if shift_end_time < shift_start_time: - attendance_clock_out_date = attendance_date + timedelta(days=1) - worked_hour = minimum_hour - if attendance_date == date(day=today.day, month=today.month, year=today.year): - shift_end_time = datetime.now().strftime("%H:%M") + + schedule_today = ( + EmployeeShiftSchedule.objects.filter(shift_id=shift_id, day__day=day).first() + if shift_id + else None + ) + + shift_start_time = schedule_today.start_time if schedule_today else "" + shift_end_time = schedule_today.end_time if schedule_today else "" + minimum_hour = schedule_today.minimum_working_hour if schedule_today else "00:00" + + if schedule_today and shift_end_time < shift_start_time: + attendance_clock_out_date = (attendance_date + timedelta(days=1)).strftime( + "%Y-%m-%d" + ) + else: + attendance_clock_out_date = attendance_date.strftime("%Y-%m-%d") + + if attendance_date == datetime.today().date(): + shift_end_time = datetime.now().time() worked_hour = "00:00" + else: + worked_hour = minimum_hour minimum_hour = attendance_day_checking(str(attendance_date), minimum_hour) - return JsonResponse( - { - "shift_start_time": shift_start_time, - "shift_end_time": shift_end_time, - "checkin_date": attendance_date.strftime("%Y-%m-%d"), - "minimum_hour": minimum_hour, - "worked_hour": worked_hour, - "checkout_date": attendance_clock_out_date.strftime("%Y-%m-%d"), - "work_type": str(work_type), - } + initial_data = { + "work_type_id": WorkType.find(request.GET.get("work_type_id")), + "shift_id": shift_id, + "employee_id": employee_queryset, + "minimum_hour": minimum_hour, + "attendance_date": attendance_date.strftime("%Y-%m-%d"), + "attendance_clock_in": ( + shift_start_time.strftime("%H:%M") if shift_start_time else "" + ), + "attendance_clock_out": ( + shift_end_time.strftime("%H:%M") if shift_end_time else "" + ), + "attendance_worked_hour": worked_hour, + "attendance_clock_in_date": attendance_date.strftime("%Y-%m-%d"), + "attendance_clock_out_date": attendance_clock_out_date, + } + form = ( + AttendanceUpdateForm(initial=initial_data) + if hx_target == "attendanceUpdateForm" + else ( + NewRequestForm(initial=initial_data) + if hx_target == "attendanceRequestDiv" + else AttendanceForm(initial=initial_data) + ) + ) + return render( + request, + "attendance/attendance/update_hx_form.html", + {"request": request, "form": form}, ) diff --git a/horilla_views/cbv_methods.py b/horilla_views/cbv_methods.py index 93df82dda..c881b929b 100644 --- a/horilla_views/cbv_methods.py +++ b/horilla_views/cbv_methods.py @@ -139,7 +139,10 @@ def csrf_token(context): """ to access csrf token inside the render_template method """ - request = context["request"] + try: + request = context["request"] + except: + request = getattr(_thread_locals, "request") csrf_input_lazy = lazy(csrf_input, SafeString, str) return csrf_input_lazy(request) diff --git a/static/index/index.js b/static/index/index.js index 10e3c549e..2ec723fed 100644 --- a/static/index/index.js +++ b/static/index/index.js @@ -106,36 +106,6 @@ nav.after( ) ); - -function shiftChange(selectElement) { - var shiftId =selectElement.val() - let parentForm = selectElement.parents().closest("form") - var attendanceDate = parentForm.find("[name=attendance_date]").first().val() - var employeeId = parentForm.find("[name=employee_id]").first().val() - $.ajax({ - type: "post", - url: "/attendance/update-shift-details", - data: { - csrfmiddlewaretoken: getCookie("csrftoken"), - "shift_id":shiftId, - "attendance_date":attendanceDate, - 'employee_id':employeeId - }, - success: function (response) { - parentForm.find("[name=attendance_clock_in]").val(response.shift_start_time) - parentForm.find("[name=attendance_clock_out]").val(response.shift_end_time) - parentForm.find("[name=attendance_worked_hour]").val(response.worked_hour) - parentForm.find("[name=minimum_hour]").val(response.minimum_hour) - parentForm.find("[name=attendance_clock_out_date]").val(response.checkout_date) - parentForm.find("[name=attendance_clock_in_date]").val(response.checkin_date) - parentForm.find("[name=work_type_id]").val(response.work_type).change() - if (parentForm.find("[name=attendance_date]").val().length == 0) { - parentForm.find("[name=attendance_date]").val(response.checkin_date) - } - } - }); -} - function attendanceDateChange(selectElement) { var selectedDate =selectElement.val() let parentForm = selectElement.parents().closest("form") diff --git a/templates/quick_access.html b/templates/quick_access.html index 7b8113bdb..91459fc98 100644 --- a/templates/quick_access.html +++ b/templates/quick_access.html @@ -105,33 +105,6 @@ // ==================== Attendance request ==================== - function shiftChange(selectElement) { - var shiftId =selectElement.val() - let parentForm = selectElement.parents().closest("form") - var attendanceDate = parentForm.find("[name=attendance_date]").first().val() - $.ajax({ - type: "post", - url: "{% url 'update-shift-details' %}", - data: { - csrfmiddlewaretoken: getCookie("csrftoken"), - "shift_id":shiftId, - "attendance_date":attendanceDate - - }, - success: function (response) { - parentForm.find("[name=attendance_clock_in]").val(response.shift_start_time) - parentForm.find("[name=attendance_clock_out]").val(response.shift_end_time) - parentForm.find("[name=attendance_worked_hour]").val(response.worked_hour) - parentForm.find("[name=minimum_hour]").val(response.minimum_hour) - parentForm.find("[name=attendance_clock_out_date]").val(response.checkout_date) - parentForm.find("[name=attendance_clock_in_date]").val(response.checkin_date) - if (parentForm.find("[name=attendance_date]").val().length == 0) { - parentForm.find("[name=attendance_date]").val(response.checkin_date) - } - } - }); - } - function dateChange(selectElement) { var selectedDate =selectElement.val() let parentForm = selectElement.parents().closest("form")