2010-02-28 20:36:51 +00:00
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
2012-08-23 15:32:03 +00:00
from datetime import datetime
2014-06-20 11:38:22 +00:00
2014-09-03 13:37:41 +00:00
from openerp import tools
2014-06-20 11:38:22 +00:00
from openerp import SUPERUSER_ID
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
2014-02-11 10:58:07 +00:00
2010-02-28 20:36:51 +00:00
AVAILABLE_PRIORITIES = [
2014-02-14 11:49:37 +00:00
( ' 0 ' , ' Bad ' ) ,
( ' 1 ' , ' Below Average ' ) ,
( ' 2 ' , ' Average ' ) ,
( ' 3 ' , ' Good ' ) ,
( ' 4 ' , ' Excellent ' )
2010-02-28 20:36:51 +00:00
]
2011-08-18 19:30:44 +00:00
class hr_recruitment_source ( osv . osv ) :
""" Sources of HR Recruitment """
_name = " hr.recruitment.source "
_description = " Source of Applicants "
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Source Name ' , required = True , translate = True ) ,
2011-08-18 19:30:44 +00:00
}
2010-05-11 13:54:14 +00:00
class hr_recruitment_stage ( osv . osv ) :
""" Stage of HR Recruitment """
_name = " hr.recruitment.stage "
_description = " Stage of Recruitment "
2010-07-20 07:17:40 +00:00
_order = ' sequence '
2010-05-11 13:54:14 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
2010-05-12 05:56:48 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Gives the sequence order when displaying a list of stages. " ) ,
2012-07-13 10:17:51 +00:00
' department_id ' : fields . many2one ( ' hr.department ' , ' Specific to a Department ' , help = " Stages of the recruitment process may be different per department. If this stage is common to all departments, keep this field empty. " ) ,
2012-05-22 14:48:06 +00:00
' requirements ' : fields . text ( ' Requirements ' ) ,
2013-12-23 09:53:28 +00:00
' template_id ' : fields . many2one ( ' email.template ' , ' Use template ' , help = " If set, a message is posted on the applicant using the template when the applicant is set to the stage. " ) ,
2013-10-18 13:21:20 +00:00
' fold ' : fields . boolean ( ' Folded in Kanban View ' ,
help = ' This stage is folded in the kanban view when '
' there are no records in that stage to display. ' ) ,
2010-05-11 13:54:14 +00:00
}
_defaults = {
' sequence ' : 1 ,
}
2010-02-28 20:36:51 +00:00
2010-07-26 06:15:27 +00:00
class hr_recruitment_degree ( osv . osv ) :
""" Degree of HR Recruitment """
_name = " hr.recruitment.degree "
_description = " Degree of Recruitment "
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
2010-07-26 06:15:27 +00:00
' sequence ' : fields . integer ( ' Sequence ' , help = " Gives the sequence order when displaying a list of degrees. " ) ,
}
_defaults = {
' sequence ' : 1 ,
}
2011-08-05 05:20:25 +00:00
_sql_constraints = [
( ' name_uniq ' , ' unique (name) ' , ' The name of the Degree of Recruitment must be unique! ' )
]
2010-07-26 06:15:27 +00:00
2013-06-27 09:48:07 +00:00
class hr_applicant ( osv . Model ) :
2010-02-28 20:36:51 +00:00
_name = " hr.applicant "
2010-05-19 18:32:32 +00:00
_description = " Applicant "
2014-08-22 12:22:26 +00:00
_order = " priority desc, id desc "
2012-08-22 15:31:45 +00:00
_inherit = [ ' mail.thread ' , ' ir.needaction_mixin ' ]
2014-04-16 08:28:51 +00:00
2012-12-18 16:31:30 +00:00
_track = {
' stage_id ' : {
2013-10-23 11:55:05 +00:00
# this is only an heuristics; depending on your particular stage configuration it may not match all 'new' stages
' hr_recruitment.mt_applicant_new ' : lambda self , cr , uid , obj , ctx = None : obj . stage_id and obj . stage_id . sequence < = 1 ,
' hr_recruitment.mt_applicant_stage_changed ' : lambda self , cr , uid , obj , ctx = None : obj . stage_id and obj . stage_id . sequence > 1 ,
2012-12-18 16:31:30 +00:00
} ,
}
2014-04-16 08:28:51 +00:00
_mail_mass_mailing = _ ( ' Applicants ' )
2010-08-02 09:57:42 +00:00
2012-05-25 11:51:43 +00:00
def _get_default_department_id ( self , cr , uid , context = None ) :
""" Gives default department by checking if present in the context """
2012-05-30 11:18:31 +00:00
return ( self . _resolve_department_id_from_context ( cr , uid , context = context ) or False )
2012-05-25 11:51:43 +00:00
def _get_default_stage_id ( self , cr , uid , context = None ) :
""" Gives default stage_id """
department_id = self . _get_default_department_id ( cr , uid , context = context )
2013-10-23 11:55:05 +00:00
return self . stage_find ( cr , uid , [ ] , department_id , [ ( ' fold ' , ' = ' , False ) ] , context = context )
2012-05-25 11:51:43 +00:00
def _resolve_department_id_from_context ( self , cr , uid , context = None ) :
""" Returns ID of department based on the value of ' default_department_id '
context key , or None if it cannot be resolved to a single
department .
"""
if context is None :
context = { }
if type ( context . get ( ' default_department_id ' ) ) in ( int , long ) :
return context . get ( ' default_department_id ' )
if isinstance ( context . get ( ' default_department_id ' ) , basestring ) :
department_name = context [ ' default_department_id ' ]
department_ids = self . pool . get ( ' hr.department ' ) . name_search ( cr , uid , name = department_name , context = context )
if len ( department_ids ) == 1 :
return int ( department_ids [ 0 ] [ 0 ] )
return None
2014-05-26 09:20:40 +00:00
def _get_default_company_id ( self , cr , uid , department_id = None , context = None ) :
company_id = False
if department_id :
department = self . pool [ ' hr.department ' ] . browse ( cr , uid , department_id , context = context )
company_id = department . company_id . id if department and department . company_id else False
if not company_id :
company_id = self . pool [ ' res.company ' ] . _company_default_get ( cr , uid , ' hr.applicant ' , context = context )
return company_id
2012-05-25 11:51:43 +00:00
def _read_group_stage_ids ( self , cr , uid , ids , domain , read_group_order = None , access_rights_uid = None , context = None ) :
access_rights_uid = access_rights_uid or uid
stage_obj = self . pool . get ( ' hr.recruitment.stage ' )
order = stage_obj . _order
# lame hack to allow reverting search, should just work in the trivial case
if read_group_order == ' stage_id desc ' :
order = " %s desc " % order
2012-05-31 13:16:26 +00:00
# retrieve section_id from the context and write the domain
# - ('id', 'in', 'ids'): add columns that should be present
# - OR ('department_id', '=', False), ('fold', '=', False): add default columns that are not folded
# - OR ('department_id', 'in', department_id), ('fold', '=', False) if department_id: add department columns that are not folded
2012-05-25 11:51:43 +00:00
department_id = self . _resolve_department_id_from_context ( cr , uid , context = context )
search_domain = [ ]
if department_id :
2012-09-06 16:18:12 +00:00
search_domain + = [ ' | ' , ( ' department_id ' , ' = ' , department_id ) ]
search_domain + = [ ' | ' , ( ' id ' , ' in ' , ids ) , ( ' department_id ' , ' = ' , False ) ]
2012-05-25 11:51:43 +00:00
stage_ids = stage_obj . _search ( cr , uid , search_domain , order = order , access_rights_uid = access_rights_uid , context = context )
result = stage_obj . name_get ( cr , access_rights_uid , stage_ids , context = context )
# restore order of the search
result . sort ( lambda x , y : cmp ( stage_ids . index ( x [ 0 ] ) , stage_ids . index ( y [ 0 ] ) ) )
2012-09-06 15:23:03 +00:00
fold = { }
for stage in stage_obj . browse ( cr , access_rights_uid , stage_ids , context = context ) :
fold [ stage . id ] = stage . fold or False
return result , fold
2010-08-02 09:57:42 +00:00
def _compute_day ( self , cr , uid , ids , fields , args , context = None ) :
2014-09-18 08:18:05 +00:00
res = dict ( ( res_id , { } ) for res_id in ids )
2010-08-02 09:57:42 +00:00
for issue in self . browse ( cr , uid , ids , context = context ) :
2014-09-03 13:37:41 +00:00
values = {
' day_open ' : 0.0 ,
' day_close ' : 0.0 ,
}
if issue . date_open :
date_create = datetime . strptime ( issue . create_date , tools . DEFAULT_SERVER_DATETIME_FORMAT )
date_open = datetime . strptime ( issue . date_open , tools . DEFAULT_SERVER_DATETIME_FORMAT )
values [ ' day_open ' ] = ( date_open - date_create ) . total_seconds ( ) / ( 24.0 * 3600 )
if issue . date_closed :
date_create = datetime . strptime ( issue . create_date , tools . DEFAULT_SERVER_DATETIME_FORMAT )
date_closed = datetime . strptime ( issue . date_closed , tools . DEFAULT_SERVER_DATETIME_FORMAT )
values [ ' day_close ' ] = ( date_closed - date_create ) . total_seconds ( ) / ( 24.0 * 3600 )
# filter only required values
2010-08-02 09:57:42 +00:00
for field in fields :
2014-09-03 13:37:41 +00:00
res [ issue . id ] [ field ] = values [ field ]
2010-08-02 09:57:42 +00:00
return res
2013-12-20 10:29:18 +00:00
def _get_attachment_number ( self , cr , uid , ids , fields , args , context = None ) :
res = dict . fromkeys ( ids , 0 )
for app_id in ids :
res [ app_id ] = self . pool [ ' ir.attachment ' ] . search_count ( cr , uid , [ ( ' res_model ' , ' = ' , ' hr.applicant ' ) , ( ' res_id ' , ' = ' , app_id ) ] , context = context )
2013-03-14 09:12:30 +00:00
return res
2010-08-02 09:57:42 +00:00
2010-02-28 20:36:51 +00:00
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Subject / Application Name ' , required = True ) ,
2010-06-10 04:38:03 +00:00
' active ' : fields . boolean ( ' Active ' , help = " If the active field is set to false, it will allow you to hide the case without removing it. " ) ,
' description ' : fields . text ( ' Description ' ) ,
2010-05-14 09:29:24 +00:00
' email_from ' : fields . char ( ' Email ' , size = 128 , help = " These people will receive email. " ) ,
2010-10-27 12:49:59 +00:00
' email_cc ' : fields . text ( ' Watchers Emails ' , size = 252 , help = " These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma " ) ,
2010-05-14 09:29:24 +00:00
' probability ' : fields . float ( ' Probability ' ) ,
2012-06-13 14:36:42 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Contact ' ) ,
2011-01-17 11:20:56 +00:00
' create_date ' : fields . datetime ( ' Creation Date ' , readonly = True , select = True ) ,
2010-10-27 12:49:59 +00:00
' write_date ' : fields . datetime ( ' Update Date ' , readonly = True ) ,
2012-12-20 11:47:30 +00:00
' stage_id ' : fields . many2one ( ' hr.recruitment.stage ' , ' Stage ' , track_visibility = ' onchange ' ,
2013-03-21 12:56:26 +00:00
domain = " [ ' | ' , ( ' department_id ' , ' = ' , department_id), ( ' department_id ' , ' = ' , False)] " ) ,
2013-09-04 14:10:24 +00:00
' last_stage_id ' : fields . many2one ( ' hr.recruitment.stage ' , ' Last Stage ' ,
help = ' Stage of the applicant before being in the current stage. Used for lost cases analysis. ' ) ,
2012-09-03 05:05:25 +00:00
' categ_ids ' : fields . many2many ( ' hr.applicant_category ' , string = ' Tags ' ) ,
2010-05-14 09:29:24 +00:00
' company_id ' : fields . many2one ( ' res.company ' , ' Company ' ) ,
2012-12-20 11:47:30 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Responsible ' , track_visibility = ' onchange ' ) ,
2011-01-17 11:20:56 +00:00
' date_closed ' : fields . datetime ( ' Closed ' , readonly = True , select = True ) ,
2013-07-08 09:11:56 +00:00
' date_open ' : fields . datetime ( ' Assigned ' , readonly = True , select = True ) ,
' date_last_stage_update ' : fields . datetime ( ' Last Stage Update ' , select = True ) ,
2010-07-26 06:15:27 +00:00
' date_action ' : fields . date ( ' Next Action Date ' ) ,
' title_action ' : fields . char ( ' Next Action ' , size = 64 ) ,
2010-02-28 20:36:51 +00:00
' priority ' : fields . selection ( AVAILABLE_PRIORITIES , ' Appreciation ' ) ,
' job_id ' : fields . many2one ( ' hr.job ' , ' Applied Job ' ) ,
2014-05-21 09:52:05 +00:00
' salary_proposed_extra ' : fields . char ( ' Proposed Salary Extra ' , help = " Salary Proposed by the Organisation, extra advantages " ) ,
' salary_expected_extra ' : fields . char ( ' Expected Salary Extra ' , help = " Salary Expected by Applicant, extra advantages " ) ,
2010-06-10 04:38:03 +00:00
' salary_proposed ' : fields . float ( ' Proposed Salary ' , help = " Salary Proposed by the Organisation " ) ,
' salary_expected ' : fields . float ( ' Expected Salary ' , help = " Salary Expected by Applicant " ) ,
2013-04-29 10:18:49 +00:00
' availability ' : fields . integer ( ' Availability ' , help = " The number of days in which the applicant will be available to start working " ) ,
2014-05-21 09:52:05 +00:00
' partner_name ' : fields . char ( " Applicant ' s Name " ) ,
2010-02-28 20:36:51 +00:00
' partner_phone ' : fields . char ( ' Phone ' , size = 32 ) ,
' partner_mobile ' : fields . char ( ' Mobile ' , size = 32 ) ,
2010-07-26 06:15:27 +00:00
' type_id ' : fields . many2one ( ' hr.recruitment.degree ' , ' Degree ' ) ,
2010-10-27 12:49:59 +00:00
' department_id ' : fields . many2one ( ' hr.department ' , ' Department ' ) ,
2014-02-07 16:26:15 +00:00
' survey ' : fields . related ( ' job_id ' , ' survey_id ' , type = ' many2one ' , relation = ' survey.survey ' , string = ' Survey ' ) ,
' response_id ' : fields . many2one ( ' survey.user_input ' , " Response " , ondelete = ' set null ' , oldname = " response " ) ,
2014-05-21 09:52:05 +00:00
' reference ' : fields . char ( ' Referred By ' ) ,
2011-08-18 19:30:44 +00:00
' source_id ' : fields . many2one ( ' hr.recruitment.source ' , ' Source ' ) ,
2014-09-03 13:37:41 +00:00
' day_open ' : fields . function ( _compute_day , string = ' Days to Open ' ,
multi = ' day_open ' , type = " float " ,
store = { ' hr.applicant ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' date_open ' ] , 10 ) } ) ,
' day_close ' : fields . function ( _compute_day , string = ' Days to Close ' ,
multi = ' day_close ' , type = " float " ,
store = { ' hr.applicant ' : ( lambda self , cr , uid , ids , c = { } : ids , [ ' date_closed ' ] , 10 ) } ) ,
2011-09-16 12:03:52 +00:00
' color ' : fields . integer ( ' Color Index ' ) ,
2013-09-09 09:59:57 +00:00
' emp_id ' : fields . many2one ( ' hr.employee ' , string = ' Employee ' , help = ' Employee linked to the applicant. ' ) ,
2012-08-10 14:43:39 +00:00
' user_email ' : fields . related ( ' user_id ' , ' email ' , type = ' char ' , string = ' User Email ' , readonly = True ) ,
2013-12-20 10:29:18 +00:00
' attachment_number ' : fields . function ( _get_attachment_number , string = ' Number of Attachments ' , type = " integer " ) ,
2010-02-28 20:36:51 +00:00
}
2010-06-10 04:38:03 +00:00
2010-05-20 06:16:37 +00:00
_defaults = {
2010-06-10 04:38:03 +00:00
' active ' : lambda * a : 1 ,
2013-06-27 10:09:22 +00:00
' user_id ' : lambda s , cr , uid , c : uid ,
2012-05-25 11:51:43 +00:00
' stage_id ' : lambda s , cr , uid , c : s . _get_default_stage_id ( cr , uid , c ) ,
' department_id ' : lambda s , cr , uid , c : s . _get_default_department_id ( cr , uid , c ) ,
2014-05-26 09:20:40 +00:00
' company_id ' : lambda s , cr , uid , c : s . _get_default_company_id ( cr , uid , s . _get_default_department_id ( cr , uid , c ) , c ) ,
2011-09-16 12:03:52 +00:00
' color ' : 0 ,
2014-08-22 12:22:26 +00:00
' priority ' : ' 0 ' ,
2013-10-18 13:21:20 +00:00
' date_last_stage_update ' : fields . datetime . now ,
2010-05-20 06:16:37 +00:00
}
2010-04-07 14:40:28 +00:00
2011-11-13 12:45:31 +00:00
_group_by_full = {
' stage_id ' : _read_group_stage_ids
}
2013-07-08 13:10:40 +00:00
def onchange_job ( self , cr , uid , ids , job_id = False , context = None ) :
2013-12-20 10:29:18 +00:00
department_id = False
2014-07-09 09:15:19 +00:00
user_id = False
2013-07-08 13:10:40 +00:00
if job_id :
job_record = self . pool . get ( ' hr.job ' ) . browse ( cr , uid , job_id , context = context )
2013-12-20 10:29:18 +00:00
department_id = job_record and job_record . department_id and job_record . department_id . id or False
2014-02-11 12:23:41 +00:00
user_id = job_record and job_record . user_id and job_record . user_id . id or False
return { ' value ' : { ' department_id ' : department_id , ' user_id ' : user_id } }
2010-05-10 12:59:15 +00:00
2013-07-08 13:10:40 +00:00
def onchange_department_id ( self , cr , uid , ids , department_id = False , stage_id = False , context = None ) :
2014-12-09 16:51:47 +00:00
values = { }
2013-07-08 13:10:40 +00:00
if not stage_id :
2014-12-09 16:51:47 +00:00
values [ ' stage_id ' ] = self . stage_find ( cr , uid , [ ] , department_id , [ ( ' fold ' , ' = ' , False ) ] , context = context )
if department_id :
department = self . pool [ ' hr.department ' ] . browse ( cr , uid , department_id , context = context )
values [ ' company_id ' ] = department . company_id . id
return { ' value ' : values }
2011-03-04 06:44:06 +00:00
2012-10-29 08:34:14 +00:00
def onchange_partner_id ( self , cr , uid , ids , partner_id , context = None ) :
data = { ' partner_phone ' : False ,
' partner_mobile ' : False ,
' email_from ' : False }
if partner_id :
addr = self . pool . get ( ' res.partner ' ) . browse ( cr , uid , partner_id , context )
data . update ( { ' partner_phone ' : addr . phone ,
' partner_mobile ' : addr . mobile ,
' email_from ' : addr . email } )
return { ' value ' : data }
2014-09-03 13:37:41 +00:00
def onchange_stage_id ( self , cr , uid , ids , stage_id , context = None ) :
if not stage_id :
return { ' value ' : { } }
stage = self . pool [ ' hr.recruitment.stage ' ] . browse ( cr , uid , stage_id , context = context )
if stage . fold :
return { ' value ' : { ' date_closed ' : fields . datetime . now ( ) } }
return { ' value ' : { ' date_closed ' : False } }
2012-05-25 11:51:43 +00:00
def stage_find ( self , cr , uid , cases , section_id , domain = [ ] , order = ' sequence ' , context = None ) :
""" Override of the base.stage method
Parameter of the stage search taken from the lead :
- department_id : if set , stages must belong to this section or
be a default case
2010-04-07 14:40:28 +00:00
"""
2012-05-25 11:51:43 +00:00
if isinstance ( cases , ( int , long ) ) :
cases = self . browse ( cr , uid , cases , context = context )
2012-05-31 14:19:30 +00:00
# collect all section_ids
department_ids = [ ]
2012-05-25 11:51:43 +00:00
if section_id :
2012-05-31 14:19:30 +00:00
department_ids . append ( section_id )
2012-05-25 11:51:43 +00:00
for case in cases :
2012-05-31 14:19:30 +00:00
if case . department_id :
department_ids . append ( case . department_id . id )
# OR all section_ids and OR with case_default
search_domain = [ ]
if department_ids :
search_domain + = [ ' | ' , ( ' department_id ' , ' in ' , department_ids ) ]
search_domain . append ( ( ' department_id ' , ' = ' , False ) )
# AND with the domain in parameter
search_domain + = list ( domain )
# perform search, return the first found
stage_ids = self . pool . get ( ' hr.recruitment.stage ' ) . search ( cr , uid , search_domain , order = order , context = context )
2012-05-22 14:48:06 +00:00
if stage_ids :
return stage_ids [ 0 ]
return False
2010-04-07 14:40:28 +00:00
def action_makeMeeting ( self , cr , uid , ids , context = None ) :
2012-07-06 12:29:59 +00:00
""" This opens Meeting ' s calendar view to schedule meeting on current applicant
@return : Dictionary value for created Meeting view
2010-04-07 14:40:28 +00:00
"""
2012-07-06 12:29:59 +00:00
applicant = self . browse ( cr , uid , ids [ 0 ] , context )
2013-03-14 09:21:10 +00:00
applicant_ids = [ ]
if applicant . partner_id :
applicant_ids . append ( applicant . partner_id . id )
2013-03-15 12:37:24 +00:00
if applicant . department_id and applicant . department_id . manager_id and applicant . department_id . manager_id . user_id and applicant . department_id . manager_id . user_id . partner_id :
applicant_ids . append ( applicant . department_id . manager_id . user_id . partner_id . id )
2012-07-06 12:29:59 +00:00
category = self . pool . get ( ' ir.model.data ' ) . get_object ( cr , uid , ' hr_recruitment ' , ' categ_meet_interview ' , context )
2014-01-15 09:38:05 +00:00
res = self . pool . get ( ' ir.actions.act_window ' ) . for_xml_id ( cr , uid , ' calendar ' , ' action_calendar_event ' , context )
2012-07-06 12:29:59 +00:00
res [ ' context ' ] = {
2013-12-20 10:29:18 +00:00
' default_partner_ids ' : applicant_ids ,
2012-07-06 12:29:59 +00:00
' default_user_id ' : uid ,
' default_name ' : applicant . name ,
2012-07-14 16:22:03 +00:00
' default_categ_ids ' : category and [ category . id ] or False ,
2012-07-06 12:29:59 +00:00
}
return res
2010-04-07 14:40:28 +00:00
2014-02-07 16:26:15 +00:00
def action_start_survey ( self , cr , uid , ids , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-02-07 16:26:15 +00:00
applicant = self . browse ( cr , uid , ids , context = context ) [ 0 ]
survey_obj = self . pool . get ( ' survey.survey ' )
response_obj = self . pool . get ( ' survey.user_input ' )
# create a response and link it to this applicant
if not applicant . response_id :
response_id = response_obj . create ( cr , uid , { ' survey_id ' : applicant . survey . id , ' partner_id ' : applicant . partner_id . id } , context = context )
self . write ( cr , uid , ids [ 0 ] , { ' response_id ' : response_id } , context = context )
else :
response_id = applicant . response_id . id
# grab the token of the response and start surveying
response = response_obj . browse ( cr , uid , response_id , context = context )
context . update ( { ' survey_token ' : response . token } )
return survey_obj . action_start_survey ( cr , uid , [ applicant . survey . id ] , context = context )
2010-04-07 13:46:01 +00:00
2014-02-07 16:26:15 +00:00
def action_print_survey ( self , cr , uid , ids , context = None ) :
""" If response is available then print this response otherwise print survey form (print template of the survey) """
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-02-07 16:26:15 +00:00
applicant = self . browse ( cr , uid , ids , context = context ) [ 0 ]
survey_obj = self . pool . get ( ' survey.survey ' )
response_obj = self . pool . get ( ' survey.user_input ' )
if not applicant . response_id :
return survey_obj . action_print_survey ( cr , uid , [ applicant . survey . id ] , context = context )
else :
response = response_obj . browse ( cr , uid , applicant . response_id . id , context = context )
context . update ( { ' survey_token ' : response . token } )
return survey_obj . action_print_survey ( cr , uid , [ applicant . survey . id ] , context = context )
2010-06-24 19:53:32 +00:00
2013-12-26 12:42:14 +00:00
def action_get_attachment_tree_view ( self , cr , uid , ids , context = None ) :
2014-02-11 10:58:07 +00:00
model , action_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' base ' , ' action_attachment ' )
2013-12-26 12:42:14 +00:00
action = self . pool . get ( model ) . read ( cr , uid , action_id , context = context )
2014-02-11 10:58:07 +00:00
action [ ' context ' ] = { ' default_res_model ' : self . _name , ' default_res_id ' : ids [ 0 ] }
2013-12-26 12:42:14 +00:00
action [ ' domain ' ] = str ( [ ' & ' , ( ' res_model ' , ' = ' , self . _name ) , ( ' res_id ' , ' in ' , ids ) ] )
return action
2013-12-20 10:29:18 +00:00
2014-06-20 11:38:22 +00:00
def message_get_reply_to ( self , cr , uid , ids , context = None ) :
""" Override to get the reply_to of the parent project. """
applicants = self . browse ( cr , SUPERUSER_ID , ids , context = context )
job_ids = set ( [ applicant . job_id . id for applicant in applicants if applicant . job_id ] )
aliases = self . pool [ ' project.project ' ] . message_get_reply_to ( cr , uid , list ( job_ids ) , context = context )
return dict ( ( applicant . id , aliases . get ( applicant . job_id and applicant . job_id . id or 0 , False ) ) for applicant in applicants )
2013-02-26 13:22:41 +00:00
def message_get_suggested_recipients ( self , cr , uid , ids , context = None ) :
recipients = super ( hr_applicant , self ) . message_get_suggested_recipients ( cr , uid , ids , context = context )
for applicant in self . browse ( cr , uid , ids , context = context ) :
if applicant . partner_id :
2013-02-28 17:05:46 +00:00
self . _message_add_suggested_recipient ( cr , uid , recipients , applicant , partner = applicant . partner_id , reason = _ ( ' Contact ' ) )
2013-02-26 13:22:41 +00:00
elif applicant . email_from :
2013-02-28 17:05:46 +00:00
self . _message_add_suggested_recipient ( cr , uid , recipients , applicant , email = applicant . email_from , reason = _ ( ' Contact Email ' ) )
2013-02-26 13:22:41 +00:00
return recipients
2011-08-22 17:16:59 +00:00
def message_new ( self , cr , uid , msg , custom_values = None , context = None ) :
2012-06-04 14:12:54 +00:00
""" Overrides mail_thread message_new that is called by the mailgateway
through message_process .
This override updates the document according to the email .
"""
2013-11-04 09:27:31 +00:00
if custom_values is None :
custom_values = { }
2013-02-06 11:32:01 +00:00
val = msg . get ( ' from ' ) . split ( ' < ' ) [ 0 ]
2013-01-10 17:27:23 +00:00
defaults = {
2012-06-04 14:12:54 +00:00
' name ' : msg . get ( ' subject ' ) or _ ( " No Subject " ) ,
2014-02-11 10:58:07 +00:00
' partner_name ' : val ,
2012-06-04 14:12:54 +00:00
' email_from ' : msg . get ( ' from ' ) ,
2010-06-24 19:53:32 +00:00
' email_cc ' : msg . get ( ' cc ' ) ,
' user_id ' : False ,
2013-01-15 13:43:59 +00:00
' partner_id ' : msg . get ( ' author_id ' , False ) ,
2013-01-10 17:27:23 +00:00
}
2012-06-04 14:12:54 +00:00
if msg . get ( ' priority ' ) :
2013-01-10 17:27:23 +00:00
defaults [ ' priority ' ] = msg . get ( ' priority ' )
defaults . update ( custom_values )
2013-11-04 09:27:31 +00:00
return super ( hr_applicant , self ) . message_new ( cr , uid , msg , custom_values = defaults , context = context )
2010-06-24 19:53:32 +00:00
2012-02-28 05:21:14 +00:00
def create ( self , cr , uid , vals , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2014-02-11 10:58:07 +00:00
context [ ' mail_create_nolog ' ] = True
2013-06-19 11:46:33 +00:00
if vals . get ( ' department_id ' ) and not context . get ( ' default_department_id ' ) :
context [ ' default_department_id ' ] = vals . get ( ' department_id ' )
2014-02-11 12:23:41 +00:00
if vals . get ( ' job_id ' ) or context . get ( ' default_job_id ' ) :
job_id = vals . get ( ' job_id ' ) or context . get ( ' default_job_id ' )
vals . update ( self . onchange_job ( cr , uid , [ ] , job_id , context = context ) [ ' value ' ] )
2014-09-03 13:37:41 +00:00
if vals . get ( ' user_id ' ) :
vals [ ' date_open ' ] = fields . datetime . now ( )
if ' stage_id ' in vals :
vals . update ( self . onchange_stage_id ( cr , uid , None , vals . get ( ' stage_id ' ) , context = context ) [ ' value ' ] )
2012-02-28 05:21:14 +00:00
obj_id = super ( hr_applicant , self ) . create ( cr , uid , vals , context = context )
2012-12-18 16:31:30 +00:00
applicant = self . browse ( cr , uid , obj_id , context = context )
if applicant . job_id :
2014-02-11 10:58:07 +00:00
name = applicant . partner_name if applicant . partner_name else applicant . name
self . pool [ ' hr.job ' ] . message_post (
cr , uid , [ applicant . job_id . id ] ,
body = _ ( ' New application from %s ' ) % name ,
subtype = " hr_recruitment.mt_job_applicant_new " , context = context )
2012-02-28 05:21:14 +00:00
return obj_id
2012-02-24 08:01:01 +00:00
2013-07-08 09:11:56 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
if isinstance ( ids , ( int , long ) ) :
ids = [ ids ]
2013-12-20 09:26:44 +00:00
res = True
2014-03-17 09:54:33 +00:00
# user_id change: update date_open
2013-07-08 09:11:56 +00:00
if vals . get ( ' user_id ' ) :
2014-03-17 09:54:33 +00:00
vals [ ' date_open ' ] = fields . datetime . now ( )
2013-09-04 14:10:24 +00:00
# stage_id: track last stage before update
if ' stage_id ' in vals :
2013-08-19 09:31:36 +00:00
vals [ ' date_last_stage_update ' ] = fields . datetime . now ( )
2014-09-03 13:37:41 +00:00
vals . update ( self . onchange_stage_id ( cr , uid , ids , vals . get ( ' stage_id ' ) , context = context ) [ ' value ' ] )
2013-09-04 14:10:24 +00:00
for applicant in self . browse ( cr , uid , ids , context = None ) :
vals [ ' last_stage_id ' ] = applicant . stage_id . id
res = super ( hr_applicant , self ) . write ( cr , uid , [ applicant . id ] , vals , context = context )
2013-12-20 09:26:44 +00:00
else :
res = super ( hr_applicant , self ) . write ( cr , uid , ids , vals , context = context )
2014-02-11 10:58:07 +00:00
# post processing: if job changed, post a message on the job
2013-12-10 08:43:09 +00:00
if vals . get ( ' job_id ' ) :
2013-12-10 12:29:30 +00:00
for applicant in self . browse ( cr , uid , ids , context = None ) :
2014-02-11 10:58:07 +00:00
name = applicant . partner_name if applicant . partner_name else applicant . name
self . pool [ ' hr.job ' ] . message_post (
cr , uid , [ vals [ ' job_id ' ] ] ,
body = _ ( ' New application from %s ' ) % name ,
subtype = " hr_recruitment.mt_job_applicant_new " , context = context )
2013-12-20 09:26:44 +00:00
# post processing: if stage changed, post a message in the chatter
if vals . get ( ' stage_id ' ) :
stage = self . pool [ ' hr.recruitment.stage ' ] . browse ( cr , uid , vals [ ' stage_id ' ] , context = context )
if stage . template_id :
# TDENOTE: probably factorize me in a message_post_with_template generic method FIXME
compose_ctx = dict ( context ,
active_ids = ids )
compose_id = self . pool [ ' mail.compose.message ' ] . create (
cr , uid , {
' model ' : self . _name ,
' composition_mode ' : ' mass_mail ' ,
' template_id ' : stage . template_id . id ,
' post ' : True ,
' notify ' : True ,
} , context = compose_ctx )
2015-03-24 14:08:43 +00:00
values = self . pool [ ' mail.compose.message ' ] . onchange_template_id (
cr , uid , [ compose_id ] , stage . template_id . id , ' mass_mail ' , self . _name , False , context = compose_ctx ) [ ' value ' ]
if values . get ( ' attachment_ids ' ) :
values [ ' attachment_ids ' ] = [ ( 6 , 0 , values [ ' attachment_ids ' ] ) ]
2013-12-20 09:26:44 +00:00
self . pool [ ' mail.compose.message ' ] . write (
cr , uid , [ compose_id ] ,
2015-03-24 14:08:43 +00:00
values ,
2013-12-20 09:26:44 +00:00
context = compose_ctx )
self . pool [ ' mail.compose.message ' ] . send_mail ( cr , uid , [ compose_id ] , context = compose_ctx )
return res
2013-07-08 09:11:56 +00:00
def create_employee_from_applicant ( self , cr , uid , ids , context = None ) :
""" Create an hr.employee from the hr.applicants """
2012-03-20 16:50:27 +00:00
if context is None :
context = { }
2011-11-28 06:33:18 +00:00
hr_employee = self . pool . get ( ' hr.employee ' )
2011-11-30 07:02:26 +00:00
model_data = self . pool . get ( ' ir.model.data ' )
act_window = self . pool . get ( ' ir.actions.act_window ' )
emp_id = False
2012-03-20 16:50:27 +00:00
for applicant in self . browse ( cr , uid , ids , context = context ) :
2013-02-15 06:42:48 +00:00
address_id = contact_name = False
2011-11-28 06:33:18 +00:00
if applicant . partner_id :
2013-06-27 15:45:05 +00:00
address_id = self . pool . get ( ' res.partner ' ) . address_get ( cr , uid , [ applicant . partner_id . id ] , [ ' contact ' ] ) [ ' contact ' ]
contact_name = self . pool . get ( ' res.partner ' ) . name_get ( cr , uid , [ applicant . partner_id . id ] ) [ 0 ] [ 1 ]
2013-02-24 11:52:27 +00:00
if applicant . job_id and ( applicant . partner_name or contact_name ) :
2014-11-13 11:30:26 +00:00
applicant . job_id . write ( { ' no_of_hired_employee ' : applicant . job_id . no_of_hired_employee + 1 } )
2014-02-05 06:05:00 +00:00
create_ctx = dict ( context , mail_broadcast = True )
2013-06-27 15:45:05 +00:00
emp_id = hr_employee . create ( cr , uid , { ' name ' : applicant . partner_name or contact_name ,
2011-11-28 06:33:18 +00:00
' job_id ' : applicant . job_id . id ,
' address_home_id ' : address_id ,
2013-03-14 08:42:21 +00:00
' department_id ' : applicant . department_id . id or False ,
2013-08-26 07:26:57 +00:00
' address_id ' : applicant . company_id and applicant . company_id . partner_id and applicant . company_id . partner_id . id or False ,
2013-03-14 08:42:21 +00:00
' work_email ' : applicant . department_id and applicant . department_id . company_id and applicant . department_id . company_id . email or False ,
' work_phone ' : applicant . department_id and applicant . department_id . company_id and applicant . department_id . company_id . phone or False ,
2013-12-27 13:02:34 +00:00
} , context = create_ctx )
2012-03-20 16:50:27 +00:00
self . write ( cr , uid , [ applicant . id ] , { ' emp_id ' : emp_id } , context = context )
2014-02-11 10:58:07 +00:00
self . pool [ ' hr.job ' ] . message_post (
cr , uid , [ applicant . job_id . id ] ,
body = _ ( ' New Employee %s Hired ' ) % applicant . partner_name if applicant . partner_name else applicant . name ,
subtype = " hr_recruitment.mt_job_applicant_hired " , context = context )
2011-11-28 06:33:18 +00:00
else :
2013-02-24 11:52:27 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You must define an Applied Job and a Contact Name for this applicant. ' ) )
2011-11-30 07:02:26 +00:00
action_model , action_id = model_data . get_object_reference ( cr , uid , ' hr ' , ' open_view_employee_list ' )
2014-07-06 14:44:26 +00:00
dict_act_window = act_window . read ( cr , uid , [ action_id ] , [ ] ) [ 0 ]
2011-11-30 07:02:26 +00:00
if emp_id :
dict_act_window [ ' res_id ' ] = emp_id
dict_act_window [ ' view_mode ' ] = ' form,tree '
return dict_act_window
2011-02-16 12:04:50 +00:00
2013-03-21 13:31:39 +00:00
def get_empty_list_help ( self , cr , uid , help , context = None ) :
2014-07-06 14:44:26 +00:00
context = dict ( context or { } )
2013-03-21 13:31:39 +00:00
context [ ' empty_list_help_model ' ] = ' hr.job '
context [ ' empty_list_help_id ' ] = context . get ( ' default_job_id ' , None )
context [ ' empty_list_help_document_name ' ] = _ ( " job applicants " )
return super ( hr_applicant , self ) . get_empty_list_help ( cr , uid , help , context = context )
2013-03-04 15:13:55 +00:00
2010-03-02 12:48:29 +00:00
class hr_job ( osv . osv ) :
_inherit = " hr.job "
_name = " hr.job "
2012-06-25 11:31:33 +00:00
_inherits = { ' mail.alias ' : ' alias_id ' }
2013-04-02 06:50:52 +00:00
2013-09-06 05:52:34 +00:00
def _get_attached_docs ( self , cr , uid , ids , field_name , arg , context = None ) :
2013-09-12 05:47:39 +00:00
res = { }
2013-09-06 05:52:34 +00:00
attachment_obj = self . pool . get ( ' ir.attachment ' )
2013-09-12 05:47:39 +00:00
for job_id in ids :
2013-12-04 10:22:28 +00:00
applicant_ids = self . pool . get ( ' hr.applicant ' ) . search ( cr , uid , [ ( ' job_id ' , ' = ' , job_id ) ] , context = context )
2014-02-11 10:58:07 +00:00
res [ job_id ] = attachment_obj . search (
cr , uid , [
' | ' ,
' & ' , ( ' res_model ' , ' = ' , ' hr.job ' ) , ( ' res_id ' , ' = ' , job_id ) ,
' & ' , ( ' res_model ' , ' = ' , ' hr.applicant ' ) , ( ' res_id ' , ' in ' , applicant_ids )
] , context = context )
2013-09-04 13:28:08 +00:00
return res
2013-05-17 05:44:03 +00:00
2014-04-15 10:54:19 +00:00
def _count_all ( self , cr , uid , ids , field_name , arg , context = None ) :
2014-05-07 13:16:29 +00:00
Applicant = self . pool [ ' hr.applicant ' ]
return {
job_id : {
' application_count ' : Applicant . search_count ( cr , uid , [ ( ' job_id ' , ' = ' , job_id ) ] , context = context ) ,
' documents_count ' : len ( self . _get_attached_docs ( cr , uid , [ job_id ] , field_name , arg , context = context ) [ job_id ] )
}
for job_id in ids
}
2014-04-15 10:54:19 +00:00
2010-03-02 12:48:29 +00:00
_columns = {
2014-02-07 16:26:15 +00:00
' survey_id ' : fields . many2one ( ' survey.survey ' , ' Interview Form ' , help = " Choose an interview form for this job position and you will be able to print/answer this interview from all applicants who apply for this job " ) ,
2013-08-27 15:07:08 +00:00
' alias_id ' : fields . many2one ( ' mail.alias ' , ' Alias ' , ondelete = " restrict " , required = True ,
2012-08-06 01:27:17 +00:00
help = " Email alias for this job position. New emails will automatically "
" create new applicants for this job position. " ) ,
2014-02-11 12:04:33 +00:00
' address_id ' : fields . many2one ( ' res.partner ' , ' Job Location ' , help = " Address where employees are working " ) ,
2013-12-24 07:22:24 +00:00
' application_ids ' : fields . one2many ( ' hr.applicant ' , ' job_id ' , ' Applications ' ) ,
2014-04-15 10:54:19 +00:00
' application_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Applications ' , multi = True ) ,
2013-05-23 13:22:11 +00:00
' manager_id ' : fields . related ( ' department_id ' , ' manager_id ' , type = ' many2one ' , string = ' Department Manager ' , relation = ' hr.employee ' , readonly = True , store = True ) ,
2014-02-11 10:58:07 +00:00
' document_ids ' : fields . function ( _get_attached_docs , type = ' one2many ' , relation = ' ir.attachment ' , string = ' Applications ' ) ,
2014-04-15 10:54:19 +00:00
' documents_count ' : fields . function ( _count_all , type = ' integer ' , string = ' Documents ' , multi = True ) ,
2013-12-24 05:20:22 +00:00
' user_id ' : fields . many2one ( ' res.users ' , ' Recruitment Responsible ' , track_visibility = ' onchange ' ) ,
2014-02-11 12:04:33 +00:00
' color ' : fields . integer ( ' Color Index ' ) ,
2013-11-21 12:22:55 +00:00
}
2013-11-11 20:06:21 +00:00
def _address_get ( self , cr , uid , context = None ) :
user = self . pool . get ( ' res.users ' ) . browse ( cr , uid , uid , context = context )
return user . company_id . partner_id . id
2014-02-10 07:21:00 +00:00
2013-11-21 12:22:55 +00:00
_defaults = {
2013-11-11 20:06:21 +00:00
' address_id ' : _address_get
2010-03-02 12:48:29 +00:00
}
2012-08-14 10:51:14 +00:00
def _auto_init ( self , cr , context = None ) :
""" Installation hook to create aliases for all jobs and avoid constraint errors. """
2013-05-22 14:32:06 +00:00
return self . pool . get ( ' mail.alias ' ) . migrate_to_alias ( cr , self . _name , self . _table , super ( hr_job , self ) . _auto_init ,
2013-05-16 16:42:07 +00:00
' hr.applicant ' , self . _columns [ ' alias_id ' ] , ' name ' , alias_prefix = ' job+ ' , alias_defaults = { ' job_id ' : ' id ' } , context = context )
2012-08-07 14:27:36 +00:00
2012-06-25 11:31:33 +00:00
def create ( self , cr , uid , vals , context = None ) :
2013-05-22 14:32:06 +00:00
alias_context = dict ( context , alias_model_name = ' hr.applicant ' , alias_parent_model_name = self . _name )
job_id = super ( hr_job , self ) . create ( cr , uid , vals , context = alias_context )
2013-04-09 11:11:58 +00:00
job = self . browse ( cr , uid , job_id , context = context )
2013-05-16 16:42:07 +00:00
self . pool . get ( ' mail.alias ' ) . write ( cr , uid , [ job . alias_id . id ] , { ' alias_parent_thread_id ' : job_id , " alias_defaults " : { ' job_id ' : job_id } } , context )
2013-04-09 11:11:58 +00:00
return job_id
2012-07-05 12:54:17 +00:00
def unlink ( self , cr , uid , ids , context = None ) :
2012-07-05 14:17:06 +00:00
# Cascade-delete mail aliases as well, as they should not exist without the job position.
mail_alias = self . pool . get ( ' mail.alias ' )
alias_ids = [ job . alias_id . id for job in self . browse ( cr , uid , ids , context = context ) if job . alias_id ]
2012-07-05 12:54:17 +00:00
res = super ( hr_job , self ) . unlink ( cr , uid , ids , context = context )
2012-07-05 14:17:06 +00:00
mail_alias . unlink ( cr , uid , alias_ids , context = context )
2012-07-05 12:54:17 +00:00
return res
2012-08-16 14:44:03 +00:00
2012-05-17 09:58:16 +00:00
def action_print_survey ( self , cr , uid , ids , context = None ) :
2014-02-07 16:26:15 +00:00
job = self . browse ( cr , uid , ids , context = context ) [ 0 ]
survey_id = job . survey_id . id
return self . pool . get ( ' survey.survey ' ) . action_print_survey ( cr , uid , [ survey_id ] , context = context )
2012-06-14 14:41:59 +00:00
2014-02-11 10:58:07 +00:00
def action_get_attachment_tree_view ( self , cr , uid , ids , context = None ) :
2013-12-24 13:38:13 +00:00
#open attachments of job and related applicantions.
2014-02-11 10:58:07 +00:00
model , action_id = self . pool . get ( ' ir.model.data ' ) . get_object_reference ( cr , uid , ' base ' , ' action_attachment ' )
2013-12-24 13:38:13 +00:00
action = self . pool . get ( model ) . read ( cr , uid , action_id , context = context )
2013-12-04 10:22:28 +00:00
applicant_ids = self . pool . get ( ' hr.applicant ' ) . search ( cr , uid , [ ( ' job_id ' , ' in ' , ids ) ] , context = context )
2014-02-11 10:58:07 +00:00
action [ ' context ' ] = { ' default_res_model ' : self . _name , ' default_res_id ' : ids [ 0 ] }
action [ ' domain ' ] = str ( [ ' | ' , ' & ' , ( ' res_model ' , ' = ' , ' hr.job ' ) , ( ' res_id ' , ' in ' , ids ) , ' & ' , ( ' res_model ' , ' = ' , ' hr.applicant ' ) , ( ' res_id ' , ' in ' , applicant_ids ) ] )
2013-12-24 13:38:13 +00:00
return action
2013-04-09 11:11:58 +00:00
2014-02-11 12:04:33 +00:00
def action_set_no_of_recruitment ( self , cr , uid , id , value , context = None ) :
return self . write ( cr , uid , [ id ] , { ' no_of_recruitment ' : value } , context = context )
2013-04-09 11:11:58 +00:00
2012-08-16 14:44:03 +00:00
class applicant_category ( osv . osv ) :
""" Category of applicant """
_name = " hr.applicant_category "
_description = " Category of applicant "
_columns = {
2014-05-21 09:52:05 +00:00
' name ' : fields . char ( ' Name ' , required = True , translate = True ) ,
2010-03-02 12:48:29 +00:00
}
2010-05-11 13:54:14 +00:00
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: