[UPDT] OFFBOARDING: Dynamic grouper in offboarding

This commit is contained in:
Horilla
2024-02-19 15:32:41 +05:30
parent 2611573376
commit 0d341c440c
10 changed files with 391 additions and 77 deletions

View File

@@ -3,10 +3,17 @@ offboarding/filters.py
This module is used to register django_filters
"""
import uuid
import django_filters
from django import forms
from base.filters import FilterSet
from offboarding.models import ResignationLetter
from offboarding.models import (
Offboarding,
OffboardingEmployee,
OffboardingStage,
ResignationLetter,
)
class LetterFilter(FilterSet):
@@ -30,3 +37,98 @@ class LetterFilter(FilterSet):
"employee_id__employee_work_info__job_position_id",
"employee_id__employee_work_info__reporting_manager_id",
]
class PipelineFilter(FilterSet):
"""
PipelineFilter
"""
search = django_filters.CharFilter(method="search_method", lookup_expr="icontains")
class Meta:
model = Offboarding
fields = "__all__"
def search_method(self, queryset, _, value):
"""
This method is used to add custom search condition
"""
return (
queryset.filter(title__icontains=value)
| queryset.filter(offboardingstage__title__icontains=value)
| queryset.filter(
offboardingstage__offboardingemployee__employee_id__employee_first_name__icontains=value
)
).distinct()
class PipelineStageFilter(FilterSet):
"""
PipelineStageFilter
"""
search = django_filters.CharFilter(method="search_method", lookup_expr="icontains")
class Meta:
model = OffboardingStage
fields = "__all__"
exclude = [
"sequence",
]
def search_method(self, queryset, _, value):
"""
This method is used to add custom search condition
"""
return (
queryset.filter(title__icontains=value)
| queryset.filter(
offboardingemployee__employee_id__employee_first_name__icontains=value
)
| queryset.filter(offboarding_id__title__icontains=value)
).distinct()
class PipelineEmployeeFilter(FilterSet):
"""
PipelineEmployeeFilter
"""
search = django_filters.CharFilter(method="search_method", lookup_expr="icontains")
notice_period_starts = django_filters.DateFilter(
field_name="notice_period_starts",
lookup_expr="gte",
widget=forms.DateInput(attrs={"type": "date"}),
)
notice_period_ends = django_filters.DateFilter(
field_name="notice_period_ends",
lookup_expr="lte",
widget=forms.DateInput(attrs={"type": "date"}),
)
class Meta:
model = OffboardingEmployee
fields = [
"stage_id",
"employee_id__gender",
"employee_id__employee_work_info__department_id",
"employee_id__employee_work_info__job_position_id",
"employee_id__employee_work_info__job_role_id",
"employee_id__employee_work_info__employee_type_id",
"employee_id__employee_work_info__shift_id",
"employee_id__employee_work_info__work_type_id",
]
def search_method(self, queryset, _, value):
"""
This method is used to add custom search condition
"""
return (
queryset.filter(employee_id__employee_first_name__icontains=value)
| queryset.filter(stage_id__title__icontains=value)
| queryset.filter(stage_id__offboarding_id__title__icontains=value)
).distinct()

View File

@@ -0,0 +1,115 @@
{% load i18n %}<div class="oh-dropdown" x-data="{open: false}">
<button type="button" class="oh-btn ml-2" @click="open = !open">
<ion-icon name="filter" class="mr-1"></ion-icon>{% trans "Filter" %}
</button>
<div
class="oh-dropdown__menu oh-dropdown__menu--right oh-dropdown__filter p-4"
x-show="open"
@click.outside="open = false"
>
<div class="oh-dropdown__filter-body">
<div class="oh-accordion">
<div class="oh-accordion-header">
{% trans 'Employee' %}
</div>
<div class="oh-accordion-body">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Notice Period Starts' %} (>=)</label>
{{employee_filter.form.notice_period_starts}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Notice Period Ends' %} (<=)</label>
{{employee_filter.form.notice_period_ends}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Department' %}</label>
{{employee_filter.form.employee_id__employee_work_info__department_id}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Job Position' %}</label>
{{employee_filter.form.employee_id__employee_work_info__job_position_id}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Job Role' %}</label>
{{employee_filter.form.employee_id__employee_work_info__job_role_id}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Employee Type' %}</label>
{{employee_filter.form.employee_id__employee_work_info__employee_type_id}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Shift' %}</label>
{{employee_filter.form.employee_id__employee_work_info__shift_id}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Work Type' %}</label>
{{employee_filter.form.employee_id__employee_work_info__work_type_id}}
</div>
</div>
</div>
</div>
</div>
<div class="oh-accordion">
<div class="oh-accordion-header">
{% trans 'Offboarding' %}
</div>
<div class="oh-accordion-body">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Managers' %}</label>
{{pipeline_filter.form.managers}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Status' %}</label>
{{pipeline_filter.form.status}}
</div>
</div>
</div>
</div>
</div>
<div class="oh-accordion">
<div class="oh-accordion-header">
{% trans 'Stage' %}
</div>
<div class="oh-accordion-body">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Offboarding' %}</label>
{{stage_filter.form.offboarding_id}}
</div>
</div>
<div class="col-sm-12 col-md-12 col-lg-6 mb-1">
<div class="oh-input-group">
<label class="oh-label">{% trans 'Status' %}</label>
{{stage_filter.form.type}}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="oh-dropdown__filter-footer">
<button class="oh-btn oh-btn--secondary oh-btn--small w-100 filterButton">{% trans 'Filter' %}</button>
</div>
</div>
</div>

View File

@@ -4,11 +4,12 @@
<h1 class="oh-main__titlebar-title fw-bold">{% trans 'Offboarding' %}</h1>
</div>
<div class="oh-main__titlebar oh-main__titlebar--right oh-d-flex-column--resp oh-mb-3--small">
<form onsubmit="event.preventDefault()" hx-target="#offboardingContainer" hx-get="{% url 'offboarding-pipeline-filter' %}" class="oh-main__titlebar oh-main__titlebar--right oh-d-flex-column--resp oh-mb-3--small" >
<div class="oh-input-group oh-input__search-group mr-4">
<ion-icon name="search-outline" class="oh-input-group__icon oh-input-group__icon--left md hydrated" role="img" aria-label="search outline"></ion-icon>
<input name="search" id="pipelineSearch" hx-target="#offboardingContainer" type="text" placeholder="Search" style="margin-right:10px" class="oh-input oh-input__icon mr-3" autocomplete="false" aria-label="Search Input" />
<ion-icon name="search-outline" class="oh-input-group__icon oh-input-group__icon--left md hydrated" role="img" aria-label="search outline"></ion-icon>
<input name="search" onkeyup="$('#hiddenSubmit').click()" id="pipelineSearch" type="text" placeholder="Search" style="margin-right:10px" class="oh-input oh-input__icon mr-3" autocomplete="false" aria-label="Search Input" />
</div>
<input type="submit" id="hiddenSubmit" hidden>
{% include 'offboarding/pipeline/filter.html' %}
{% if perms.offboarding.add_offboarding %}
<div class="oh-main__titlebar-button-container">
@@ -20,7 +21,7 @@
</div>
</div>
{% endif %}
</div>
</form>
</section>
<div class="oh-modal" id="offboardingModal" role="dialog" aria-hidden="true">

View File

@@ -19,18 +19,55 @@
}
</style>
{% include "filter_tags.html" %}
<script>
function switchTab(e) {
let parentContainerEl = e.target.closest(".oh-tabs");
let tabElement = e.target.closest(".oh-tabs__tab");
let targetSelector = e.target.dataset.target;
let targetEl = parentContainerEl
? parentContainerEl.querySelector(targetSelector)
: null;
// Highlight active tabs
if (tabElement && !tabElement.classList.contains("oh-tabs__tab--active")) {
parentContainerEl
.querySelectorAll(".oh-tabs__tab--active")
.forEach(function (item) {
item.classList.remove("oh-tabs__tab--active");
});
if (!tabElement.classList.contains("oh-tabs__new-tab")) {
tabElement.classList.add("oh-tabs__tab--active");
}
}
// Switch tabs
if (targetEl && !targetEl.classList.contains("oh-tabs__content--active")) {
parentContainerEl
.querySelectorAll(".oh-tabs__content--active")
.forEach(function (item) {
item.classList.remove("oh-tabs__content--active");
});
targetEl.classList.add("oh-tabs__content--active");
}
}
</script>
<div id="messages" class="oh-alert-container"></div>
<div class="oh-wrapper">
<div class="oh-tabs">
<div class="oh-tabs" onclick="switchTab(event)">
<ul class="oh-tabs__tablist">
{% for offboarding in offboardings %}
{% if perms.offboarding.view_offboarding or request.user.employee_get|is_in_offboarding:offboarding %}
<li class="oh-tabs__tab" onclick="localStorage.setItem('activeTabOffboarding',$(this).attr('data-target'));" data-target="#Offboarding{{ offboarding.id }}">
{{ offboarding.title }}
<li class="oh-tabs__tab" onclick="localStorage.setItem('activeTabOffboarding',$(this).attr('data-target'));" data-target="#Offboarding{{ offboarding.offboarding.id }}">
{{ offboarding.offboarding.title }}
<div class="d-flex">
<div class="oh-tabs__input-badge-container">
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2" id="recruitmentCandidateCount1" title="{{ offboarding.offboardingstage_set.all|length }} Stages" onclick="event.stopPropagation()">
{{ offboarding.offboardingstage_set.all|length }}
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2" id="recruitmentCandidateCount1" title="{{ offboarding.offboarding.stages|length }} Stages" onclick="event.stopPropagation()">
{{ offboarding.offboarding.stages|length }}
</span>
</div>
<div class="oh-dropdown" x-data="{open: false}">
@@ -41,12 +78,12 @@
<ul class="oh-dropdown__items">
{% if perms.offboarding.change_offboarding or request.user.employee_get|is_offboarding_manager %}
<li class="oh-dropdown__item">
<a hx-get="{% url "create-offboarding" %}?instance_id={{offboarding.id}}" hx-target="#offboardingModalBody" data-toggle="oh-modal-toggle" data-target="#offboardingModal" class="oh-dropdown__link">{% trans "Edit" %}</a>
<a hx-get="{% url "create-offboarding" %}?instance_id={{offboarding.offboarding.id}}" hx-target="#offboardingModalBody" data-toggle="oh-modal-toggle" data-target="#offboardingModal" class="oh-dropdown__link">{% trans "Edit" %}</a>
</li>
{% endif %}
{% if perms.offboarding.delete_offboarding %}
<li class="oh-dropdown__item">
<form action="{% url "delete-offboarding" %}?id={{offboarding.id}}" onsubmit="return confirm('Are you sure you want to delete this offboarding?');" method="post">
<form action="{% url "delete-offboarding" %}?id={{offboarding.offboarding.id}}" onsubmit="return confirm('Are you sure you want to delete this offboarding?');" method="post">
{% csrf_token %}
<button type="submit" class="oh-dropdown__link oh-dropdown__link--danger">
{% trans "Delete" %}
@@ -65,9 +102,9 @@
<div class="oh-tabs__contents">
{% for offboarding in offboardings %}
{% if perms.offboarding.view_offboarding or request.user.employee_get|is_in_offboarding:offboarding %}
<div class="oh-tabs__content" id="Offboarding{{ offboarding.id }}">
<div class="oh-tabs__content" id="Offboarding{{ offboarding.offboarding.id }}">
{% if perms.offboarding.add_offboardingstage or request.user.employee_get|any_manager %}
<a hx-get="{% url 'create-offboarding-stage' %}?offboarding_id={{offboarding.id}}" style="width: 100px;" hx-target="#offboardingModalBody" data-toggle="oh-modal-toggle" data-target="#offboardingModal" class="mb-3 oh-btn oh-btn--secondary">
<a hx-get="{% url 'create-offboarding-stage' %}?offboarding_id={{offboarding.offboarding.id}}" style="width: 100px;" hx-target="#offboardingModalBody" data-toggle="oh-modal-toggle" data-target="#offboardingModal" class="mb-3 oh-btn oh-btn--secondary">
<ion-icon name="add-outline"></ion-icon>
{% trans 'Stage' %}
</a>

View File

@@ -5,42 +5,13 @@
background-color: rgba(255, 68, 0, 0.076);
}
</style>
{% include 'offboarding/pipeline/nav.html' %}
{% include 'offboarding/pipeline/offboardings.html' %}
<div id="offboardingContainer">
{% include 'offboarding/pipeline/offboardings.html' %}
</div>
<script>
$('#pipelineSearch').keyup(function (e) {
e.preventDefault()
var search = $(this).val().toLowerCase()
$('[data-employee]').each(function () {
var employeeFullName = $(this).attr('data-employee')
if (employeeFullName.toLowerCase().includes(search)) {
$(this).show()
$(this).addClass('search-highlight')
} else {
$(this).hide()
$(this).removeClass('search-highlight')
}
})
if (search == '') {
$('.search-highlight').removeClass('search-highlight')
$('[data-employee]').show()
}
$('[title="Toggle Archived"]').change()
if (search != '') {
$('#filterTagContainerSectionNav').html('')
$('#filterTagContainerSectionNav').append(
'<span class="oh-titlebar__tag filter-field pipelineSearch">Search :' +
search +
`<button class="oh-titlebar__tag-close" onclick="$('#pipelineSearch').val('');$('#pipelineSearch').keyup()">
<ion-icon name="close-outline">
</ion-icon>
</button>
</span>`
)
} else {
$('#filterTagContainerSectionNav').html('')
}
})
// intial select notice period starts and end
function intialNoticePeriod($element) {
let employeeId = $element.val()

View File

@@ -1,16 +1,16 @@
{% load i18n offboarding_filter %}
{% for stage in offboarding.offboardingstage_set.all %}
{% for stage in offboarding.offboarding.stages %}
<div class="oh-accordion-meta" id="accordion{{stage.id}}">
<div class="oh-accordion-meta__item">
<div class="oh-accordion-meta__header oh-accordion-meta__header--show">
<div class="oh-accordion-meta__header {% if stage.grouper.type != "archived" or not stage.list|length %} oh-accordion-meta__header--show" {% endif %}>
<span class="oh-accordion-meta__title" data-offboarding-id="{{offboarding.id}}">
<span class="d-flex" onclick="event.stopPropagation()">
<span class="oh-badge oh-badge--secondary oh-badge--small oh-badge--round ms-2 mr-2"
id="offboardingBadge{{offboarding.id}}_{{forloop.counter}}" title="{{stage.offboardingemployee_set.all|length}} {% trans "Employees" %}" onclick="event.stopPropagation()">
{{ stage.offboardingemployee_set.all|length }}
id="offboardingBadge{{offboarding.id}}_{{forloop.counter}}" title="{{stage.list|length}} {% trans "Employees" %}" onclick="event.stopPropagation()">
{{ stage.list|length }}
</span>
{{stage.title}}
{% if stage.is_archived_stage %}
{{stage.grouper.title}}
{% if stage.grouper.is_archived_stage %}
<div class="oh-switch ml-2">
<input type="checkbox" class="show-archived oh-switch__checkbox" title="{% trans "Toggle Archived" %}" onchange="showArchived($(this))">
</div>
@@ -28,7 +28,7 @@
<ul class="oh-dropdown__items">
{% if perms.offboarding.add_offboardingemployee or request.user.employee_get|any_manager %}
<li class="oh-dropdown__item">
<a hx-get="{% url "add-employee" %}?stage_id={{stage.id}}" data-target="#offboardingModal"
<a hx-get="{% url "add-employee" %}?stage_id={{stage.grouper.id}}" data-target="#offboardingModal"
data-toggle="oh-modal-toggle" hx-target="#offboardingModalBody" class="oh-dropdown__link">
{% trans "Add Employee" %}</a>
</li>
@@ -36,14 +36,14 @@
{% if perms.offboarding.change_offboardingstage or request.user.employee_get|is_offboarding_manager %}
<li class="oh-dropdown__item">
<a
hx-get="{% url "create-offboarding-stage" %}?offboarding_id={{offboarding.id}}&instance_id={{stage.id}}"
hx-get="{% url "create-offboarding-stage" %}?offboarding_id={{offboarding.offboarding.id}}&instance_id={{stage.grouper.id}}"
data-target="#offboardingModal"
data-toggle="oh-modal-toggle" hx-target="#offboardingModalBody" class="oh-dropdown__link">{% trans "Edit" %}</a>
</li>
{% endif %}
{% if perms.offboarding.delete_offboarding %}
<li class="oh-dropdown__item">
<a href="{% url "delete-offboarding-stage" %}?ids={{stage.id}}"
<a href="{% url "delete-offboarding-stage" %}?ids={{stage.grouper.id}}"
onclick="return confirm('Are you sure want to delete this stage?')"
class="oh-dropdown__link oh-dropdown__link--danger">{% trans "Delete" %}</a>
</li>
@@ -53,7 +53,7 @@
</div>
</div>
</div>
<div class="oh-accordion-meta__body">
<div class="oh-accordion-meta__body {% if stage.grouper.type == "archived" or not stage.list|length %} d-none {% endif %}">
<div class="oh-sticky-table oh-sticky-table--no-overflow mb-5">
<div class="oh-sticky-table__table">
<div class="oh-sticky-table__thead">
@@ -66,8 +66,8 @@
<div class="oh-sticky-table__th">{% trans "Stage" %}</div>
{% endif %}
<div class="oh-sticky-table__th">{% trans "Actions" %}</div>
{% for task in stage.offboardingtask_set.all %}
<div class="oh-sticky-table__th" style="width: 200px;" hx-get="{% url "offboarding-add-task" %}?stage_id={{stage.id}}&instance_id={{task.id}}" hx-target="#offboardingModalBody" data-toggle="oh-modal-toggle" data-target="#offboardingModal">
{% for task in stage.grouper.offboardingtask_set.all %}
<div class="oh-sticky-table__th" style="width: 200px;" hx-get="{% url "offboarding-add-task" %}?stage_id={{stage.grouper.id}}&instance_id={{task.id}}" hx-target="#offboardingModalBody" data-toggle="oh-modal-toggle" data-target="#offboardingModal">
<div class="d-flex justify-content-between">
<span title="Click to edit">
{{task.title}}
@@ -80,14 +80,14 @@
{% endfor %}
<div class="oh-sticky-table__th" style="width: 120px;">
{% if perms.offboarding.add_offboardingtask or request.user.employee_get|any_manager %}
<button class="oh-checkpoint-badge text-success" data-toggle="oh-modal-toggle" data-target="#offboardingModal" hx-get="{% url "offboarding-add-task" %}?stage_id={{stage.id}}" hx-target="#offboardingModalBody">
<button class="oh-checkpoint-badge text-success" data-toggle="oh-modal-toggle" data-target="#offboardingModal" hx-get="{% url "offboarding-add-task" %}?stage_id={{stage.grouper.id}}" hx-target="#offboardingModalBody">
{% trans "Add Task" %}
</button>
{% endif %}
</div>
</div>
</div>
<div class="oh-sticky-table__tbody" id="tableBody{{stage.id}}" data-stage-id="{{stage.id}}" data-archive-stage="{{stage.is_archived_stage|lower}}" data-offboarding-id="{{offboarding.id}}">
<div class="oh-sticky-table__tbody" id="tableBody{{stage.grouper.id}}" data-stage-id="{{stage.grouper.id}}" data-archive-stage="{{stage.grouper.is_archived_stage|lower}}" data-offboarding-id="{{offboarding.offboarding.id}}">
{% include "offboarding/task/table_body.html" %}
</div>
</div>

View File

@@ -5,7 +5,7 @@
submitButton.click()
}
</script>
<div class="oh-card" id="offboardingBody{{offboarding.id}}">
<div class="oh-card" id="offboardingBody{{offboarding.offboarding.id}}">
{% include "offboarding/stage/offboarding_body.html" %}
</div>
<div class="oh-activity-sidebar" id="activitySidebar">

View File

@@ -4,8 +4,8 @@
{{response_message}}
</div>
</div>
{% endif %} {% for employee in stage.offboardingemployee_set.all %}
{% if perms.offboarding.view_offboarding or request.user.employee_get|is_in_managers:offboarding or request.user.employee_get|is_in_managers:stage or request.user.employee_get|is_in_managers:employee %}
{% endif %} {% for employee in stage.list %}
{% if perms.offboarding.view_offboarding or request.user.employee_get|is_in_managers:offboarding.offboarding or request.user.employee_get|is_in_managers:stage.grouper or request.user.employee_get|is_in_managers:employee %}
<div
class="oh-sticky-table__tr oh-multiple-table-sort__movable"
data-employee="{{employee.employee_id.get_full_name}}"
@@ -36,8 +36,8 @@
{% if request.user.employee_get|is_any_stage_manager or perms.offboarding.change_offboarding or perms.offboarding.change_offboardingemployee %}
<div class="oh-sticky-table__td" onclick="event.stopPropagation()">
<form hx-get="{% url "offboarding-change-stage" %}?employee_ids={{employee.id}}"
hx-target="#offboardingBody{{offboarding.id}}">
{{ stage_forms|stages:stage }}
hx-target="#offboardingBody{{offboarding.offboarding.id}}">
{{ stage_forms|stages:employee.stage_id }}
<input type="submit" hidden />
</form>
</div>
@@ -82,7 +82,7 @@
{% else %}
<a
type="button"
hx-get="{% url "add-employee" %}?instance_id={{employee.id}}&stage_id={{stage.id}}"
hx-get="{% url "add-employee" %}?instance_id={{employee.id}}&stage_id={{stage.grouper.id}}"
hx-target="#offboardingModalBody"
data-toggle="oh-modal-toggle"
data-target="#offboardingModal"
@@ -105,13 +105,13 @@
{% endif %}
</div>
</div>
{% for task in stage.offboardingtask_set.all %}
{% for task in stage.grouper.offboardingtask_set.all %}
<div class="oh-sticky-table__td">
{% if task|have_task:employee %}
{% for assinged_tasks in employee|get_assigned_task:task %}
<select
hx-get="{% url "update-task-status" %}?stage_id={{stage.id}}&employee_ids={{employee.id}}&task_id={{assinged_tasks.task_id.id}}"
hx-target="#offboardingBody{{offboarding.id}}"
hx-get="{% url "update-task-status" %}?stage_id={{stage.grouper.id}}&employee_ids={{employee.id}}&task_id={{assinged_tasks.task_id.id}}"
hx-target="#offboardingBody{{offboarding.offboarding.id}}"
name="task_status"
id="task_status{{assinged_tasks.id}}"
class="oh-select-custom w-100"

View File

@@ -3,6 +3,7 @@ offboarding/urls.py
This module is used to register url mappings to functions
"""
from django.urls import path
from offboarding import views
@@ -66,4 +67,5 @@ urlpatterns = [
name="enable-resignation-request",
),
path("get-notice-period", views.get_notice_period, name="get-notice-period"),
path("offboarding-pipeline-filter",views.filter_pipeline,name="offboarding-pipeline-filter")
]

View File

@@ -14,7 +14,12 @@ from offboarding.decorators import (
offboarding_manager_can_enter,
offboarding_or_stage_manager_can_enter,
)
from offboarding.filters import LetterFilter
from offboarding.filters import (
LetterFilter,
PipelineEmployeeFilter,
PipelineFilter,
PipelineStageFilter,
)
from offboarding.forms import (
NoteForm,
OffboardingEmployeeForm,
@@ -37,13 +42,53 @@ from offboarding.models import (
)
from notifications.signals import notify
from django.utils.translation import gettext_lazy as _
from onboarding.filters import OnboardingStageFilter
from payroll.models.models import Contract
from recruitment.pipeline_grouper import group_by_queryset
# Create your views here.
def pipeline_grouper(filters={}, offboardings=[]):
groups = []
for offboarding in offboardings:
stages = PipelineStageFilter(
filters, queryset=offboarding.offboardingstage_set.all()
).qs.order_by("id")
all_stages_grouper = []
data = {"offboarding": offboarding, "stages": []}
for stage in stages:
all_stages_grouper.append({"grouper": stage, "list": []})
stage_employees = PipelineEmployeeFilter(
filters,
OffboardingEmployee.objects.filter(stage_id=stage).order_by("-id"),
).qs
page_name = "page" + stage.title + str(offboarding.id)
grouper = group_by_queryset(
stage_employees,
"stage_id",
filters.get(page_name),
page_name,
).object_list
data["stages"] = data["stages"] + grouper
existing_grouper_ids = list({item["grouper"].id for item in data["stages"]})
for item in all_stages_grouper:
if item["grouper"].id not in existing_grouper_ids:
data["stages"].append(
{
"grouper": item["grouper"],
"list": [],
"dynamic_name": f'dynamic_page_page{item["grouper"].id}',
}
)
groups.append(data)
return groups
@login_required
@any_manager_can_enter(
"offboarding.view_offboarding", offboarding_employee_can_enter=True
@@ -52,14 +97,49 @@ def pipeline(request):
"""
Offboarding pipleine view
"""
offboardings = Offboarding.objects.all()
offboardings = PipelineFilter().qs
groups = pipeline_grouper({}, offboardings)
for item in groups:
setattr(item["offboarding"], "stages", item["stages"])
stage_forms = {}
for offboarding in offboardings:
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
filter_dict = parse_qs(request.GET.urlencode())
return render(
request,
"offboarding/pipeline/pipeline.html",
{
"offboardings": groups,
"employee_filter": PipelineEmployeeFilter(),
"pipeline_filter": PipelineFilter(),
"stage_filter": PipelineStageFilter(),
"stage_forms": stage_forms,
"filter_dict": filter_dict,
},
)
@login_required
@permission_required("offboarding_view_offboardingemployee")
def filter_pipeline(request):
"""
This method is used filter offboarding process
"""
offboardings = PipelineFilter(request.GET).qs
groups = pipeline_grouper(request.GET, offboardings)
for item in groups:
setattr(item["offboarding"], "stages", item["stages"])
stage_forms = {}
for offboarding in offboardings:
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
return render(
request,
"offboarding/pipeline/pipeline.html",
{"offboardings": offboardings, "stage_forms": stage_forms},
"offboarding/pipeline/offboardings.html",
{
"offboardings": groups,
"stage_forms": stage_forms,
"filter_dict": parse_qs(request.GET.urlencode()),
},
)
@@ -239,11 +319,14 @@ def change_stage(request):
redirect="offboarding/offboarding-pipeline",
icon="information",
)
groups = pipeline_grouper({}, [stage.offboarding_id])
for item in groups:
setattr(item["offboarding"], "stages", item["stages"])
return render(
request,
"offboarding/stage/offboarding_body.html",
{
"offboarding": stage.offboarding_id,
"offboarding": groups[0],
"stage_forms": stage_forms,
"response_message": _("stage changed successfully."),
},
@@ -406,11 +489,14 @@ def update_task_status(request, *args, **kwargs):
stage_forms[str(stage.offboarding_id.id)] = StageSelectForm(
offboarding=stage.offboarding_id
)
groups = pipeline_grouper({}, [stage.offboarding_id])
for item in groups:
setattr(item["offboarding"], "stages", item["stages"])
return render(
request,
"offboarding/stage/offboarding_body.html",
{
"offboarding": stage.offboarding_id,
"offboarding": groups[0],
"stage_forms": stage_forms,
"response_message": _("Task status changed successfully."),
},