[MERGE] merged the dev branch containing the HR improvements

bzr revid: qdp-launchpad@openerp.com-20110311172952-jqlv6z6kf9x64fr8
This commit is contained in:
Quentin (OpenERP)
2011-03-11 18:29:52 +01:00
16 changed files with 198 additions and 64 deletions
+46 -27
View File
@@ -20,7 +20,7 @@
##############################################################################
from osv import fields, osv
import logging
import addons
class hr_employee_category(osv.osv):
@@ -81,22 +81,20 @@ class hr_job(osv.osv):
def _no_of_employee(self, cr, uid, ids, name, args, context=None):
res = {}
for job in self.browse(cr, uid, ids, context=context):
res[job.id] = len(job.employee_ids or [])
return res
def _no_of_recruitement(self, cr, uid, ids, name, args, context=None):
res = {}
for job in self.browse(cr, uid, ids, context=context):
res[job.id] = job.expected_employees - job.no_of_employee
nb_employees = len(job.employee_ids or [])
res[job.id] = {
'no_of_employee': nb_employees,
'expected_employees': nb_employees + job.no_of_recruitment,
}
return res
_name = "hr.job"
_description = "Job Description"
_columns = {
'name': fields.char('Job Name', size=128, required=True, select=True),
'expected_employees': fields.integer('Expected Employees', help='Required number of Employees in total for that job.'),
'no_of_employee': fields.function(_no_of_employee, method=True, string="No of Employee", help='Number of employee with that job.'),
'no_of_recruitment': fields.function(_no_of_recruitement, method=True, string='Expected in Recruitment', readonly=True),
'expected_employees': fields.function(_no_of_employee, method=True, string='Expected Employees', help='Required number of Employees in total for that job.', multi="no_of_employee"),
'no_of_employee': fields.function(_no_of_employee, method=True, string="No of Employee", help='Number of employee with that job.', multi="no_of_employee"),
'no_of_recruitment': fields.float('Expected in Recruitment'),
'employee_ids': fields.one2many('hr.employee', 'job_id', 'Employees'),
'description': fields.text('Job Description'),
'requirements': fields.text('Requirements'),
@@ -110,24 +108,23 @@ class hr_job(osv.osv):
'state': 'open',
}
def on_change_expected_employee(self, cr, uid, ids, expected_employee, no_of_employee, context=None):
def on_change_expected_employee(self, cr, uid, ids, no_of_recruitment, no_of_employee, context=None):
if context is None:
context = {}
result = {}
if expected_employee:
result['no_of_recruitment'] = expected_employee - no_of_employee
return {'value': result}
return {'value': {'expected_employees': no_of_recruitment + no_of_employee}}
def job_old(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'old'})
self.write(cr, uid, ids, {'state': 'old', 'no_of_recruitment': 0})
return True
def job_recruitement(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'recruit'})
for job in self.browse(cr, uid, ids):
no_of_recruitment = job.no_of_recruitment == 0 and 1 or job.no_of_recruitment
self.write(cr, uid, [job.id], {'state': 'recruit', 'no_of_recruitment': no_of_recruitment})
return True
def job_open(self, cr, uid, ids, *args):
self.write(cr, uid, ids, {'state': 'open'})
self.write(cr, uid, ids, {'state': 'open', 'no_of_recruitment': 0})
return True
hr_job()
@@ -154,7 +151,7 @@ class hr_employee(osv.osv):
'work_email': fields.char('Work E-mail', size=240),
'work_location': fields.char('Office Location', size=32),
'notes': fields.text('Notes'),
'parent_id': fields.related('department_id', 'manager_id', relation='hr.employee', string='Manager', type='many2one', store=True, select=True, readonly=True, help="It is linked with manager of Department"),
'parent_id': fields.many2one('hr.employee', 'Manager'),
'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Category'),
'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),
@@ -178,6 +175,13 @@ class hr_employee(osv.osv):
address_id = address and address['default'] or False
return {'value': {'address_id' : address_id}}
def onchange_department_id(self, cr, uid, ids, department_id, context=None):
value = {'parent_id': False}
if department_id:
department = self.pool.get('hr.department').browse(cr, uid, department_id)
value['parent_id'] = department.manager_id.id
return {'value': value}
def onchange_user(self, cr, uid, ids, user_id, context=None):
work_email = False
if user_id:
@@ -204,15 +208,8 @@ class hr_employee(osv.osv):
level -= 1
return True
def _check_department_id(self, cr, uid, ids, context=None):
for emp in self.browse(cr, uid, ids, context=context):
if emp.department_id.manager_id and emp.id == emp.department_id.manager_id.id:
return False
return True
_constraints = [
(_check_recursion, 'Error ! You cannot create recursive Hierarchy of Employees.', ['parent_id']),
(_check_department_id, 'Error ! You cannot select a department for which the employee is the manager.', ['department_id']),
]
hr_employee()
@@ -227,4 +224,26 @@ class hr_department(osv.osv):
hr_department()
class res_users(osv.osv):
_name = 'res.users'
_inherit = 'res.users'
def create(self, cr, uid, data, context=None):
user_id = super(res_users, self).create(cr, uid, data, context=context)
data_obj = self.pool.get('ir.model.data')
try:
data_id = data_obj._get_id(cr, uid, 'hr', 'ir_ui_view_sc_employee')
view_id = data_obj.browse(cr, uid, data_id, context=context).res_id
self.pool.get('ir.ui.view_sc').copy(cr, uid, view_id, default = {
'user_id': user_id}, context=context)
except:
# Tolerate a missing shortcut. See product/product.py for similar code.
logging.getLogger('orm').debug('Skipped meetings shortcut for user "%s"', data.get('name','<new'))
return user_id
res_users()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
+15 -7
View File
@@ -28,7 +28,7 @@
<field name="company_id" widget="selection" groups="base.group_multi_company,base.group_extended" on_change="onchange_company(company_id)"/>
<field name="active" groups="base.group_extended"/>
<newline/>
<field name="department_id" widget="selection" />
<field name="department_id" widget="selection" on_change="onchange_department_id(department_id)" />
<field name="parent_id" />
</group>
<group colspan="2" col="1">
@@ -156,6 +156,13 @@
<menuitem action="open_view_employee_list_my" id="menu_open_view_employee_list_my" sequence="3" parent="menu_hr_main"/>
<record id="ir_ui_view_sc_employee" model="ir.ui.view_sc">
<field name="name">Employees</field>
<field name="resource">ir.ui.menu</field>
<field name="user_id" ref="base.user_root"/>
<field name="res_id" ref="hr.menu_open_view_employee_list_my"/>
</record>
<!--
=======================
Employee marital status
@@ -219,7 +226,7 @@
</record>
<record id="action2" model="ir.actions.act_window">
<field name="name">Employee Hierarchy</field>
<field name="name">Subordonate Hierarchy</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hr.employee</field>
<field name="domain">[('id','in',active_ids)]</field>
@@ -231,7 +238,7 @@
<field eval="'action'" name="key"/>
<field eval="'client_action_multi'" name="key2"/>
<field eval="['hr.employee']" name="models"/>
<field name="name">Employees Hierarchy</field>
<field name="name">Subordonate Hierarchy</field>
<field eval="'ir.actions.act_window,'+str(action2)" name="value"/>
<field eval="True" name="isobject"/>
<field eval="True" name="replace"/>
@@ -287,7 +294,7 @@
</record>
<menuitem action="open_view_categ_form" id="menu_view_employee_category_form"
parent="menu_view_employee_category_configuration_form" sequence="1" groups="base.group_extended"/>
parent="menu_view_employee_category_configuration_form" sequence="1"/>
<record id="open_view_categ_tree" model="ir.actions.act_window">
<field name="name">Categories structure</field>
@@ -313,7 +320,7 @@
<field eval="True" name="object"/>
</record>
<menuitem action="open_view_categ_tree" groups="base.group_extended"
<menuitem action="open_view_categ_tree"
id="menu_view_employee_category_tree" parent="hr.menu_view_employee_category_form"/>
<record id="view_hr_job_form" model="ir.ui.view">
@@ -326,9 +333,10 @@
<field name="name" />
<field name="department_id" />
<field name="company_id" widget="selection" groups="base.group_multi_company"/>
<field name="expected_employees" on_change="on_change_expected_employee(expected_employees,no_of_employee)"/>
<newline/>
<field name="no_of_recruitment" on_change="on_change_expected_employee(no_of_recruitment,no_of_employee)"/>
<field name="no_of_employee"/>
<field name="no_of_recruitment"/>
<field name="expected_employees"/>
</group>
<newline/>
<notebook colspan="4">
+1 -1
View File
@@ -7,7 +7,7 @@
</record>
<record id="base.group_hr_user" model="res.groups">
<field name="name">Human Resources / User</field>
<field name="name">Human Resources / Officer</field>
</record>
</data>
</openerp>
+12 -8
View File
@@ -4,22 +4,26 @@
<!-- Casual leave -->
<record model="hr.holidays.status" id="holiday_status_cl">
<field name="name">Casual Leave</field>
<field name="name">Legal Leaves</field>
<field name="limit">False</field>
<field name="color_name">black</field>
</record>
<!-- Legal Holidays -->
<record model="hr.holidays.status" id="holiday_status_sl">
<field name="name">Legal Holidays</field>
<field name="color_name">blue</field>
</record>
<!-- Sick leave -->
<record model="hr.holidays.status" id="holiday_status_sl">
<field name="name">Sick Leave</field>
<field name="name">Sick Leaves</field>
<field name="limit">True</field>
<field name="color_name">red</field>
</record>
<!-- Compensatory Days -->
<record model="hr.holidays.status" id="holiday_status_comp">
<field name="name">Compensatory Days</field>
<field name="limit">False</field>
<field name="color_name">brown</field>
</record>
</data>
</openerp>
+3
View File
@@ -31,6 +31,9 @@
<field name="employee_id" ref="hr.employee1"/>
</record>
<workflow action="confirm" model="hr.holidays" ref="hr_holidays_employee1_allocation_cl"/>
<workflow action="validate" model="hr.holidays" ref="hr_holidays_employee1_allocation_cl"/>
<workflow action="confirm" model="hr.holidays" ref="hr_holidays_employee1_sl"/>
<workflow action="validate" model="hr.holidays" ref="hr_holidays_employee1_sl"/>
</data>
+10 -10
View File
@@ -24,7 +24,7 @@
help="My Leaves" />
</field>
<field name="department_id" widget="selection">
<filter icon="terp-personal+" help="My Department Holidays"
<filter icon="terp-personal+" help="My Department Leaves"
domain="[('department_id.manager_id','=',uid)]" />
</field>
<field name="holiday_status_id" widget="selection"/>
@@ -70,7 +70,7 @@
<form string="Leave Request">
<group col="8" colspan="4">
<field name="name" attrs="{'readonly':[('state','!=','draft'),('state','!=','confirm')]}" />
<field name="holiday_type" on_change="onchange_type(holiday_type)" attrs="{'readonly':[('state','!=','draft')]}" width="130" groups="base.group_hr_manager, base.group_extended" string="Leave Category"/>
<field name="holiday_type" on_change="onchange_type(holiday_type)" attrs="{'readonly':[('state','!=','draft')]}" width="130" groups="base.group_hr_manager"/>
<group attrs="{'invisible':[('holiday_type','=','employee')]}">
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'readonly':[('state','!=','draft')]}"/>
</group>
@@ -93,11 +93,11 @@
<newline/>
<field name="state" colspan="2"/>
<group colspan="2" col="6">
<button string="Refuse" name="refuse" states="confirm,validate,validate1" type="workflow" icon="gtk-no" groups="base.group_hr_user,base.group_hr_manager"/>
<button string="Refuse" name="refuse" states="confirm" type="workflow" icon="gtk-no" groups="base.group_hr_user,base.group_hr_manager"/>
<button string="Confirm" name="confirm" states="draft" type="workflow" icon="gtk-yes"/>
<button string="Approve" name="validate" states="confirm" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
<button string="Approved" name="second_validate" states="validate1" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
<button string="Set to Draft" name="set_to_draft" states="refuse" type="object" icon="gtk-convert" groups="base.group_hr_user"/>
<button string="Set to Draft" name="set_to_draft" states="refuse,validate,validate1" type="object" icon="gtk-convert" groups="base.group_hr_user"/>
</group>
</page>
</notebook>
@@ -114,7 +114,7 @@
<form string="Allocation Request">
<group col="8" colspan="4">
<field name="name" />
<field name="holiday_type" on_change="onchange_type(holiday_type)" attrs="{'readonly':[('state','!=','draft')]}" string="Allocation Category" groups="base.group_hr_manager, base.group_extended"/>
<field name="holiday_type" on_change="onchange_type(holiday_type)" attrs="{'readonly':[('state','!=','draft')]}" string="Allocation Category" groups="base.group_hr_manager"/>
<group attrs="{'invisible':[('holiday_type','=','category')]}">
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')]}"/>
</group>
@@ -135,11 +135,11 @@
<newline/>
<field name="state" colspan="2"/>
<group colspan="2" col="6">
<button string="Refuse" name="refuse" states="confirm,validate,validate1" type="workflow" icon="gtk-no" groups="base.group_hr_user"/>
<button string="Refuse" name="refuse" states="confirm" type="workflow" icon="gtk-no" groups="base.group_hr_user"/>
<button string="Confirm" name="confirm" states="draft" type="workflow" icon="gtk-yes"/>
<button string="Approve" name="validate" states="confirm" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
<button string="Approved" name="second_validate" states="validate1" type="workflow" icon="gtk-apply" groups="base.group_hr_user"/>
<button string="Set to Draft" name="set_to_draft" states="cancel" type="object" icon="gtk-convert" groups="base.group_hr_user"/>
<button string="Set to Draft" name="set_to_draft" states="cancel,validate,validate1" type="object" icon="gtk-convert" groups="base.group_hr_user"/>
</group>
</page>
</notebook>
@@ -250,7 +250,7 @@
<!-- My leave dashboard -->
<menuitem
name="Holidays"
name="Leaves"
parent="hr.menu_hr_root"
id="menu_open_ask_holidays"
sequence="5"/>
@@ -413,7 +413,7 @@
<field name="search_view_id" ref="view_hr_holidays_status_search"/>
</record>
<menuitem sequence="3" id="hr.menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Holidays"/>
<menuitem sequence="3" id="hr.menu_open_view_attendance_reason_config" parent="hr.menu_hr_configuration" name="Leaves"/>
<menuitem name="Leave Type"
action="open_view_holiday_status"
@@ -434,7 +434,7 @@
</record>
<!-- Shortcuts -->
<act_window name="Holidays"
<act_window name="Leaves"
domain="[('type','=','remove')]"
context="{'search_default_employee_id': [active_id], 'default_employee_id': active_id}"
res_model="hr.holidays"
+1
View File
@@ -36,6 +36,7 @@ system to store and search in your CV base.
'depends': ['decimal_precision', 'hr', 'survey', 'crm'],
'update_xml': [
'wizard/hr_recruitment_phonecall_view.xml',
'wizard/hr_recruitment_employee_hired.xml',
'wizard/hr_recruitment_create_partner_job_view.xml',
'hr_recruitment_view.xml',
'hr_recruitment_menu.xml',
+18 -6
View File
@@ -414,24 +414,36 @@ class hr_applicant(crm.crm_case, osv.osv):
@param *args: Give Tuple Value
"""
employee_obj = self.pool.get('hr.employee')
job_obj = self.pool.get('hr.job')
partner_obj = self.pool.get('res.partner')
address_id = False
res = super(hr_applicant, self).case_close(cr, uid, ids, *args)
for (id, name) in self.name_get(cr, uid, ids):
message = _("Applicant '%s' is being hired.") % name
self.log(cr, uid, id, message)
return res
def case_close_with_emp(self, cr, uid, ids, *args):
"""
@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 case's Ids
@param *args: Give Tuple Value
"""
employee_obj = self.pool.get('hr.employee')
partner_obj = self.pool.get('res.partner')
address_id = False
applicant = self.browse(cr, uid, ids)[0]
if applicant.partner_id:
address_id = partner_obj.address_get(cr, uid, [applicant.partner_id.id], ['contact'])['contact']
if applicant.job_id:
self.pool.get('hr.job').write(cr, uid, [applicant.job_id.id], {'no_of_recruitment': applicant.job_id.no_of_recruitment - 1})
emp_id = employee_obj.create(cr,uid,{'name': applicant.partner_name or applicant.name,
'job_id': applicant.job_id.id,
'address_home_id':address_id,
'department_id':applicant.department_id.id
'address_home_id': address_id,
'department_id': applicant.department_id.id
})
return res
else:
raise osv.except_osv(_('Warning!'),_('You must define Applied Job for Applicant !'))
return self.case_close(cr, uid, ids, *args)
def case_reset(self, cr, uid, ids, *args):
"""Resets case as draft
@@ -77,7 +77,6 @@
<field name="name" string="Subject"/>
<field name="partner_name"/>
<field name="job_id" on_change="onchange_job(job_id)"/>
<button string="Phone Call" name="%(action_hr_recruitment_phonecall)d" icon="terp-call-start" type="action" groups="base.group_extended"/>
<button name="action_makeMeeting" type="object" string="Meeting" icon="gtk-index"/>
<newline/>
<field name="department_id" widget="selection" on_change="onchange_department_id(department_id)"/>
@@ -134,7 +133,7 @@
<button name="case_cancel" string="Refused" states="draft,open,pending" type="object" icon="gtk-cancel"/>
<button name="case_open" string="In Progress" states="draft,pending" type="object" icon="gtk-go-forward"/>
<button name="case_pending" string="Pending" states="open" type="object" icon="gtk-media-pause"/>
<button name="case_close" string="Hired" states="open,pending" type="object" icon="terp-partner"/>
<button name="%(action_hr_recruitment_hired_employee)d" string="Hired" states="open,pending" type="action" icon="terp-partner"/>
<button name="case_reset" string="Reset to New" states="done,cancel" type="object" icon="gtk-convert"/>
</group>
</page>
@@ -34,6 +34,7 @@
partner_name: Marion Jones
partner_phone: '1111112223'
response: 0.0
job_id: hr.job_jr_developers
salary_expected: 0.0
salary_proposed: 0.0
stage_id: hr_recrutiment_stage_first0
+1
View File
@@ -22,6 +22,7 @@
import hr_recruitment_phonecall
import hr_recruitment_create_partner_job
import hr_recruitment_employee_hired
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
# $Id$
#
# 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/>.
#
##############################################################################
from osv import osv, fields
from tools.translate import _
class hired_employee(osv.osv_memory):
_name = 'hired.employee'
_description = 'Create Employee'
def case_close(self, cr, uid,ids, context=None):
"""
@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 case's Ids
@param *args: Give Tuple Value
"""
if context is None:
context = {}
self.pool.get('hr.applicant').case_close(cr, uid,context.get('active_ids',[]))
return {}
def case_close_with_emp(self, cr, uid,ids, context=None):
"""
@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 case's Ids
"""
if context is None:
context = {}
self.pool.get('hr.applicant').case_close_with_emp(cr, uid,context.get('active_ids', []))
return {}
hired_employee()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data>
<record id="view_hr_recruitment_hired_employee" model="ir.ui.view">
<field name="name">hr.recruitment.hired2employee.form</field>
<field name="model">hired.employee</field>
<field name="type">form</field>
<field name="arch" type="xml">
<form string="Create New Employee">
<label string="Would you like to create an employee ?" colspan="4" />
<separator string="" colspan="4"/>
<newline />
<button special="cancel" string="Cancel" icon='gtk-cancel'/>
<button name="case_close" string="No" icon='gtk-no' type="object"/>
<button name="case_close_with_emp" string="Yes" colspan="1" type="object" icon="terp-camera_test"/>
</form>
</field>
</record>
<record id="action_hr_recruitment_hired_employee" model="ir.actions.act_window">
<field name="name">Create Employee</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">hired.employee</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
</data>
</openerp>
+1 -1
View File
@@ -73,7 +73,7 @@
<group expand="0" string="Group By...">
<filter string="Users" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<separator orientation="vertical"/>
<filter string="Anlytic account" icon="terp-folder-green" domain="[]" context="{'group_by':'account_id'}"/>
<filter string="Analytic account" icon="terp-folder-green" domain="[]" context="{'group_by':'account_id'}"/>
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>
<separator orientation="vertical"/>
<filter string="Date" icon="terp-go-month" domain="[]" context="{'group_by':'date'}"/>
@@ -269,7 +269,7 @@ class hr_timesheet_sheet(osv.osv):
'draft': [('readonly', False)],
'new': [('readonly', False)]}
),
'attendances_ids' : one2many_mod2('hr.attendance', 'sheet_id', 'Attendances', readonly=True,),
'attendances_ids' : one2many_mod2('hr.attendance', 'sheet_id', 'Attendances'),
'state' : fields.selection([
('new', 'New'),
('draft','Draft'),
@@ -144,7 +144,7 @@
</notebook>
<group col="6" colspan="4">
<field name="state"/>
<button name="button_confirm" states="draft" string="Confirm" type="object" icon="terp-check"/>
<button name="button_confirm" states="draft" string="Submit to Manager" type="object" icon="terp-check"/>
<button name="action_set_to_draft" states="done" string="Set to Draft" type="object" icon="terp-stock_effects-object-colorize"/>
<button name="cancel" states="confirm" string="Refuse" type="workflow" icon="gtk-cancel" groups="base.group_hr_user"/>
<button name="done" states="confirm" string="Approve" type="workflow" icon="terp-camera_test" groups="base.group_hr_user"/>