[REF] hr_recruitment: removed base_stage inheritance, state field. Updated views / reports. Still not updated subtypes.

bzr revid: tde@openerp.com-20130627094807-8vg21s2w0lqblrza
This commit is contained in:
Thibault Delavallée 2013-06-27 11:48:07 +02:00
parent 75771769d2
commit 9dfa8563ef
7 changed files with 36 additions and 175 deletions

View File

@ -22,7 +22,7 @@
<field name="res_model">hr.applicant</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state','in',('draft','open'))]</field>
<field name="domain">[('stage_id.fold', '!=', True)]</field>
<field name="view_id" ref="view_applicants_status_tree"/>
</record>

View File

@ -19,23 +19,13 @@
#
##############################################################################
import time
from openerp import tools
from openerp.addons.base_status.base_stage import base_stage
from datetime import datetime
from openerp.osv import fields, osv
from openerp.tools.translate import _
from openerp.tools import html2plaintext
AVAILABLE_STATES = [
('draft', 'New'),
('cancel', 'Refused'),
('open', 'In Progress'),
('pending', 'Pending'),
('done', 'Hired')
]
AVAILABLE_PRIORITIES = [
('', ''),
('5', 'Not Good'),
@ -62,13 +52,11 @@ class hr_recruitment_stage(osv.osv):
'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."),
'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."),
'state': fields.selection(AVAILABLE_STATES, 'Status', required=True, help="The related status for the stage. The status of your document will automatically change according to the selected stage. Example, a stage is related to the status 'Close', when your document reach this stage, it will be automatically closed."),
'fold': fields.boolean('Hide in views if empty', help="This stage is not visible, for example in status bar or kanban view, when there are no records in that stage to display."),
'requirements': fields.text('Requirements'),
}
_defaults = {
'sequence': 1,
'state': 'draft',
'fold': False,
}
@ -87,19 +75,19 @@ class hr_recruitment_degree(osv.osv):
('name_uniq', 'unique (name)', 'The name of the Degree of Recruitment must be unique!')
]
class hr_applicant(base_stage, osv.Model):
class hr_applicant(osv.Model):
_name = "hr.applicant"
_description = "Applicant"
_order = "id desc"
_inherit = ['mail.thread', 'ir.needaction_mixin']
_track = {
'state': {
'hr_recruitment.mt_applicant_hired': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done',
'hr_recruitment.mt_applicant_refused': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel',
},
'stage_id': {
'hr_recruitment.mt_stage_changed': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['done', 'cancel'],
},
# 'state': {
# 'hr_recruitment.mt_applicant_hired': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done',
# 'hr_recruitment.mt_applicant_refused': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'cancel',
# },
# 'stage_id': {
# 'hr_recruitment.mt_stage_changed': lambda self, cr, uid, obj, ctx=None: obj['state'] not in ['done', 'cancel'],
# },
}
def _get_default_department_id(self, cr, uid, context=None):
@ -109,7 +97,7 @@ class hr_applicant(base_stage, osv.Model):
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, [('state', '=', 'draft')], context=context)
return self.stage_find(cr, uid, [], department_id, [('sequence', '=', '1')], 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'
@ -197,13 +185,6 @@ class hr_applicant(base_stage, osv.Model):
'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)]"),
'state': fields.related('stage_id', 'state', type="selection", store=True,
selection=AVAILABLE_STATES, string="Status", readonly=True,
help='The status is set to \'Draft\', when a case is created.\
If the case is in progress the status is set to \'Open\'.\
When the case is over, the status is set to \'Done\'.\
If the case needs to be reviewed then the status is \
set to \'Pending\'.'),
'categ_ids': fields.many2many('hr.applicant_category', string='Tags'),
'company_id': fields.many2one('res.company', 'Company'),
'user_id': fields.many2one('res.users', 'Responsible', track_visibility='onchange'),
@ -409,20 +390,6 @@ class hr_applicant(base_stage, osv.Model):
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)
return obj_id
def case_open(self, cr, uid, ids, context=None):
"""
open Request of the applicant for the hr_recruitment
"""
res = super(hr_applicant, self).case_open(cr, uid, ids, context)
date = self.read(cr, uid, ids, ['date_open'])[0]
if not date['date_open']:
self.write(cr, uid, ids, {'date_open': time.strftime('%Y-%m-%d %H:%M:%S'),})
return res
def case_close(self, cr, uid, ids, context=None):
res = super(hr_applicant, self).case_close(cr, uid, ids, context)
return res
def case_close_with_emp(self, cr, uid, ids, context=None):
if context is None:
context = {}
@ -454,26 +421,6 @@ class hr_applicant(base_stage, osv.Model):
dict_act_window['view_mode'] = 'form,tree'
return dict_act_window
def case_cancel(self, cr, uid, ids, context=None):
"""Overrides cancel for crm_case for setting probability
"""
res = super(hr_applicant, self).case_cancel(cr, uid, ids, context)
self.write(cr, uid, ids, {'probability': 0.0})
return res
def case_pending(self, cr, uid, ids, context=None):
"""Marks case as pending"""
res = super(hr_applicant, self).case_pending(cr, uid, ids, context)
self.write(cr, uid, ids, {'probability': 0.0})
return res
def case_reset(self, cr, uid, ids, context=None):
"""Resets case as draft
"""
res = super(hr_applicant, self).case_reset(cr, uid, ids, context)
self.write(cr, uid, ids, {'date_open': False, 'date_closed': False})
return res
def set_priority(self, cr, uid, ids, priority, *args):
"""Set applicant priority
"""

View File

@ -51,34 +51,29 @@
<field name="name">Doctoral Degree</field>
<field name="sequence">4</field>
</record>
<record model="hr.recruitment.stage" id="stage_job1">
<field name="name">Initial Qualification</field>
<field name="state">draft</field>
<field name="sequence">1</field>
</record>
<record model="hr.recruitment.stage" id="stage_job2">
<field name="name">First Interview</field>
<field name="state">open</field>
<field name="sequence">2</field>
</record>
<record model="hr.recruitment.stage" id="stage_job3">
<field name="name">Second Interview</field>
<field name="state">open</field>
<field name="sequence">3</field>
</record>
<record model="hr.recruitment.stage" id="stage_job4">
<field name="name">Contract Proposed</field>
<field name="state">pending</field>
<field name="sequence">4</field>
</record>
<record model="hr.recruitment.stage" id="stage_job5">
<field name="name">Contract Signed</field>
<field name="state">done</field>
<field name="sequence">5</field>
</record>
<record model="hr.recruitment.stage" id="stage_job6">
<field name="name">Refused</field>
<field name="state">cancel</field>
<field name="sequence">6</field>
<field name="fold" eval="True"/>
</record>
@ -467,24 +462,24 @@
<field name="res_model">hr.job</field>
</record>
<!-- Applicant-related subtypes for messaging / Chatter -->
<record id="mt_stage_changed" model="mail.message.subtype">
<record id="mt_applicant_new" model="mail.message.subtype">
<field name="name">New Applicant</field>
<field name="res_model">hr.applicant</field>
<field name="default" eval="False"/>
<field name="description">Applicant created</field>
</record>
<record id="mt_applicant_stage_changed" model="mail.message.subtype">
<field name="name">Stage Changed</field>
<field name="res_model">hr.applicant</field>
<field name="default" eval="False"/>
<field name="description">Stage changed</field>
</record>
<record id="mt_applicant_hired" model="mail.message.subtype">
<record id="mt_applicant_employee" model="mail.message.subtype">
<field name="name">Applicant Hired</field>
<field name="res_model">hr.applicant</field>
<field name="default" eval="False"/>
<field name="description">Applicant hired</field>
</record>
<record id="mt_applicant_refused" model="mail.message.subtype">
<field name="name">Applicant Refused</field>
<field name="res_model">hr.applicant</field>
<field name="default" eval="False"/>
<field name="description">Applicant refused</field>
</record>
<!-- Applicant Categories(Tag) -->
<record id="tag_applicant_reserve" model="hr.applicant_category">
<field name="name">Reserve</field>

View File

@ -39,7 +39,7 @@
<field name="name">Applicants</field>
<field name="model">hr.applicant</field>
<field name="arch" type="xml">
<tree string="Applicants" fonts="bold:message_unread==True" colors="grey:state in ('cancel','done');blue:state=='pending'">
<tree string="Applicants" fonts="bold:message_unread==True">
<field name="message_unread" invisible="1"/>
<field name="create_date"/>
<field name="name" string="Subject"/>
@ -58,7 +58,6 @@
<field name="availability" invisible="1"/>
<field name="department_id" invisible="context.get('invisible_department', True)"/>
<field name="user_id"/>
<field name="state" invisible="1"/>
</tree>
</field>
</record>
@ -69,11 +68,9 @@
<field name="arch" type="xml">
<form string="Jobs - Recruitment Form" version="7.0">
<header>
<button name="case_close_with_emp" string="Hire &amp; Create Employee" type="object"
<!-- <button name="case_close_with_emp" string="Hire &amp; Create Employee" type="object"
class="oe_highlight"
attrs="{'invisible':['|', ('emp_id','!=',False), ('state','=','cancel')]}"/>
<button name="case_cancel" string="Refuse" type="object"
states="draft,open,pending" class="oe_highlight"/>
attrs="{'invisible':[('emp_id','!=',False)]}"/> -->
<field name="stage_id" widget="statusbar" clickable="True"/>
<field name="emp_id" invisible="1"/>
</header>
@ -115,7 +112,6 @@
<field name="title_action" class="oe_inline" placeholder="e.g. Call for interview"/>
</div>
<field name="priority"/>
<field name="state" invisible="1"/>
<field name="source_id"/>
<field name="reference"/>
</group>
@ -165,7 +161,7 @@
<graph string="Cases By Stage and Estimates" type="bar" orientation="vertical">
<field name="job_id"/>
<field name="salary_expected" operator="+"/>
<field name="state" group="True"/>
<field name="stage_id" group="True"/>
</graph>
</field>
</record>
@ -176,14 +172,11 @@
<field name="arch" type="xml">
<search string="Search Jobs">
<field name="partner_name" filter_domain="['|','|',('name','ilike',self),('partner_name','ilike',self),('email_from','ilike',self)]" string="Subject / Applicant"/>
<filter string="Unassigned" domain="[('user_id', '=', False)]"/>
<filter string="My" domain="[('user_id', '=', uid)]"/>
<separator/>
<filter string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
<separator/>
<filter string="New" domain="[('state','=','draft')]" help="All Initial Jobs"/>
<filter string="In Progress" domain="[('state','=','open')]" help="Open Jobs"/>
<filter string="Pending" domain="[('state','=','pending')]" help="Pending Jobs"/>
<separator/>
<filter string="Unassigned Recruitments" domain="[('user_id','=',False)]" help="Unassigned Recruitments"/>
<separator/>
<filter string="Next Actions" context="{'invisible_next_action':False, 'invisible_next_date':False}"
domain="[('date_action','&lt;&gt;',False)]" help="Filter and view on next actions and date"/>
<field name="job_id"/>
@ -342,7 +335,6 @@
<field name="sequence" invisible="1"/>
<field name="name"/>
<field name="department_id"/>
<field name="state"/>
</tree>
</field>
</record>
@ -360,7 +352,6 @@
<field name="department_id"/>
</group>
<group>
<field name="state"/>
<field name="sequence"/>
<field name="fold"/>
</group>

View File

@ -18,20 +18,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import tools
from openerp.osv import fields,osv
from openerp.osv import fields, osv
from .. import hr_recruitment
from openerp.addons.decimal_precision import decimal_precision as dp
AVAILABLE_STATES = [
('draft','New'),
('open','Open'),
('cancel', 'Refused'),
('done', 'Hired'),
('pending','Pending')
]
class hr_recruitment_report(osv.osv):
_name = "hr.recruitment.report"
_description = "Recruitments Statistics"
@ -41,7 +34,7 @@ class hr_recruitment_report(osv.osv):
_columns = {
'user_id': fields.many2one('res.users', 'User', readonly=True),
'nbr': fields.integer('# of Applications', readonly=True),
'state': fields.selection(AVAILABLE_STATES, 'Status', size=16, readonly=True),
# TDE TODO: use MONTHS
'month':fields.selection([('01', 'January'), ('02', 'February'), \
('03', 'March'), ('04', 'April'),\
('05', 'May'), ('06', 'June'), \
@ -79,7 +72,6 @@ class hr_recruitment_report(osv.osv):
to_char(s.create_date, 'YYYY') as year,
to_char(s.create_date, 'MM') as month,
to_char(s.create_date, 'YYYY-MM-DD') as day,
s.state,
s.partner_id,
s.company_id,
s.user_id,
@ -105,7 +97,6 @@ class hr_recruitment_report(osv.osv):
s.date_open,
s.create_date,
s.date_closed,
s.state,
s.partner_id,
s.company_id,
s.user_id,

View File

@ -14,7 +14,6 @@
<field name="type_id" invisible="1"/>
<field name="partner_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company" invisible="1"/>
<field name="state" invisible="1"/>
<field name="year" invisible="1"/>
<field name="day" invisible="1"/>
<field name="month" invisible="1"/>
@ -46,17 +45,15 @@
<field name="model">hr.recruitment.report</field>
<field name="arch" type="xml">
<search string="Recruitment Analysis">
<filter string="New" icon="terp-document-new" domain="[('state','=','draft')]" help = "Draft recruitment"/>
<filter string="In progress" icon="terp-camera_test" domain="[('state', '=' ,'open')]" help = "In progress recruitment"/>
<filter string="Pending" icon="terp-gtk-media-pause" domain="[('state','=','pending')]" help = "Pending recruitment"/>
<filter string="Hired" icon="terp-camera_test" domain="[('state','=','done')]" help = "Hired employees"/>
<separator/>
<filter icon="terp-personal" string="My Recruitment" help="My Recruitment" domain="[('user_id','=',uid)]"/>
<field name="job_id"/>
<field name="department_id"/>
<field name="user_id" string="Responsible"/>
<field name="user_id"/>
<filter string="New" domain="[('sequence', '=', 1)]"/>
<separator/>
<filter string="Unassigned" domain="[('user_id', '=', False)]"/>
<filter string="My" domain="[('user_id', '=', uid)]"/>
<separator/>
<group expand="0" string="Extended Filters...">
<!--field name="job_id"/-->
<field name="priority"/>
<field name="stage_id"/>
<field name="company_id" groups="base.group_multi_company"/>

View File

@ -17,33 +17,8 @@
resume_ids = self.pool.get('ir.attachment').search(cr, uid, [('datas_fname','=','resume.pdf'),('res_model','=',self._name),('res_id','=',applicant.id)])
assert applicant.name == "Application for the post of Jr.application Programmer.", "Applicant name does not match."
assert applicant.stage_id.id == ref('hr_recruitment.stage_job1'), "Stage should be 'Initial qualification' and is '%s'." % (applicant.stage_id.name)
assert applicant.state == "draft", "Applicant state should be 'draft'."
assert applicant.stage_id.sequence == 1, "Applicant stage sequence should be 1."
assert len(resume_ids), "Resume is not attached."
-
I refuse the applicant (hr_case_programmer)
-
!python {model: hr.applicant}: |
self.case_cancel(cr, uid, [ref("hr_case_programmer")])
-
I check the details of the refused applicant.
-
!python {model: hr.applicant}: |
applicant = self.browse(cr, uid, ref("hr_case_programmer"), context=context)
assert applicant.stage_id.id == ref('hr_recruitment.stage_job6'), "Stage should be 'Refused' and is %s." % (applicant.stage_id.name)
assert applicant.state == 'cancel', "Applicant is not in 'cancel' state."
-
I reset and re-open the previously refused applicant.
-
!python {model: hr.applicant}: |
self.case_reset(cr, uid, [ref("hr_case_programmer")])
self.case_open(cr, uid, [ref("hr_case_programmer")])
-
I check the details of the re-opened applicant.
-
!python {model: hr.applicant}: |
applicant = self.browse(cr, uid, ref("hr_case_programmer"), context=context)
assert applicant.stage_id.id == ref('hr_recruitment.stage_job2'), "Stage should be 'First interview' and is '%s'." % (applicant.stage_id.name)
assert applicant.state == "open", "Applicant state should be 'open'."
-
I assign the Job position to the applicant
-
@ -54,21 +29,6 @@
-
!python {model: hr.applicant}: |
self.action_makeMeeting(cr, uid, [ref('hr_case_programmer')])
-
I check Initial Qualification of applicant.
-
!python {model: hr.applicant}: |
self.stage_next(cr, uid, [ref('hr_case_programmer')])
-
I schedule First Interview of applicant.
-
!python {model: hr.applicant}: |
self.stage_next(cr, uid, [ref('hr_case_programmer')])
-
On a successful First Interview of applicant, I schedule Second Interview.
-
!python {model: hr.applicant}: |
self.stage_next(cr, uid, [ref('hr_case_programmer')])
-
Applicant fillup the answer of the interview quetion.
-
@ -84,39 +44,19 @@
-
!python {model: hr.applicant}: |
self.action_print_survey(cr, uid, [ref('hr_case_programmer')])
-
On a successful Second Interview of applicant Contract is Proposed to applicant.
-
!python {model: hr.applicant}: |
self.stage_next(cr, uid, [ref('hr_case_programmer')])
self.stage_previous(cr, uid, [ref('hr_case_programmer')])
-
I Hired Applicant.
-
!python {model: hr.applicant}: |
self.case_close_with_emp(cr, uid, [ref('hr_case_programmer')])
-
I check that applicant is "Hired".
-
!assert {model: hr.applicant, id: hr_case_programmer, string: Applicant state is done}:
- state == 'done'
-
I do not give employment to the hired the applicant.
-
!python {model: hired.employee}: |
context.update({'active_model': 'hr.applicant', 'active_ids': [ref("hr_recruitment.hr_case_programmer")], 'active_id': ref("hr_recruitment.hr_case_programmer")})
emp_id = self.create(cr, uid, {}, context=context)
self.case_close(cr, uid, [emp_id], context=context)
-
Now I give employment to hired applicant .
-
!python {model: hr.applicant}: |
hired_emp_obj = self.pool.get('hired.employee')
self.case_reset(cr, uid, [ref("hr_case_programmer")])
self.case_open(cr, uid, [ref("hr_case_programmer")])
context.update({'active_model': 'hr.applicant', 'active_ids': [ref("hr_recruitment.hr_case_programmer")], 'active_id': ref("hr_recruitment.hr_case_programmer")})
emp_hr_id = hired_emp_obj.create(cr, uid, {}, context=context)
hired_emp_obj.case_close_with_emp(cr, uid, [emp_hr_id], context=context)
-
Now hired employee want to be a partner of company.
-