From aa6f72a6ff7c4ae182f57c3b75808e876277ed62 Mon Sep 17 00:00:00 2001 From: Horilla Date: Thu, 22 Aug 2024 17:39:42 +0530 Subject: [PATCH] [UPDT] LEAVE: Added htmx for available days message display in leave request --- leave/forms.py | 73 ++++-- leave/models.py | 72 ++++-- .../employee_available_leave_count.html | 53 +++++ .../leave_request/leave_request_form.html | 1 + .../leave/leave_request/leave_type_field.html | 8 + .../leave_request/request_update_form.html | 2 +- .../leave/user_leave/user_request_view.html | 57 ----- leave/threading.py | 49 ++-- leave/urls.py | 6 +- static/images/ui/info.png | Bin 0 -> 20169 bytes static/index/index.js | 225 ------------------ 11 files changed, 195 insertions(+), 351 deletions(-) create mode 100644 leave/templates/leave/leave_request/employee_available_leave_count.html create mode 100644 static/images/ui/info.png diff --git a/leave/forms.py b/leave/forms.py index 01e1cd83f..5b66d7750 100644 --- a/leave/forms.py +++ b/leave/forms.py @@ -320,14 +320,19 @@ class LeaveRequestCreationForm(ModelForm): unique_dates = list(set(month_year)) if f"{today.month}-{today.year}" in unique_dates: unique_dates.remove(f"{today.strftime('%m')}-{today.year}") - forcasted_leaves = available_leave.forcasted_leaves() - if leave_type_id.reset_based == "monthly": - if f"{today.year}-{today.strftime('%m')}" not in unique_dates: - for item in unique_dates: - try: - total_leave_days += forcasted_leaves[item] - except: - pass + + forcated_days = available_leave.forcasted_leaves(start_date) + total_leave_days = ( + available_leave.leave_type_id.carryforward_max + if available_leave.leave_type_id.carryforward_type + in ["carryforward", "carryforward expire"] + and available_leave.leave_type_id.carryforward_max < total_leave_days + else total_leave_days + ) + if available_leave.leave_type_id.carryforward_type == "no carryforward": + total_leave_days = 0 + total_leave_days += forcated_days + if not effective_requested_days <= total_leave_days: raise forms.ValidationError(_("Employee doesn't have enough leave days..")) @@ -338,19 +343,27 @@ class LeaveRequestCreationForm(ModelForm): super().__init__(*args, **kwargs) self.fields["leave_type_id"].widget.attrs.update( { - "onchange": "empleavetypeChange($(this))", + "hx-include": "#id_employee_id, #id_start_date", + "hx-target": "#availableLeaveCount", + "hx-swap": "outerHTML", + "hx-trigger": "change", + "hx-get": "/leave/employee-available-leave-count", } ) self.fields["employee_id"].widget.attrs.update( { "hx-target": "#id_leave_type_id_parent_div", "hx-trigger": "change", - "hx-get": "/leave/get-employee-leave-types", + "hx-get": "/leave/get-employee-leave-types?form=LeaveRequestCreationForm", } ) self.fields["start_date"].widget.attrs.update( { - "onchange": "dateChange($(this))", + "hx-include": "#id_employee_id, #id_leave_type_id", + "hx-target": "#availableLeaveCount", + "hx-swap": "outerHTML", + "hx-trigger": "change", + "hx-get": "/leave/employee-available-leave-count", } ) @@ -431,14 +444,19 @@ class LeaveRequestUpdationForm(ModelForm): unique_dates = list(set(month_year)) if f"{today.month}-{today.year}" in unique_dates: unique_dates.remove(f"{today.strftime('%m')}-{today.year}") - forcasted_leaves = available_leave.forcasted_leaves() - if leave_type_id.reset_based == "monthly": - if f"{today.year}-{today.strftime('%m')}" not in unique_dates: - for item in unique_dates: - try: - total_leave_days += forcasted_leaves[item] - except: - pass + + forcated_days = available_leave.forcasted_leaves(start_date) + total_leave_days = ( + available_leave.leave_type_id.carryforward_max + if available_leave.leave_type_id.carryforward_type + in ["carryforward", "carryforward expire"] + and available_leave.leave_type_id.carryforward_max < total_leave_days + else total_leave_days + ) + if available_leave.leave_type_id.carryforward_type == "no carryforward": + total_leave_days = 0 + total_leave_days += forcated_days + if not effective_requested_days <= total_leave_days: raise forms.ValidationError(_("Employee doesn't have enough leave days..")) @@ -449,19 +467,30 @@ class LeaveRequestUpdationForm(ModelForm): super().__init__(*args, **kwargs) self.fields["leave_type_id"].widget.attrs.update( { - "onchange": "empleavetypeChange($(this))", + "id": "id_request_update_leave_type_id", + "hx-include": "#id_request_update_employee_id, #id_request_udpate_start_date", + "hx-target": "#assinedLeaveAvailableCount", + "hx-swap": "outerHTML", + "hx-trigger": "change", + "hx-get": "/leave/employee-available-leave-count", } ) self.fields["employee_id"].widget.attrs.update( { + "id": "id_request_update_employee_id", "hx-target": "#id_leave_type_id_parent_div", "hx-trigger": "change", - "hx-get": "/leave/get-employee-leave-types", + "hx-get": "/leave/get-employee-leave-types?form=LeaveRequestUpdationForm", } ) self.fields["start_date"].widget.attrs.update( { - "onchange": "dateChange($(this))", + "id": "id_request_udpate_start_date", + "hx-include": "#id_request_update_employee_id, #id_request_update_leave_type_id", + "hx-target": "#assinedLeaveAvailableCount", + "hx-swap": "outerHTML", + "hx-trigger": "change", + "hx-get": "/leave/employee-available-leave-count", } ) diff --git a/leave/models.py b/leave/models.py index e59b94f39..e9545d369 100644 --- a/leave/models.py +++ b/leave/models.py @@ -223,6 +223,51 @@ class LeaveType(HorillaModel): url = self.icon.url return url + def leave_type_next_reset_date(self): + today = datetime.now().date() + + if not self.reset: + return None + + def get_reset_day(month, day): + return ( + calendar.monthrange(today.year, month)[1] + if day == "last day" + else int(day) + ) + + if self.reset_based == "yearly": + month, day = int(self.reset_month), get_reset_day( + int(self.reset_month), self.reset_day + ) + reset_date = datetime( + today.year + (datetime(today.year, month, day).date() < today), + month, + day, + ).date() + + elif self.reset_based == "monthly": + month = today.month + reset_date = datetime( + today.year, month, get_reset_day(month, self.reset_day) + ).date() + if reset_date < today: + month = (month % 12) + 1 + year = today.year + (month == 1) + reset_date = datetime( + year, month, get_reset_day(month, self.reset_day) + ).date() + + elif self.reset_based == "weekly": + target_weekday = WEEK_DAYS[self.reset_day] + days_until_reset = (target_weekday - today.weekday()) % 7 or 7 + reset_date = today + timedelta(days=days_until_reset) + + else: + reset_date = None + + return reset_date + def clean(self, *args, **kwargs): if self.is_compensatory_leave: if LeaveType.objects.filter(is_compensatory_leave=True).count() >= 1: @@ -321,25 +366,14 @@ class AvailableLeave(HorillaModel): def __str__(self): return f"{self.employee_id} | {self.leave_type_id}" - def forcasted_leaves(self): - forecasted_leave = {} - if self.leave_type_id.reset_based == "monthly": - today = datetime.now() - for i in range(1, 7): # Calculate for the next 6 months - next_month = today + relativedelta(months=i) - if self.leave_type_id.carryforward_max: - forecasted_leave[next_month.strftime("%Y-%m")] = ( - self.available_days - + min( - self.leave_type_id.carryforward_max, - (self.leave_type_id.total_days * i), - ) - ) - else: - forecasted_leave[next_month.strftime("%Y-%m")] = ( - self.available_days + (self.leave_type_id.total_days * i) - ) - return forecasted_leave + def forcasted_leaves(self, date): + if isinstance(date, str): + date = datetime.strptime(date, "%Y-%m-%d").date() + next_reset_date = self.leave_type_id.leave_type_next_reset_date() + if next_reset_date <= date: + return self.leave_type_id.total_days + + return 0 # Resetting carryforward days diff --git a/leave/templates/leave/leave_request/employee_available_leave_count.html b/leave/templates/leave/leave_request/employee_available_leave_count.html new file mode 100644 index 000000000..c117c6739 --- /dev/null +++ b/leave/templates/leave/leave_request/employee_available_leave_count.html @@ -0,0 +1,53 @@ +{% load i18n %} +{% load static %} + +
+ {% if not leave_type_id %} + + {% elif not available_leave %} +
+ {% trans "Leave type is not assigned for the selected employee." %} +
+ {% elif total_leave_days == 0.0 %} +
+ {% trans "Available Leaves" %} : {{ total_leave_days }} +
+ {% else %} +
+ {% trans "Available Leaves" %} : {{ total_leave_days }} + {% if forcated_days and forcated_days > 0 %} + + {% endif %} + + +
+ {% endif %} +
\ No newline at end of file diff --git a/leave/templates/leave/leave_request/leave_request_form.html b/leave/templates/leave/leave_request/leave_request_form.html index b161672b6..c503cd518 100644 --- a/leave/templates/leave/leave_request/leave_request_form.html +++ b/leave/templates/leave/leave_request/leave_request_form.html @@ -28,6 +28,7 @@ > +
{% trans form.leave_type_id.label %} {{form.leave_type_id}} + diff --git a/leave/templates/leave/leave_request/request_update_form.html b/leave/templates/leave/leave_request/request_update_form.html index ba4c76cb4..b6774553b 100644 --- a/leave/templates/leave/leave_request/request_update_form.html +++ b/leave/templates/leave/leave_request/request_update_form.html @@ -6,6 +6,7 @@ +
$(document).ready(function () { $("select").on("select2:select", function (e) { - $(".leave-message").hide(); $(this).closest("select")[0].dispatchEvent(new Event("change")); }); }); diff --git a/leave/templates/leave/user_leave/user_request_view.html b/leave/templates/leave/user_leave/user_request_view.html index 3152206f8..3f5bb9878 100644 --- a/leave/templates/leave/user_leave/user_request_view.html +++ b/leave/templates/leave/user_leave/user_request_view.html @@ -408,63 +408,6 @@ }); }); - function typeChange(selectElement) { - var selectedLeavetype =selectElement.val() - let parentForm = selectElement.parents().closest("form") - var employeeId = parentForm.find('[name = employee_id]').val() - $.ajax({ - type: "post", - url: "{% url 'employee-leave-details' %}", - data: { - csrfmiddlewaretoken: getCookie("csrftoken"), - "leave_type":selectedLeavetype, - "employee_id":employeeId, - }, - success: function (response) { - - // Assuming parentForm is a reference to the form containing the element to update - var messageDiv = parentForm.find(".leave-message"); - - // Check if the messageDiv already exists, if not create it - if (!messageDiv.length) { - messageDiv = $("
"); - parentForm.prepend(messageDiv); - } - // Checking leave type is selected in the form or not - if (response.leave_count === ''){ - messageDiv.hide() - } - else if (response.leave_count === 0.0){ - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else{ - messageDiv.show() - // Set the message content and apply styling - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': '#dff0d8', - 'border': '2px solid #3c763d', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - - } - }); - } function enlargeImage(src,$element) { $(".enlargeImageContainer").empty() diff --git a/leave/threading.py b/leave/threading.py index 8433c92da..0accd46df 100644 --- a/leave/threading.py +++ b/leave/threading.py @@ -26,32 +26,33 @@ class LeaveMailSendThread(Thread): if leave_request_id != "#": link = int(leave_request_id) for recipient in recipients: - html_message = render_to_string( - "base/mail_templates/leave_request_template.html", - { - "link": link, - "instance": recipient, - "host": host, - "protocol": protocol, - "subject": subject, - "content": content, - }, - ) - - email = EmailMessage( - subject, - html_message, - email_backend.dynamic_from_email_with_display_name, - [recipient.email], - ) - email.content_subtype = "html" - try: - email.send() - except: - messages.error( - self.request, f"Mail not sent to {recipient.get_full_name()}" + if recipient: + html_message = render_to_string( + "base/mail_templates/leave_request_template.html", + { + "link": link, + "instance": recipient, + "host": host, + "protocol": protocol, + "subject": subject, + "content": content, + }, ) + email = EmailMessage( + subject, + html_message, + email_backend.dynamic_from_email_with_display_name, + [recipient.email], + ) + email.content_subtype = "html" + try: + email.send() + except: + messages.error( + self.request, f"Mail not sent to {recipient.get_full_name()}" + ) + def run(self) -> None: super().run() if self.type == "request": diff --git a/leave/urls.py b/leave/urls.py index 5312ce2e6..0d82f170b 100644 --- a/leave/urls.py +++ b/leave/urls.py @@ -267,9 +267,9 @@ urlpatterns = [ name="user-request-select-filter", ), path( - "employee-leave-details", - views.employee_leave_details, - name="employee-leave-details", + "employee-available-leave-count", + views.employee_available_leave_count, + name="employee-available-leave-count", ), path( "leave-request-add-comment//", diff --git a/static/images/ui/info.png b/static/images/ui/info.png new file mode 100644 index 0000000000000000000000000000000000000000..a762a6c7a75298f892716580d8609baea0bb97af GIT binary patch literal 20169 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
"); - parentForm.prepend(messageDiv); - } - // Checking leave type is selected in the form or not - if (response.leave_count != '' && response.employee != ''){ - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': '#dff0d8', - 'border': '2px solid #3c763d', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else if ( selectedLeavetype === ''){ - messageDiv.hide() - } - else if (selectedLeavetype != '' && response.leave_count === '' && response.employee != ''){ - messageDiv.show() - messageDiv.text("Leave type is not assigned for selecetd employee."); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': 'auto' - }); - } - else if (response.leave_count === 0.0){ - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else{ - messageDiv.hide() - } - - } - }); -} - - -function employeeChange(selectElement) { - var employeeId =selectElement.val() - let parentForm = selectElement.parents().closest("form") - var leavetypeId = parentForm.find('[name = leave_type_id]').val() - var start_date = parentForm.find('[name = start_date_id]').val() - $.ajax({ - type: "post", - url: "/leave/employee-leave-details", - data: { - csrfmiddlewaretoken: getCookie("csrftoken"), - "leave_type":leavetypeId, - "employee_id":employeeId, - "date":start_date, - }, - success: function (response) { - - // Assuming parentForm is a reference to the form containing the element to update - var messageDiv = parentForm.find(".leave-message"); - - // Check if the messageDiv already exists, if not create it - if (!messageDiv.length) { - messageDiv = $("
"); - parentForm.prepend(messageDiv); - } - // Checking leave type is selected in the form or not - if (response.leave_count != '' && response.employee != ''){ - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': '#dff0d8', - 'border': '2px solid #3c763d', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else if ( leavetypeId === ''){ - messageDiv.hide() - } - else if (leavetypeId != '' && response.leave_count === '' && response.employee != ''){ - messageDiv.show() - messageDiv.text("Leave type is not assigned for selecetd employee."); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': 'auto' - }); - } - else if (response.leave_count === 0.0){ - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else{ - messageDiv.hide() - } - - } - }); -} - -function dateChange(selectElement) { - let parentForm = selectElement.parents().closest("form") - var employeeId = parentForm.find('[name = employee_id]').val() - var leavetypeId = parentForm.find('[name = leave_type_id]').val() - var start_date = selectElement.val() - $.ajax({ - type: "post", - url: "/leave/employee-leave-details", - data: { - csrfmiddlewaretoken: getCookie("csrftoken"), - "leave_type":leavetypeId, - "employee_id":employeeId, - "date": start_date, - }, - success: function (response) { - // Assuming parentForm is a reference to the form containing the element to update - var messageDiv = parentForm.find(".leave-message"); - - // Check if the messageDiv already exists, if not create it - if (!messageDiv.length) { - messageDiv = $("
"); - parentForm.prepend(messageDiv); - } - // Checking leave type is selected in the form or not - if (response.leave_count != '' && response.employee != '') { - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': '#dff0d8', - 'border': '2px solid #3c763d', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else if ( leavetypeId === ''){ - messageDiv.hide() - } - else if (leavetypeId != '' && response.leave_count === '' && response.employee != ''){ - messageDiv.show() - messageDiv.text("Leave type is not assigned for selecetd employee."); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': 'auto' - }); - } - else if (response.leave_count === 0.0){ - messageDiv.show() - messageDiv.text("Available Leaves : " + response.leave_count); - messageDiv.css({ - 'background-color': 'rgb(229 79 56 / 17%)', - 'border': '2px solid hsl(8,77%,56%)', - 'border-radius': '18px', - 'padding': '10px', - 'font-weight': 'bold', - 'margin-bottom': '15px', - 'width': '35%' - }); - } - else{ - messageDiv.hide() - } - } - }); -} - function shiftChange(selectElement) { var shiftId =selectElement.val() let parentForm = selectElement.parents().closest("form")