[MIGR] hr : migrate to new api
- Rewrite the code to new api without changes business behavior - Remove old v7 backward compatibility method - Regroup view definitions in the same xml file - Use read_group for computed fields
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- notify all employees of module installation -->
|
||||
<record model="mail.message" id="module_install_notification">
|
||||
<record id="module_install_notification" model="mail.message">
|
||||
<field name="model">mail.channel</field>
|
||||
<field name="res_id" ref="mail.channel_all_employees"/>
|
||||
<field name="message_type">notification</field>
|
||||
@@ -16,9 +16,10 @@ Leave Management (keep track of employee leaves), Expense Management (manage emp
|
||||
<record id="dep_administration" model="hr.department">
|
||||
<field name="name">Administration</field>
|
||||
</record>
|
||||
|
||||
<record id="dep_sales" model="hr.department">
|
||||
<field name="name">Sales</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
+12
-14
@@ -1,9 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
|
||||
<!--Users-->
|
||||
|
||||
<!--Department-->
|
||||
|
||||
<record id="dep_management" model="hr.department">
|
||||
@@ -64,7 +62,7 @@ Good knowledge of Python
|
||||
Good knowledge of HTML and Javascript
|
||||
Knowledge of UML-like modeling
|
||||
Good language skills, other than English (Dutch and French preferred, others welcome)
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="job_consultant" model="hr.job">
|
||||
@@ -291,7 +289,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_phone">+3282823500</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_han-image.png"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_jve" model="hr.employee">
|
||||
<field name="name">Jan Van Eyck</field>
|
||||
<field name="department_id" ref="dep_rd"/>
|
||||
@@ -301,7 +299,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_email">jve@openerp.com</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_jve-image.jpg"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_jep" model="hr.employee">
|
||||
<field name="name">Jean-Pierre Carnaud</field>
|
||||
<field name="department_id" ref="dep_ps"/>
|
||||
@@ -311,7 +309,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_email">jep@openerp.com</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_jep-image.jpg"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_jod" model="hr.employee">
|
||||
<field name="name">John Doe</field>
|
||||
<field name="department_id" ref="dep_sales"/>
|
||||
@@ -321,7 +319,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_email">jod@openerp.com</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_jod-image.png"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_jog" model="hr.employee">
|
||||
<field name="name">João Gomer</field>
|
||||
<field name="department_id" ref="dep_rd"/>
|
||||
@@ -331,7 +329,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_email">jog@openerp.com</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_jog-image.jpg"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_jgo" model="hr.employee">
|
||||
<field name="name">Juan Gomez</field>
|
||||
<field name="department_id" ref="dep_ps"/>
|
||||
@@ -340,7 +338,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_phone">+3282823500</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_jgo-image.jpg"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_lur" model="hr.employee">
|
||||
<field name="name">Luigi Rondi</field>
|
||||
<field name="department_id" ref="dep_sales"/>
|
||||
@@ -350,7 +348,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_email">lur@openerp.com</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_lur-image.png"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_hne" model="hr.employee">
|
||||
<field name="name">Николай Петра</field>
|
||||
<field name="department_id" ref="dep_ps"/>
|
||||
@@ -359,7 +357,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_phone">+3282823500</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_hne-image.png"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_djj" model="hr.employee">
|
||||
<field name="name">佐藤さくら (demo_ja_JP)</field>
|
||||
<field name="department_id" ref="dep_ps"/>
|
||||
@@ -368,7 +366,7 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="work_phone">+3282823500</field>
|
||||
<field name="image" type="base64" file="hr/static/img/employee_djj-image.png"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="employee_dzc" model="hr.employee">
|
||||
<field name="name">趙生 (demo_zh_CN)</field>
|
||||
<field name="department_id" ref="dep_rd"/>
|
||||
@@ -378,4 +376,4 @@ If you have development competencies, we can propose you specific traineeships</
|
||||
<field name="image" type="base64" file="hr/static/img/employee_dzc-image.jpg"/>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data>
|
||||
<record model="web.tip" id="hr_tip_1">
|
||||
<record id="hr_tip_1" model="web.tip">
|
||||
<field name="title"></field>
|
||||
<field name="description">Get all applications related to this job position.</field>
|
||||
<field name="model">hr.job</field>
|
||||
@@ -11,7 +11,7 @@
|
||||
<field name="placement">bottom</field>
|
||||
</record>
|
||||
|
||||
<record model="web.tip" id="hr_tip_2">
|
||||
<record id="hr_tip_2" model="web.tip">
|
||||
<field name="title"></field>
|
||||
<field name="description">Click here to change the recruitment goal!</field>
|
||||
<field name="model">hr.job</field>
|
||||
@@ -21,4 +21,4 @@
|
||||
<field name="placement">bottom</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
+207
-261
@@ -3,132 +3,97 @@
|
||||
|
||||
import logging
|
||||
|
||||
import openerp
|
||||
from openerp import api
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp import tools
|
||||
from openerp.modules.module import get_module_resource
|
||||
from openerp.osv import fields, osv
|
||||
from openerp.tools.translate import _
|
||||
from odoo import api, fields, models
|
||||
from odoo import tools, _
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.modules.module import get_module_resource
|
||||
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class hr_employee_category(osv.Model):
|
||||
class EmployeeCategory(models.Model):
|
||||
|
||||
_name = "hr.employee.category"
|
||||
_description = "Employee Category"
|
||||
_columns = {
|
||||
'name': fields.char("Employee Tag", required=True),
|
||||
'color': fields.integer('Color Index'),
|
||||
'employee_ids': fields.many2many('hr.employee', 'employee_category_rel', 'category_id', 'emp_id', 'Employees'),
|
||||
}
|
||||
|
||||
name = fields.Char(string="Employee Tag", required=True)
|
||||
color = fields.Integer(string='Color Index')
|
||||
employee_ids = fields.Many2many('hr.employee', 'employee_category_rel', 'category_id', 'emp_id', string='Employees')
|
||||
|
||||
_sql_constraints = [
|
||||
('name_uniq', 'unique (name)', "Tag name already exists !"),
|
||||
('name_uniq', 'unique (name)', "Tag name already exists !"),
|
||||
]
|
||||
|
||||
|
||||
class hr_job(osv.Model):
|
||||
|
||||
def _get_nbr_employees(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
for job in self.browse(cr, uid, ids, context=context):
|
||||
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
|
||||
|
||||
def _get_job_position(self, cr, uid, ids, context=None):
|
||||
res = []
|
||||
for employee in self.pool.get('hr.employee').browse(cr, uid, ids, context=context):
|
||||
if employee.job_id:
|
||||
res.append(employee.job_id.id)
|
||||
return res
|
||||
class Job(models.Model):
|
||||
|
||||
_name = "hr.job"
|
||||
_description = "Job Position"
|
||||
_inherit = ['mail.thread']
|
||||
_columns = {
|
||||
'name': fields.char('Job Name', required=True, select=True, translate=True),
|
||||
'expected_employees': fields.function(_get_nbr_employees, string='Total Forecasted Employees',
|
||||
help='Expected number of employees for this job position after new recruitment.',
|
||||
store = {
|
||||
'hr.job': (lambda self,cr,uid,ids,c=None: ids, ['no_of_recruitment'], 10),
|
||||
'hr.employee': (_get_job_position, ['job_id'], 10),
|
||||
}, type='integer',
|
||||
multi='_get_nbr_employees'),
|
||||
'no_of_employee': fields.function(_get_nbr_employees, string="Current Number of Employees",
|
||||
help='Number of employees currently occupying this job position.',
|
||||
store = {
|
||||
'hr.employee': (_get_job_position, ['job_id'], 10),
|
||||
}, type='integer',
|
||||
multi='_get_nbr_employees'),
|
||||
'no_of_recruitment': fields.integer('Expected New Employees', copy=False,
|
||||
help='Number of new employees you expect to recruit.'),
|
||||
'no_of_hired_employee': fields.integer('Hired Employees', copy=False,
|
||||
help='Number of hired employees for this job position during recruitment phase.'),
|
||||
'employee_ids': fields.one2many('hr.employee', 'job_id', 'Employees', groups='base.group_user'),
|
||||
'description': fields.text('Job Description'),
|
||||
'requirements': fields.text('Requirements'),
|
||||
'department_id': fields.many2one('hr.department', 'Department'),
|
||||
'company_id': fields.many2one('res.company', 'Company'),
|
||||
'state': fields.selection([('recruit', 'Recruitment in Progress'), ('open', 'Recruitment Closed')],
|
||||
string='Status', readonly=True, required=True,
|
||||
track_visibility='always', copy=False,
|
||||
help="Set whether the recruitment process is open or closed for this job position."),
|
||||
'write_date': fields.datetime('Update Date', readonly=True),
|
||||
}
|
||||
|
||||
_defaults = {
|
||||
'company_id': lambda self, cr, uid, ctx=None: self.pool.get('res.company')._company_default_get(cr, uid, 'hr.job', context=ctx),
|
||||
'state': 'recruit',
|
||||
'no_of_recruitment' : 1,
|
||||
}
|
||||
name = fields.Char(string='Job Name', required=True, index=True, translate=True)
|
||||
expected_employees = fields.Integer(compute='_compute_employees', string='Total Forecasted Employees', store=True,
|
||||
help='Expected number of employees for this job position after new recruitment.')
|
||||
no_of_employee = fields.Integer(compute='_compute_employees', string="Current Number of Employees", store=True,
|
||||
help='Number of employees currently occupying this job position.')
|
||||
no_of_recruitment = fields.Integer(string='Expected New Employees', copy=False,
|
||||
help='Number of new employees you expect to recruit.', default=1)
|
||||
no_of_hired_employee = fields.Integer(string='Hired Employees', copy=False,
|
||||
help='Number of hired employees for this job position during recruitment phase.')
|
||||
employee_ids = fields.One2many('hr.employee', 'job_id', string='Employees', groups='base.group_user')
|
||||
description = fields.Text(string='Job Description')
|
||||
requirements = fields.Text('Requirements')
|
||||
department_id = fields.Many2one('hr.department', string='Department')
|
||||
company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id)
|
||||
state = fields.Selection([
|
||||
('recruit', 'Recruitment in Progress'),
|
||||
('open', 'Recruitment Closed')
|
||||
], string='Status', readonly=True, required=True, track_visibility='always', copy=False, default='recruit', help="Set whether the recruitment process is open or closed for this job position.")
|
||||
|
||||
_sql_constraints = [
|
||||
('name_company_uniq', 'unique(name, company_id, department_id)', 'The name of the job position must be unique per department in company!'),
|
||||
|
||||
]
|
||||
|
||||
def set_recruit(self, cr, uid, ids, context=None):
|
||||
for job in self.browse(cr, uid, ids, context=context):
|
||||
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}, context=context)
|
||||
@api.depends('no_of_recruitment', 'employee_ids.job_id')
|
||||
def _compute_employees(self):
|
||||
employee_data = self.env['hr.employee'].read_group([('job_id', 'in', self.ids)], ['job_id'], ['job_id'])
|
||||
result = dict((data['job_id'][0], data['job_id_count']) for data in employee_data)
|
||||
for job in self:
|
||||
job.no_of_employee = result.get(job.id, 0)
|
||||
job.expected_employees = result.get(job.id, 0) + job.no_of_recruitment
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
""" We don't want the current user to be follower of all created job """
|
||||
return super(Job, self.with_context(mail_create_nosubscribe=True)).create(values)
|
||||
|
||||
@api.multi
|
||||
def copy(self, default=None):
|
||||
self.ensure_one()
|
||||
default = dict(default or {})
|
||||
if 'name' not in default:
|
||||
default['name'] = _("%s (copy)") % (self.name)
|
||||
return super(Job, self).copy(default=default)
|
||||
|
||||
@api.multi
|
||||
def set_recruit(self):
|
||||
for record in self:
|
||||
no_of_recruitment = 1 if record.no_of_recruitment == 0 else record.no_of_recruitment
|
||||
record.write({'state': 'recruit', 'no_of_recruitment': no_of_recruitment})
|
||||
return True
|
||||
|
||||
def set_open(self, cr, uid, ids, context=None):
|
||||
self.write(cr, uid, ids, {
|
||||
@api.multi
|
||||
def set_open(self):
|
||||
return self.write({
|
||||
'state': 'open',
|
||||
'no_of_recruitment': 0,
|
||||
'no_of_hired_employee': 0
|
||||
}, context=context)
|
||||
return True
|
||||
|
||||
# TDE note: done in new api, because called with new api -> context is a
|
||||
# frozendict -> error when tryign to manipulate it
|
||||
@api.model
|
||||
def create(self, values):
|
||||
return super(hr_job, self.with_context(mail_create_nosubscribe=True)).create(values)
|
||||
|
||||
def copy(self, cr, uid, id, default=None, context=None):
|
||||
if default is None:
|
||||
default = {}
|
||||
if 'name' not in default:
|
||||
job = self.browse(cr, uid, id, context=context)
|
||||
default['name'] = _("%s (copy)") % (job.name)
|
||||
return super(hr_job, self).copy(cr, uid, id, default=default, context=context)
|
||||
|
||||
# ----------------------------------------
|
||||
# Compatibility methods
|
||||
# ----------------------------------------
|
||||
_no_of_employee = _get_nbr_employees # v7 compatibility
|
||||
job_open = set_open # v7 compatibility
|
||||
job_recruitment = set_recruit # v7 compatibility
|
||||
})
|
||||
|
||||
|
||||
class hr_employee(osv.osv):
|
||||
class Employee(models.Model):
|
||||
|
||||
_name = "hr.employee"
|
||||
_description = "Employee"
|
||||
_order = 'name_related'
|
||||
@@ -137,46 +102,60 @@ class hr_employee(osv.osv):
|
||||
|
||||
_mail_post_access = 'read'
|
||||
|
||||
_columns = {
|
||||
#we need a related field in order to be able to sort the employee by name
|
||||
'name_related': fields.related('resource_id', 'name', type='char', string='Name', readonly=True, store=True),
|
||||
'country_id': fields.many2one('res.country', 'Nationality (Country)'),
|
||||
'birthday': fields.date("Date of Birth"),
|
||||
'ssnid': fields.char('SSN No', help='Social Security Number'),
|
||||
'sinid': fields.char('SIN No', help="Social Insurance Number"),
|
||||
'identification_id': fields.char('Identification No'),
|
||||
'gender': fields.selection([('male', 'Male'), ('female', 'Female'), ('other', 'Other')], 'Gender'),
|
||||
'marital': fields.selection([('single', 'Single'), ('married', 'Married'), ('widower', 'Widower'), ('divorced', 'Divorced')], 'Marital Status'),
|
||||
'department_id': fields.many2one('hr.department', 'Department'),
|
||||
'address_id': fields.many2one('res.partner', 'Working Address'),
|
||||
'address_home_id': fields.many2one('res.partner', 'Home Address'),
|
||||
'bank_account_id': fields.many2one('res.partner.bank', 'Bank Account Number', domain="[('partner_id','=',address_home_id)]", help="Employee bank salary account"),
|
||||
'work_phone': fields.char('Work Phone', readonly=False),
|
||||
'mobile_phone': fields.char('Work Mobile', readonly=False),
|
||||
'work_email': fields.char('Work Email', size=240),
|
||||
'work_location': fields.char('Work Location'),
|
||||
'notes': fields.text('Notes'),
|
||||
'parent_id': fields.many2one('hr.employee', 'Manager'),
|
||||
'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Tags'),
|
||||
'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
|
||||
'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True, auto_join=True),
|
||||
'coach_id': fields.many2one('hr.employee', 'Coach'),
|
||||
'job_id': fields.many2one('hr.job', 'Job Title'),
|
||||
'passport_id': fields.char('Passport No'),
|
||||
'color': fields.integer('Color Index'),
|
||||
'city': fields.related('address_id', 'city', type='char', string='City'),
|
||||
'login': fields.related('user_id', 'login', type='char', string='Login', readonly=1),
|
||||
'last_login': fields.related('user_id', 'date', type='datetime', string='Latest Connection', readonly=1),
|
||||
}
|
||||
@api.model
|
||||
def _default_image(self):
|
||||
image_path = get_module_resource('hr', 'static/src/img', 'default_image.png')
|
||||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
|
||||
# we need a related field in order to be able to sort the employee by name
|
||||
name_related = fields.Char('Name', related='resource_id.name', readonly=True, store=True)
|
||||
country_id = fields.Many2one('res.country', string='Nationality (Country)')
|
||||
birthday = fields.Date('Date of Birth')
|
||||
ssnid = fields.Char('SSN No', help='Social Security Number')
|
||||
sinid = fields.Char('SIN No', help='Social Insurance Number')
|
||||
identification_id = fields.Char(string='Identification No')
|
||||
gender = fields.Selection([
|
||||
('male', 'Male'),
|
||||
('female', 'Female'),
|
||||
('other', 'Other')
|
||||
])
|
||||
marital = fields.Selection([
|
||||
('single', 'Single'),
|
||||
('married', 'Married'),
|
||||
('widower', 'Widower'),
|
||||
('divorced', 'Divorced')
|
||||
], string='Marital Status')
|
||||
department_id = fields.Many2one('hr.department', string='Department')
|
||||
address_id = fields.Many2one('res.partner', string='Working Address')
|
||||
address_home_id = fields.Many2one('res.partner', string='Home Address')
|
||||
bank_account_id = fields.Many2one('res.partner.bank', string='Bank Account Number',
|
||||
domain="[('partner_id', '=', address_home_id)]", help='Employee bank salary account')
|
||||
work_phone = fields.Char('Work Phone')
|
||||
mobile_phone = fields.Char('Work Mobile')
|
||||
work_email = fields.Char('Work Email')
|
||||
work_location = fields.Char('Work Location')
|
||||
notes = fields.Text('Notes')
|
||||
parent_id = fields.Many2one('hr.employee', string='Manager')
|
||||
category_ids = fields.Many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', string='Tags')
|
||||
child_ids = fields.One2many('hr.employee', 'parent_id', string='Subordinates')
|
||||
resource_id = fields.Many2one('resource.resource', string='Resource',
|
||||
ondelete='cascade', required=True, auto_join=True)
|
||||
coach_id = fields.Many2one('hr.employee', string='Coach')
|
||||
job_id = fields.Many2one('hr.job', string='Job Title')
|
||||
passport_id = fields.Char('Passport No')
|
||||
color = fields.Integer('Color Index', default=0)
|
||||
city = fields.Char(related='address_id.city')
|
||||
login = fields.Char(related='user_id.login', readonly=True)
|
||||
last_login = fields.Datetime(related='user_id.login_date', string='Latest Connection', readonly=True)
|
||||
|
||||
# image: all image fields are base64 encoded and PIL-supported
|
||||
image = openerp.fields.Binary("Photo", attachment=True,
|
||||
image = fields.Binary("Photo", default=_default_image, attachment=True,
|
||||
help="This field holds the image used as photo for the employee, limited to 1024x1024px.")
|
||||
image_medium = openerp.fields.Binary("Medium-sized photo", attachment=True,
|
||||
image_medium = fields.Binary("Medium-sized photo", attachment=True,
|
||||
help="Medium-sized photo of the employee. It is automatically "\
|
||||
"resized as a 128x128px image, with aspect ratio preserved. "\
|
||||
"Use this field in form views or some kanban views.")
|
||||
image_small = openerp.fields.Binary("Small-sized photo", attachment=True,
|
||||
image_small = fields.Binary("Small-sized photo", attachment=True,
|
||||
help="Small-sized photo of the employee. It is automatically "\
|
||||
"resized as a 64x64px image, with aspect ratio preserved. "\
|
||||
"Use this field anywhere a small image is required.")
|
||||
@@ -191,67 +170,66 @@ class hr_employee(osv.osv):
|
||||
'color': 0,
|
||||
}
|
||||
|
||||
@api.constrains('parent_id')
|
||||
def _check_parent_id(self):
|
||||
for employee in self:
|
||||
if not employee._check_recursion():
|
||||
raise ValidationError(_('Error! You cannot create recursive hierarchy of Employee(s).'))
|
||||
|
||||
@api.onchange('address_id')
|
||||
def _onchange_address(self):
|
||||
self.work_phone = self.address_id.phone
|
||||
self.mobile_phone = self.address_id.mobile
|
||||
|
||||
@api.onchange('company_id')
|
||||
def _onchange_company(self):
|
||||
address = self.company_id.partner_id.address_get(['default'])
|
||||
self.address_id = address['default'] if address else False
|
||||
|
||||
@api.onchange('department_id')
|
||||
def _onchange_department(self):
|
||||
self.parent_id = self.department_id.manager_id
|
||||
|
||||
@api.onchange('user_id')
|
||||
def _onchange_user(self):
|
||||
self.work_email = self.user_id.email
|
||||
self.name = self.user_id.name
|
||||
self.image = self.user_id.image
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
tools.image_resize_images(vals)
|
||||
return super(hr_employee, self).create(vals)
|
||||
return super(Employee, self).create(vals)
|
||||
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
tools.image_resize_images(vals)
|
||||
return super(hr_employee, self).write(vals)
|
||||
return super(Employee, self).write(vals)
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
resource_ids = []
|
||||
for employee in self.browse(cr, uid, ids, context=context):
|
||||
resource_ids.append(employee.resource_id.id)
|
||||
super(hr_employee, self).unlink(cr, uid, ids, context=context)
|
||||
return self.pool.get('resource.resource').unlink(cr, uid, resource_ids, context=context)
|
||||
@api.multi
|
||||
def unlink(self):
|
||||
resources = self.mapped('resource_id')
|
||||
super(Employee, self).unlink()
|
||||
return resources.unlink()
|
||||
|
||||
def onchange_address_id(self, cr, uid, ids, address, context=None):
|
||||
if address:
|
||||
address = self.pool.get('res.partner').browse(cr, uid, address, context=context)
|
||||
return {'value': {'work_phone': address.phone, 'mobile_phone': address.mobile}}
|
||||
return {'value': {}}
|
||||
|
||||
def onchange_company(self, cr, uid, ids, company, context=None):
|
||||
address_id = False
|
||||
if company:
|
||||
company_id = self.pool.get('res.company').browse(cr, uid, company, context=context)
|
||||
address = self.pool.get('res.partner').address_get(cr, uid, [company_id.partner_id.id], ['contact'])
|
||||
address_id = address and address['contact'] 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, name, image, user_id, context=None):
|
||||
if user_id:
|
||||
user = self.pool['res.users'].browse(cr, uid, user_id, context=context)
|
||||
values = {
|
||||
'name': name or user.name,
|
||||
'work_email': user.email,
|
||||
'image': image or user.image,
|
||||
}
|
||||
return {'value': values}
|
||||
|
||||
def action_follow(self, cr, uid, ids, context=None):
|
||||
@api.multi
|
||||
def action_follow(self):
|
||||
""" Wrapper because message_subscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_subscribe_users(cr, uid, ids, context=context)
|
||||
that receive the context without the wrapper.
|
||||
"""
|
||||
return self.message_subscribe_users()
|
||||
|
||||
def action_unfollow(self, cr, uid, ids, context=None):
|
||||
@api.multi
|
||||
def action_unfollow(self):
|
||||
""" Wrapper because message_unsubscribe_users take a user_ids=None
|
||||
that receive the context without the wrapper. """
|
||||
return self.message_unsubscribe_users(cr, uid, ids, context=context)
|
||||
that receive the context without the wrapper.
|
||||
"""
|
||||
return self.message_unsubscribe_users()
|
||||
|
||||
def _message_get_auto_subscribe_fields(self, cr, uid, updated_fields, auto_follow_fields=None, context=None):
|
||||
@api.model
|
||||
def _message_get_auto_subscribe_fields(self, updated_fields, auto_follow_fields=None):
|
||||
""" Overwrite of the original method to always follow user_id field,
|
||||
even when not track_visibility so that a user will follow it's employee
|
||||
even when not track_visibility so that a user will follow it's employee
|
||||
"""
|
||||
if auto_follow_fields is None:
|
||||
auto_follow_fields = ['user_id']
|
||||
@@ -261,103 +239,71 @@ class hr_employee(osv.osv):
|
||||
user_field_lst.append(name)
|
||||
return user_field_lst
|
||||
|
||||
_constraints = [(osv.osv._check_recursion, _('Error! You cannot create recursive hierarchy of Employee(s).'), ['parent_id']),]
|
||||
|
||||
class Department(models.Model):
|
||||
|
||||
class hr_department(osv.osv):
|
||||
_name = "hr.department"
|
||||
_description = "Department"
|
||||
_description = "Hr Department"
|
||||
_inherit = ['mail.thread', 'ir.needaction_mixin']
|
||||
|
||||
_columns = {
|
||||
'name': fields.char('Department Name', required=True),
|
||||
'active': fields.boolean('Active'),
|
||||
'company_id': fields.many2one('res.company', 'Company', select=True, required=False),
|
||||
'parent_id': fields.many2one('hr.department', 'Parent Department', select=True),
|
||||
'child_ids': fields.one2many('hr.department', 'parent_id', 'Child Departments'),
|
||||
'manager_id': fields.many2one('hr.employee', 'Manager', track_visibility='onchange'),
|
||||
'member_ids': fields.one2many('hr.employee', 'department_id', 'Members', readonly=True),
|
||||
'jobs_ids': fields.one2many('hr.job', 'department_id', 'Jobs'),
|
||||
'note': fields.text('Note'),
|
||||
'color': fields.integer('Color Index'),
|
||||
}
|
||||
name = fields.Char('Department Name', required=True)
|
||||
active = fields.Boolean('Active', default=True)
|
||||
company_id = fields.Many2one('res.company', string='Company', index=True, default=lambda self: self.env.user.company_id)
|
||||
parent_id = fields.Many2one('hr.department', string='Parent Department', index=True)
|
||||
child_ids = fields.One2many('hr.department', 'parent_id', string='Child Departments')
|
||||
manager_id = fields.Many2one('hr.employee', string='Manager', track_visibility='onchange')
|
||||
member_ids = fields.One2many('hr.employee', 'department_id', string='Members', readonly=True)
|
||||
jobs_ids = fields.One2many('hr.job', 'department_id', string='Jobs')
|
||||
note = fields.Text('Note')
|
||||
color = fields.Integer('Color Index')
|
||||
|
||||
_defaults = {
|
||||
'active': True,
|
||||
'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'hr.department', context=c),
|
||||
}
|
||||
@api.constrains('parent_id')
|
||||
def _check_parent_id(self):
|
||||
if not self._check_recursion():
|
||||
raise ValidationError(_('Error! You cannot create recursive departments.'))
|
||||
|
||||
_constraints = [
|
||||
(osv.osv._check_recursion, _('Error! You cannot create recursive departments.'), ['parent_id'])
|
||||
]
|
||||
@api.multi
|
||||
def name_get(self):
|
||||
result = []
|
||||
for record in self:
|
||||
name = record.name
|
||||
if record.parent_id:
|
||||
name = "%s / %s" % (record.parent_id.name_get()[1], name)
|
||||
result.append((record.id, name))
|
||||
return result
|
||||
|
||||
def name_get(self, cr, uid, ids, context=None):
|
||||
if not ids:
|
||||
return []
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
if context is None:
|
||||
context = {}
|
||||
reads = self.read(cr, uid, ids, ['name','parent_id'], context=context)
|
||||
res = []
|
||||
for record in reads:
|
||||
name = record['name']
|
||||
if record['parent_id']:
|
||||
name = record['parent_id'][1]+' / '+name
|
||||
res.append((record['id'], name))
|
||||
return res
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
context = dict(context, mail_create_nosubscribe=True)
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
# TDE note: auto-subscription of manager done by hand, because currently
|
||||
# the tracking allows to track+subscribe fields linked to a res.user record
|
||||
# An update of the limited behavior should come, but not currently done.
|
||||
manager_id = vals.get("manager_id")
|
||||
new_id = super(hr_department, self).create(cr, uid, vals, context=context)
|
||||
if manager_id:
|
||||
employee = self.pool.get('hr.employee').browse(cr, uid, manager_id, context=context)
|
||||
if employee.user_id:
|
||||
self.message_subscribe_users(cr, uid, [new_id], user_ids=[employee.user_id.id], context=context)
|
||||
return new_id
|
||||
department = super(Department, self.with_context(mail_create_nosubscribe=True)).create(vals)
|
||||
manager = self.env['hr.employee'].browse(vals.get("manager_id"))
|
||||
if manager.user_id:
|
||||
department.message_subscribe_users(user_ids=manager.user_id.ids)
|
||||
return department
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
""" If updating manager of a department, we need to update all the employees
|
||||
of department hierarchy, and subscribe the new manager.
|
||||
"""
|
||||
# TDE note: auto-subscription of manager done by hand, because currently
|
||||
# the tracking allows to track+subscribe fields linked to a res.user record
|
||||
# An update of the limited behavior should come, but not currently done.
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
employee_ids = []
|
||||
if 'manager_id' in vals:
|
||||
manager_id = vals.get("manager_id")
|
||||
if manager_id:
|
||||
employee = self.pool['hr.employee'].browse(cr, uid, manager_id, context=context)
|
||||
if employee.user_id:
|
||||
self.message_subscribe_users(cr, uid, ids, user_ids=[employee.user_id.id], context=context)
|
||||
for department in self.browse(cr, uid, ids, context=context):
|
||||
employee_ids += self.pool['hr.employee'].search(
|
||||
cr, uid, [
|
||||
('id', '!=', manager_id),
|
||||
('department_id', '=', department.id),
|
||||
('parent_id', '=', department.manager_id.id)
|
||||
], context=context)
|
||||
self.pool['hr.employee'].write(cr, uid, employee_ids, {'parent_id': manager_id}, context=context)
|
||||
return super(hr_department, self).write(cr, uid, ids, vals, context=context)
|
||||
|
||||
|
||||
class res_users(osv.osv):
|
||||
_name = 'res.users'
|
||||
_inherit = 'res.users'
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
result = super(res_users, self).write(cr, uid, ids, vals, context=context)
|
||||
employee_obj = self.pool.get('hr.employee')
|
||||
if vals.get('name'):
|
||||
for user_id in ids:
|
||||
if user_id == SUPERUSER_ID:
|
||||
employee_ids = employee_obj.search(cr, uid, [('user_id', '=', user_id)])
|
||||
employee_obj.write(cr, uid, employee_ids, {'name': vals['name']}, context=context)
|
||||
return result
|
||||
manager = self.env['hr.employee'].browse(manager_id)
|
||||
# subscribe the manager user
|
||||
if manager.user_id:
|
||||
self.message_subscribe_users(user_ids=manager.user_id.ids)
|
||||
employees = self.env['hr.employee']
|
||||
for department in self:
|
||||
employees = employees | self.env['hr.employee'].search([
|
||||
('id', '!=', manager_id),
|
||||
('department_id', '=', department.id),
|
||||
('parent_id', '=', department.manager_id.id)
|
||||
])
|
||||
employees.write({'parent_id': manager_id})
|
||||
return super(Department, self).write(vals)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp import api, models
|
||||
from odoo import api, models
|
||||
|
||||
class Partner(models.Model):
|
||||
_name = "res.partner"
|
||||
|
||||
_inherit = ['res.partner']
|
||||
|
||||
@api.model
|
||||
|
||||
@@ -1,40 +1,48 @@
|
||||
from openerp import api
|
||||
from openerp.osv import fields, osv
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, models, fields
|
||||
from odoo import SUPERUSER_ID
|
||||
|
||||
|
||||
class res_users(osv.Model):
|
||||
""" Update of res.users class
|
||||
class User(models.Model):
|
||||
|
||||
- add field for the related employee of the user
|
||||
- if adding groups to an user, check if base.group_user is in it (member of
|
||||
'Employee'), create an employee form linked to it. """
|
||||
_name = 'res.users'
|
||||
_inherit = ['res.users']
|
||||
|
||||
_columns = {
|
||||
'employee_ids': fields.one2many('hr.employee', 'user_id', 'Related employees'),
|
||||
}
|
||||
employee_ids = fields.One2many('hr.employee', 'user_id', string='Related employees')
|
||||
|
||||
def _message_post_get_eid(self, cr, uid, thread_id, context=None):
|
||||
assert thread_id, "res.users does not support posting global messages"
|
||||
if context and 'thread_model' in context:
|
||||
context = dict(context or {})
|
||||
context['thread_model'] = 'hr.employee'
|
||||
if isinstance(thread_id, (list, tuple)):
|
||||
thread_id = thread_id[0]
|
||||
return self.pool.get('hr.employee').search(cr, uid, [('user_id', '=', thread_id)], context=context)
|
||||
@api.multi
|
||||
def write(self, vals):
|
||||
""" When renaming admin user, we want its new name propagated to its related employees """
|
||||
result = super(User, self).write(vals)
|
||||
Employee = self.env['hr.employee']
|
||||
if vals.get('name'):
|
||||
for user in self.filtered(lambda user: user.id == SUPERUSER_ID):
|
||||
employees = Employee.search([('user_id', '=', user.id)])
|
||||
employees.write({'name': vals['name']})
|
||||
return result
|
||||
|
||||
@api.cr_uid_ids_context
|
||||
def message_post(self, cr, uid, thread_id, context=None, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related employee.
|
||||
@api.multi
|
||||
def _get_related_employees(self):
|
||||
self.ensure_one()
|
||||
ctx = dict(self.env.context)
|
||||
if 'thread_model' in ctx:
|
||||
ctx['thread_model'] = 'hr.employee'
|
||||
return self.env['hr.employee'].with_context(ctx).search([('user_id', '=', self.id)])
|
||||
|
||||
@api.multi
|
||||
def message_post(self, **kwargs):
|
||||
""" Redirect the posting of message on res.users to the related employees.
|
||||
This is done because when giving the context of Chatter on the
|
||||
various mailboxes, we do not have access to the current partner_id. """
|
||||
various mailboxes, we do not have access to the current partner_id.
|
||||
"""
|
||||
self.ensure_one()
|
||||
if kwargs.get('message_type') == 'email':
|
||||
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
||||
res = None
|
||||
employee_ids = self._message_post_get_eid(cr, uid, thread_id, context=context)
|
||||
if not employee_ids: # no employee: fall back on previous behavior
|
||||
return super(res_users, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
||||
for employee_id in employee_ids:
|
||||
res = self.pool.get('hr.employee').message_post(cr, uid, employee_id, context=context, **kwargs)
|
||||
return res
|
||||
return super(User, self).message_post(**kwargs)
|
||||
message_id = None
|
||||
employees = self._get_related_employees()
|
||||
if not employees: # no employee: fall back on previous behavior
|
||||
return super(User, self).message_post(**kwargs)
|
||||
for employee in employees:
|
||||
message_id = employee.message_post(**kwargs)
|
||||
return message_id
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data noupdate="0">
|
||||
<odoo>
|
||||
|
||||
<record model="res.groups" id="base.group_user">
|
||||
<record id="base.group_user" model="res.groups">
|
||||
<field name="comment">the user will be able to manage his own human resources stuff (leave request, timesheets, ...), if he is linked to an employee in the system.</field>
|
||||
</record>
|
||||
|
||||
@@ -12,6 +11,7 @@
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="comment">the user will be able to approve document created by employees.</field>
|
||||
</record>
|
||||
|
||||
<record id="base.group_hr_manager" model="res.groups">
|
||||
<field name="name">Manager</field>
|
||||
<field name="comment">the user will have an access to the human resources configuration as well as statistic reports.</field>
|
||||
@@ -19,7 +19,7 @@
|
||||
<field name="implied_ids" eval="[(4, ref('base.group_hr_user'))]"/>
|
||||
<field name="users" eval="[(4, ref('base.user_root'))]"/>
|
||||
</record>
|
||||
|
||||
|
||||
<record id="base.default_user" model="res.users">
|
||||
<field name="groups_id" eval="[(4,ref('base.group_hr_manager'))]"/>
|
||||
</record>
|
||||
@@ -29,21 +29,21 @@
|
||||
<field name="category_id" ref="base.module_category_hidden"/>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
<data noupdate="1">
|
||||
|
||||
<record id="hr_dept_comp_rule" model="ir.rule">
|
||||
<field name="name">Department multi company rule</field>
|
||||
<field name="model_id" ref="model_hr_department"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_job_comp_rule" model="ir.rule">
|
||||
<field name="name">Job multi company rule</field>
|
||||
<field name="model_id" ref="model_hr_job"/>
|
||||
<field eval="True" name="global"/>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="domain_force">['|',('company_id','=',False),('company_id','child_of',[user.company_id.id])]</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
<template id="assets_backend" name="hr assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/hr/static/src/less/hr.less"/>
|
||||
</xpath>
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
||||
<odoo>
|
||||
|
||||
<template id="assets_backend" name="hr assets" inherit_id="web.assets_backend">
|
||||
<xpath expr="." position="inside">
|
||||
<link rel="stylesheet" href="/hr/static/src/less/hr.less"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,17 +1,35 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<!-- Top menu item -->
|
||||
<menuitem name="Employees"
|
||||
<menuitem
|
||||
id="menu_hr_root"
|
||||
name="Employees"
|
||||
groups="base.group_hr_manager,base.group_hr_user,base.group_user"
|
||||
icon="fa-user"
|
||||
web_icon="hr,static/description/icon.png"
|
||||
sequence="75"/>
|
||||
<menuitem id="menu_hr_main" parent="menu_hr_root" name="Human Resources" sequence="0"/>
|
||||
<menuitem id="menu_hr_reporting_timesheet" name="Reports" parent="menu_hr_root" sequence="99" groups="base.group_hr_manager,base.group_hr_user"/>
|
||||
<menuitem id="menu_human_resources_configuration" name="Configuration" parent="menu_hr_root" sequence="100" groups="base.group_hr_manager"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_main"
|
||||
name="Human Resources"
|
||||
parent="menu_hr_root"
|
||||
sequence="0"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_hr_reporting_timesheet"
|
||||
name="Reports"
|
||||
parent="menu_hr_root"
|
||||
groups="base.group_hr_manager,base.group_hr_user"
|
||||
sequence="99"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_human_resources_configuration"
|
||||
name="Configuration"
|
||||
parent="menu_hr_root"
|
||||
groups="base.group_hr_manager"
|
||||
sequence="100"/>
|
||||
|
||||
<!-- Employee -->
|
||||
<record id="view_employee_form" model="ir.ui.view">
|
||||
@@ -39,7 +57,7 @@
|
||||
<page name="public" string="Public Information">
|
||||
<group>
|
||||
<group string="Contact Information">
|
||||
<field name="address_id" on_change="onchange_address_id(address_id)"
|
||||
<field name="address_id"
|
||||
context="{'show_address': 1}"
|
||||
options='{"always_reload": True, "highlight_first_line": True}'/>
|
||||
<field name="mobile_phone"/>
|
||||
@@ -48,7 +66,7 @@
|
||||
<field name="work_phone"/>
|
||||
</group>
|
||||
<group string="Position">
|
||||
<field name="department_id" on_change="onchange_department_id(department_id)"/>
|
||||
<field name="department_id"/>
|
||||
<field name="job_id"/>
|
||||
<field name="parent_id"/>
|
||||
<field name="coach_id"/>
|
||||
@@ -82,8 +100,8 @@
|
||||
<page string="HR Settings" groups="base.group_hr_user">
|
||||
<group>
|
||||
<group string='Status' name="active_group">
|
||||
<field name="company_id" groups="base.group_multi_company" on_change="onchange_company(company_id)"/>
|
||||
<field name="user_id" on_change="onchange_user(name, image, user_id)" string="Related User"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
<field name="user_id" string="Related User"/>
|
||||
</group>
|
||||
</group>
|
||||
</page>
|
||||
@@ -116,7 +134,7 @@
|
||||
</record>
|
||||
|
||||
<record id="view_employee_filter" model="ir.ui.view">
|
||||
<field name="name">Employees</field>
|
||||
<field name="name">hr.employee.search</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Employees">
|
||||
@@ -137,8 +155,8 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="hr_kanban_view_employees">
|
||||
<field name="name">HR - Employess Kanban</field>
|
||||
<record id="hr_kanban_view_employees" model="ir.ui.view">
|
||||
<field name="name">hr.employee.kanban</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
@@ -229,14 +247,18 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<menuitem action="open_view_employee_list_my" id="menu_open_view_employee_list_my" sequence="3" parent="menu_hr_root"/>
|
||||
<menuitem
|
||||
id="menu_open_view_employee_list_my"
|
||||
action="open_view_employee_list_my"
|
||||
parent="menu_hr_root"
|
||||
sequence="3"/>
|
||||
|
||||
<!-- Employee tree by manager -->
|
||||
<record id="view_partner_tree2" model="ir.ui.view">
|
||||
<field name="name">hr.employee.tree</field>
|
||||
<field name="model">hr.employee</field>
|
||||
<field name="field_parent">child_ids</field>
|
||||
<field eval="20" name="priority"/>
|
||||
<field name="priority" eval="20"/>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Employees">
|
||||
<field name="name"/>
|
||||
@@ -281,6 +303,7 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_employee_category_list" model="ir.ui.view">
|
||||
<field name="name">hr.employee.category.list</field>
|
||||
<field name="model">hr.employee.category</field>
|
||||
@@ -291,14 +314,20 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="open_view_categ_form" model="ir.actions.act_window">
|
||||
<field name="name">Employee Tags</field>
|
||||
<field name="res_model">hr.employee.category</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<menuitem action="open_view_categ_form" id="menu_view_employee_category_form"
|
||||
parent="menu_human_resources_configuration" sequence="1" groups="base.group_no_one"/>
|
||||
|
||||
<menuitem
|
||||
id="menu_view_employee_category_form"
|
||||
action="open_view_categ_form"
|
||||
parent="menu_human_resources_configuration"
|
||||
groups="base.group_no_one"
|
||||
sequence="1"/>
|
||||
|
||||
<!-- hr.job -->
|
||||
<record id="view_hr_job_form" model="ir.ui.view">
|
||||
@@ -354,7 +383,7 @@
|
||||
</record>
|
||||
|
||||
<record id="view_job_filter" model="ir.ui.view">
|
||||
<field name="name">Job</field>
|
||||
<field name="name">hr.job.search</field>
|
||||
<field name="model">hr.job</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Jobs">
|
||||
@@ -373,7 +402,7 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="action_hr_job">
|
||||
<record id="action_hr_job" model="ir.actions.act_window">
|
||||
<field name="name">Job Positions</field>
|
||||
<field name="res_model">hr.job</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -396,7 +425,7 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="act_employee_from_department">
|
||||
<record id="act_employee_from_department" model="ir.actions.act_window">
|
||||
<field name="name">Employees</field>
|
||||
<field name="res_model">hr.employee</field>
|
||||
<field name="view_type">form</field>
|
||||
@@ -561,4 +590,4 @@
|
||||
groups="base.group_hr_user"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user