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-12-06 14:56:32 +00:00
from openerp import tools
2010-08-02 09:57:42 +00:00
2012-08-23 15:32:03 +00:00
from datetime import datetime
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
from openerp . tools import html2plaintext
2010-02-28 20:36:51 +00:00
AVAILABLE_PRIORITIES = [
2011-08-18 19:30:44 +00:00
( ' ' , ' ' ) ,
2010-05-14 09:29:24 +00:00
( ' 5 ' , ' Not Good ' ) ,
( ' 4 ' , ' On Average ' ) ,
( ' 3 ' , ' Good ' ) ,
( ' 2 ' , ' Very Good ' ) ,
2010-05-12 08:36:32 +00:00
( ' 1 ' , ' 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 = {
' name ' : fields . char ( ' Source Name ' , size = 64 , required = True , translate = True ) ,
}
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 = {
2010-05-12 05:56:48 +00:00
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
' 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 = {
' name ' : fields . char ( ' Name ' , size = 64 , required = True , translate = True ) ,
' 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 "
2010-02-28 20:36:51 +00:00
_order = " id desc "
2012-08-22 15:31:45 +00:00
_inherit = [ ' mail.thread ' , ' ir.needaction_mixin ' ]
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
} ,
}
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
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 ) :
"""
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of Openday ’ s IDs
@return : difference between current date and log date
@param context : A standard dictionary for contextual values
"""
res = { }
for issue in self . browse ( cr , uid , ids , context = context ) :
for field in fields :
res [ issue . id ] = { }
duration = 0
ans = False
hours = 0
if field in [ ' day_open ' ] :
if issue . date_open :
date_create = datetime . strptime ( issue . create_date , " % Y- % m- %d % H: % M: % S " )
date_open = datetime . strptime ( issue . date_open , " % Y- % m- %d % H: % M: % S " )
ans = date_open - date_create
elif field in [ ' day_close ' ] :
if issue . date_closed :
date_create = datetime . strptime ( issue . create_date , " % Y- % m- %d % H: % M: % S " )
date_close = datetime . strptime ( issue . date_closed , " % Y- % m- %d % H: % M: % S " )
ans = date_close - date_create
if ans :
duration = float ( ans . days )
res [ issue . id ] [ field ] = abs ( float ( duration ) )
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 = {
2013-09-10 13:17:04 +00:00
' name ' : fields . char ( ' Subject / Application Name ' , size = 128 , 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 ' ) ,
2011-08-18 19:30:44 +00:00
' salary_proposed_extra ' : fields . char ( ' Proposed Salary Extra ' , size = 100 , help = " Salary Proposed by the Organisation, extra advantages " ) ,
' salary_expected_extra ' : fields . char ( ' Expected Salary Extra ' , size = 100 , 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 " ) ,
2010-02-28 20:36:51 +00:00
' partner_name ' : fields . char ( " Applicant ' s Name " , size = 64 ) ,
' 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 ' ) ,
' survey ' : fields . related ( ' job_id ' , ' survey_id ' , type = ' many2one ' , relation = ' survey ' , string = ' Survey ' ) ,
' response ' : fields . integer ( " Response " ) ,
2012-05-17 09:34:46 +00:00
' reference ' : fields . char ( ' Referred By ' , size = 128 ) ,
2011-08-18 19:30:44 +00:00
' source_id ' : fields . many2one ( ' hr.recruitment.source ' , ' Source ' ) ,
2010-08-02 09:57:42 +00:00
' day_open ' : fields . function ( _compute_day , string = ' Days to Open ' , \
2011-07-05 12:28:57 +00:00
multi = ' day_open ' , type = " float " , store = True ) ,
2010-08-02 09:57:42 +00:00
' day_close ' : fields . function ( _compute_day , string = ' Days to Close ' , \
2011-07-05 12:28:57 +00:00
multi = ' day_close ' , type = " float " , store = True ) ,
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 ) ,
2012-07-05 12:22:07 +00:00
' company_id ' : lambda s , cr , uid , c : s . pool . get ( ' res.company ' ) . _company_default_get ( cr , uid , ' hr.applicant ' , context = c ) ,
2011-09-16 12:03:52 +00:00
' color ' : 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
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
return { ' value ' : { ' department_id ' : department_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 ) :
if not stage_id :
2013-10-23 11:55:05 +00:00
stage_id = self . stage_find ( cr , uid , [ ] , department_id , [ ( ' fold ' , ' = ' , False ) ] , context = context )
2011-03-04 07:25:51 +00:00
return { ' value ' : { ' stage_id ' : stage_id } }
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 }
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 )
res = self . pool . get ( ' ir.actions.act_window ' ) . for_xml_id ( cr , uid , ' base_calendar ' , ' action_crm_meeting ' , context )
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
2010-04-07 13:46:01 +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 ) .
@param self : The object pointer
@param cr : the current row , from the database cursor ,
@param uid : the current user ’ s ID for security checks ,
@param ids : List of Survey IDs
@param context : A standard dictionary for contextual values
2010-10-27 12:49:59 +00:00
@return : Dictionary value for print survey form .
2010-04-07 13:46:01 +00:00
"""
2010-11-23 07:05:05 +00:00
if context is None :
2010-04-07 13:46:01 +00:00
context = { }
2010-07-27 07:11:45 +00:00
record = self . browse ( cr , uid , ids , context = context )
2010-04-08 05:25:40 +00:00
record = record and record [ 0 ]
2010-10-27 12:49:59 +00:00
context . update ( { ' survey_id ' : record . survey . id , ' response_id ' : [ record . response ] , ' response_no ' : 0 , } )
2010-11-19 13:48:01 +00:00
value = self . pool . get ( " survey " ) . action_print_survey ( cr , uid , ids , context = context )
2010-04-09 11:22:38 +00:00
return value
2010-06-24 19:53:32 +00:00
2013-12-20 10:29:18 +00:00
def action_get_attachment_tree_view ( self , cr , uid , ids , context ) :
domain = [ ' & ' , ( ' res_model ' , ' = ' , ' hr.applicant ' ) , ( ' res_id ' , ' in ' , ids ) ]
return {
' name ' : _ ( ' Attachments ' ) ,
' domain ' : domain ,
' res_model ' : ' ir.attachment ' ,
' type ' : ' ir.actions.act_window ' ,
' view_id ' : False ,
' view_mode ' : ' tree,form ' ,
' view_type ' : ' form ' ,
' limit ' : 80 ,
' context ' : " { ' default_res_model ' : ' %s ' } " % ( self . _name )
}
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 " ) ,
2013-02-06 11:32:01 +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 ) :
2013-06-19 11:46:33 +00:00
if context is None :
context = { }
if vals . get ( ' department_id ' ) and not context . get ( ' default_department_id ' ) :
context [ ' default_department_id ' ] = vals . get ( ' department_id ' )
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 :
self . pool . get ( ' hr.job ' ) . message_post ( cr , uid , [ applicant . job_id . id ] , body = _ ( ' Applicant <b>created</b> ' ) , subtype = " hr_recruitment.mt_job_new_applicant " , 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
2013-07-08 09:11:56 +00:00
# user_id change: update date_start
if vals . get ( ' user_id ' ) :
vals [ ' date_start ' ] = 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 ( )
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 )
# 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 ,
' same_thread ' : True ,
' post ' : True ,
' notify ' : True ,
} , context = compose_ctx )
self . pool [ ' mail.compose.message ' ] . write (
cr , uid , [ compose_id ] ,
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 ' ] ,
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 ) :
2011-11-28 06:33:18 +00:00
applicant . job_id . write ( { ' no_of_recruitment ' : applicant . job_id . no_of_recruitment - 1 } )
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 ,
2011-11-28 06:33:18 +00:00
} )
2012-03-20 16:50:27 +00:00
self . write ( cr , uid , [ applicant . id ] , { ' emp_id ' : emp_id } , 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 ' )
dict_act_window = act_window . read ( cr , uid , action_id , [ ] )
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
2011-12-06 17:37:55 +00:00
def set_priority ( self , cr , uid , ids , priority , * args ) :
""" Set applicant priority
2011-09-16 12:03:52 +00:00
"""
2012-11-19 14:20:59 +00:00
return self . write ( cr , uid , ids , { ' priority ' : priority } )
2011-09-16 12:03:52 +00:00
def set_high_priority ( self , cr , uid , ids , * args ) :
2011-12-06 17:37:55 +00:00
""" Set applicant priority to high
2011-09-16 12:03:52 +00:00
"""
return self . set_priority ( cr , uid , ids , ' 1 ' )
def set_normal_priority ( self , cr , uid , ids , * args ) :
2011-12-06 17:37:55 +00:00
""" Set applicant priority to normal
2011-09-16 12:03:52 +00:00
"""
return self . set_priority ( cr , uid , ids , ' 3 ' )
2010-08-02 09:57:42 +00:00
2013-03-21 13:31:39 +00:00
def get_empty_list_help ( self , cr , uid , help , context = None ) :
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 ' }
2010-03-02 12:48:29 +00:00
_columns = {
2011-11-08 10:21:53 +00:00
' survey_id ' : fields . many2one ( ' 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. " ) ,
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 ) :
if context is None :
context = { }
2012-05-22 09:55:32 +00:00
datas = { }
record = self . browse ( cr , uid , ids , context = context ) [ 0 ]
if record . survey_id :
datas [ ' ids ' ] = [ record . survey_id . id ]
datas [ ' model ' ] = ' survey.print '
2013-04-09 11:11:58 +00:00
context . update ( { ' response_id ' : [ 0 ] , ' response_no ' : 0 } )
2012-05-22 09:55:32 +00:00
return {
2012-10-02 10:29:15 +00:00
' type ' : ' ir.actions.report.xml ' ,
' report_name ' : ' survey.form ' ,
' datas ' : datas ,
2013-04-09 11:11:58 +00:00
' context ' : context ,
' nodestroy ' : True ,
2012-10-02 10:29:15 +00:00
}
2012-06-14 14:41:59 +00:00
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 = {
' name ' : fields . char ( ' Name ' , size = 64 , 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: