2024-02-26 20:03:58 +05:30
|
|
|
import json
|
2024-05-07 12:23:36 +05:30
|
|
|
from datetime import datetime, timedelta
|
2024-01-25 15:59:15 +05:30
|
|
|
from urllib.parse import parse_qs
|
2024-05-07 12:23:36 +05:30
|
|
|
|
2024-08-05 14:22:44 +05:30
|
|
|
from django.apps import apps
|
2024-01-23 15:21:53 +05:30
|
|
|
from django.contrib import messages
|
2024-01-24 12:27:28 +05:30
|
|
|
from django.contrib.auth.models import User
|
2024-12-05 14:45:39 +05:30
|
|
|
from django.core.paginator import Paginator
|
2024-05-07 12:23:36 +05:30
|
|
|
from django.http import HttpResponse, JsonResponse
|
|
|
|
|
from django.shortcuts import redirect, render
|
2024-06-27 14:49:28 +05:30
|
|
|
from django.urls import reverse
|
2024-05-07 12:23:36 +05:30
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
2024-01-30 19:10:54 +05:30
|
|
|
from base.context_processors import intial_notice_period
|
2024-11-26 14:24:55 +05:30
|
|
|
from base.methods import closest_numbers, eval_validate, paginator_qry, sortby
|
2024-12-25 12:02:37 +05:30
|
|
|
from base.views import general_settings
|
2024-01-23 15:21:53 +05:30
|
|
|
from employee.models import Employee
|
2024-05-30 10:04:58 +05:30
|
|
|
from horilla.decorators import (
|
|
|
|
|
hx_request_required,
|
|
|
|
|
login_required,
|
|
|
|
|
manager_can_enter,
|
|
|
|
|
permission_required,
|
|
|
|
|
)
|
2024-06-20 11:47:45 +05:30
|
|
|
from horilla.group_by import group_by_queryset as group_by
|
2024-08-05 14:22:44 +05:30
|
|
|
from horilla.methods import get_horilla_model_class
|
2024-05-07 12:23:36 +05:30
|
|
|
from notifications.signals import notify
|
2024-01-24 12:27:28 +05:30
|
|
|
from offboarding.decorators import (
|
|
|
|
|
any_manager_can_enter,
|
2024-02-26 20:03:58 +05:30
|
|
|
check_feature_enabled,
|
2024-01-24 12:27:28 +05:30
|
|
|
offboarding_manager_can_enter,
|
|
|
|
|
offboarding_or_stage_manager_can_enter,
|
|
|
|
|
)
|
2024-02-19 15:32:41 +05:30
|
|
|
from offboarding.filters import (
|
|
|
|
|
LetterFilter,
|
2024-02-26 20:03:58 +05:30
|
|
|
LetterReGroup,
|
2024-02-19 15:32:41 +05:30
|
|
|
PipelineEmployeeFilter,
|
|
|
|
|
PipelineFilter,
|
|
|
|
|
PipelineStageFilter,
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
from offboarding.forms import (
|
|
|
|
|
NoteForm,
|
|
|
|
|
OffboardingEmployeeForm,
|
|
|
|
|
OffboardingForm,
|
|
|
|
|
OffboardingStageForm,
|
2024-01-25 15:59:15 +05:30
|
|
|
ResignationLetterForm,
|
2024-01-23 15:21:53 +05:30
|
|
|
StageSelectForm,
|
|
|
|
|
TaskForm,
|
|
|
|
|
)
|
|
|
|
|
from offboarding.models import (
|
|
|
|
|
EmployeeTask,
|
|
|
|
|
Offboarding,
|
|
|
|
|
OffboardingEmployee,
|
2024-01-25 15:59:15 +05:30
|
|
|
OffboardingGeneralSetting,
|
2024-01-23 15:21:53 +05:30
|
|
|
OffboardingNote,
|
|
|
|
|
OffboardingStage,
|
|
|
|
|
OffboardingStageMultipleFile,
|
|
|
|
|
OffboardingTask,
|
2024-01-25 15:59:15 +05:30
|
|
|
ResignationLetter,
|
2024-01-23 15:21:53 +05:30
|
|
|
)
|
2024-01-30 19:10:54 +05:30
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
|
2024-02-19 15:32:41 +05:30
|
|
|
def pipeline_grouper(filters={}, offboardings=[]):
|
|
|
|
|
groups = []
|
2024-02-20 14:17:21 +05:30
|
|
|
|
2024-02-19 15:32:41 +05:30
|
|
|
for offboarding in offboardings:
|
2024-02-27 23:42:00 +05:30
|
|
|
employees = []
|
2024-02-19 15:32:41 +05:30
|
|
|
stages = PipelineStageFilter(
|
|
|
|
|
filters, queryset=offboarding.offboardingstage_set.all()
|
|
|
|
|
).qs.order_by("id")
|
|
|
|
|
all_stages_grouper = []
|
2024-02-27 23:42:00 +05:30
|
|
|
data = {"offboarding": offboarding, "stages": [], "employees": []}
|
2024-02-19 15:32:41 +05:30
|
|
|
for stage in stages:
|
|
|
|
|
all_stages_grouper.append({"grouper": stage, "list": []})
|
|
|
|
|
stage_employees = PipelineEmployeeFilter(
|
|
|
|
|
filters,
|
2024-03-21 14:22:49 +05:30
|
|
|
OffboardingEmployee.objects.filter(
|
|
|
|
|
stage_id=stage, employee_id__is_active=True
|
|
|
|
|
),
|
2024-02-20 14:17:21 +05:30
|
|
|
).qs.order_by("stage_id__id")
|
2024-02-19 15:32:41 +05:30
|
|
|
page_name = "page" + stage.title + str(offboarding.id)
|
2024-08-05 14:22:44 +05:30
|
|
|
employee_grouper = group_by(
|
2024-02-19 15:32:41 +05:30
|
|
|
stage_employees,
|
|
|
|
|
"stage_id",
|
|
|
|
|
filters.get(page_name),
|
|
|
|
|
page_name,
|
|
|
|
|
).object_list
|
2024-02-27 23:42:00 +05:30
|
|
|
employees = employees + [
|
|
|
|
|
employee.id for employee in stage.offboardingemployee_set.all()
|
|
|
|
|
]
|
2024-02-20 14:17:21 +05:30
|
|
|
data["stages"] = data["stages"] + employee_grouper
|
2024-02-19 15:32:41 +05:30
|
|
|
|
2024-02-20 14:17:21 +05:30
|
|
|
ordered_data = []
|
2024-02-20 17:05:43 +05:30
|
|
|
|
|
|
|
|
# combining un used groups in to the grouper
|
|
|
|
|
groupers = data["stages"]
|
|
|
|
|
for stage in stages:
|
|
|
|
|
found = False
|
|
|
|
|
for grouper in groupers:
|
|
|
|
|
if grouper["grouper"] == stage:
|
|
|
|
|
ordered_data.append(grouper)
|
|
|
|
|
found = True
|
|
|
|
|
break
|
|
|
|
|
if not found:
|
|
|
|
|
ordered_data.append({"grouper": stage})
|
2024-02-20 14:17:21 +05:30
|
|
|
data = {
|
|
|
|
|
"offboarding": offboarding,
|
|
|
|
|
"stages": ordered_data,
|
2024-02-27 23:42:00 +05:30
|
|
|
"employee_ids": employees,
|
2024-02-20 14:17:21 +05:30
|
|
|
}
|
2024-02-19 15:32:41 +05:30
|
|
|
groups.append(data)
|
2024-02-20 17:05:43 +05:30
|
|
|
|
2024-02-19 15:32:41 +05:30
|
|
|
return groups
|
|
|
|
|
|
|
|
|
|
|
2024-12-05 14:45:39 +05:30
|
|
|
def paginator_qry_offboarding_limited(qryset, page_number):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to generate common paginator limit.
|
|
|
|
|
"""
|
|
|
|
|
paginator = Paginator(qryset, 3)
|
|
|
|
|
qryset = paginator.get_page(page_number)
|
|
|
|
|
return qryset
|
|
|
|
|
|
|
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
@login_required
|
2024-01-24 12:27:28 +05:30
|
|
|
@any_manager_can_enter(
|
|
|
|
|
"offboarding.view_offboarding", offboarding_employee_can_enter=True
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
def pipeline(request):
|
|
|
|
|
"""
|
2024-04-15 13:27:41 +05:30
|
|
|
Offboarding pipeline view
|
2024-01-23 15:21:53 +05:30
|
|
|
"""
|
2024-12-05 14:45:39 +05:30
|
|
|
# Apply filters and pagination
|
2024-02-19 15:32:41 +05:30
|
|
|
offboardings = PipelineFilter().qs
|
2024-12-05 14:45:39 +05:30
|
|
|
paginated_offboardings = paginator_qry_offboarding_limited(
|
|
|
|
|
offboardings, request.GET.get("page")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Group data after pagination
|
|
|
|
|
groups = pipeline_grouper({}, paginated_offboardings)
|
|
|
|
|
|
2024-02-19 15:32:41 +05:30
|
|
|
for item in groups:
|
|
|
|
|
setattr(item["offboarding"], "stages", item["stages"])
|
2024-12-05 14:45:39 +05:30
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
stage_forms = {}
|
2024-12-05 14:45:39 +05:30
|
|
|
for offboarding in paginated_offboardings:
|
2024-01-23 15:21:53 +05:30
|
|
|
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
|
2024-02-28 14:39:57 +05:30
|
|
|
|
2024-02-19 15:32:41 +05:30
|
|
|
filter_dict = parse_qs(request.GET.urlencode())
|
2024-02-27 23:42:00 +05:30
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/pipeline/pipeline.html",
|
2024-02-19 15:32:41 +05:30
|
|
|
{
|
2024-12-05 14:45:39 +05:30
|
|
|
"offboardings": groups, # Grouped data
|
|
|
|
|
"paginated_offboardings": paginated_offboardings, # Original paginated object
|
2024-02-19 15:32:41 +05:30
|
|
|
"employee_filter": PipelineEmployeeFilter(),
|
|
|
|
|
"pipeline_filter": PipelineFilter(),
|
|
|
|
|
"stage_filter": PipelineStageFilter(),
|
|
|
|
|
"stage_forms": stage_forms,
|
|
|
|
|
"filter_dict": filter_dict,
|
2024-03-10 19:37:46 +05:30
|
|
|
"today": datetime.today().date(),
|
2024-02-19 15:32:41 +05:30
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-10-16 00:23:55 +05:30
|
|
|
@any_manager_can_enter(
|
|
|
|
|
"offboarding.view_offboarding", offboarding_employee_can_enter=True
|
|
|
|
|
)
|
2024-02-19 15:32:41 +05:30
|
|
|
def filter_pipeline(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used filter offboarding process
|
|
|
|
|
"""
|
|
|
|
|
offboardings = PipelineFilter(request.GET).qs
|
2024-12-05 14:45:39 +05:30
|
|
|
paginated_offboardings = paginator_qry_offboarding_limited(
|
|
|
|
|
offboardings, request.GET.get("page")
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
groups = pipeline_grouper(request.GET, paginated_offboardings)
|
2024-02-19 15:32:41 +05:30
|
|
|
for item in groups:
|
|
|
|
|
setattr(item["offboarding"], "stages", item["stages"])
|
|
|
|
|
stage_forms = {}
|
2024-12-05 14:45:39 +05:30
|
|
|
for offboarding in paginated_offboardings:
|
2024-02-19 15:32:41 +05:30
|
|
|
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
|
|
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/pipeline/offboardings.html",
|
|
|
|
|
{
|
|
|
|
|
"offboardings": groups,
|
2024-12-05 14:45:39 +05:30
|
|
|
"paginated_offboardings": paginated_offboardings,
|
2024-02-19 15:32:41 +05:30
|
|
|
"stage_forms": stage_forms,
|
|
|
|
|
"filter_dict": parse_qs(request.GET.urlencode()),
|
|
|
|
|
},
|
2024-01-23 15:21:53 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-01-23 15:21:53 +05:30
|
|
|
@permission_required("offboarding.add_offboarding")
|
|
|
|
|
def create_offboarding(request):
|
|
|
|
|
"""
|
|
|
|
|
Create offboarding view
|
|
|
|
|
"""
|
2024-11-26 14:24:55 +05:30
|
|
|
instance_id = eval_validate(str(request.GET.get("instance_id")))
|
2024-01-23 15:21:53 +05:30
|
|
|
instance = None
|
|
|
|
|
if instance_id and isinstance(instance_id, int):
|
|
|
|
|
instance = Offboarding.objects.filter(id=instance_id).first()
|
|
|
|
|
form = OffboardingForm(instance=instance)
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
form = OffboardingForm(request.POST, instance=instance)
|
|
|
|
|
if form.is_valid():
|
2024-10-23 12:55:42 +05:30
|
|
|
off_boarding = form.save()
|
2024-01-24 12:27:28 +05:30
|
|
|
messages.success(request, _("Offboarding saved"))
|
2024-10-23 12:55:42 +05:30
|
|
|
users = [
|
|
|
|
|
employee.employee_user_id for employee in off_boarding.managers.all()
|
|
|
|
|
]
|
|
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
|
|
|
|
recipient=users,
|
|
|
|
|
verb="You are chosen as an offboarding manager",
|
|
|
|
|
verb_ar="لقد تم اختيارك كمدير عملية المغادرة",
|
|
|
|
|
verb_de="Sie wurden als Offboarding-Manager ausgewählt",
|
|
|
|
|
verb_es="Has sido elegido como gerente de offboarding",
|
|
|
|
|
verb_fr="Vous avez été choisi comme responsable du processus de départ",
|
|
|
|
|
icon="people-circle",
|
|
|
|
|
redirect=reverse("offboarding-pipeline"),
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
return HttpResponse("<script>window.location.reload()</script>")
|
|
|
|
|
|
|
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/pipeline/form.html",
|
|
|
|
|
{
|
|
|
|
|
"form": form,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@permission_required("offboarding.delete_offboarding")
|
2024-05-21 13:05:32 +05:30
|
|
|
def delete_offboarding(request, id):
|
2024-01-23 15:21:53 +05:30
|
|
|
"""
|
|
|
|
|
This method is used to delete offboardings
|
|
|
|
|
"""
|
2024-05-21 13:05:32 +05:30
|
|
|
try:
|
|
|
|
|
offboarding = Offboarding.objects.get(id=id)
|
|
|
|
|
offboarding.delete()
|
|
|
|
|
messages.success(request, _("Offboarding deleted"))
|
|
|
|
|
except (Offboarding.DoesNotExist, OverflowError):
|
|
|
|
|
messages.error(request, _("Offboarding not found"))
|
|
|
|
|
return redirect(filter_pipeline)
|
2024-01-23 15:21:53 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@offboarding_manager_can_enter("offboarding.add_offboardingstage")
|
|
|
|
|
def create_stage(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to create stages for offboardings
|
|
|
|
|
"""
|
|
|
|
|
offboarding_id = request.GET["offboarding_id"]
|
2024-11-26 14:24:55 +05:30
|
|
|
instance_id = eval_validate(str(request.GET.get("instance_id")))
|
2024-01-23 15:21:53 +05:30
|
|
|
instance = None
|
|
|
|
|
if instance_id and isinstance(instance_id, int):
|
|
|
|
|
instance = OffboardingStage.objects.get(id=instance_id)
|
|
|
|
|
offboarding = Offboarding.objects.get(id=offboarding_id)
|
|
|
|
|
form = OffboardingStageForm(instance=instance)
|
|
|
|
|
form.instance.offboarding_id = offboarding
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
form = OffboardingStageForm(request.POST, instance=instance)
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
instance = form.save(commit=False)
|
|
|
|
|
instance.offboarding_id = offboarding
|
|
|
|
|
instance.save()
|
|
|
|
|
instance.managers.set(form.data.getlist("managers"))
|
2024-01-24 12:27:28 +05:30
|
|
|
messages.success(request, _("Stage saved"))
|
2024-10-23 12:55:42 +05:30
|
|
|
users = [employee.employee_user_id for employee in instance.managers.all()]
|
|
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
|
|
|
|
recipient=users,
|
|
|
|
|
verb="You are chosen as offboarding stage manager",
|
|
|
|
|
verb_ar="لقد تم اختيارك كمدير لمرحلة عملية المغادرة",
|
|
|
|
|
verb_de="Sie wurden als Manager der Offboarding-Phase ausgewählt",
|
|
|
|
|
verb_es="Has sido elegido como gerente de la etapa de offboarding",
|
|
|
|
|
verb_fr="Vous avez été choisi comme responsable de l'étape de départ",
|
|
|
|
|
icon="people-circle",
|
|
|
|
|
redirect=reverse("offboarding-pipeline"),
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
return HttpResponse("<script>window.location.reload()</script>")
|
|
|
|
|
return render(request, "offboarding/stage/form.html", {"form": form})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@any_manager_can_enter("offboarding.add_offboardingemployee")
|
|
|
|
|
def add_employee(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to add employee to the stage
|
|
|
|
|
"""
|
2024-02-28 14:39:57 +05:30
|
|
|
default_notice_period = (
|
|
|
|
|
intial_notice_period(request)["get_initial_notice_period"]
|
|
|
|
|
if intial_notice_period(request)["get_initial_notice_period"]
|
|
|
|
|
else 0
|
|
|
|
|
)
|
2024-03-21 14:22:49 +05:30
|
|
|
end_date = datetime.today() + timedelta(days=default_notice_period)
|
2024-01-23 15:21:53 +05:30
|
|
|
stage_id = request.GET["stage_id"]
|
2024-11-26 14:24:55 +05:30
|
|
|
instance_id = eval_validate(str(request.GET.get("instance_id")))
|
2024-01-23 15:21:53 +05:30
|
|
|
instance = None
|
|
|
|
|
if instance_id and isinstance(instance_id, int):
|
|
|
|
|
instance = OffboardingEmployee.objects.get(id=instance_id)
|
|
|
|
|
stage = OffboardingStage.objects.get(id=stage_id)
|
2024-03-10 19:37:46 +05:30
|
|
|
form = OffboardingEmployeeForm(
|
|
|
|
|
initial={"stage_id": stage, "notice_period_ends": end_date}, instance=instance
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
form.instance.stage_id = stage
|
|
|
|
|
if request.method == "POST":
|
2024-01-24 12:27:28 +05:30
|
|
|
form = OffboardingEmployeeForm(request.POST, instance=instance)
|
2024-01-23 15:21:53 +05:30
|
|
|
if form.is_valid():
|
|
|
|
|
instance = form.save(commit=False)
|
|
|
|
|
instance.stage_id = stage
|
|
|
|
|
instance.save()
|
2024-02-03 14:00:42 +05:30
|
|
|
messages.success(request, _("Employee saved"))
|
2024-01-24 12:27:28 +05:30
|
|
|
if not instance_id:
|
|
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
|
|
|
|
recipient=instance.employee_id.employee_user_id,
|
|
|
|
|
verb=f"You have been added to the {stage} of {stage.offboarding_id}",
|
2024-06-27 14:49:28 +05:30
|
|
|
verb_ar=f"لقد تمت إضافتك إلى {stage} من {stage.offboarding_id}",
|
|
|
|
|
verb_de=f"Du wurdest zu {stage} von {stage.offboarding_id} hinzugefügt",
|
|
|
|
|
verb_es=f"Has sido añadido a {stage} de {stage.offboarding_id}",
|
|
|
|
|
verb_fr=f"Vous avez été ajouté à {stage} de {stage.offboarding_id}",
|
|
|
|
|
redirect=reverse("offboarding-pipeline"),
|
2024-01-24 12:27:28 +05:30
|
|
|
icon="information",
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
return HttpResponse("<script>window.location.reload()</script>")
|
|
|
|
|
return render(request, "offboarding/employee/form.html", {"form": form})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@permission_required("offboarding.delete_offboardingemployee")
|
|
|
|
|
def delete_employee(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to delete the offboarding employee
|
|
|
|
|
"""
|
|
|
|
|
employee_ids = request.GET.getlist("employee_ids")
|
2024-01-25 15:59:15 +05:30
|
|
|
instances = OffboardingEmployee.objects.filter(id__in=employee_ids)
|
2024-04-15 13:27:41 +05:30
|
|
|
if instances:
|
|
|
|
|
instances.delete()
|
|
|
|
|
messages.success(request, _("Offboarding employee deleted"))
|
|
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
|
|
|
|
recipient=User.objects.filter(
|
|
|
|
|
id__in=instances.values_list("employee_id__employee_user_id", flat=True)
|
|
|
|
|
),
|
|
|
|
|
verb=f"You have been removed from the offboarding",
|
2024-06-27 14:49:28 +05:30
|
|
|
verb_ar=f"لقد تمت إزالتك من إنهاء الخدمة",
|
|
|
|
|
verb_de=f"Du wurdest aus dem Offboarding entfernt",
|
|
|
|
|
verb_es=f"Has sido eliminado del offboarding",
|
|
|
|
|
verb_fr=f"Vous avez été retiré de l'offboarding",
|
|
|
|
|
redirect=reverse("offboarding-pipeline"),
|
2024-04-15 13:27:41 +05:30
|
|
|
icon="information",
|
|
|
|
|
)
|
|
|
|
|
else:
|
2024-05-21 13:05:32 +05:30
|
|
|
messages.error(request, _("Employees not found"))
|
|
|
|
|
return redirect(filter_pipeline)
|
2024-01-23 15:21:53 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@permission_required("offboarding.delete_offboardingstage")
|
|
|
|
|
def delete_stage(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to delete the offboarding stage
|
|
|
|
|
"""
|
|
|
|
|
ids = request.GET.getlist("ids")
|
2024-05-21 13:05:32 +05:30
|
|
|
try:
|
|
|
|
|
instances = OffboardingStage.objects.filter(id__in=ids)
|
|
|
|
|
if instances:
|
|
|
|
|
instances.delete()
|
|
|
|
|
messages.success(request, _("Stage deleted"))
|
|
|
|
|
else:
|
|
|
|
|
messages.error(request, _("Stage not found"))
|
|
|
|
|
except OverflowError:
|
|
|
|
|
messages.error(request, _("Stage not found"))
|
2024-12-05 14:45:39 +05:30
|
|
|
return HttpResponse("<script>window.location.reload()</script>")
|
2024-01-23 15:21:53 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-01-23 15:21:53 +05:30
|
|
|
@any_manager_can_enter("offboarding.change_offboarding")
|
|
|
|
|
def change_stage(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to update the stages of the employee
|
|
|
|
|
"""
|
|
|
|
|
employee_ids = request.GET.getlist("employee_ids")
|
|
|
|
|
stage_id = request.GET["stage_id"]
|
|
|
|
|
employees = OffboardingEmployee.objects.filter(id__in=employee_ids)
|
|
|
|
|
stage = OffboardingStage.objects.get(id=stage_id)
|
|
|
|
|
# This wont trigger the save method inside the offboarding employee
|
|
|
|
|
# employees.update(stage_id=stage)
|
|
|
|
|
for employee in employees:
|
|
|
|
|
employee.stage_id = stage
|
|
|
|
|
employee.save()
|
2024-02-21 10:47:13 +05:30
|
|
|
# if stage.type == "archived":
|
|
|
|
|
# Employee.objects.filter(
|
|
|
|
|
# id__in=employees.values_list("employee_id__id", flat=True)
|
|
|
|
|
# ).update(is_active=False)
|
2024-01-23 15:21:53 +05:30
|
|
|
stage_forms = {}
|
|
|
|
|
stage_forms[str(stage.offboarding_id.id)] = StageSelectForm(
|
|
|
|
|
offboarding=stage.offboarding_id
|
|
|
|
|
)
|
2024-01-24 12:27:28 +05:30
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
2024-01-25 15:59:15 +05:30
|
|
|
recipient=User.objects.filter(
|
|
|
|
|
id__in=employees.values_list("employee_id__employee_user_id", flat=True)
|
|
|
|
|
),
|
2024-01-24 12:27:28 +05:30
|
|
|
verb=f"Offboarding stage has been changed",
|
2024-06-27 14:49:28 +05:30
|
|
|
verb_ar=f"تم تغيير مرحلة إنهاء الخدمة",
|
|
|
|
|
verb_de=f"Die Offboarding-Stufe wurde geändert",
|
|
|
|
|
verb_es=f"Se ha cambiado la etapa de offboarding",
|
|
|
|
|
verb_fr=f"L'étape d'offboarding a été changée",
|
|
|
|
|
redirect=reverse("offboarding-pipeline"),
|
2024-01-24 12:27:28 +05:30
|
|
|
icon="information",
|
|
|
|
|
)
|
2024-02-19 15:32:41 +05:30
|
|
|
groups = pipeline_grouper({}, [stage.offboarding_id])
|
|
|
|
|
for item in groups:
|
|
|
|
|
setattr(item["offboarding"], "stages", item["stages"])
|
2024-01-23 15:21:53 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/stage/offboarding_body.html",
|
2024-01-25 15:59:15 +05:30
|
|
|
{
|
2024-02-19 15:32:41 +05:30
|
|
|
"offboarding": groups[0],
|
2024-01-25 15:59:15 +05:30
|
|
|
"stage_forms": stage_forms,
|
|
|
|
|
"response_message": _("stage changed successfully."),
|
2024-03-10 19:37:46 +05:30
|
|
|
"today": datetime.today().date(),
|
2024-01-25 15:59:15 +05:30
|
|
|
},
|
2024-01-23 15:21:53 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-01-25 15:59:15 +05:30
|
|
|
@any_manager_can_enter(
|
|
|
|
|
"offboarding.view_offboardingnote", offboarding_employee_can_enter=True
|
|
|
|
|
)
|
2024-02-20 14:17:21 +05:30
|
|
|
def view_notes(request, employee_id=None):
|
2024-01-23 15:21:53 +05:30
|
|
|
"""
|
|
|
|
|
This method is used to render all the notes of the employee
|
|
|
|
|
"""
|
|
|
|
|
if request.FILES:
|
|
|
|
|
files = request.FILES.getlist("files")
|
|
|
|
|
note_id = request.GET["note_id"]
|
|
|
|
|
note = OffboardingNote.objects.get(id=note_id)
|
|
|
|
|
attachments = []
|
|
|
|
|
for file in files:
|
|
|
|
|
attachment = OffboardingStageMultipleFile()
|
|
|
|
|
attachment.attachment = file
|
|
|
|
|
attachment.save()
|
|
|
|
|
attachments.append(attachment)
|
|
|
|
|
note.attachments.add(*attachments)
|
2024-02-20 14:17:21 +05:30
|
|
|
offboarding_employee_id = employee_id
|
2024-01-23 15:21:53 +05:30
|
|
|
employee = OffboardingEmployee.objects.get(id=offboarding_employee_id)
|
2024-02-20 14:17:21 +05:30
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/note/view_notes.html",
|
|
|
|
|
{
|
|
|
|
|
"employee": employee,
|
|
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-03-21 14:22:49 +05:30
|
|
|
# @any_manager_can_enter("offboarding.add_offboardingnote")
|
2024-01-23 15:21:53 +05:30
|
|
|
def add_note(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to create note for the offboarding employee
|
|
|
|
|
"""
|
|
|
|
|
employee_id = request.GET["employee_id"]
|
|
|
|
|
employee = OffboardingEmployee.objects.get(id=employee_id)
|
|
|
|
|
form = NoteForm()
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
form = NoteForm(request.POST, request.FILES)
|
|
|
|
|
form.instance.employee_id = employee
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
form.save()
|
2024-02-20 14:17:21 +05:30
|
|
|
messages.success(request, _("Note added successfully"))
|
|
|
|
|
return redirect("view-offboarding-note", employee_id=employee.id)
|
2024-01-23 15:21:53 +05:30
|
|
|
return render(
|
2024-02-20 14:17:21 +05:30
|
|
|
request,
|
|
|
|
|
"offboarding/note/view_notes.html",
|
|
|
|
|
{
|
|
|
|
|
"form": form,
|
|
|
|
|
"employee": employee,
|
|
|
|
|
},
|
2024-01-23 15:21:53 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2024-02-20 14:17:21 +05:30
|
|
|
@login_required
|
|
|
|
|
@manager_can_enter(perm="offboarding.delete_offboardingNote")
|
|
|
|
|
def offboarding_note_delete(request, note_id):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to delete the offboarding note
|
|
|
|
|
"""
|
2024-11-19 10:51:44 +05:30
|
|
|
script = ""
|
2024-02-20 14:17:21 +05:30
|
|
|
try:
|
|
|
|
|
note = OffboardingNote.objects.get(id=note_id)
|
|
|
|
|
note.delete()
|
2024-11-19 10:51:44 +05:30
|
|
|
messages.success(request, _("The note has been successfully deleted."))
|
2024-02-20 14:17:21 +05:30
|
|
|
except OffboardingNote.DoesNotExist:
|
|
|
|
|
messages.error(request, _("Note not found."))
|
2024-11-19 10:51:44 +05:30
|
|
|
script = "<script>window.location.reload()</script>"
|
2024-02-20 14:17:21 +05:30
|
|
|
|
2024-11-19 10:51:44 +05:30
|
|
|
return HttpResponse(script)
|
2024-02-20 14:17:21 +05:30
|
|
|
|
|
|
|
|
|
2024-01-23 15:21:53 +05:30
|
|
|
@login_required
|
|
|
|
|
@permission_required("offboarding.delete_offboardingnote")
|
|
|
|
|
def delete_attachment(request):
|
|
|
|
|
"""
|
|
|
|
|
Used to delete attachment
|
|
|
|
|
"""
|
2024-11-19 10:51:44 +05:30
|
|
|
script = ""
|
2024-01-23 15:21:53 +05:30
|
|
|
ids = request.GET.getlist("ids")
|
|
|
|
|
OffboardingStageMultipleFile.objects.filter(id__in=ids).delete()
|
2024-11-19 10:51:44 +05:30
|
|
|
messages.success(request, _("File deleted successfully"))
|
|
|
|
|
return HttpResponse(script)
|
2024-01-23 15:21:53 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@offboarding_or_stage_manager_can_enter("offboarding.add_offboardingtask")
|
|
|
|
|
def add_task(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to add offboarding tasks
|
|
|
|
|
"""
|
|
|
|
|
stage_id = request.GET.get("stage_id")
|
2024-11-26 14:24:55 +05:30
|
|
|
instance_id = eval_validate(str(request.GET.get("instance_id")))
|
2024-01-23 15:21:53 +05:30
|
|
|
employees = OffboardingEmployee.objects.filter(stage_id=stage_id)
|
|
|
|
|
instance = None
|
|
|
|
|
if instance_id:
|
|
|
|
|
instance = OffboardingTask.objects.filter(id=instance_id).first()
|
|
|
|
|
form = TaskForm(
|
|
|
|
|
initial={
|
|
|
|
|
"stage_id": stage_id,
|
|
|
|
|
"tasks_to": employees,
|
|
|
|
|
},
|
|
|
|
|
instance=instance,
|
|
|
|
|
)
|
|
|
|
|
if request.method == "POST":
|
2024-01-25 15:59:15 +05:30
|
|
|
form = TaskForm(
|
|
|
|
|
request.POST,
|
|
|
|
|
instance=instance,
|
|
|
|
|
initial={
|
|
|
|
|
"stage_id": stage_id,
|
|
|
|
|
},
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
if form.is_valid():
|
|
|
|
|
form.save()
|
2024-03-18 12:33:36 +05:30
|
|
|
messages.success(request, _("Task Added"))
|
2024-01-25 15:59:15 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/task/form.html",
|
|
|
|
|
{
|
|
|
|
|
"form": form,
|
|
|
|
|
},
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-01-24 12:27:28 +05:30
|
|
|
@any_manager_can_enter(
|
|
|
|
|
"offboarding.change_employeetask", offboarding_employee_can_enter=True
|
|
|
|
|
)
|
2024-01-25 15:59:15 +05:30
|
|
|
def update_task_status(request, *args, **kwargs):
|
2024-01-23 15:21:53 +05:30
|
|
|
"""
|
|
|
|
|
This method is used to update the assigned tasks status
|
|
|
|
|
"""
|
|
|
|
|
stage_id = request.GET["stage_id"]
|
|
|
|
|
employee_ids = request.GET.getlist("employee_ids")
|
|
|
|
|
task_id = request.GET["task_id"]
|
|
|
|
|
status = request.GET["task_status"]
|
2024-01-24 12:27:28 +05:30
|
|
|
employee_task = EmployeeTask.objects.filter(
|
2024-01-23 15:21:53 +05:30
|
|
|
employee_id__id__in=employee_ids, task_id__id=task_id
|
2024-01-24 12:27:28 +05:30
|
|
|
)
|
|
|
|
|
employee_task.update(status=status)
|
|
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
2024-01-25 15:59:15 +05:30
|
|
|
recipient=User.objects.filter(
|
|
|
|
|
id__in=employee_task.values_list(
|
|
|
|
|
"task_id__managers__employee_user_id", flat=True
|
|
|
|
|
)
|
|
|
|
|
),
|
2024-01-24 12:27:28 +05:30
|
|
|
verb=f"Offboarding Task status has been updated",
|
2024-06-27 14:49:28 +05:30
|
|
|
verb_ar=f"تم تحديث حالة مهمة إنهاء الخدمة",
|
|
|
|
|
verb_de=f"Der Status der Offboarding-Aufgabe wurde aktualisiert",
|
|
|
|
|
verb_es=f"Se ha actualizado el estado de la tarea de offboarding",
|
|
|
|
|
verb_fr=f"Le statut de la tâche d'offboarding a été mis à jour",
|
|
|
|
|
redirect=reverse("offboarding-pipeline"),
|
2024-01-24 12:27:28 +05:30
|
|
|
icon="information",
|
|
|
|
|
)
|
2024-01-23 15:21:53 +05:30
|
|
|
stage = OffboardingStage.objects.get(id=stage_id)
|
|
|
|
|
stage_forms = {}
|
|
|
|
|
stage_forms[str(stage.offboarding_id.id)] = StageSelectForm(
|
|
|
|
|
offboarding=stage.offboarding_id
|
|
|
|
|
)
|
2024-02-19 15:32:41 +05:30
|
|
|
groups = pipeline_grouper({}, [stage.offboarding_id])
|
|
|
|
|
for item in groups:
|
|
|
|
|
setattr(item["offboarding"], "stages", item["stages"])
|
2024-01-23 15:21:53 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/stage/offboarding_body.html",
|
2024-01-25 15:59:15 +05:30
|
|
|
{
|
2024-02-19 15:32:41 +05:30
|
|
|
"offboarding": groups[0],
|
2024-01-25 15:59:15 +05:30
|
|
|
"stage_forms": stage_forms,
|
|
|
|
|
"response_message": _("Task status changed successfully."),
|
|
|
|
|
},
|
2024-01-23 15:21:53 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@any_manager_can_enter("offboarding.add_employeetask")
|
|
|
|
|
def task_assign(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to assign task to employees
|
|
|
|
|
"""
|
|
|
|
|
employee_ids = request.GET.getlist("employee_ids")
|
|
|
|
|
task_id = request.GET["task_id"]
|
|
|
|
|
employees = OffboardingEmployee.objects.filter(id__in=employee_ids)
|
|
|
|
|
task = OffboardingTask.objects.get(id=task_id)
|
|
|
|
|
for employee in employees:
|
2024-03-02 10:23:39 +05:30
|
|
|
try:
|
2024-04-15 13:27:41 +05:30
|
|
|
assigned_task = EmployeeTask()
|
|
|
|
|
assigned_task.employee_id = employee
|
|
|
|
|
assigned_task.task_id = task
|
|
|
|
|
assigned_task.save()
|
2024-03-02 10:23:39 +05:30
|
|
|
except:
|
|
|
|
|
pass
|
2024-01-23 15:21:53 +05:30
|
|
|
offboarding = employees.first().stage_id.offboarding_id
|
|
|
|
|
stage_forms = {}
|
|
|
|
|
stage_forms[str(offboarding.id)] = StageSelectForm(offboarding=offboarding)
|
2024-02-20 14:17:21 +05:30
|
|
|
groups = pipeline_grouper({}, [task.stage_id.offboarding_id])
|
|
|
|
|
for item in groups:
|
|
|
|
|
setattr(item["offboarding"], "stages", item["stages"])
|
2024-01-23 15:21:53 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/stage/offboarding_body.html",
|
2024-02-20 14:17:21 +05:30
|
|
|
{
|
|
|
|
|
"offboarding": groups[0],
|
|
|
|
|
"stage_forms": stage_forms,
|
|
|
|
|
"response_message": _("Task Assigned"),
|
2024-03-10 19:37:46 +05:30
|
|
|
"today": datetime.today().date(),
|
2024-02-20 14:17:21 +05:30
|
|
|
},
|
2024-01-23 15:21:53 +05:30
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-10-16 00:23:55 +05:30
|
|
|
@offboarding_or_stage_manager_can_enter("offboarding.delete_offboardingtask")
|
2024-01-23 15:21:53 +05:30
|
|
|
def delete_task(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to delete the task
|
|
|
|
|
"""
|
|
|
|
|
task_ids = request.GET.getlist("task_ids")
|
2024-05-21 13:05:32 +05:30
|
|
|
tasks = OffboardingTask.objects.filter(id__in=task_ids)
|
|
|
|
|
if tasks:
|
|
|
|
|
tasks.delete()
|
|
|
|
|
messages.success(request, _("Task deleted"))
|
|
|
|
|
else:
|
|
|
|
|
messages.error(request, _("Task not found"))
|
|
|
|
|
return redirect(filter_pipeline)
|
2024-01-24 16:37:52 +05:30
|
|
|
|
2024-01-25 15:59:15 +05:30
|
|
|
|
2024-01-24 16:37:52 +05:30
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-01-25 15:59:15 +05:30
|
|
|
def offboarding_individual_view(request, emp_id):
|
2024-01-24 16:37:52 +05:30
|
|
|
"""
|
|
|
|
|
This method is used to get the individual view of the offboarding employees
|
|
|
|
|
parameters:
|
|
|
|
|
emp_id(int): the id of the offboarding employee
|
|
|
|
|
"""
|
|
|
|
|
employee = OffboardingEmployee.objects.get(id=emp_id)
|
|
|
|
|
tasks = EmployeeTask.objects.filter(employee_id=emp_id)
|
|
|
|
|
stage_forms = {}
|
2024-01-25 15:59:15 +05:30
|
|
|
offboarding_stages = OffboardingStage.objects.filter(
|
|
|
|
|
offboarding_id=employee.stage_id.offboarding_id
|
|
|
|
|
)
|
|
|
|
|
stage_forms[str(employee.stage_id.offboarding_id.id)] = StageSelectForm(
|
|
|
|
|
offboarding=employee.stage_id.offboarding_id
|
|
|
|
|
)
|
2024-01-24 16:37:52 +05:30
|
|
|
context = {
|
2024-01-25 15:59:15 +05:30
|
|
|
"employee": employee,
|
|
|
|
|
"tasks": tasks,
|
2024-01-24 16:37:52 +05:30
|
|
|
"choices": EmployeeTask.statuses,
|
2024-01-25 15:59:15 +05:30
|
|
|
"offboarding_stages": offboarding_stages,
|
|
|
|
|
"stage_forms": stage_forms,
|
2024-01-24 16:37:52 +05:30
|
|
|
}
|
2024-02-27 23:42:00 +05:30
|
|
|
|
|
|
|
|
requests_ids_json = request.GET.get("requests_ids")
|
|
|
|
|
if requests_ids_json:
|
|
|
|
|
requests_ids = json.loads(requests_ids_json)
|
|
|
|
|
previous_id, next_id = closest_numbers(requests_ids, emp_id)
|
|
|
|
|
context["requests_ids"] = requests_ids_json
|
|
|
|
|
context["previous"] = previous_id
|
|
|
|
|
context["next"] = next_id
|
2024-01-25 15:59:15 +05:30
|
|
|
return render(request, "offboarding/pipeline/individual_view.html", context)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@permission_required("offboarding.view_resignationletter")
|
2024-02-26 20:03:58 +05:30
|
|
|
@check_feature_enabled("resignation_request")
|
2024-01-25 15:59:15 +05:30
|
|
|
def request_view(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to view the resignation request
|
|
|
|
|
"""
|
|
|
|
|
defatul_filter = {"status": "requested"}
|
2024-05-21 13:05:32 +05:30
|
|
|
filter_instance = LetterFilter()
|
|
|
|
|
letters = ResignationLetter.objects.all()
|
2024-01-25 15:59:15 +05:30
|
|
|
offboardings = Offboarding.objects.all()
|
|
|
|
|
|
|
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/resignation/requests_view.html",
|
|
|
|
|
{
|
2024-05-21 13:05:32 +05:30
|
|
|
"letters": paginator_qry(letters, request.GET.get("page")),
|
2024-01-25 15:59:15 +05:30
|
|
|
"f": filter_instance,
|
|
|
|
|
"filter_dict": {"status": ["Requested"]},
|
|
|
|
|
"offboardings": offboardings,
|
2024-02-26 20:03:58 +05:30
|
|
|
"gp_fields": LetterReGroup.fields,
|
2024-01-25 15:59:15 +05:30
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-02-26 20:03:58 +05:30
|
|
|
@permission_required("offboarding.view_resignationletter")
|
|
|
|
|
def request_single_view(request, id):
|
|
|
|
|
letter = ResignationLetter.objects.get(id=id)
|
|
|
|
|
context = {
|
|
|
|
|
"letter": letter,
|
|
|
|
|
}
|
|
|
|
|
requests_ids_json = request.GET.get("requests_ids")
|
|
|
|
|
if requests_ids_json:
|
|
|
|
|
requests_ids = json.loads(requests_ids_json)
|
|
|
|
|
previous_id, next_id = closest_numbers(requests_ids, id)
|
|
|
|
|
context["requests_ids"] = requests_ids_json
|
|
|
|
|
context["previous"] = previous_id
|
|
|
|
|
context["next"] = next_id
|
|
|
|
|
return render(
|
|
|
|
|
request,
|
|
|
|
|
"offboarding/resignation/request_single_view.html",
|
|
|
|
|
context,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-02-26 20:03:58 +05:30
|
|
|
@check_feature_enabled("resignation_request")
|
2024-01-25 15:59:15 +05:30
|
|
|
def search_resignation_request(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to search/filter the letter
|
|
|
|
|
"""
|
|
|
|
|
if request.user.has_perm("offboarding.view_resignationletter"):
|
|
|
|
|
letters = LetterFilter(request.GET).qs
|
|
|
|
|
else:
|
|
|
|
|
letters = ResignationLetter.objects.filter(
|
|
|
|
|
employee_id__employee_user_id=request.user
|
|
|
|
|
)
|
2024-02-26 20:03:58 +05:30
|
|
|
field = request.GET.get("field")
|
2024-01-25 15:59:15 +05:30
|
|
|
data_dict = parse_qs(request.GET.urlencode())
|
2024-02-26 20:03:58 +05:30
|
|
|
template = "offboarding/resignation/request_cards.html"
|
|
|
|
|
if request.GET.get("view") == "list":
|
|
|
|
|
template = "offboarding/resignation/request_list.html"
|
|
|
|
|
|
|
|
|
|
if request.GET.get("sortby"):
|
|
|
|
|
letters = sortby(request, letters, "sortby")
|
|
|
|
|
data_dict.pop("sortby")
|
|
|
|
|
|
|
|
|
|
if field != "" and field is not None:
|
|
|
|
|
letters = group_by(letters, field, request.GET.get("page"), "page")
|
|
|
|
|
list_values = [entry["list"] for entry in letters]
|
|
|
|
|
id_list = []
|
|
|
|
|
for value in list_values:
|
|
|
|
|
for instance in value.object_list:
|
|
|
|
|
id_list.append(instance.id)
|
|
|
|
|
|
|
|
|
|
requests_ids = json.dumps(list(id_list))
|
|
|
|
|
template = "offboarding/resignation/group_by.html"
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
letters = paginator_qry(letters, request.GET.get("page"))
|
|
|
|
|
requests_ids = json.dumps([instance.id for instance in letters.object_list])
|
|
|
|
|
|
|
|
|
|
if request.GET.get("view"):
|
|
|
|
|
data_dict.pop("view")
|
2024-03-18 12:33:36 +05:30
|
|
|
pagination = (
|
|
|
|
|
False
|
|
|
|
|
if request.META.get("HTTP_REFERER")
|
|
|
|
|
and request.META.get("HTTP_REFERER").endswith("employee-profile/")
|
|
|
|
|
else True
|
|
|
|
|
)
|
2024-01-25 15:59:15 +05:30
|
|
|
return render(
|
|
|
|
|
request,
|
2024-02-26 20:03:58 +05:30
|
|
|
template,
|
2024-01-25 15:59:15 +05:30
|
|
|
{
|
2024-02-26 20:03:58 +05:30
|
|
|
"letters": letters,
|
2024-01-25 15:59:15 +05:30
|
|
|
"filter_dict": data_dict,
|
|
|
|
|
"pd": request.GET.urlencode(),
|
2024-03-18 12:33:36 +05:30
|
|
|
"pagination": pagination,
|
2024-02-26 20:03:58 +05:30
|
|
|
"requests_ids": requests_ids,
|
|
|
|
|
"field": field,
|
2024-01-25 15:59:15 +05:30
|
|
|
},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-02-26 20:03:58 +05:30
|
|
|
@check_feature_enabled("resignation_request")
|
2024-01-25 15:59:15 +05:30
|
|
|
def delete_resignation_request(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to delete resignation letter instance
|
|
|
|
|
"""
|
|
|
|
|
ids = request.GET.getlist("letter_ids")
|
|
|
|
|
ResignationLetter.objects.filter(id__in=ids).delete()
|
2024-03-18 12:33:36 +05:30
|
|
|
messages.success(request, _("Resignation letter deleted"))
|
2024-04-15 13:27:41 +05:30
|
|
|
if request.META.get("HTTP_REFERER") and request.META.get("HTTP_REFERER").endswith(
|
|
|
|
|
"employee-profile/"
|
|
|
|
|
):
|
2024-03-18 12:33:36 +05:30
|
|
|
return redirect("/employee/employee-profile/")
|
|
|
|
|
else:
|
|
|
|
|
return redirect(request_view)
|
2024-01-25 15:59:15 +05:30
|
|
|
|
2024-01-30 19:10:54 +05:30
|
|
|
|
2024-01-29 11:47:23 +05:30
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-02-26 20:03:58 +05:30
|
|
|
@check_feature_enabled("resignation_request")
|
2024-01-25 15:59:15 +05:30
|
|
|
def create_resignation_request(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to render form to create resignation requests
|
|
|
|
|
"""
|
2024-11-26 14:24:55 +05:30
|
|
|
instance_id = eval_validate(str(request.GET.get("instance_id")))
|
2024-01-25 15:59:15 +05:30
|
|
|
instance = None
|
|
|
|
|
if instance_id:
|
|
|
|
|
instance = ResignationLetter.objects.get(id=instance_id)
|
|
|
|
|
form = ResignationLetterForm(instance=instance)
|
|
|
|
|
if request.method == "POST":
|
|
|
|
|
form = ResignationLetterForm(request.POST, instance=instance)
|
|
|
|
|
if form.is_valid():
|
|
|
|
|
form.save()
|
2024-03-18 12:33:36 +05:30
|
|
|
messages.success(request, _("Resignation letter saved"))
|
2024-01-25 15:59:15 +05:30
|
|
|
return HttpResponse("<script>window.location.reload()</script>")
|
|
|
|
|
return render(request, "offboarding/resignation/form.html", {"form": form})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-02-26 20:03:58 +05:30
|
|
|
@check_feature_enabled("resignation_request")
|
2024-01-25 15:59:15 +05:30
|
|
|
@permission_required("offboarding.change_resignationletter")
|
|
|
|
|
def update_status(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to update the status of resignation letter
|
|
|
|
|
"""
|
|
|
|
|
ids = request.GET.getlist("letter_ids")
|
|
|
|
|
status = request.GET["status"]
|
|
|
|
|
offboarding_id = request.GET.get("offboarding_id")
|
2024-08-05 14:22:44 +05:30
|
|
|
default_notice_end = (
|
|
|
|
|
get_horilla_model_class(
|
|
|
|
|
app_label="payroll", model="payrollgeneralsetting"
|
|
|
|
|
).objects.first()
|
|
|
|
|
if apps.is_installed("payroll")
|
|
|
|
|
else None
|
|
|
|
|
)
|
|
|
|
|
|
2024-01-25 15:59:15 +05:30
|
|
|
if offboarding_id:
|
|
|
|
|
offboarding = Offboarding.objects.get(id=offboarding_id)
|
|
|
|
|
notice_period_starts = request.GET.get("notice_period_starts")
|
|
|
|
|
notice_period_ends = request.GET.get("notice_period_ends")
|
2024-02-20 17:05:43 +05:30
|
|
|
if notice_period_starts:
|
2024-02-28 14:39:57 +05:30
|
|
|
notice_period_starts = datetime.strptime(
|
2024-01-25 15:59:15 +05:30
|
|
|
notice_period_starts, "%Y-%m-%d"
|
|
|
|
|
).date()
|
2024-02-28 14:39:57 +05:30
|
|
|
today = datetime.today()
|
2024-02-20 17:05:43 +05:30
|
|
|
if notice_period_ends:
|
2024-02-28 14:39:57 +05:30
|
|
|
notice_period_ends = datetime.strptime(
|
2024-01-25 15:59:15 +05:30
|
|
|
notice_period_ends, "%Y-%m-%d"
|
|
|
|
|
).date()
|
2024-02-20 17:05:43 +05:30
|
|
|
else:
|
|
|
|
|
notice_period_ends = None
|
2024-03-21 14:22:49 +05:30
|
|
|
if default_notice_end:
|
|
|
|
|
notice_period_ends = notice_period_starts + timedelta(
|
|
|
|
|
days=default_notice_end.notice_period
|
|
|
|
|
)
|
2024-02-20 17:05:43 +05:30
|
|
|
if not notice_period_starts:
|
|
|
|
|
notice_period_starts = today
|
2024-01-25 15:59:15 +05:30
|
|
|
|
|
|
|
|
letters = ResignationLetter.objects.filter(id__in=ids)
|
|
|
|
|
# if use update method instead of save then save method will not trigger
|
|
|
|
|
if status in ["approved", "rejected"]:
|
|
|
|
|
for letter in letters:
|
|
|
|
|
letter.status = status
|
|
|
|
|
letter.save()
|
|
|
|
|
if status == "approved":
|
|
|
|
|
letter.to_offboarding_employee(
|
|
|
|
|
offboarding, notice_period_starts, notice_period_ends
|
|
|
|
|
)
|
|
|
|
|
messages.success(
|
2024-03-18 12:33:36 +05:30
|
|
|
request, f"Resignation request has been {letter.get_status_display()}"
|
2024-01-25 15:59:15 +05:30
|
|
|
)
|
|
|
|
|
notify.send(
|
|
|
|
|
request.user.employee_get,
|
|
|
|
|
recipient=letter.employee_id.employee_user_id,
|
2024-03-18 12:33:36 +05:30
|
|
|
verb=f"Resignation request has been {letter.get_status_display()}",
|
2024-06-27 14:49:28 +05:30
|
|
|
verb_ar=f"تم {letter.get_status_display()} طلب الاستقالة",
|
|
|
|
|
verb_de=f"Der Rücktrittsantrag wurde {letter.get_status_display()}",
|
|
|
|
|
verb_es=f"La solicitud de renuncia ha sido {letter.get_status_display()}",
|
|
|
|
|
verb_fr=f"La demande de démission a été {letter.get_status_display()}",
|
2024-01-25 15:59:15 +05:30
|
|
|
redirect="#",
|
|
|
|
|
icon="information",
|
|
|
|
|
)
|
|
|
|
|
return redirect(request_view)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
2024-05-30 10:04:58 +05:30
|
|
|
@hx_request_required
|
2024-01-30 19:10:54 +05:30
|
|
|
@permission_required("offboarding.add_offboardinggeneralsetting")
|
2024-01-25 15:59:15 +05:30
|
|
|
def enable_resignation_request(request):
|
|
|
|
|
"""
|
|
|
|
|
Enable disable resignation letter feature
|
|
|
|
|
"""
|
|
|
|
|
resignation_request_feature = OffboardingGeneralSetting.objects.first()
|
2024-01-30 19:10:54 +05:30
|
|
|
resignation_request_feature = (
|
|
|
|
|
resignation_request_feature
|
|
|
|
|
if resignation_request_feature
|
|
|
|
|
else OffboardingGeneralSetting()
|
|
|
|
|
)
|
|
|
|
|
resignation_request_feature.resignation_request = (
|
|
|
|
|
"resignation_request" in request.GET.keys()
|
|
|
|
|
)
|
2024-01-25 15:59:15 +05:30
|
|
|
resignation_request_feature.save()
|
2024-12-25 12:02:37 +05:30
|
|
|
message_text = (
|
|
|
|
|
"enabled" if resignation_request_feature.resignation_request else "disabled"
|
|
|
|
|
)
|
|
|
|
|
messages.success(
|
|
|
|
|
request,
|
|
|
|
|
_("Resignation Request setting has been {} successfully.").format(message_text),
|
|
|
|
|
)
|
|
|
|
|
if request.META.get("HTTP_HX_REQUEST"):
|
|
|
|
|
return HttpResponse(
|
|
|
|
|
"""
|
|
|
|
|
<span hx-trigger="load"
|
|
|
|
|
hx-get="/"
|
|
|
|
|
hx-swap="outerHTML"
|
|
|
|
|
hx-select="#offboardingGenericNav"
|
|
|
|
|
hx-target="#offboardingGenericNav">
|
|
|
|
|
</span>
|
|
|
|
|
"""
|
|
|
|
|
)
|
|
|
|
|
return redirect(general_settings)
|
2024-01-30 19:10:54 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
@login_required
|
|
|
|
|
@permission_required("offboarding.add_offboardingemployee")
|
|
|
|
|
def get_notice_period(request):
|
|
|
|
|
"""
|
|
|
|
|
This method is used to get initial details for notice period
|
|
|
|
|
"""
|
|
|
|
|
employee_id = request.GET["employee_id"]
|
2024-08-05 14:22:44 +05:30
|
|
|
if apps.is_installed("payroll"):
|
|
|
|
|
Contract = get_horilla_model_class(app_label="payroll", model="contract")
|
|
|
|
|
employee_contract = (
|
|
|
|
|
(
|
|
|
|
|
Contract.objects.order_by("-id")
|
|
|
|
|
.filter(employee_id__id=employee_id)
|
|
|
|
|
.first()
|
|
|
|
|
)
|
|
|
|
|
if Contract.objects.filter(
|
|
|
|
|
employee_id__id=employee_id, contract_status="active"
|
|
|
|
|
).first()
|
|
|
|
|
else Contract.objects.filter(
|
|
|
|
|
employee_id__id=employee_id, contract_status="active"
|
|
|
|
|
).first()
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
employee_contract = None
|
2024-01-30 19:10:54 +05:30
|
|
|
|
|
|
|
|
response = {
|
|
|
|
|
"notice_period": intial_notice_period(request)["get_initial_notice_period"],
|
|
|
|
|
"unit": "month",
|
2024-02-28 14:39:57 +05:30
|
|
|
"notice_period_starts": str(datetime.today().date()),
|
2024-01-30 19:10:54 +05:30
|
|
|
}
|
|
|
|
|
if employee_contract:
|
2024-03-21 14:22:49 +05:30
|
|
|
response["notice_period"] = employee_contract.notice_period_in_days
|
2024-01-30 19:10:54 +05:30
|
|
|
return JsonResponse(response)
|
2024-02-28 14:39:57 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_notice_period_end_date(request):
|
2024-08-05 14:22:44 +05:30
|
|
|
"""
|
|
|
|
|
Calculates and returns the end date of the notice period based on the provided start date.
|
|
|
|
|
"""
|
2024-02-28 14:39:57 +05:30
|
|
|
start_date = request.GET.get("start_date")
|
2024-03-10 19:37:46 +05:30
|
|
|
start_date = datetime.strptime(start_date, "%Y-%m-%d").date()
|
2024-02-28 14:39:57 +05:30
|
|
|
notice_period = intial_notice_period(request)["get_initial_notice_period"]
|
2024-03-21 14:22:49 +05:30
|
|
|
end_date = start_date + timedelta(days=notice_period)
|
2024-02-28 14:39:57 +05:30
|
|
|
response = {
|
|
|
|
|
"end_date": end_date,
|
|
|
|
|
}
|
2024-03-10 19:37:46 +05:30
|
|
|
return JsonResponse(response)
|