2023-06-06 12:27:41 +05:30
"""
views . py
This module contains the view functions for handling HTTP requests and rendering
responses in your application .
Each view function corresponds to a specific URL route and performs the necessary
actions to handle the request , process data , and generate a response .
This module is part of the recruitment project and is intended to
provide the main entry points for interacting with the application ' s functionality.
"""
2023-12-18 17:20:28 +05:30
2023-09-14 09:55:20 +05:30
from urllib . parse import parse_qs
2023-08-31 16:45:36 +05:30
import json , contextlib , random , secrets
2023-12-21 16:37:23 +05:30
from django import template
2023-12-18 17:20:28 +05:30
from django . core . mail import EmailMessage
from django . template . loader import render_to_string
2023-05-10 15:06:57 +05:30
from django . core . mail import send_mail
2023-08-21 17:28:32 +05:30
from django . contrib . auth . models import User
2023-09-20 14:52:02 +05:30
from django . utils . translation import gettext as __
2023-05-10 15:06:57 +05:30
from django . utils . translation import gettext_lazy as _
from django . shortcuts import render , redirect
from django . contrib . auth import login
2023-08-31 16:45:36 +05:30
from django . http import HttpResponse , JsonResponse , HttpResponseRedirect
2023-05-10 15:06:57 +05:30
from django . contrib import messages
from django . core . paginator import Paginator
2023-06-06 12:27:41 +05:30
from django . views . decorators . http import require_http_methods
2023-08-31 16:45:36 +05:30
from base . models import JobPosition
2023-05-10 15:06:57 +05:30
from notifications . signals import notify
2023-08-31 16:45:36 +05:30
from horilla import settings
2024-02-05 13:53:16 +05:30
from horilla . decorators import login_required , hx_request_required
2023-06-06 12:27:41 +05:30
from horilla . decorators import permission_required
2024-02-03 13:59:47 +05:30
from base . methods import generate_pdf , get_key_instances , get_pagination , sortby
2024-02-15 12:12:23 +05:30
from onboarding . filters import OnboardingCandidateFilter , OnboardingStageFilter
2024-02-06 13:01:09 +05:30
from recruitment . forms import RejectedCandidateForm
2024-02-20 17:05:43 +05:30
from recruitment . models import (
Candidate ,
Recruitment ,
RecruitmentMailTemplate ,
RejectedCandidate ,
)
2024-01-03 10:13:46 +05:30
from recruitment . filters import CandidateFilter , RecruitmentFilter
2023-06-06 12:27:41 +05:30
from employee . models import Employee , EmployeeWorkInformation , EmployeeBankDetails
2023-09-15 11:13:26 +05:30
from django . db . models import ProtectedError
2023-06-06 12:27:41 +05:30
from onboarding . forms import (
OnboardingCandidateForm ,
2024-01-20 12:51:17 +05:30
OnboardingTaskForm ,
2023-06-06 12:27:41 +05:30
UserCreationForm ,
OnboardingViewTaskForm ,
OnboardingViewStageForm ,
EmployeeCreationForm ,
BankDetailsCreationForm ,
)
from onboarding . models import (
OnboardingStage ,
OnboardingTask ,
CandidateStage ,
CandidateTask ,
OnboardingPortal ,
)
from onboarding . decorators import (
all_manager_can_enter ,
stage_manager_can_enter ,
recruitment_manager_can_enter ,
)
2024-02-15 12:12:23 +05:30
from recruitment . pipeline_grouper import group_by_queryset
2023-05-10 15:06:57 +05:30
@login_required
@hx_request_required
2023-06-06 12:27:41 +05:30
@recruitment_manager_can_enter ( " onboarding.add_onboardingstage " )
def stage_creation ( request , obj_id ) :
2023-05-10 15:06:57 +05:30
"""
function used to create onboarding stage .
Parameters :
request ( HttpRequest ) : The HTTP request object .
2023-06-06 12:27:41 +05:30
obj_id : recruitment id
2023-05-10 15:06:57 +05:30
Returns :
GET : return onboarding stage creation form template
POST : return stage save function
"""
form = OnboardingViewStageForm ( )
if request . method == " POST " :
2023-06-06 12:27:41 +05:30
recruitment = Recruitment . objects . get ( id = obj_id )
2023-05-10 15:06:57 +05:30
form = OnboardingViewStageForm ( request . POST )
if form . is_valid ( ) :
2023-06-06 12:27:41 +05:30
return stage_save ( form , recruitment , request , obj_id )
2023-09-27 13:55:34 +05:30
return render ( request , " onboarding/stage_form.html " , { " form " : form , " id " : obj_id } )
2023-05-10 15:06:57 +05:30
2023-06-06 12:27:41 +05:30
def stage_save ( form , recruitment , request , rec_id ) :
2023-05-10 15:06:57 +05:30
"""
function used to save onboarding stage .
Parameters :
request ( HttpRequest ) : The HTTP request object .
recruitment : recruitment object
2023-06-06 12:27:41 +05:30
rec_id : recruitment id
2023-05-10 15:06:57 +05:30
Returns :
2023-06-06 12:27:41 +05:30
GET : return onboarding view
2023-05-10 15:06:57 +05:30
"""
2024-01-20 12:51:17 +05:30
stage = form . save ( commit = False )
stage . recruitment_id = recruitment
2023-05-10 15:06:57 +05:30
stage . save ( )
messages . success ( request , _ ( " New stage created successfully.. " ) )
users = [ employee . employee_user_id for employee in stage . employee_id . all ( ) ]
notify . send (
request . user . employee_get ,
recipient = users ,
2023-05-18 15:05:28 +05:30
verb = " You are chosen as onboarding stage manager " ,
2023-07-26 12:15:01 +05:30
verb_ar = " لقد تم اختيارك كمدير مرحلة التدريب. " ,
verb_de = " Sie wurden als Onboarding-Stage-Manager ausgewählt. " ,
verb_es = " Ha sido seleccionado/a como responsable de etapa de incorporación. " ,
verb_fr = " Vous avez été choisi(e) en tant que responsable de l ' étape d ' intégration. " ,
2023-05-10 15:06:57 +05:30
icon = " people-circle " ,
redirect = " /onboarding/onboarding-view " ,
)
2023-06-06 12:27:41 +05:30
response = render (
2023-09-27 13:55:34 +05:30
request , " onboarding/stage_form.html " , { " form " : form , " id " : rec_id }
2023-06-06 12:27:41 +05:30
)
return HttpResponse (
response . content . decode ( " utf-8 " ) + " <script>location.reload();</script> "
)
2023-05-10 15:06:57 +05:30
@login_required
@hx_request_required
2023-06-06 12:27:41 +05:30
@recruitment_manager_can_enter ( " onboarding.change_onboardingstage " )
2023-05-10 15:06:57 +05:30
def stage_update ( request , stage_id , recruitment_id ) :
"""
function used to update onboarding stage .
Parameters :
request ( HttpRequest ) : The HTTP request object .
stage_id : stage id
2023-06-06 12:27:41 +05:30
recruitment_id : recruitment id
2023-05-10 15:06:57 +05:30
Returns :
GET : return onboarding stage update form template
POST : return onboarding view
"""
onboarding_stage = OnboardingStage . objects . get ( id = stage_id )
form = OnboardingViewStageForm ( instance = onboarding_stage )
2023-06-06 12:27:41 +05:30
if request . method == " POST " :
2023-05-10 15:06:57 +05:30
form = OnboardingViewStageForm ( request . POST , instance = onboarding_stage )
if form . is_valid ( ) :
stage = form . save ( )
2023-06-06 12:27:41 +05:30
messages . info ( request , _ ( " Stage is updated successfully.. " ) )
users = [ employee . employee_user_id for employee in stage . employee_id . all ( ) ]
2023-05-10 15:06:57 +05:30
notify . send (
request . user . employee_get ,
recipient = users ,
2023-05-18 15:05:28 +05:30
verb = " You are chosen as onboarding stage manager " ,
2023-07-26 12:15:01 +05:30
verb_ar = " لقد تم اختيارك كمدير مرحلة التدريب. " ,
verb_de = " Sie wurden als Onboarding-Stage-Manager ausgewählt. " ,
verb_es = " Ha sido seleccionado/a como responsable de etapa de incorporación. " ,
verb_fr = " Vous avez été choisi(e) en tant que responsable de l ' étape d ' intégration. " ,
2023-05-10 15:06:57 +05:30
icon = " people-circle " ,
redirect = " /onboarding/onboarding-view " ,
)
2023-06-06 12:27:41 +05:30
response = render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/stage_update.html " ,
2023-06-06 12:27:41 +05:30
{ " form " : form , " stage_id " : stage_id , " recruitment_id " : recruitment_id } ,
)
return HttpResponse (
response . content . decode ( " utf-8 " ) + " <script>location.reload();</script> "
)
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/stage_update.html " ,
2023-06-06 12:27:41 +05:30
{ " form " : form , " stage_id " : stage_id , " recruitment_id " : recruitment_id } ,
)
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " onboarding.delete_onboardingstage " )
@recruitment_manager_can_enter ( " onboarding.delete_onboardingstage " )
2023-05-10 15:06:57 +05:30
def stage_delete ( request , stage_id ) :
2023-06-06 12:27:41 +05:30
"""
2023-05-10 15:06:57 +05:30
function used to delete onboarding stage .
Parameters :
request ( HttpRequest ) : The HTTP request object .
stage_id : stage id
Returns :
GET : return onboarding view
"""
2023-09-15 11:13:26 +05:30
try :
OnboardingStage . objects . get ( id = stage_id ) . delete ( )
messages . success ( request , _ ( " The stage deleted successfully... " ) )
2023-09-20 14:52:02 +05:30
2023-09-15 11:13:26 +05:30
except OnboardingStage . DoesNotExist :
messages . error ( request , _ ( " Stage not found. " ) )
except ProtectedError :
2023-05-10 15:06:57 +05:30
messages . error ( request , _ ( " There are candidates in this stage... " ) )
2023-08-31 16:45:36 +05:30
return HttpResponseRedirect ( request . META . get ( " HTTP_REFERER " , " / " ) )
2023-05-10 15:06:57 +05:30
@login_required
@hx_request_required
2023-06-06 12:27:41 +05:30
@stage_manager_can_enter ( " onboarding.add_onboardingtask " )
2024-01-20 12:51:17 +05:30
def task_creation ( request ) :
2023-05-10 15:06:57 +05:30
"""
function used to create onboarding task .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return onboarding task creation form template
POST : return onboarding view
"""
2024-01-23 15:29:05 +05:30
stage_id = request . GET . get ( " stage_id " )
2024-01-20 12:51:17 +05:30
stage = OnboardingStage . objects . get ( id = stage_id )
2024-01-23 15:29:05 +05:30
form = OnboardingViewTaskForm ( initial = { " stage_id " : stage } )
2024-01-20 12:51:17 +05:30
2023-05-10 15:06:57 +05:30
if request . method == " POST " :
2024-01-23 15:29:05 +05:30
form_data = OnboardingViewTaskForm ( request . POST , initial = { " stage_id " : stage } )
2023-05-10 15:06:57 +05:30
if form_data . is_valid ( ) :
2024-01-23 15:29:05 +05:30
candidates = form_data . cleaned_data [ " candidates " ]
stage_id = form_data . cleaned_data [ " stage_id " ]
managers = form_data . cleaned_data [ " managers " ]
title = form_data . cleaned_data [ " task_title " ]
onboarding_task = OnboardingTask ( task_title = title , stage_id = stage_id )
2024-01-20 12:51:17 +05:30
onboarding_task . save ( )
onboarding_task . employee_id . set ( managers )
onboarding_task . candidates . set ( candidates )
if candidates :
for cand in candidates :
2024-01-23 15:29:05 +05:30
task = CandidateTask (
candidate_id = cand ,
stage_id = stage_id ,
onboarding_task_id = onboarding_task ,
)
2024-01-20 12:51:17 +05:30
task . save ( )
2024-01-23 15:29:05 +05:30
users = [
manager . employee_user_id
for manager in onboarding_task . employee_id . all ( )
]
2023-05-10 15:06:57 +05:30
notify . send (
request . user . employee_get ,
recipient = users ,
2023-07-26 12:15:01 +05:30
verb = " You are chosen as an onboarding task manager " ,
verb_ar = " لقد تم اختيارك كمدير مهام التدريب. " ,
verb_de = " Sie wurden als Onboarding-Aufgabenmanager ausgewählt. " ,
verb_es = " Ha sido seleccionado/a como responsable de tareas de incorporación. " ,
verb_fr = " Vous avez été choisi(e) en tant que responsable des tâches d ' intégration. " ,
2023-05-10 15:06:57 +05:30
icon = " people-circle " ,
redirect = " /onboarding/onboarding-view " ,
)
2023-06-06 12:27:41 +05:30
response = render (
2024-01-23 15:29:05 +05:30
request ,
" onboarding/task_form.html " ,
{ " form " : form , " stage_id " : stage_id } ,
2023-06-06 12:27:41 +05:30
)
2024-01-20 12:51:17 +05:30
messages . success ( request , _ ( " New task created successfully... " ) )
2024-01-23 15:29:05 +05:30
2023-06-06 12:27:41 +05:30
return HttpResponse (
response . content . decode ( " utf-8 " ) + " <script>location.reload();</script> "
)
2024-01-23 15:29:05 +05:30
return render (
request , " onboarding/task_form.html " , { " form " : form , " stage_id " : stage_id }
)
2023-05-10 15:06:57 +05:30
@login_required
@hx_request_required
2023-06-06 12:27:41 +05:30
@stage_manager_can_enter ( " onboarding.change_onboardingtask " )
2024-01-23 15:29:05 +05:30
def task_update (
request ,
task_id ,
) :
2023-05-10 15:06:57 +05:30
"""
function used to update onboarding task .
Parameters :
request ( HttpRequest ) : The HTTP request object .
task_id : task id
Returns :
GET : return onboarding task update form template
POST : return onboarding view
"""
onboarding_task = OnboardingTask . objects . get ( id = task_id )
2023-06-06 12:27:41 +05:30
if request . method == " POST " :
2024-01-20 12:51:17 +05:30
form = OnboardingTaskForm ( request . POST , instance = onboarding_task )
2023-05-10 15:06:57 +05:30
if form . is_valid ( ) :
task = form . save ( )
2024-01-20 12:51:17 +05:30
for cand_task in onboarding_task . candidatetask_set . all ( ) :
if cand_task . candidate_id not in task . candidates . all ( ) :
cand_task . delete ( )
else :
cand_task . stage_id = task . stage_id
2023-06-06 12:27:41 +05:30
messages . info ( request , _ ( " Task updated successfully.. " ) )
users = [ employee . employee_user_id for employee in task . employee_id . all ( ) ]
2023-05-10 15:06:57 +05:30
notify . send (
request . user . employee_get ,
recipient = users ,
2023-07-26 12:15:01 +05:30
verb = " You are chosen as an onboarding task manager " ,
verb_ar = " لقد تم اختيارك كمدير مهام التدريب. " ,
verb_de = " Sie wurden als Onboarding-Aufgabenmanager ausgewählt. " ,
verb_es = " Ha sido seleccionado/a como responsable de tareas de incorporación. " ,
verb_fr = " Vous avez été choisi(e) en tant que responsable des tâches d ' intégration. " ,
2023-05-10 15:06:57 +05:30
icon = " people-circle " ,
redirect = " /onboarding/onboarding-view " ,
)
2023-06-06 12:27:41 +05:30
response = render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/task_update.html " ,
2024-01-23 15:29:05 +05:30
{
" form " : form ,
" task_id " : task_id ,
} ,
2023-06-06 12:27:41 +05:30
)
return HttpResponse (
response . content . decode ( " utf-8 " ) + " <script>location.reload();</script> "
)
2024-01-20 12:51:17 +05:30
form = OnboardingTaskForm ( instance = onboarding_task )
2023-06-06 12:27:41 +05:30
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/task_update.html " ,
2024-01-23 15:29:05 +05:30
{
" form " : form ,
" task_id " : task_id ,
} ,
2023-06-06 12:27:41 +05:30
)
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " onboarding.delete_onboardingtask " )
@stage_manager_can_enter ( " onboarding.delete_onboardingtask " )
2023-05-10 15:06:57 +05:30
def task_delete ( request , task_id ) :
"""
function used to delete onboarding task .
Parameters :
request ( HttpRequest ) : The HTTP request object .
task_id : task id
Returns :
GET : return onboarding view
"""
2023-09-15 11:13:26 +05:30
try :
OnboardingTask . objects . get ( id = task_id ) . delete ( )
messages . success ( request , _ ( " The task deleted successfully... " ) )
except OnboardingTask . DoesNotExist :
messages . error ( request , _ ( " Task not found. " ) )
except ProtectedError :
2023-09-20 14:52:02 +05:30
messages . error (
request ,
_ (
" You cannot delete this task because some candidates are associated with it. "
) ,
)
2023-05-10 15:06:57 +05:30
return redirect ( onboarding_view )
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " recruitment.add_candidate " )
2023-05-10 15:06:57 +05:30
def candidate_creation ( request ) :
"""
function used to create hired candidates .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return candidate creation form template
POST : return candidate view
"""
form = OnboardingCandidateForm ( )
2023-06-06 12:27:41 +05:30
if request . method == " POST " :
2023-05-10 15:06:57 +05:30
form = OnboardingCandidateForm ( request . POST , request . FILES )
if form . is_valid ( ) :
candidate = form . save ( )
candidate . hired = True
candidate . save ( )
2023-06-06 12:27:41 +05:30
messages . success ( request , _ ( " New candidate created successfully.. " ) )
2023-05-10 15:06:57 +05:30
return redirect ( candidates_view )
2023-09-27 13:55:34 +05:30
return render ( request , " onboarding/candidate_creation.html " , { " form " : form } )
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " recruitment.change_candidate " )
def candidate_update ( request , obj_id ) :
2023-05-10 15:06:57 +05:30
"""
function used to update hired candidates .
Parameters :
request ( HttpRequest ) : The HTTP request object .
2023-06-06 12:27:41 +05:30
obj_id : recruitment id
2023-05-10 15:06:57 +05:30
Returns :
GET : return candidate update form template
POST : return candidate view
"""
2023-06-06 12:27:41 +05:30
candidate = Candidate . objects . get ( id = obj_id )
2023-05-10 15:06:57 +05:30
form = OnboardingCandidateForm ( instance = candidate )
2023-06-06 12:27:41 +05:30
if request . method == " POST " :
form = OnboardingCandidateForm ( request . POST , request . FILES , instance = candidate )
2023-05-10 15:06:57 +05:30
if form . is_valid ( ) :
form . save ( )
2023-06-06 12:27:41 +05:30
messages . info ( request , _ ( " Candidate detail is updated successfully.. " ) )
2023-05-10 15:06:57 +05:30
return redirect ( candidates_view )
2023-09-27 13:55:34 +05:30
return render ( request , " onboarding/candidate_update.html " , { " form " : form } )
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " recruitment.delete_candidate " )
def candidate_delete ( request , obj_id ) :
2023-05-10 15:06:57 +05:30
"""
function used to delete hired candidates .
Parameters :
request ( HttpRequest ) : The HTTP request object .
2023-06-06 12:27:41 +05:30
obj_id : recruitment id
2023-05-10 15:06:57 +05:30
Returns :
GET : return candidate view
"""
2023-09-15 11:13:26 +05:30
try :
Candidate . objects . get ( id = obj_id ) . delete ( )
messages . success ( request , _ ( " Candidate deleted successfully.. " ) )
except Candidate . DoesNotExist :
messages . error ( request , _ ( " Candidate not found. " ) )
2023-09-20 14:52:02 +05:30
except ProtectedError as e :
models_verbose_name_sets = set ( )
for obj in e . protected_objects :
models_verbose_name_sets . add ( __ ( obj . _meta . verbose_name ) )
models_verbose_name_str = ( " , " ) . join ( models_verbose_name_sets )
messages . error (
request ,
_ (
" You cannot delete this candidate. The candidate is included in the {} " . format (
models_verbose_name_str
)
) ,
)
2023-05-10 15:06:57 +05:30
return redirect ( candidates_view )
2023-11-08 16:12:02 +05:30
2023-10-19 12:37:23 +05:30
@login_required
2024-02-05 13:53:16 +05:30
@all_manager_can_enter ( " onboarding.view_candidatestage " )
2023-11-08 16:12:02 +05:30
def candidates_single_view ( request , id , * * kwargs ) :
2023-11-06 12:04:59 +05:30
"""
2023-11-08 16:12:02 +05:30
Candidate individual view for the onboarding candidates
2023-11-06 12:04:59 +05:30
"""
candidate = Candidate . objects . get ( id = id )
2023-10-19 12:37:23 +05:30
if not CandidateStage . objects . filter ( candidate_id = candidate ) . exists ( ) :
try :
onboarding_stage = OnboardingStage . objects . filter (
recruitment_id = candidate . recruitment_id
) . order_by ( " sequence " ) [ 0 ]
CandidateStage (
candidate_id = candidate , onboarding_stage_id = onboarding_stage
) . save ( )
except Exception :
messages . error (
request ,
_ ( " %(recruitment)s has no stage.. " )
% { " recruitment " : candidate . recruitment_id } ,
)
if tasks := OnboardingTask . objects . filter (
recruitment_id = candidate . recruitment_id
) :
for task in tasks :
if not CandidateTask . objects . filter (
candidate_id = candidate , onboarding_task_id = task
) . exists ( ) :
CandidateTask (
candidate_id = candidate , onboarding_task_id = task
) . save ( )
2023-11-08 16:12:02 +05:30
recruitment = candidate . recruitment_id
2023-10-19 12:37:23 +05:30
choices = CandidateTask . choice
context = {
2023-11-08 16:12:02 +05:30
" recruitment " : recruitment ,
" choices " : choices ,
" candidate " : candidate ,
2024-01-23 15:29:05 +05:30
" single_view " : True ,
2023-11-08 16:12:02 +05:30
}
2023-10-19 12:37:23 +05:30
return render (
request ,
" onboarding/single_view.html " ,
context ,
)
2023-05-10 15:06:57 +05:30
def paginator_qry ( qryset , page_number ) :
"""
function used to paginate query set
"""
2024-01-20 16:37:12 +05:30
paginator = Paginator ( qryset , get_pagination ( ) )
2023-05-10 15:06:57 +05:30
qryset = paginator . get_page ( page_number )
return qryset
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " candidate.view_candidate " )
2023-05-10 15:06:57 +05:30
def candidates_view ( request ) :
"""
function used to view hired candidates .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return candidate view template
"""
2023-12-19 13:02:15 +05:30
queryset = Candidate . objects . filter (
hired = True ,
recruitment_id__closed = False ,
)
2023-06-06 12:27:41 +05:30
candidate_filter_obj = CandidateFilter ( )
2023-09-12 11:59:58 +05:30
previous_data = request . GET . urlencode ( )
2023-06-06 12:27:41 +05:30
page_number = request . GET . get ( " page " )
2023-05-10 15:06:57 +05:30
page_obj = paginator_qry ( queryset , page_number )
2023-12-21 16:37:23 +05:30
mail_templates = RecruitmentMailTemplate . objects . all ( )
2023-06-06 12:27:41 +05:30
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/candidates_view.html " ,
2023-06-06 12:27:41 +05:30
{
" candidates " : page_obj ,
" form " : candidate_filter_obj . form ,
" pd " : previous_data ,
2023-12-21 16:37:23 +05:30
" mail_templates " : mail_templates ,
" hired_candidates " : queryset ,
2023-06-06 12:27:41 +05:30
} ,
)
2023-09-11 15:37:32 +05:30
2023-08-31 16:45:36 +05:30
@login_required
@permission_required ( perm = " recruitment.view_candidate " )
def hired_candidate_view ( request ) :
2023-09-12 11:59:58 +05:30
previous_data = request . GET . urlencode ( )
2023-12-19 13:02:15 +05:30
candidates = Candidate . objects . filter (
hired = True ,
recruitment_id__closed = False ,
)
2023-08-31 16:45:36 +05:30
if request . GET . get ( " is_active " ) is None :
candidates = candidates . filter ( is_active = True )
candidates = CandidateFilter ( request . GET , queryset = candidates ) . qs
return render (
request ,
" candidate/candidate_card.html " ,
{
" data " : paginator_qry ( candidates , request . GET . get ( " page " ) ) ,
" pd " : previous_data ,
} ,
)
2023-05-10 15:06:57 +05:30
2023-09-11 15:37:32 +05:30
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@permission_required ( " candidate.view_candidate " )
2023-05-10 15:06:57 +05:30
def candidate_filter ( request ) :
"""
function used to filter hired candidates .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
2023-06-06 12:27:41 +05:30
GET : return candidate view template
2023-05-10 15:06:57 +05:30
"""
2023-12-19 13:02:15 +05:30
queryset = Candidate . objects . filter (
hired = True ,
recruitment_id__closed = False ,
)
2024-02-03 13:59:47 +05:30
candidates = CandidateFilter ( request . GET , queryset ) . qs
2023-09-12 11:59:58 +05:30
previous_data = request . GET . urlencode ( )
2023-06-06 12:27:41 +05:30
page_number = request . GET . get ( " page " )
2023-09-14 09:55:20 +05:30
data_dict = parse_qs ( previous_data )
get_key_instances ( Candidate , data_dict )
2024-02-03 13:59:47 +05:30
candidates = sortby ( request , candidates , " orderby " )
page_obj = paginator_qry ( candidates , page_number )
2023-06-06 12:27:41 +05:30
return render (
request ,
" onboarding/candidates.html " ,
2023-09-14 09:55:20 +05:30
{ " candidates " : page_obj , " pd " : previous_data , " filter_dict " : data_dict } ,
2023-06-06 12:27:41 +05:30
)
2023-05-10 15:06:57 +05:30
@login_required
2023-12-19 13:02:15 +05:30
@all_manager_can_enter ( " recruitment.view_recruitment " )
2023-05-10 15:06:57 +05:30
def email_send ( request ) :
"""
function used to send onboarding portal for hired candidates .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
2023-08-31 16:45:36 +05:30
GET : return json response
2023-05-10 15:06:57 +05:30
"""
2023-12-18 17:20:28 +05:30
host = request . get_host ( )
protocol = " https " if request . is_secure ( ) else " http "
2023-12-21 16:37:23 +05:30
candidates = request . POST . getlist ( " ids " )
other_attachments = request . FILES . getlist ( " other_attachments " )
template_attachment_ids = request . POST . getlist ( " template_attachment_ids " )
if not candidates :
messages . info ( request , " Please choose chandidates " )
return HttpResponse ( " <script>window.location.reload()</script> " )
bodys = list (
RecruitmentMailTemplate . objects . filter (
id__in = template_attachment_ids
) . values_list ( " body " , flat = True )
)
if not candidates :
messages . info ( request , " Please choose candidates " )
attachments_other = [ ]
for file in other_attachments :
attachments_other . append ( ( file . name , file . read ( ) , file . content_type ) )
file . close ( )
2023-12-19 13:02:15 +05:30
for cand_id in candidates :
2023-12-21 16:37:23 +05:30
attachments = list ( set ( attachments_other ) | set ( [ ] ) )
2023-06-06 12:27:41 +05:30
candidate = Candidate . objects . get ( id = cand_id )
2023-12-21 16:37:23 +05:30
for html in bodys :
# due to not having solid template we first need to pass the context
template_bdy = template . Template ( html )
context = template . Context (
{ " instance " : candidate , " self " : request . user . employee_get }
)
render_bdy = template_bdy . render ( context )
attachments . append (
(
" Document " ,
generate_pdf ( render_bdy , { } , path = False , title = " Document " ) . content ,
" application/pdf " ,
)
)
2023-12-19 13:02:15 +05:30
token = secrets . token_hex ( 15 )
existing_portal = OnboardingPortal . objects . filter ( candidate_id = candidate )
if existing_portal . exists ( ) :
new_portal = existing_portal . first ( )
new_portal . token = token
new_portal . used = False
new_portal . save ( )
else :
OnboardingPortal ( candidate_id = candidate , token = token ) . save ( )
html_message = render_to_string (
" onboarding/mail_templates/default.html " ,
{
" portal " : f " { protocol } :// { host } /onboarding/user-creation/ { token } " ,
" instance " : candidate ,
" host " : host ,
" protocol " : protocol ,
} ,
)
email = EmailMessage (
f " Hello { candidate . name } , Congratulations on your selection! " ,
html_message ,
settings . EMAIL_HOST_USER ,
[ candidate . email ] ,
)
email . content_subtype = " html "
2023-12-21 16:37:23 +05:30
email . attachments = attachments
2023-12-19 13:02:15 +05:30
try :
email . send ( )
# to check ajax or not
2023-12-21 16:37:23 +05:30
messages . success ( request , " Portal link sent to the candidate " )
2023-12-19 13:02:15 +05:30
except :
messages . error ( request , f " Mail not send to { candidate . name } " )
candidate . start_onboard = True
candidate . save ( )
2024-02-03 13:59:47 +05:30
try :
onboarding_candidate = CandidateStage ( )
onboarding_candidate . onboarding_stage_id = (
candidate . recruitment_id . onboarding_stage . first ( )
)
onboarding_candidate . candidate_id = candidate
onboarding_candidate . save ( )
except :
messages . error ( request , " Something went wrong. " )
2023-12-21 16:37:23 +05:30
return HttpResponse ( " <script>window.location.reload()</script> " )
2023-05-10 15:06:57 +05:30
2024-02-20 17:05:43 +05:30
def onboarding_query_grouper ( request , queryset ) :
2024-02-15 12:12:23 +05:30
"""
This method is used to make group of the onboarding records
"""
groups = [ ]
for rec in queryset :
2024-02-20 17:05:43 +05:30
stages = OnboardingStageFilter (
request . GET , queryset = rec . onboarding_stage . all ( )
) . qs . order_by ( " sequence " )
2024-02-15 12:12:23 +05:30
all_stages_grouper = [ ]
data = { " recruitment " : rec , " stages " : [ ] }
2024-02-20 17:05:43 +05:30
for stage in stages :
all_stages_grouper . append ( { " grouper " : stage , " list " : [ ] } )
2024-02-15 12:12:23 +05:30
stage_candidates = OnboardingCandidateFilter (
request . GET ,
2024-02-20 17:05:43 +05:30
stage . candidate . filter (
2024-02-15 12:12:23 +05:30
candidate_id__is_active = True ,
) ,
2024-02-20 17:05:43 +05:30
) . qs . order_by ( " sequence " )
2024-02-15 12:12:23 +05:30
page_name = " page " + stage . stage_title + str ( rec . id )
grouper = group_by_queryset (
stage_candidates ,
" onboarding_stage_id " ,
request . GET . get ( page_name ) ,
page_name ,
) . object_list
data [ " stages " ] = data [ " stages " ] + grouper
2024-02-20 17:05:43 +05:30
ordered_data = [ ]
# 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
2024-02-22 22:57:56 +05:30
break
2024-02-20 17:05:43 +05:30
if not found :
ordered_data . append ( { " grouper " : stage } )
data = {
" recruitment " : rec ,
" stages " : ordered_data ,
}
2024-02-15 12:12:23 +05:30
groups . append ( data )
return groups
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@all_manager_can_enter ( " onboarding.view_candidatestage " )
2023-05-10 15:06:57 +05:30
def onboarding_view ( request ) :
"""
function used to view onboarding main view .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return onboarding view template
"""
2024-02-15 12:12:23 +05:30
filter_obj = RecruitmentFilter ( request . GET )
# is active filteration not providing on pipeline
recruitments = filter_obj . qs . filter ( is_active = True )
2024-02-20 17:05:43 +05:30
2024-02-15 12:12:23 +05:30
status = request . GET . get ( " closed " )
2023-08-31 16:45:36 +05:30
2023-05-10 15:06:57 +05:30
onboarding_stages = OnboardingStage . objects . all ( )
2023-08-31 16:45:36 +05:30
choices = CandidateTask . choice
2024-01-03 10:13:46 +05:30
previous_data = request . GET . urlencode ( )
2024-02-20 17:05:43 +05:30
paginator = Paginator ( recruitments . order_by ( " id " ) , 4 )
2024-01-03 10:13:46 +05:30
page_number = request . GET . get ( " page " )
page_obj = paginator . get_page ( page_number )
2024-02-20 17:05:43 +05:30
groups = onboarding_query_grouper ( request , page_obj )
2024-02-15 12:12:23 +05:30
for item in groups :
setattr ( item [ " recruitment " ] , " stages " , item [ " stages " ] )
filter_dict = parse_qs ( request . GET . urlencode ( ) )
for key , val in filter_dict . copy ( ) . items ( ) :
if val [ 0 ] == " unknown " or key == " view " :
del filter_dict [ key ]
2023-06-06 12:27:41 +05:30
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/onboarding_view.html " ,
2023-06-06 12:27:41 +05:30
{
2024-01-03 10:13:46 +05:30
" recruitments " : page_obj ,
2024-02-15 12:12:23 +05:30
" rec_filter_obj " : filter_obj ,
2023-06-06 12:27:41 +05:30
" onboarding_stages " : onboarding_stages ,
" choices " : choices ,
2024-02-15 12:12:23 +05:30
" filter_dict " : filter_dict ,
2023-09-11 15:37:32 +05:30
" status " : status ,
2024-01-03 10:13:46 +05:30
" pd " : previous_data ,
2023-06-06 12:27:41 +05:30
} ,
)
2023-05-10 15:06:57 +05:30
2023-08-31 16:45:36 +05:30
@login_required
@all_manager_can_enter ( " onboarding.view_candidatestage " )
def kanban_view ( request ) :
2024-02-15 12:12:23 +05:30
filter_obj = RecruitmentFilter ( request . GET )
# is active filteration not providing on pipeline
recruitments = filter_obj . qs . filter ( is_active = True )
2024-02-20 17:05:43 +05:30
2024-02-15 12:12:23 +05:30
status = request . GET . get ( " closed " )
2024-02-22 13:55:54 +05:30
2023-08-31 16:45:36 +05:30
onboarding_stages = OnboardingStage . objects . all ( )
choices = CandidateTask . choice
stage_form = OnboardingViewStageForm ( )
2024-01-03 10:13:46 +05:30
previous_data = request . GET . urlencode ( )
2024-01-23 15:29:05 +05:30
filter_obj = RecruitmentFilter ( request . GET , queryset = recruitments )
2024-02-15 12:12:23 +05:30
paginator = Paginator ( recruitments , 4 )
2024-01-03 10:13:46 +05:30
page_number = request . GET . get ( " page " )
page_obj = paginator . get_page ( page_number )
2024-02-20 17:05:43 +05:30
groups = onboarding_query_grouper ( request , page_obj )
2024-02-15 12:12:23 +05:30
for item in groups :
setattr ( item [ " recruitment " ] , " stages " , item [ " stages " ] )
filter_dict = parse_qs ( request . GET . urlencode ( ) )
for key , val in filter_dict . copy ( ) . items ( ) :
if val [ 0 ] == " unknown " or key == " view " :
del filter_dict [ key ]
2024-01-03 10:13:46 +05:30
2023-08-31 16:45:36 +05:30
return render (
request ,
" onboarding/kanban/kanban.html " ,
{
2024-01-03 10:13:46 +05:30
" recruitments " : page_obj ,
2024-02-15 12:12:23 +05:30
" rec_filter_obj " : filter_obj ,
2023-08-31 16:45:36 +05:30
" onboarding_stages " : onboarding_stages ,
" choices " : choices ,
2024-02-15 12:12:23 +05:30
" filter_dict " : filter_dict ,
2023-08-31 16:45:36 +05:30
" stage_form " : stage_form ,
2023-09-11 15:37:32 +05:30
" status " : status ,
" choices " : choices ,
2024-01-23 15:29:05 +05:30
" pd " : previous_data ,
2024-02-15 12:12:23 +05:30
" card " : True ,
2023-08-31 16:45:36 +05:30
} ,
2023-09-11 15:37:32 +05:30
)
2023-08-31 16:45:36 +05:30
2023-05-10 15:06:57 +05:30
def user_creation ( request , token ) :
"""
function used to create user account in onboarding portal .
Parameters :
request ( HttpRequest ) : The HTTP request object .
token : random generated onboarding portal token
Returns :
GET : return user creation form template
POST : return user_save function
"""
try :
onboarding_portal = OnboardingPortal . objects . get ( token = token )
2023-08-21 17:28:32 +05:30
candidate = onboarding_portal . candidate_id
user = User . objects . filter ( username = candidate . email ) . first ( )
2023-09-11 15:37:32 +05:30
2023-08-21 17:28:32 +05:30
form = UserCreationForm ( instance = user )
2023-09-11 15:37:32 +05:30
if (
not onboarding_portal
or onboarding_portal . used is True
and request . user . is_anonymous
) :
2023-12-19 13:02:15 +05:30
return render ( request , " 404.html " )
2023-05-10 15:06:57 +05:30
try :
2023-06-06 12:27:41 +05:30
if request . method == " POST " :
2023-08-21 17:28:32 +05:30
form = UserCreationForm ( request . POST , instance = user )
2023-05-10 15:06:57 +05:30
if form . is_valid ( ) :
return user_save ( form , onboarding_portal , request , token )
2023-06-06 12:27:41 +05:30
except Exception :
messages . error ( request , _ ( " User with email-id already exists.. " ) )
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/user_creation.html " ,
2023-06-06 12:27:41 +05:30
{
" form " : form ,
" company " : onboarding_portal . candidate_id . recruitment_id . company_id ,
} ,
)
except Exception as error :
return HttpResponse ( error )
2023-05-10 15:06:57 +05:30
def user_save ( form , onboarding_portal , request , token ) :
"""
function used to save user .
Parameters :
request ( HttpRequest ) : The HTTP request object .
onboarding_portal : onboarding portal object
token : random generated onboarding portal token
Returns :
GET : return profile view
"""
user = form . save ( commit = False )
user . username = onboarding_portal . candidate_id . email
user . save ( )
onboarding_portal . used = True
onboarding_portal . save ( )
login ( request , user )
2023-08-21 17:28:32 +05:30
onboarding_portal . count = 1
2023-05-10 15:06:57 +05:30
messages . success ( request , _ ( " Account created successfully.. " ) )
2023-06-06 12:27:41 +05:30
return redirect ( " profile-view " , token )
2023-05-10 15:06:57 +05:30
def profile_view ( request , token ) :
"""
function used to view user profile .
Parameters :
request ( HttpRequest ) : The HTTP request object .
token : random generated onboarding portal token
Returns :
GET : return user profile template
POST : update profile image of the user
"""
2023-08-21 17:28:32 +05:30
onboarding_portal = OnboardingPortal . objects . filter ( token = token ) . first ( )
if onboarding_portal is None :
return HttpResponse ( " Denied " )
candidate = onboarding_portal . candidate_id
2023-09-11 15:37:32 +05:30
user = User . objects . get ( username = candidate . email )
2023-06-06 12:27:41 +05:30
if request . method == " POST " :
profile = request . FILES . get ( " profile " )
2023-05-10 15:06:57 +05:30
if profile is not None :
candidate . profile = profile
candidate . save ( )
2023-08-21 17:28:32 +05:30
onboarding_portal . count = 2
2023-06-06 12:27:41 +05:30
messages . success ( request , _ ( " Profile picture updated successfully.. " ) )
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/profile_view.html " ,
2023-06-06 12:27:41 +05:30
{
" candidate " : candidate ,
" token " : token ,
" company " : candidate . recruitment_id . company_id ,
} ,
)
2023-05-10 15:06:57 +05:30
def employee_creation ( request , token ) :
"""
function used to create employee .
Parameters :
request ( HttpRequest ) : The HTTP request object .
token : random generated onboarding portal token .
Returns :
GET : return employee creation profile template .
POST : return employee bank detail creation template .
"""
2023-08-21 17:28:32 +05:30
onboarding_portal = OnboardingPortal . objects . filter ( token = token ) . first ( )
if onboarding_portal is None :
return HttpResponse ( " Denied. " )
candidate = onboarding_portal . candidate_id
initial = {
" employee_first_name " : candidate . name ,
" phone " : candidate . mobile ,
" address " : candidate . address ,
" dob " : candidate . dob ,
}
user = User . objects . filter ( username = candidate . email ) . first ( )
if Employee . objects . filter ( employee_user_id = user ) . first ( ) is not None :
2023-09-11 15:37:32 +05:30
initial = Employee . objects . filter ( employee_user_id = user ) . first ( ) . __dict__
2023-08-21 17:28:32 +05:30
2023-06-06 12:27:41 +05:30
form = EmployeeCreationForm (
2023-08-21 17:28:32 +05:30
initial ,
2023-06-06 12:27:41 +05:30
)
2023-08-21 17:28:32 +05:30
form . errors . clear ( )
if request . method == " POST " :
instance = Employee . objects . filter ( employee_user_id = user ) . first ( )
form_data = EmployeeCreationForm (
request . POST ,
instance = instance ,
2023-06-06 12:27:41 +05:30
)
2023-08-21 17:28:32 +05:30
if form_data . is_valid ( ) :
employee_personal_info = form_data . save ( commit = False )
employee_personal_info . employee_user_id = user
employee_personal_info . email = candidate . email
employee_personal_info . employee_profile = candidate . profile
employee_personal_info . save ( )
2023-10-17 16:12:08 +05:30
job_position = onboarding_portal . candidate_id . job_position_id
2023-12-19 13:02:15 +05:30
existing_work_info = EmployeeWorkInformation . objects . filter (
2023-08-21 17:28:32 +05:30
employee_id = employee_personal_info ,
2023-12-19 13:02:15 +05:30
) . first ( )
work_info = (
existing_work_info if existing_work_info else EmployeeWorkInformation ( )
2023-08-21 17:28:32 +05:30
)
2023-12-19 13:02:15 +05:30
work_info . employee_id = employee_personal_info
work_info . job_position_id = job_position
work_info . date_joining = candidate . joining_date
work_info . save ( )
2023-09-11 15:37:32 +05:30
onboarding_portal . count = 3
2023-08-21 17:28:32 +05:30
onboarding_portal . save ( )
messages . success (
request , _ ( " Employee personal details created successfully.. " )
)
return redirect ( " employee-bank-details " , token )
onboarding_portal . count + = 1
onboarding_portal . save ( )
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/employee_creation.html " ,
2023-08-21 17:28:32 +05:30
{ " form " : form , " employee " : candidate . recruitment_id . company_id } ,
)
2023-05-10 15:06:57 +05:30
def employee_bank_details ( request , token ) :
"""
function used to create employee bank details creation .
Parameters :
request ( HttpRequest ) : The HTTP request object .
token : random generated onboarding portal token
Returns :
GET : return bank details creation template
POST : return employee_bank_details_save function
"""
onboarding_portal = OnboardingPortal . objects . get ( token = token )
2023-08-21 17:28:32 +05:30
user = User . objects . filter ( username = onboarding_portal . candidate_id . email ) . first ( )
2023-09-11 15:37:32 +05:30
employee = Employee . objects . filter ( employee_user_id = user ) . first ( )
form = BankDetailsCreationForm (
instance = EmployeeBankDetails . objects . filter ( employee_id = employee ) . first ( )
)
2023-08-21 17:28:32 +05:30
if request . method == " POST " :
2023-09-11 15:37:32 +05:30
form = BankDetailsCreationForm (
request . POST ,
instance = EmployeeBankDetails . objects . filter ( employee_id = employee ) . first ( ) ,
)
2023-08-21 17:28:32 +05:30
if form . is_valid ( ) :
return employee_bank_details_save ( form , request , onboarding_portal )
return redirect ( welcome_aboard )
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/employee_bank_details.html " ,
2023-08-21 17:28:32 +05:30
{
" form " : form ,
" company " : onboarding_portal . candidate_id . recruitment_id . company_id ,
} ,
)
2023-05-10 15:06:57 +05:30
def employee_bank_details_save ( form , request , onboarding_portal ) :
"""
function used to save employee bank details .
Parameters :
request ( HttpRequest ) : The HTTP request object .
form : Form object .
onboarding_portal : Onboarding portal object .
Returns :
GET : return welcome onboard view
"""
employee_bank_detail = form . save ( commit = False )
employee_bank_detail . employee_id = Employee . objects . get (
2023-06-06 12:27:41 +05:30
employee_user_id = request . user
)
2023-05-10 15:06:57 +05:30
employee_bank_detail . save ( )
2023-08-21 17:28:32 +05:30
onboarding_portal . count = 4
2023-05-10 15:06:57 +05:30
onboarding_portal . save ( )
2023-06-06 12:27:41 +05:30
messages . success ( request , _ ( " Employee bank details created successfully.. " ) )
2023-05-10 15:06:57 +05:30
return redirect ( welcome_aboard )
@login_required
def welcome_aboard ( request ) :
"""
function used to view welcome aboard .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return welcome onboard view
"""
2023-09-27 13:55:34 +05:30
return render ( request , " onboarding/welcome_aboard.html " )
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@require_http_methods ( [ " POST " ] )
@all_manager_can_enter ( " onboarding.change_candidatetask " )
2024-01-20 12:51:17 +05:30
def candidate_task_update ( request , taskId ) :
2023-05-10 15:06:57 +05:30
"""
function used to update candidate task .
Parameters :
request ( HttpRequest ) : The HTTP request object .
2023-06-06 12:27:41 +05:30
obj_id : candidate task id
2023-05-10 15:06:57 +05:30
Returns :
POST : return candidate task template
"""
2024-01-20 12:51:17 +05:30
status = request . POST . get ( " status " )
if request . POST . get ( " single_view " ) :
candidate_task = CandidateTask . objects . get ( id = taskId )
else :
canId = request . POST . get ( " candId " )
onboarding_task = OnboardingTask . objects . get ( id = taskId )
2024-01-23 15:29:05 +05:30
candidate = Candidate . objects . get ( id = canId )
candidate_task = CandidateTask . objects . filter (
candidate_id = candidate , onboarding_task_id = onboarding_task
) . first ( )
2023-06-06 12:27:41 +05:30
candidate_task . status = status
candidate_task . save ( )
users = [
employee . employee_user_id
for employee in candidate_task . onboarding_task_id . employee_id . all ( )
]
notify . send (
request . user . employee_get ,
recipient = users ,
verb = f " The task { candidate_task . onboarding_task_id } of \
{ candidate_task . candidate_id } was updated to { candidate_task . status } . " ,
2023-07-26 12:15:01 +05:30
verb_ar = f " تم تحديث المهمة { candidate_task . onboarding_task_id } للمرشح { candidate_task . candidate_id } إلى { candidate_task . status } . " ,
verb_de = f " Die Aufgabe { candidate_task . onboarding_task_id } des Kandidaten { candidate_task . candidate_id } wurde auf { candidate_task . status } aktualisiert. " ,
verb_es = f " La tarea { candidate_task . onboarding_task_id } del candidato { candidate_task . candidate_id } se ha actualizado a { candidate_task . status } . " ,
verb_fr = f " La tâche { candidate_task . onboarding_task_id } du candidat { candidate_task . candidate_id } a été mise à jour à { candidate_task . status } . " ,
2023-06-06 12:27:41 +05:30
icon = " people-circle " ,
redirect = " /onboarding/onboarding-view " ,
)
2024-01-20 12:51:17 +05:30
return JsonResponse (
2024-02-16 16:44:35 +05:30
{ " message " : _ ( " Candidate onboarding task updated " ) , " type " : " success " }
2024-01-20 12:51:17 +05:30
)
2024-01-23 15:29:05 +05:30
2024-01-20 12:51:17 +05:30
@login_required
2024-01-23 15:29:05 +05:30
def get_status ( request , task_id ) :
2024-01-20 12:51:17 +05:30
"""
htmx function that return the status of candidate task
Parameters :
request ( HttpRequest ) : The HTTP request object .
task_id : Onboarding task id
Returns :
POST : return candidate task template
"""
2024-01-23 15:29:05 +05:30
cand_id = request . GET . get ( " cand_id " )
cand_stage = request . GET . get ( " cand_stage " )
cand_stage_obj = CandidateStage . objects . get ( id = cand_stage )
2024-01-20 12:51:17 +05:30
onboarding_task = OnboardingTask . objects . get ( id = task_id )
2024-01-23 15:29:05 +05:30
candidate = Candidate . objects . get ( id = cand_id )
candidate_task = CandidateTask . objects . filter (
candidate_id = candidate , onboarding_task_id = onboarding_task
) . first ( )
2024-01-20 12:51:17 +05:30
status = candidate_task . status
2024-01-23 15:29:05 +05:30
return render (
request ,
" onboarding/candidate_task.html " ,
{
" status " : status ,
" task " : onboarding_task ,
" candidate " : cand_stage_obj ,
" second_load " : True ,
" choices " : CandidateTask . choice ,
} ,
)
2024-01-20 12:51:17 +05:30
@login_required
@all_manager_can_enter ( " onboarding.change_candidatetask " )
2024-01-23 15:29:05 +05:30
def assign_task ( request , task_id ) :
2024-01-20 12:51:17 +05:30
"""
2024-01-23 15:29:05 +05:30
htmx function that used to assign a onboarding task to candidate
2024-01-20 12:51:17 +05:30
Parameters :
request ( HttpRequest ) : The HTTP request object .
task_id : Onboarding task id
Returns :
POST : return candidate task template
"""
2024-01-23 15:29:05 +05:30
stage_id = request . GET . get ( " stage_id " )
cand_id = request . GET . get ( " cand_id " )
cand_stage = request . GET . get ( " cand_stage " )
cand_stage_obj = CandidateStage . objects . get ( id = cand_stage )
onboarding_task = OnboardingTask . objects . get ( id = task_id )
candidate = Candidate . objects . get ( id = cand_id )
2024-01-20 12:51:17 +05:30
onboarding_stage = OnboardingStage . objects . get ( id = stage_id )
2024-01-23 15:29:05 +05:30
cand_task , created = CandidateTask . objects . get_or_create (
2024-01-20 12:51:17 +05:30
candidate_id = candidate ,
2024-01-23 15:29:05 +05:30
stage_id = onboarding_stage ,
onboarding_task_id = onboarding_task ,
2023-06-06 12:27:41 +05:30
)
2024-01-20 12:51:17 +05:30
cand_task . save ( )
onboarding_task . candidates . add ( candidate )
2024-01-23 15:29:05 +05:30
return render (
request ,
" onboarding/candidate_task.html " ,
{
" status " : cand_task . status ,
" task " : onboarding_task ,
" candidate " : cand_stage_obj ,
" second_load " : True ,
" choices " : CandidateTask . choice ,
} ,
)
2023-05-10 15:06:57 +05:30
@login_required
2023-06-06 12:27:41 +05:30
@require_http_methods ( [ " POST " ] )
@stage_manager_can_enter ( " onboarding.change_candidatestage " )
2023-05-10 15:06:57 +05:30
def candidate_stage_update ( request , candidate_id , recruitment_id ) :
"""
function used to update candidate stage .
Parameters :
request ( HttpRequest ) : The HTTP request object .
candidate_id : Candidate id
recruitment_id : Recruitment id
Returns :
POST : return candidate task template
"""
2023-06-06 12:27:41 +05:30
stage_id = request . POST . get ( " stage " )
2024-02-15 12:12:23 +05:30
recruitments = Recruitment . objects . filter ( id = recruitment_id )
2024-02-20 17:05:43 +05:30
groups = onboarding_query_grouper ( request , recruitments )
2024-02-15 12:12:23 +05:30
for item in groups :
setattr ( item [ " recruitment " ] , " stages " , item [ " stages " ] )
2023-06-06 12:27:41 +05:30
stage = OnboardingStage . objects . get ( id = stage_id )
candidate = Candidate . objects . get ( id = candidate_id )
candidate_stage = CandidateStage . objects . get ( candidate_id = candidate )
candidate_stage . onboarding_stage_id = stage
candidate_stage . save ( )
onboarding_stages = OnboardingStage . objects . all ( )
2023-08-31 16:45:36 +05:30
choices = CandidateTask . choice
2023-06-06 12:27:41 +05:30
users = [
employee . employee_user_id
for employee in candidate_stage . onboarding_stage_id . employee_id . all ( )
]
2023-08-31 16:45:36 +05:30
if request . POST . get ( " is_ajax " ) is None :
notify . send (
request . user . employee_get ,
recipient = users ,
verb = f " The stage of { candidate_stage . candidate_id } \
was updated to { candidate_stage . onboarding_stage_id } . " ,
verb_ar = f " تم تحديث مرحلة المرشح { candidate_stage . candidate_id } إلى { candidate_stage . onboarding_stage_id } . " ,
verb_de = f " Die Phase des Kandidaten { candidate_stage . candidate_id } wurde auf { candidate_stage . onboarding_stage_id } aktualisiert. " ,
verb_es = f " La etapa del candidato { candidate_stage . candidate_id } se ha actualizado a { candidate_stage . onboarding_stage_id } . " ,
verb_fr = f " L ' étape du candidat { candidate_stage . candidate_id } a été mise à jour à { candidate_stage . onboarding_stage_id } . " ,
icon = " people-circle " ,
redirect = " /onboarding/onboarding-view " ,
)
return render (
request ,
2023-09-27 13:55:34 +05:30
" onboarding/onboarding_table.html " ,
2023-08-31 16:45:36 +05:30
{
2024-02-15 12:12:23 +05:30
" recruitment " : groups [ 0 ] [ " recruitment " ] ,
2023-08-31 16:45:36 +05:30
" onboarding_stages " : onboarding_stages ,
" choices " : choices ,
} ,
)
2023-09-11 15:37:32 +05:30
return JsonResponse (
2023-09-12 11:59:58 +05:30
{ " message " : _ ( " Candidate onboarding stage updated " ) , " type " : " success " }
2023-09-11 15:37:32 +05:30
)
2023-05-10 15:06:57 +05:30
2023-10-20 14:48:55 +05:30
@login_required
@require_http_methods ( [ " POST " ] )
@stage_manager_can_enter ( " onboarding.change_candidatestage " )
def candidate_stage_bulk_update ( request ) :
candiate_ids = request . POST [ " ids " ]
recrutment_id = request . POST [ " recruitment " ]
candidate_id_list = json . loads ( candiate_ids )
stage = request . POST [ " stage " ]
onboarding_stages = OnboardingStage . objects . all ( )
2024-02-16 16:44:35 +05:30
recruitments = Recruitment . objects . filter ( id = int ( recrutment_id ) )
2024-02-20 17:05:43 +05:30
groups = onboarding_query_grouper ( request , recruitments )
2024-02-16 16:44:35 +05:30
for item in groups :
setattr ( item [ " recruitment " ] , " stages " , item [ " stages " ] )
2023-10-20 14:48:55 +05:30
choices = CandidateTask . choice
2024-02-20 17:05:43 +05:30
CandidateStage . objects . filter ( candidate_id__id__in = candidate_id_list ) . update (
onboarding_stage_id = stage
)
2024-02-16 16:44:35 +05:30
type = " info "
message = " No candidates selected "
if candidate_id_list :
type = " success "
message = " Candidate stage updated successfully "
2023-10-20 14:48:55 +05:30
response = render (
request ,
" onboarding/onboarding_table.html " ,
{
2024-02-16 16:44:35 +05:30
" recruitment " : groups [ 0 ] [ " recruitment " ] ,
2023-10-20 14:48:55 +05:30
" onboarding_stages " : onboarding_stages ,
" choices " : choices ,
} ,
)
return HttpResponse (
2023-11-08 16:12:02 +05:30
response . content . decode ( " utf-8 " )
2024-02-16 16:44:35 +05:30
+ f ' <div><div class= " oh-alert-container " ><div class= " oh-alert oh-alert--animated oh-alert-- { type } " > { message } </div> </div></div> '
2023-10-20 14:48:55 +05:30
)
@login_required
@require_http_methods ( [ " POST " ] )
@all_manager_can_enter ( " onboarding.change_candidatetask " )
def candidate_task_bulk_update ( request ) :
candiate_ids = request . POST [ " ids " ]
candidate_id_list = json . loads ( candiate_ids )
task = request . POST [ " task " ]
status = request . POST [ " status " ]
2023-11-08 16:12:02 +05:30
count = CandidateTask . objects . filter (
candidate_id__id__in = candidate_id_list , onboarding_task_id = task
) . update ( status = status )
2023-10-20 14:48:55 +05:30
# messages.success(request,f"{count} candidate's task status updated successfully")
return JsonResponse (
{ " message " : _ ( " Candidate onboarding stage updated " ) , " type " : " success " }
)
2023-05-10 15:06:57 +05:30
@login_required
2023-10-24 19:17:43 +05:30
def hired_candidate_chart ( request ) :
2023-05-10 15:06:57 +05:30
"""
function used to show hired candidates in all recruitments .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return Json response labels , data , background_color , border_color .
"""
labels = [ ]
data = [ ]
background_color = [ ]
border_color = [ ]
2024-02-17 14:43:31 +05:30
recruitments = Recruitment . objects . filter ( closed = False , is_active = True )
2023-05-10 15:06:57 +05:30
for recruitment in recruitments :
2023-06-06 12:27:41 +05:30
red = random . randint ( 0 , 255 )
green = random . randint ( 0 , 255 )
blue = random . randint ( 0 , 255 )
background_color . append ( f " rgba( { red } , { green } , { blue } , 0.2 " )
border_color . append ( f " rgb( { red } , { green } , { blue } ) " )
2023-05-10 15:06:57 +05:30
labels . append ( f " { recruitment } " )
2023-06-06 12:27:41 +05:30
data . append ( recruitment . candidate . filter ( hired = True ) . count ( ) )
return JsonResponse (
{
" labels " : labels ,
" data " : data ,
" background_color " : background_color ,
" border_color " : border_color ,
2023-11-08 16:12:02 +05:30
" message " : _ ( " No data Found... " ) ,
2023-06-06 12:27:41 +05:30
} ,
safe = False ,
)
2023-05-10 15:06:57 +05:30
2023-11-08 16:12:02 +05:30
2023-05-10 15:06:57 +05:30
@login_required
2023-10-24 19:17:43 +05:30
def onboard_candidate_chart ( request ) :
2023-05-10 15:06:57 +05:30
"""
function used to show onboard started candidates in recruitments .
Parameters :
request ( HttpRequest ) : The HTTP request object .
Returns :
GET : return Json response labels , data , background_color , border_color .
"""
labels = [ ]
data = [ ]
background_color = [ ]
border_color = [ ]
2024-02-17 14:43:31 +05:30
recruitments = Recruitment . objects . filter ( closed = False , is_active = True )
2023-05-10 15:06:57 +05:30
for recruitment in recruitments :
2023-06-06 12:27:41 +05:30
red = random . randint ( 0 , 255 )
green = random . randint ( 0 , 255 )
blue = random . randint ( 0 , 255 )
background_color . append ( f " rgba( { red } , { green } , { blue } , 0.2 " )
border_color . append ( f " rgb( { red } , { green } , { blue } ) " )
2023-09-01 11:39:05 +05:30
labels . append ( recruitment . title )
2024-02-20 17:05:43 +05:30
data . append ( recruitment . candidate . filter ( start_onboard = True ) . count ( ) )
2023-06-06 12:27:41 +05:30
return JsonResponse (
{
" labels " : labels ,
" data " : data ,
" background_color " : background_color ,
" border_color " : border_color ,
2023-11-08 16:12:02 +05:30
" message " : _ ( " No data Found... " ) ,
2023-06-06 12:27:41 +05:30
} ,
safe = False ,
)
@login_required
@permission_required ( " candidate.view_candidate " )
def update_joining ( request ) :
"""
Ajax method to update joinng date
"""
cand_id = request . POST [ " candId " ]
date = request . POST [ " date " ]
candidate_obj = Candidate . objects . get ( id = cand_id )
candidate_obj . joining_date = date
candidate_obj . save ( )
2023-09-11 15:37:32 +05:30
return JsonResponse (
{
" type " : " success " ,
2023-09-15 11:13:26 +05:30
" message " : _ ( " {candidate} ' s Date of joining updated sussefully " ) . format (
candidate = candidate_obj . name
) ,
2023-09-11 15:37:32 +05:30
}
)
2023-08-31 16:45:36 +05:30
@login_required
@permission_required ( " candidate.view_candidate " )
def view_dashboard ( request ) :
2023-09-11 15:37:32 +05:30
recruitment = Recruitment . objects . all ( ) . values_list ( " title " , flat = True )
2023-08-31 16:45:36 +05:30
candidates = Candidate . objects . all ( )
2023-09-04 09:57:12 +05:30
hired = candidates . filter ( start_onboard = True )
2023-09-11 15:37:32 +05:30
onboard_candidates = Candidate . objects . filter ( start_onboard = True )
job_positions = onboard_candidates . values_list (
" job_position_id__job_position " , flat = True
)
2023-08-31 16:45:36 +05:30
context = {
2023-09-11 15:37:32 +05:30
" recruitment " : list ( recruitment ) ,
" candidates " : candidates ,
" hired " : hired ,
" onboard_candidates " : onboard_candidates ,
" job_positions " : list ( set ( job_positions ) ) ,
2023-08-31 16:45:36 +05:30
}
2023-09-11 15:37:32 +05:30
return render ( request , " onboarding/dashboard.html " , context = context )
2023-08-31 16:45:36 +05:30
@login_required
@permission_required ( " candidate.view_candidate " )
def dashboard_stage_chart ( request ) :
recruitment = request . GET . get ( " recruitment " )
2023-09-11 15:37:32 +05:30
labels = OnboardingStage . objects . filter (
recruitment_id__title = recruitment
) . values_list ( " stage_title " , flat = True )
2023-08-31 16:45:36 +05:30
labels = list ( labels )
candidate_counts = [ ]
border_color = [ ]
2023-09-11 15:37:32 +05:30
background_color = [ ]
2023-08-31 16:45:36 +05:30
for label in labels :
red = random . randint ( 0 , 255 )
green = random . randint ( 0 , 255 )
blue = random . randint ( 0 , 255 )
background_color . append ( f " rgba( { red } , { green } , { blue } , 0.3 " )
border_color . append ( f " rgb( { red } , { green } , { blue } ) " )
2023-09-11 15:37:32 +05:30
count = CandidateStage . objects . filter (
onboarding_stage_id__stage_title = label ,
onboarding_stage_id__recruitment_id__title = recruitment ,
) . count ( )
2023-08-31 16:45:36 +05:30
candidate_counts . append ( count )
response = {
2023-09-11 15:37:32 +05:30
" labels " : labels ,
" data " : candidate_counts ,
" recruitment " : recruitment ,
" background_color " : background_color ,
" border_color " : border_color ,
2023-09-27 13:55:34 +05:30
" message " : _ ( " No candidates started onboarding.... " ) ,
2023-08-31 16:45:36 +05:30
}
return JsonResponse ( response )
@login_required
@stage_manager_can_enter ( " recruitment.change_candidate " )
def candidate_sequence_update ( request ) :
"""
This method is used to update the sequence of candidate
"""
sequence_data = json . loads ( request . POST [ " sequenceData " ] )
updated = False
for cand_id , seq in sequence_data . items ( ) :
cand = CandidateStage . objects . get ( id = cand_id )
if cand . sequence != seq :
cand . sequence = seq
cand . save ( )
updated = True
if updated :
2023-09-15 11:13:26 +05:30
return JsonResponse (
{ " message " : _ ( " Candidate sequence updated " ) , " type " : " info " }
)
2023-08-31 16:45:36 +05:30
return JsonResponse ( { " type " : " fail " } )
@login_required
@stage_manager_can_enter ( " recruitment.change_stage " )
def stage_sequence_update ( request ) :
"""
This method is used to update the sequence of the stages
"""
sequence_data = json . loads ( request . POST [ " sequenceData " ] )
updated = False
for stage_id , seq in sequence_data . items ( ) :
stage = OnboardingStage . objects . get ( id = stage_id )
if stage . sequence != seq :
stage . sequence = seq
stage . save ( )
updated = True
2023-09-11 15:37:32 +05:30
2023-08-31 16:45:36 +05:30
if updated :
2023-09-15 11:13:26 +05:30
return JsonResponse ( { " type " : " success " , " message " : _ ( " Stage sequence updated " ) } )
2023-08-31 16:45:36 +05:30
return JsonResponse ( { " type " : " fail " } )
2023-09-15 11:13:26 +05:30
@login_required
@require_http_methods ( [ " POST " ] )
@hx_request_required
def stage_name_update ( request , stage_id ) :
"""
This method is used to update the name of recruitment stage
"""
stage_obj = OnboardingStage . objects . get ( id = stage_id )
stage_obj . stage_title = request . POST [ " stage " ]
stage_obj . save ( )
message = _ ( " The stage title has been updated successfully " )
return HttpResponse (
f ' <div class= " oh-alert-container " ><div class= " oh-alert oh-alert--animated oh-alert--success " > { message } </div></div> '
)
2023-08-31 16:45:36 +05:30
@login_required
@stage_manager_can_enter ( " recruitment.change_candidate " )
2023-09-11 15:37:32 +05:30
def onboarding_send_mail ( request , candidate_id ) :
2023-08-31 16:45:36 +05:30
"""
This method is used to send mail to the candidate from onboarding view
"""
candidate = Candidate . objects . get ( id = candidate_id )
candidate_mail = candidate . email
2023-09-11 15:37:32 +05:30
response = render (
2023-09-27 13:55:34 +05:30
request , " onboarding/send_mail_form.html " , { " candidate " : candidate }
2023-09-11 15:37:32 +05:30
)
2023-08-31 16:45:36 +05:30
if request . method == " POST " :
2023-09-11 15:37:32 +05:30
subject = request . POST [ " subject " ]
2023-08-31 16:45:36 +05:30
body = request . POST [ " body " ]
with contextlib . suppress ( Exception ) :
res = send_mail (
2023-09-11 15:37:32 +05:30
subject ,
body ,
settings . EMAIL_HOST_USER ,
[ candidate_mail ] ,
fail_silently = False ,
2023-08-31 16:45:36 +05:30
)
if res == 1 :
2023-09-11 15:37:32 +05:30
messages . success ( request , _ ( " Mail sent successfully " ) )
2023-08-31 16:45:36 +05:30
else :
2023-09-11 15:37:32 +05:30
messages . error ( request , _ ( " Something went wrong " ) )
2023-08-31 16:45:36 +05:30
return HttpResponse (
response . content . decode ( " utf-8 " ) + " <script>location.reload();</script> "
)
return response
2024-01-23 15:29:05 +05:30
@login_required
@stage_manager_can_enter ( " recruitment.change_stage " )
def update_probation_end ( request ) :
"""
This method is used to update the probotion end date
"""
candidate_id = request . GET . getlist ( " candidate_id " )
probation_end = request . GET [ " probation_end " ]
Candidate . objects . filter ( id__in = candidate_id ) . update ( probation_end = probation_end )
2024-02-03 13:59:47 +05:30
return JsonResponse ( { " message " : " Probation end date updated " , " type " : " success " } )
2024-02-05 13:53:16 +05:30
@login_required
@all_manager_can_enter ( " onboarding.change_onboardingtask " )
def task_report ( request ) :
"""
This method is used to show the task report .
"""
employee_id = request . GET . get ( " employee_id " )
if not employee_id :
employee_id = request . user . employee_get . id
my_tasks = OnboardingTask . objects . filter (
employee_id__id = employee_id ,
2024-02-20 17:05:43 +05:30
candidates__is_active = True ,
2024-02-05 13:53:16 +05:30
candidates__recruitment_id__closed = False ,
) . distinct ( )
tasks = [ ]
for task in my_tasks :
tasks . append (
{
" task " : task ,
" total_candidates " : task . candidatetask_set . count ( ) ,
" todo " : task . candidatetask_set . filter ( status = " todo " ) . count ( ) ,
" scheduled " : task . candidatetask_set . filter ( status = " scheduled " ) . count ( ) ,
" ongoing " : task . candidatetask_set . filter ( status = " ongoing " ) . count ( ) ,
" stuck " : task . candidatetask_set . filter ( status = " stuck " ) . count ( ) ,
" done " : task . candidatetask_set . filter ( status = " done " ) . count ( ) ,
}
)
return render ( request , " onboarding/dashboard/task_report.html " , { " tasks " : tasks } )
@login_required
@all_manager_can_enter ( " onboarding.view_candidatetask " )
def candidate_tasks_status ( request ) :
"""
This method is used to render template to show the onboarding tasks
"""
task_id = request . GET [ " task_id " ]
candidate_tasks = CandidateTask . objects . filter ( onboarding_task_id__id = task_id )
return render (
request ,
" onboarding/dashboard/status_list.html " ,
{ " candidate_tasks " : candidate_tasks } ,
)
@login_required
@all_manager_can_enter ( " onboarding.change_candidatetask " )
def change_task_status ( request ) :
"""
This method is to update the candidate task
"""
task_id = request . GET [ " task_id " ]
candidate_task = CandidateTask . objects . get ( id = task_id )
status = request . GET [ " status " ]
if status in [
" todo " ,
" scheduled " ,
" ongoing " ,
" stuck " ,
" done " ,
] :
candidate_task . status = status
candidate_task . save ( )
return HttpResponse ( " Success " )
2024-02-06 13:01:09 +05:30
@login_required
@permission_required ( " recruitment.change_recruitment " )
def update_offer_letter_status ( request ) :
"""
This method is used to update the offer letter status
"""
candidate_id = request . GET [ " candidate_id " ]
status = request . GET [ " status " ]
candidate = Candidate . objects . get ( id = candidate_id )
if status in [ " not_sent " , " sent " , " accepted " , " rejected " , " joined " ] :
candidate . offer_letter_status = status
candidate . save ( )
return HttpResponse ( " Success " )
@login_required
@permission_required ( " recruitment.add_rejectedcandidate " )
def add_to_rejected_candidates ( request ) :
"""
This method is used to add candidates to rejected candidates
"""
candidate_id = request . GET . get ( " candidate_id " )
instance = None
if candidate_id :
instance = RejectedCandidate . objects . filter ( candidate_id = candidate_id ) . first ( )
2024-02-20 17:05:43 +05:30
form = RejectedCandidateForm (
initial = { " candidate_id " : candidate_id } , instance = instance
)
2024-02-06 13:01:09 +05:30
if request . method == " POST " :
2024-02-20 17:05:43 +05:30
form = RejectedCandidateForm ( request . POST , instance = instance )
2024-02-06 13:01:09 +05:30
if form . is_valid ( ) :
form . save ( )
2024-02-20 17:05:43 +05:30
messages . success ( request , " Candidate reject reason saved " )
2024-02-06 13:01:09 +05:30
return HttpResponse ( " <script>window.location.reload()</script> " )
return render ( request , " onboarding/rejection/form.html " , { " form " : form } )
2024-02-22 22:57:56 +05:30
@login_required
def candidate_select ( request ) :
"""
This method is used for select all in candidate
"""
page_number = request . GET . get ( " page " )
employees = queryset = Candidate . objects . filter (
hired = True ,
recruitment_id__closed = False ,
is_active = True ,
)
employee_ids = [ str ( emp . id ) for emp in employees ]
total_count = employees . count ( )
context = { " employee_ids " : employee_ids , " total_count " : total_count }
return JsonResponse ( context , safe = False )
@login_required
@permission_required ( " recruitment.view_candidate " )
def candidate_select_filter ( request ) :
"""
This method is used to select all filtered candidates
"""
page_number = request . GET . get ( " page " )
filtered = request . GET . get ( " filter " )
filters = json . loads ( filtered ) if filtered else { }
if page_number == " all " :
candidate_filter = CandidateFilter (
filters ,
queryset = Candidate . objects . filter (
hired = True ,
recruitment_id__closed = False ,
is_active = True ,
) ,
)
# Get the filtered queryset
filtered_candidates = candidate_filter . qs
employee_ids = [ str ( emp . id ) for emp in filtered_candidates ]
total_count = filtered_candidates . count ( )
context = { " employee_ids " : employee_ids , " total_count " : total_count }
return JsonResponse ( context )