[ADD] CONFIGURATION: Conditional approval option in leave request

This commit is contained in:
Horilla
2024-01-12 21:31:15 +05:30
parent 367e67d9b6
commit 1b82377597
17 changed files with 2372 additions and 1500 deletions

View File

@@ -282,3 +282,5 @@ _("ticket-detail"),
_("ticket-type-view"),
_("tag-view"),
_("mail-server-conf"),
_("configuration"),
_("multiple-approval-condition"),

View File

@@ -4,11 +4,13 @@ from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import redirect
from django.urls import reverse
from base.models import MultipleApprovalManagers
from employee.models import Employee, EmployeeWorkInformation
from django.contrib import messages
from django.shortcuts import render
from horilla.settings import TEMPLATES, BASE_DIR
from horilla import settings
from leave.models import LeaveRequestConditionApproval
logger = logging.getLogger(__name__)
@@ -81,8 +83,19 @@ def manager_can_enter(function, perm):
"""
def _function(request, *args, **kwargs):
leave_perm = [
"leave.view_leaverequest",
"leave.change_leaverequest",
"leave.delete_leaverequest",
]
user = request.user
employee = Employee.objects.filter(employee_user_id=user).first()
if perm in leave_perm:
is_approval_manager = MultipleApprovalManagers.objects.filter(
employee_id=employee.id
).exists()
if is_approval_manager:
return function(request, *args, **kwargs)
is_manager = EmployeeWorkInformation.objects.filter(
reporting_manager_id=employee
).exists()
@@ -116,7 +129,7 @@ def login_required(view_func):
except Exception as e:
logger.exception(e)
if not settings.DEBUG:
return render(request,"went_wrong.html")
return render(request, "went_wrong.html")
return view_func(request, *args, **kwargs)
return func

File diff suppressed because it is too large Load Diff

View File

@@ -87,6 +87,7 @@ sidebar_urls = [
"tag-view",
"ticket-type-view",
"mail-server-conf",
"multiple-approval-condition",
]
remove_urls = [
"objective-detailed-view",

View File

@@ -3,7 +3,15 @@ Module for registering LeaveType, LeaveRequest, AvailableLeave, Holiday, and Com
models with the Django admin site.
"""
from django.contrib import admin
from .models import LeaveType, LeaveRequest, AvailableLeave, Holiday, CompanyLeave,LeaveAllocationRequest
from .models import (
LeaveRequestConditionApproval,
LeaveType,
LeaveRequest,
AvailableLeave,
Holiday,
CompanyLeave,
LeaveAllocationRequest,
)
# Register your models here.
@@ -13,3 +21,4 @@ admin.site.register(AvailableLeave)
admin.site.register(Holiday)
admin.site.register(CompanyLeave)
admin.site.register(LeaveAllocationRequest)
admin.site.register(LeaveRequestConditionApproval)

View File

@@ -1,11 +1,13 @@
import calendar
from collections.abc import Iterable
from datetime import datetime, timedelta
import operator
from django.db import models
from django.utils import timezone
from django.core.exceptions import ValidationError
from dateutil.relativedelta import relativedelta
from django.utils.translation import gettext_lazy as _
from base import thread_local_middleware
from base.models import Company, MultipleApprovalCondition
from base.horilla_company_manager import HorillaCompanyManager
from employee.models import Employee
@@ -14,6 +16,15 @@ from django.core.files.storage import default_storage
from django.conf import settings
operator_mapping = {
"equal": operator.eq,
"notequal": operator.ne,
"lt": operator.lt,
"gt": operator.gt,
"le": operator.le,
"ge": operator.ge,
"icontains": operator.contains,
}
# Create your models here.
BREAKDOWN = [
("full_day", _("Full Day")),
@@ -522,15 +533,23 @@ class LeaveRequest(models.Model):
department_id = self.employee_id.employee_work_info.department_id
requested_days = self.requested_days
applicable_condition = False
conditions = MultipleApprovalCondition.objects.filter(department=department_id)
for condition in conditions:
operator = condition.condition_operator
if operator == "range":
start_value = float(condition.condition_start_value)
end_value = float(condition.condition_end_value)
if start_value <= requested_days <= end_value:
applicable_condition = condition
break
conditions = MultipleApprovalCondition.objects.filter(department=department_id).order_by('condition_value')
if conditions:
for condition in conditions:
operator = condition.condition_operator
if operator == "range":
start_value = float(condition.condition_start_value)
end_value = float(condition.condition_end_value)
if start_value <= requested_days <= end_value:
applicable_condition = condition
break
else:
operator_func = operator_mapping.get(condition.condition_operator)
condition_value = type(requested_days)(condition.condition_value)
if operator_func(requested_days, condition_value):
applicable_condition = condition
break
if applicable_condition and self.status=="requested":
LeaveRequestConditionApproval.objects.filter(leave_request_id=self).delete()
sequence = 0
@@ -593,7 +612,7 @@ class LeaveRequest(models.Model):
self.status = "approved"
available_leave.save()
def conditional_approvals(self, *args, **kwargs):
def multiple_approvals(self, *args, **kwargs):
approvals = LeaveRequestConditionApproval.objects.filter(leave_request_id=self)
requested_query = approvals.filter(is_approved=False).order_by("sequence")
approved_query = approvals.filter(is_approved=True).order_by("sequence")
@@ -605,10 +624,21 @@ class LeaveRequest(models.Model):
"managers": managers,
"approved": approved_query,
"requested": requested_query,
"approvals":approvals,
}
else:
result = False
return result
def is_approved(self):
request = getattr(thread_local_middleware._thread_locals,"request",None)
if request:
employee = Employee.objects.filter(employee_user_id = request.user).first()
condition_approval = LeaveRequestConditionApproval.objects.filter(leave_request_id=self,manager_id = employee.id).first()
if condition_approval:
return not condition_approval.is_approved
else:
return True
class LeaveAllocationRequest(models.Model):

View File

@@ -1,4 +1,20 @@
{% load i18n %}
{% if messages %}
<div class="oh-wrapper">
{% for message in messages %}
<div class="oh-alert-container">
<div class="oh-alert oh-alert--animated {{ message.tags }}">
{{ message }}
</div>
</div>
{% endfor %}
</div>
<script>
setTimeout(() => {
$('.oh-modal__close').click();
}, 1000);
</script>
{% endif %}
{% if form.errors %}
<!-- form errors -->
<div class="oh-wrapper">

View File

@@ -1,4 +1,20 @@
{% load i18n %}
{% if messages %}
<div class="oh-wrapper">
{% for message in messages %}
<div class="oh-alert-container">
<div class="oh-alert oh-alert--animated {{ message.tags }}">
{{ message }}
</div>
</div>
{% endfor %}
</div>
<script>
setTimeout(() => {
$('.oh-modal__close').click();
}, 1000);
</script>
{% endif %}
{% if form.errors %}
<!-- form errors -->
<div class="oh-wrapper">

View File

@@ -1,6 +1,6 @@
{% extends 'index.html' %} {% block content %} {% load static %} {% load i18n %}
<!-- start of message -->
{% if messages %}
{% comment %} {% if messages %}
<div class="oh-wrapper">
{% for message in messages %}
<div class="oh-alert-container">
@@ -10,7 +10,7 @@
</div>
{% endfor %}
</div>
{% endif %}
{% endif %} {% endcomment %}
<!-- end of messages -->
<!-- start of nav bar -->
@@ -194,7 +194,9 @@
<span class="oh-modal__dialog-title" id="editDialogDialog"
>{% trans "Create Holiday" %}</span
>
<button class="oh-modal__close" aria-label="Close">
<button class="oh-modal__close" aria-label="Close"
hx-get="{% url 'holiday-filter' %}" hx-target="#holidays"
>
<ion-icon name="close-outline"></ion-icon>
</button>
</div>
@@ -217,7 +219,9 @@
<span class="oh-modal__dialog-title" id="editDialogDialog"
>{% trans "Update Holiday" %}</span
>
<button class="oh-modal__close" aria-label="Close">
<button class="oh-modal__close" aria-label="Close"
hx-get="{% url 'holiday-filter' %}" hx-target="#holidays"
>
<ion-icon name="close-outline"></ion-icon>
</button>
</div>

View File

@@ -77,7 +77,7 @@
{% if not dashboard %}
<div class="oh-sticky-table__th" >{% trans "Penalties" %}</div>
<div class="oh-sticky-table__th">{% trans "Options" %}</div>
{% if request.user|is_reportingmanager or perms.leave.chanage_leaverequest or perms.leave.delete_leaverequest %}
{% if request.user|is_reportingmanager or perms.leave.chanage_leaverequest or perms.leave.delete_leaverequest or request.user|is_leave_approval_manager %}
<div class="oh-sticky-table__th">{% trans "Actions" %}</div>
{% endif %}
{% endif %}
@@ -114,7 +114,15 @@
<div class="oh-sticky-table__td {% if leave_request.status == 'cancelled' %} diff-cell{% endif %} dateformat_changer">{{leave_request.start_date}}</div>
<div class="oh-sticky-table__td {% if leave_request.status == 'cancelled' %} diff-cell{% endif %} dateformat_changer">{{leave_request.end_date}}</div>
<div class="oh-sticky-table__td {% if leave_request.status == 'cancelled' %} diff-cell{% endif %}">{{leave_request.requested_days}}</div>
<div class="oh-sticky-table__td {% if leave_request.status == 'cancelled' %} diff-cell{% endif %}">{{leave_request.get_status_display}}</div>
<div class="oh-sticky-table__td {% if leave_request.status == 'cancelled' %} diff-cell{% endif %}">
{% if leave_request.multiple_approvals and leave_request.status == "requested" %}
<div class="oh-checkpoint-badge oh-checkpoint-badge--secondary" title="{% for manager in leave_request.multiple_approvals.managers %}{{ manager }}{% if not forloop.last %} , {% endif %}{% endfor %}">
{{leave_request.multiple_approvals.approved|length}} / {{leave_request.multiple_approvals.managers|length}} {% trans "Approved" %}
</div>
{% else %}
{{leave_request.get_status_display}}
{% endif %}
</div>
{% if not dashboard %}
<div class="oh-sticky-table__td">
{% if leave_request.get_penalties_count %}
@@ -123,7 +131,8 @@
</div>
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
<div class="oh-btn-group" >
{% if leave_request.status == 'requested' %}
{% if leave_request.is_approved and leave_request.status == 'requested' %}
<a type="submit" href="{% url 'request-approve' leave_request.id %}" title="{% trans 'Approve' %}"
class="oh-btn oh-btn--success w-100">
<ion-icon class="me-1" name="checkmark-outline"></ion-icon>
@@ -154,7 +163,7 @@
</div>
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
<div class="oh-btn-group">
{% if request.user|is_reportingmanager or perms.attendance.chanage_penaltyaccount %}
{% if request.user|is_reportingmanager or perms.attendance.chanage_penaltyaccount or request.user|is_leave_approval_manager %}
<button
data-toggle="oh-modal-toggle"
data-target="#penaltyModal"
@@ -166,13 +175,13 @@
<ion-icon name="information-circle-outline"></ion-icon>
</button>
{% endif %}
{% if request.user|is_reportingmanager or perms.leave.chanage_leaverequest or perms.leave.delete_leaverequest %}
{% if request.user|is_reportingmanager or perms.leave.chanage_leaverequest %}
{% if request.user|is_reportingmanager or perms.leave.chanage_leaverequest or perms.leave.delete_leaverequest or request.user|is_leave_approval_manager%}
{% if request.user|is_reportingmanager or perms.leave.chanage_leaverequest or request.user|is_leave_approval_manager %}
<button class="oh-btn oh-btn--light-bkg w-100" title="{% trans 'Edit' %}" data-toggle="oh-modal-toggle"
data-target="#editModal2" hx-get="{% url 'request-update' leave_request.id %}"
hx-target="#updateForm"><ion-icon name="create-outline"></ion-icon></button>
{% endif %}
{% if request.user|is_reportingmanager or perms.leave.delete_leaverequest %}
{% if request.user|is_reportingmanager or perms.leave.delete_leaverequest or request.user|is_leave_approval_manager %}
<a class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100" id="delete-link"
href="{% url 'request-delete' leave_request.id %}" onclick="return confirm('{% trans "Are you sure you want to delete ?" %}');" title="{% trans 'Delete' %}"><ion-icon
name="trash-outline"></ion-icon></a>

View File

@@ -62,6 +62,25 @@
<span class="oh-timeoff-modal__stat-count">{{leave_request.created_by}}</span>
</div>
</div>
{% if leave_request.multiple_approvals %}
<div class="oh-timeoff-modal__stats w-100 mt-3">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Multiple Approvals" %}</span>
{% for approval in leave_request.multiple_approvals.approvals %}
<div class="oh-timeoff-modal__stat-description">{{forloop.counter}}.{{approval.manager_id}} :
{% if approval.is_approved %}{% trans "Approved" %}
{% else %}
{% if approval.is_rejected %}
{% trans "Rejected" %}
{% else %}
{% trans "Not Marked" %}
{% endif %}
{% endif %}
</div>
{% endfor %}
</div>
</div>
{% endif %}
<div class="oh-timeoff-modal__stats w-100 mt-3">
<div class="oh-timeoff-modal__stat">
@@ -96,7 +115,7 @@
</div>
<div class="oh-modal__dialog-footer oh-timeoff-modal__footer">
{% if leave_request.status == 'requested' %}
{% if leave_request.status == 'requested' %}
<a type="submit" href="{% url 'request-approve' leave_request.id %}" title="{% trans 'Approve' %}"
class="oh-btn oh-btn--success w-100">
<ion-icon class="me-1" name="checkmark-outline"></ion-icon>

View File

@@ -0,0 +1,23 @@
{% extends "index.html" %}{% block content %}{% load static %}{% load i18n %}
<section class="oh-wrapper oh-main__topbar" x-data="{searchShow: false}">
<div class="oh-main__titlebar oh-main__titlebar--left">
<h1 class="oh-main__titlebar-title fw-bold">
{% trans "Multiple Approval Condition" %}
</h1>
<a
class="oh-main__titlebar-search-toggle"
role="button"
aria-label="Toggle Search"
@click="searchShow = !searchShow"
>
<ion-icon
name="search-outline"
class="oh-main__titlebar-serach-icon"
></ion-icon>
</a>
</div>
</section>
<div class="oh-wrapper" id="multipleApproveCondition">
{% include "leave/leave_request/penalty/create.html" %}
</div>
{% endblock content %}

View File

@@ -0,0 +1,122 @@
{% load static %} {% load i18n %} {% load basefilters %}
<div class="container-fluid">
<div class="row">
<div class="col-md-9">
<div class="oh-sticky-table">
<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 "Department" %}</div>
<div class="oh-sticky-table__th">{% trans "Condition Field" %}</div>
<div class="oh-sticky-table__th">{% trans "Condition Operator" %}</div>
<div class="oh-sticky-table__th">{% trans "Condition Value" %}</div>
<div class="oh-sticky-table__th">{% trans "Approval Managers" %}</div>
{% if perms.leave.change_availableleave or perms.leave.delete_availableleave or request.user|is_reportingmanager %}
<div class="oh-sticky-table__th">{% trans "Actions" %}</div>
{% endif %}
</div>
</div>
<div class="oh-sticky-table__tbody">
{% for condition in conditions %}
<div class="oh-sticky-table__tr" draggable="true">
<div class="oh-sticky-table__td">
{{condition.department}}
</div>
<div class="oh-sticky-table__td">{{condition.get_condition_field_display}}</div>
<div class="oh-sticky-table__td">{{condition.get_condition_operator_display}}</div>
<div class="oh-sticky-table__td">
{% if condition.condition_operator == "range" %}
{{condition.condition_start_value}} - {{condition.condition_end_value}}
{% else %}
{{condition.condition_value}}
{% endif %}
</div>
<div class="oh-sticky-table__td">
{% for manager in condition.approval_managers %}
{{ forloop.counter }}. {{ manager }}<br>
{% endfor %}</div>
{% if perms.leave.change_availableleave or perms.leave.delete_availableleave or request.user|is_reportingmanager %}
<div class="oh-sticky-table__td">
<div class="oh-btn-group">
{% if request.user|is_reportingmanager or perms.leave.change_availableleave %}
<button title="{% trans 'Edit' %}"
class="oh-btn oh-btn--light-bkg w-100"
hx-target="#multipleApproveCondition"
hx-get = "{% url 'multiple-level-approval-edit' condition.id %}"
><ion-icon name="create-outline"></ion-icon></button>
{% endif %}
{% if request.user|is_reportingmanager or perms.leave.delete_availableleave %}
<a href={% url "multiple-level-approval-delete" condition.id %} class="oh-btn oh-btn--danger-outline oh-btn--light-bkg w-100" onclick="return confirm('{% trans "Are you sure you want to delete ?" %}');" id="delete-link"
title="{% trans 'Delete' %}"><ion-icon
name="trash-outline"></ion-icon></a>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="col-md-3 oh-faq-card" style="padding: 0.7rem;">
<form
hx-post=" {% if create %}
{% url 'multiple-level-approval-create' %}
{% else %}
{% url 'multiple-level-approval-edit' condition.id %}
{% endif %}"
hx-target="#multipleApproveCondition"
>
{{form}}
<a href="#" role="button" style="color: green" id="id_addMore">{% trans "Add more managers.." %}</a>
<div class="oh-modal__dialog-footer" style="padding:1.0rem .2rem 1.0rem;">
<button type="submit" class="oh-btn oh-btn--secondary w-100">
{% trans "Apply" %}
</button>
</div>
</form>
</div>
</div>
</div>
<script>
function toggleFields(element) {
if (element.val() == "range") {
$("#id_condition_value").hide();
$('label[for="id_condition_start_value"]').show();
$('label[for="id_condition_end_value"]').show();
$("#id_condition_start_value").show();
$("#id_condition_end_value").show();
} else {
$("#id_condition_value").show();
$("#id_condition_start_value").hide();
$("#id_condition_end_value").hide();
$('label[for="id_condition_start_value"]').hide();
$('label[for="id_condition_end_value"]').hide();
}
}
$(document).ready(function () {
var i = 0;
var j = 0;
toggleFields($('#id_condition_operator'));
$("#id_addMore").click(function (e) {
var existingSelect = $("#id_multi_approval_manager").clone();
existingSelect.attr(
"class",
"select2 select2-container select2-container--default"
);
existingSelect.attr("dir", "ltr");
existingSelect.css({
height: "48.54px",
border: "1px solid rgb(210 213 216)",
width: "100%",
"margin-top": "10px",
});
existingSelect.attr("name", "multi_approval_manager_" + i++);
existingSelect.attr("id", "id_multi_approval_manager_" + j++);
existingSelect.insertBefore("#id_addMore");
});
});
</script>

View File

@@ -47,7 +47,7 @@
<div
class="oh-input-group oh-input__search-group"
:class="searchShow ? 'oh-input__search-group--show' : ''"
>
>
<ion-icon
name="search-outline"
class="oh-input-group__icon oh-input-group__icon--left"

View File

@@ -1,4 +1,4 @@
{% load i18n %}
{% load i18n %} {% load yes_no %}
{% if request.GET.instances_ids %}
<div class="oh-modal__dialog oh-modal__dialog--navigation m-0 p-0">
<button
@@ -32,7 +32,7 @@
<div class="oh-timeoff-modal__stats-container">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Period In" %}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.period_in}}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.get_period_in_display}}</span>
</div>
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "count" %}</span>
@@ -44,12 +44,12 @@
</div>
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Reset" %}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.reset}}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.reset|yes_no}}</span>
</div>
{% if leave_type.reset_based %}
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Reset Based" %}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.reset_based}}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.get_reset_based_display}}</span>
</div>
{% endif %}
{% if leave_type.reset_month %}
@@ -67,13 +67,13 @@
{% if leave_type.reset_weekend %}
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Reset weekend" %}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.reset_weekend}}</span>
<span class="oh-timeoff-modal__stat-count">{{leave_type.get_reset_weekend_display}}</span>
</div>
{% endif %}
<div class="oh-timeoff-modal__stats ">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Carryforward Type" %}</span>
<div class="oh-timeoff-modal__stat-count">{{leave_type.carryforward_type}}</div>
<div class="oh-timeoff-modal__stat-count">{{leave_type.get_carryforward_type_display}}</div>
</div>
</div>
{% if leave_type.carryforward_max %}
@@ -97,32 +97,32 @@
<div class="oh-timeoff-modal__stats ">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Payment Type" %}</span>
<div class="oh-timeoff-modal__stat-count">{{leave_type.payment}}</div>
<div class="oh-timeoff-modal__stat-count">{{leave_type.get_payment_display}}</div>
</div>
</div>
<div class="oh-timeoff-modal__stats ">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Require Approval" %}</span>
<div class="oh-timeoff-modal__stat-count">{{leave_type.require_approval}}</div>
<div class="oh-timeoff-modal__stat-count">{{leave_type.require_approval|yes_no}}</div>
</div>
</div>
<div class="oh-timeoff-modal__stats">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Require Attachment" %}</span>
<div class="oh-timeoff-modal__stat-description">{{leave_type.require_attachment }}</div>
<div class="oh-timeoff-modal__stat-description">{{leave_type.require_attachment|yes_no }}</div>
</div>
</div>
<div class="oh-timeoff-modal__stats ">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Exclude company Leaves" %}</span>
<div class="oh-timeoff-modal__stat-count">{{leave_type.exclude_company_leave}}</div>
<div class="oh-timeoff-modal__stat-count">{{leave_type.exclude_company_leave|yes_no}}</div>
</div>
</div>
<div class="oh-timeoff-modal__stats ">
<div class="oh-timeoff-modal__stat">
<span class="oh-timeoff-modal__stat-title">{% trans "Exclude Holidays" %}</span>
<div class="oh-timeoff-modal__stat-count">{{leave_type.exclude_holiday}}</div>
<div class="oh-timeoff-modal__stat-count">{{leave_type.exclude_holiday|yes_no}}</div>
</div>
</div>

View File

@@ -31,7 +31,7 @@ urlpatterns = [
views.leave_requests_export,
name="leave-requests-info-export",
),
path("request-view", views.leave_request_view, name="request-view"),
path("request-view/", views.leave_request_view, name="request-view"),
path(
"request-approve/<int:id>", views.leave_request_approve, name="request-approve"
),

View File

@@ -21,7 +21,7 @@ from attendance.forms import PenaltyAccountForm
from attendance.models import PenaltyAccount
from horilla.decorators import login_required, hx_request_required
from horilla.decorators import permission_required, manager_can_enter
from base.methods import closest_numbers, export_data
from base.methods import closest_numbers, export_data, filter_conditional_leave_request
from base.threading import MailSendThread
from base.models import *
from base.methods import (
@@ -346,7 +346,11 @@ def leave_request_view(request):
GET : return leave request view template
"""
queryset = LeaveRequestFilter(request.GET).qs.order_by("-id")
queryset = filtersubordinates(request, queryset, "leave.view_leaverequest")
multiple_approvals = filter_conditional_leave_request(request)
queryset = (
filtersubordinates(request, queryset, "leave.view_leaverequest")
| multiple_approvals
)
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
leave_request_filter = LeaveRequestFilter()
@@ -559,8 +563,31 @@ def leave_request_approve(request, id, emp_id=None):
available_leave.available_days = temp - leave_request.requested_days
leave_request.approved_available_days = leave_request.requested_days
leave_request.status = "approved"
available_leave.save()
leave_request.save()
if not leave_request.multiple_approvals():
available_leave.save()
leave_request.save()
else:
if request.user.is_superuser:
LeaveRequestConditionApproval.objects.filter(
leave_request_id=leave_request
).update(is_approved=True)
available_leave.save()
leave_request.save()
else:
conditional_requests = leave_request.multiple_approvals()
approver = [
manager
for manager in conditional_requests["managers"]
if manager.employee_user_id == request.user
]
condition_approval = LeaveRequestConditionApproval.objects.filter(
manager_id=approver[0], leave_request_id=leave_request
).first()
condition_approval.is_approved = True
condition_approval.save()
if approver[0] == conditional_requests["managers"][-1]:
available_leave.save()
leave_request.save()
messages.success(request, _("Leave request approved successfully.."))
with contextlib.suppress(Exception):
notify.send(
@@ -627,6 +654,20 @@ def leave_request_cancel(request, id, emp_id=None):
leave_request.status = "cancelled_and_rejected"
else:
leave_request.status = "rejected"
if leave_request.multiple_approvals() and not request.user.is_superuser:
conditional_requests = leave_request.multiple_approvals()
approver = [
manager
for manager in conditional_requests["managers"]
if manager.employee_user_id == request.user
]
condition_approval = LeaveRequestConditionApproval.objects.filter(
manager_id=approver[0], leave_request_id=leave_request
).first()
condition_approval.is_approved = False
condition_approval.is_rejected = True
condition_approval.save()
leave_request.reject_reason = form.cleaned_data["reason"]
leave_request.save()
available_leave.save()
@@ -1143,13 +1184,6 @@ def holiday_creation(request):
if form.is_valid():
form.save()
messages.success(request, _("New holiday created successfully.."))
response = render(
request, "leave/holiday/holiday_form.html", {"form": form}
)
return HttpResponse(
response.content.decode("utf-8")
+ "<script>location. reload();</script>"
)
return render(request, "leave/holiday/holiday_form.html", {"form": form})
@@ -1247,7 +1281,6 @@ def holiday_info_export(request):
@login_required
@permission_required("leave.view_holiday")
def holiday_view(request):
"""
function used to view holidays.
@@ -1258,7 +1291,7 @@ def holiday_view(request):
Returns:
GET : return holiday view template
"""
queryset = Holiday.objects.all()
queryset = Holiday.objects.all()[::-1]
previous_data = request.GET.urlencode()
page_number = request.GET.get("page")
page_obj = paginator_qry(queryset, page_number)
@@ -1295,7 +1328,7 @@ def holiday_filter(request):
previous_data = request.GET.urlencode()
holiday_filter = HolidayFilter(request.GET, queryset).qs
page_number = request.GET.get("page")
page_obj = paginator_qry(holiday_filter, page_number)
page_obj = paginator_qry(holiday_filter[::-1], page_number)
data_dict = parse_qs(previous_data)
get_key_instances(Holiday, data_dict)
return render(
@@ -1327,15 +1360,6 @@ def holiday_update(request, id):
if form.is_valid():
form.save()
messages.info(request, _("Holiday updated successfully.."))
response = render(
request,
"leave/holiday/holiday_update_form.html",
{"form": form, "id": id},
)
return HttpResponse(
response.content.decode("utf-8")
+ "<script>location. reload();</script>"
)
return render(
request, "leave/holiday/holiday_update_form.html", {"form": form, "id": id}
)
@@ -1420,7 +1444,6 @@ def company_leave_creation(request):
@login_required
@permission_required("leave.view_companyleave")
def company_leave_view(request):
"""
function used to view company leave.
@@ -1900,8 +1923,8 @@ def user_request_view(request):
request_ids = json.dumps(
list(page_obj.object_list.values_list("id", flat=True))
)
user_leave = AvailableLeave.objects.filter(employee_id = user.id)
user_leave = AvailableLeave.objects.filter(employee_id=user.id)
current_date = date.today()
return render(
@@ -1914,8 +1937,7 @@ def user_request_view(request):
"current_date": current_date,
"gp_fields": MyLeaveRequestReGroup.fields,
"request_ids": request_ids,
"user_leaves":user_leave,
"user_leaves": user_leave,
},
)
except Exception as e:
@@ -1959,8 +1981,8 @@ def user_request_filter(request):
status_list = data_dict["status"]
if len(status_list) > 1:
data_dict["status"] = [status_list[-1]]
user_leave = AvailableLeave.objects.filter(employee_id = user.id)
user_leave = AvailableLeave.objects.filter(employee_id=user.id)
context = {
"leave_requests": page_obj,
@@ -1969,8 +1991,7 @@ def user_request_filter(request):
"field": field,
"current_date": date.today(),
"request_ids": request_ids,
"user_leaves":user_leave,
"user_leaves": user_leave,
}
return render(request, template, context=context)
except Exception as e:
@@ -3167,8 +3188,6 @@ def employee_leave_details(request):
return JsonResponse({"leave_count": balance_count, "employee": employee})
@login_required
@manager_can_enter("leave.change_availableleave")
def cut_available_leave(request, instance_id):
@@ -3185,7 +3204,9 @@ def cut_available_leave(request, instance_id):
penalty = PenaltyAccount()
# leave request id
penalty.leave_request_id = instance
penalty.deduct_from_carry_forward = penalty_instance.deduct_from_carry_forward
penalty.deduct_from_carry_forward = (
penalty_instance.deduct_from_carry_forward
)
penalty.employee_id = instance.employee_id
penalty.leave_type_id = penalty_instance.leave_type_id
penalty.minus_leaves = penalty_instance.minus_leaves
@@ -3207,4 +3228,6 @@ def view_penalties(request):
This method is used to filter or view the penalties
"""
records = PenaltyFilter(request.GET).qs
return render(request, "leave/leave_request/penalty/penalty_view.html", {"records": records})
return render(
request, "leave/leave_request/penalty/penalty_view.html", {"records": records}
)