diff --git a/addons/hr_recruitment/hr_recruitment.py b/addons/hr_recruitment/hr_recruitment.py
index e88c55df98c..e7a1f47ae55 100644
--- a/addons/hr_recruitment/hr_recruitment.py
+++ b/addons/hr_recruitment/hr_recruitment.py
@@ -36,6 +36,7 @@ AVAILABLE_PRIORITIES = [
('3', 'Excellent')
]
+
class hr_recruitment_source(osv.osv):
""" Sources of HR Recruitment """
_name = "hr.recruitment.source"
@@ -95,10 +96,14 @@ class hr_recruitment_stage(osv.osv):
_name = "hr.recruitment.stage"
_description = "Stage of Recruitment"
_order = 'sequence'
+
_columns = {
- 'name': fields.char('Name', required=True, translate=True),
+ 'name': fields.char('Stage Name', required=True, translate=True),
'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of stages."),
- '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."),
+ 'case_default': fields.boolean(
+ 'Default for New Recruitment',
+ help="If you check this field, this stage will be proposed by default on each new Recruitment. It will not assign this stage to existing Recruitments."),
+ 'job_ids': fields.many2many('hr.job', 'job_stage_rel', 'stage_id', 'job_id', 'Job Stages'),
'requirements': fields.text('Requirements'),
'template_id': fields.many2one('mail.template', 'Use template', help="If set, a message is posted on the applicant using the template when the applicant is set to the stage."),
'legend_priority': fields.text(
@@ -108,10 +113,13 @@ class hr_recruitment_stage(osv.osv):
help='This stage is folded in the kanban view when'
'there are no records in that stage to display.'),
}
+
_defaults = {
'sequence': 1,
+ 'job_ids': lambda self, cr, uid, context=None: [context['default_job_id']] if context and context.get('default_job_id') else None,
}
+
class hr_recruitment_degree(osv.osv):
""" Degree of HR Recruitment """
_name = "hr.recruitment.degree"
@@ -127,6 +135,7 @@ class hr_recruitment_degree(osv.osv):
('name_uniq', 'unique (name)', 'The name of the Degree of Recruitment must be unique!')
]
+
class hr_applicant(osv.Model):
_name = "hr.applicant"
_description = "Applicant"
@@ -134,30 +143,9 @@ class hr_applicant(osv.Model):
_inherit = ['mail.thread', 'ir.needaction_mixin', 'utm.mixin']
_mail_mass_mailing = _('Applicants')
- def _get_default_department_id(self, cr, uid, context=None):
- """ Gives default department by checking if present in the context """
- return (self._resolve_department_id_from_context(cr, uid, context=context) or False)
-
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)
- return self.stage_find(cr, uid, [], department_id, [('fold', '=', False)], context=context)
-
- 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
+ job_id = context and context.get('default_job_id')
+ return self.stage_find(cr, uid, [], job_id, [('fold', '=', False)], context=context)
def _get_default_company_id(self, cr, uid, department_id=None, context=None):
company_id = False
@@ -175,15 +163,14 @@ class hr_applicant(osv.Model):
# lame hack to allow reverting search, should just work in the trivial case
if read_group_order == 'stage_id desc':
order = "%s desc" % order
- # 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
- department_id = self._resolve_department_id_from_context(cr, uid, context=context)
+ # retrieve job_id from the context and write the domain: ids + contextual columns (job or default)
+ job_id = context and context.get('default_job_id')
search_domain = []
- if department_id:
- search_domain += ['|', ('department_id', '=', department_id)]
- search_domain += ['|', ('id', 'in', ids), ('department_id', '=', False)]
+ if job_id:
+ search_domain += ['|', ('job_ids', '=', job_id)]
+ else:
+ search_domain += ['|', ('case_default', '=', True)]
+ search_domain += [('id', 'in', ids)]
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
@@ -233,8 +220,9 @@ class hr_applicant(osv.Model):
'partner_id': fields.many2one('res.partner', 'Contact'),
'create_date': fields.datetime('Creation Date', readonly=True, select=True),
'write_date': fields.datetime('Update Date', readonly=True),
- 'stage_id': fields.many2one ('hr.recruitment.stage', 'Stage', track_visibility='onchange',
- domain="['|', ('department_id', '=', department_id), ('department_id', '=', False)]"),
+ 'stage_id': fields.many2one(
+ 'hr.recruitment.stage', 'Stage', track_visibility='onchange',
+ domain="['|', ('case_default', '=', True), ('job_ids', '=', job_id)]", copy=False, select=1),
'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.'),
'categ_ids': fields.many2many('hr.applicant.category', string='Tags'),
@@ -276,9 +264,8 @@ class hr_applicant(osv.Model):
_defaults = {
'active': lambda *a: 1,
'user_id': lambda s, cr, uid, c: uid,
- '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),
- 'company_id': lambda s, cr, uid, c: s._get_default_company_id(cr, uid, s._get_default_department_id(cr, uid, c), c),
+ 'stage_id': _get_default_stage_id,
+ 'company_id': lambda s, cr, uid, c: s._get_default_company_id(cr, uid, c and c.get('default_department_id'), c),
'color': 0,
'priority': '0',
'date_last_stage_update': fields.datetime.now,
@@ -296,23 +283,16 @@ class hr_applicant(osv.Model):
action['res_id'] = applicant and applicant.emp_id.id or False
return action
- def onchange_job(self, cr, uid, ids, job_id=False, context=None):
+ def onchange_job(self, cr, uid, ids, job_id=False, stage_id=False, context=None):
department_id = False
user_id = False
if job_id:
job_record = self.pool.get('hr.job').browse(cr, uid, job_id, context=context)
department_id = job_record and job_record.department_id and job_record.department_id.id or False
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}}
-
- def onchange_department_id(self, cr, uid, ids, department_id=False, stage_id=False, context=None):
- values = {}
- if not stage_id:
- 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}
+ if not stage_id and job_id:
+ stage_id = self.stage_find(cr, uid, [], job_id, [('fold', '=', False)], context=context)
+ return {'value': {'department_id': department_id, 'user_id': user_id, 'stage_id': stage_id}}
def onchange_partner_id(self, cr, uid, ids, partner_id, context=None):
data = {'partner_phone': False,
@@ -333,30 +313,26 @@ class hr_applicant(osv.Model):
return {'value': {'date_closed': fields.datetime.now()}}
return {'value': {'date_closed': False}}
- def stage_find(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
+ def stage_find(self, cr, uid, applicants, job_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
+ - job_id: if set, stages must belong to this section or
be a default case
"""
- if isinstance(cases, (int, long)):
- cases = self.browse(cr, uid, cases, context=context)
- # collect all section_ids
- department_ids = []
- if section_id:
- department_ids.append(section_id)
- for case in cases:
- 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))
+ if isinstance(applicants, (int, long)):
+ applicants = self.browse(cr, uid, applicants, context=context)
+ job_ids = set([applicant.job_id.id for applicant in applicants if applicant.job_id])
+ if job_id:
+ job_ids.add(job_id)
+ # OR all job_id and OR with applicant_default
+ if job_ids:
+ search_domain = ['|', ('case_default', '=', True), ('job_ids', 'in', list(job_ids))]
+ else:
+ search_domain = [('case_default', '=', True)]
# 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)
+ stage_ids = self.pool.get('hr.recruitment.stage').search(cr, uid, search_domain, order=order, limit=1, context=context)
if stage_ids:
return stage_ids[0]
return False
@@ -605,15 +581,12 @@ class hr_job(osv.osv):
_name = "hr.job"
_inherits = {'mail.alias': 'alias_id'}
-
-
def _track_subtype(self, cr, uid, ids, init_values, context=None):
record = self.browse(cr, uid, ids[0], context=context)
if 'state' in init_values and record.state == 'open':
return 'hr_recruitment.mt_job_new'
return super(hr_job, self)._track_subtype(cr, uid, ids, init_values, context=context)
-
def _get_attached_docs(self, cr, uid, ids, field_name, arg, context=None):
res = {}
attachment_obj = self.pool.get('ir.attachment')
@@ -646,6 +619,7 @@ class hr_job(osv.osv):
'application_ids': fields.one2many('hr.applicant', 'job_id', 'Applications'),
'application_count': fields.function(_count_all, type='integer', string='Applications', multi=True),
'manager_id': fields.related('department_id', 'manager_id', type='many2one', string='Department Manager', relation='hr.employee', readonly=True, store=True),
+ 'stage_ids': fields.many2many('hr.recruitment.stage', 'job_stage_rel', 'job_id', 'stage_id', 'Job Stages'),
'document_ids': fields.function(_get_attached_docs, type='one2many', relation='ir.attachment', string='Applications'),
'documents_count': fields.function(_count_all, type='integer', string='Documents', multi=True),
'user_id': fields.many2one('res.users', 'Recruitment Responsible', track_visibility='onchange'),
@@ -656,8 +630,12 @@ class hr_job(osv.osv):
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
return user.company_id.partner_id.id
+ def _get_type_common(self, cr, uid, context=None):
+ return self.pool['hr.recruitment.stage'].search(cr, uid, [('case_default', '=', True)], context=context)
+
_defaults = {
- 'address_id': _address_get
+ 'address_id': _address_get,
+ 'stage_ids': _get_type_common,
}
def _auto_init(self, cr, context=None):
diff --git a/addons/hr_recruitment/hr_recruitment_data.xml b/addons/hr_recruitment/hr_recruitment_data.xml
index 15a625ecb42..9dc711971de 100644
--- a/addons/hr_recruitment/hr_recruitment_data.xml
+++ b/addons/hr_recruitment/hr_recruitment_data.xml
@@ -93,30 +93,36 @@
Initial Qualification
1
+
First Interview
2
+
Second Interview
3
+
- Contract Proposed
+ Contract Proposal
4
+
Contract Signed
5
+
Refused
6
+
diff --git a/addons/hr_recruitment/hr_recruitment_demo.xml b/addons/hr_recruitment/hr_recruitment_demo.xml
index 03d31d0851d..8c828a7bde7 100644
--- a/addons/hr_recruitment/hr_recruitment_demo.xml
+++ b/addons/hr_recruitment/hr_recruitment_demo.xml
@@ -127,34 +127,41 @@
recruit
4
+
+
+
recruit
1
+
1
recruit
+
recruit
3
+
recruit
6
+
- -->
+
hr.applicant
diff --git a/addons/hr_recruitment/hr_recruitment_view.xml b/addons/hr_recruitment/hr_recruitment_view.xml
index 6cc630bff22..aa7c902430e 100644
--- a/addons/hr_recruitment/hr_recruitment_view.xml
+++ b/addons/hr_recruitment/hr_recruitment_view.xml
@@ -60,7 +60,7 @@