Odoo中文社区可以通过以下三个域名访问:shine-it.net , odoocn.org,odoo.net.cn

原论坛用户的基本信息和发帖这里都予以保留,请注意:原论坛用户无需重新注册新用户,但是您的密码需要重置

开发人员可以登录gitter讨论组: http://gitter.im/odoo-china/Talk, 需要github账号

如果您登录系统碰到问题,请在微信公众号留言:

对HR模块的一些扩展(用户和部门之间的关系)



  • HR模块主要包含了hr.employee(员工), hr.department(部门), hr.job(岗位), hr.employee.category(员工分类)对象,以及扩展继承了res.users(用户)对象。<br />其中hr.employee和res.users对象之间的关系是,hr.employee -> resource.resource -> res.users。但是,在HR模块里,res.users扩展了一个属性,employee_ids用来记录用户关联了哪些员工。<br />现在我们做些扩展,需要知道用户属于哪些部门,他的上级有哪些部门,下级有哪些部门。<br />对res_users类进行扩展,_get_self_department_ids函数是用来获取用户关联部门的,_get_parent_ids函数是用来获取用户关联部门的所有父节点(所有的上级部门),_get_child_ids函数是用来获取用户关联部门的所有子节点(所有的下级部门)。<br /><br />写完这三个函数后,我们在columns中扩展出对应的属性即可。<br />[code]<br />        'department_ids' : fields.function(_get_self_department_ids, type='many2many' , relation= "hr.department", string= "部门" ),<br />        'child_department_ids' : fields.function(_get_child_ids, type='many2many' , relation= "hr.department", string= "子部门集合" ),<br />        'parent_department_ids' : fields.function(_get_parent_ids, type='many2many' , relation= "hr.department", string= "父部门集合" ),<br />[/code]<br /><br />完整代码如下<br />[code]<br />class res_users(osv.osv):<br />    _name = 'res.users'<br />    _inherit = 'res.users'<br />    def create(self, cr, uid, data, context= None):<br />        user_id = super(res_users, self).create(cr, uid, data, context=context)<br />        # add shortcut unless 'noshortcut' is True in context<br />        if not(context and context.get('noshortcut', False)):<br />            data_obj = self.pool.get('ir.model.data')<br />            try:<br />                data_id = data_obj._get_id(cr, uid, 'hr ', 'ir_ui_view_sc_employee' )<br />                view_id  = data_obj.browse(cr, uid, data_id, context=context).res_id<br />                self.pool.get('ir.ui.view_sc').copy(cr, uid, view_id, default = {<br />                                            'user_id': user_id}, context=context)<br />            except:<br />                # Tolerate a missing shortcut. See product/product.py for similar code.<br />                _logger.debug( 'Skipped meetings shortcut for user "%s".', data.get('name', '<new'))<br />        return user_id<br />   <br />    # 获取用户关联的部门<br />    def _get_self_department_ids(self, cr, uid, ids, field_name, arg, context=None):<br />        result = {}<br />        for user in self.browse(cr, uid, ids, context=context):<br />            if user.employee_ids:<br />                departs = []<br />                for emp in user.employee_ids:<br />                    departs.append(emp.department_id)<br />                result[user.id] = departs<br />        return result<br />   <br />    # 向下递归,寻找所有子节点<br />    def _get_child_ids(self, cr, uid, ids, field_name, arg, context=None):<br />        result = {}<br />        for user in self.browse(cr, uid, ids, context=context):<br />            if user.employee_ids:<br />                departs = []<br />                for emp in user.employee_ids:<br />                    sql = '''<br />WITH RECURSIVE r AS (<br />SELECT * FROM hr_department WHERE id = %d<br />union   ALL<br />SELECT hr_department.* FROM hr_department, r WHERE hr_department.parent_id = r.id<br />)<br />SELECT * FROM r where r.id <> %d<br />ORDER BY id;''' % (emp.department_id.id, emp.department_id.id)<br />                    cr.execute(sql)<br />                    for depart in cr.fetchall():<br />                        departs.append(depart)<br />                result[user.id] = departs<br />        return result<br />   <br />    # 向上递归,寻找所有父节点<br />    def _get_parent_ids(self, cr, uid, ids, field_name, arg, context=None):<br />        result = {}<br />        for user in self.browse(cr, uid, ids, context=context):<br />            if user.employee_ids:<br />                departs = []<br />                for emp in user.employee_ids:<br />                    sql = '''<br />WITH RECURSIVE r AS (<br />SELECT parent_id FROM hr_department WHERE id = %d<br />union   ALL<br />SELECT hr_department.parent_id FROM hr_department, r WHERE hr_department.id = r.parent_id<br />)<br />SELECT * FROM hr_department where id in (select parent_id from r)''' % (emp.department_id.id, )<br />                    cr.execute(sql)<br />                    for depart in cr.fetchall():<br />                        departs.append(depart)<br />                result[user.id] = departs<br />        return result<br />    _columns = {<br />        'employee_ids': fields.one2many('hr.employee', 'user_id', 'Related employees' ),<br />        'department_ids': fields.function(_get_self_department_ids, type='many2many' , relation="hr.department", string= "部门"),<br />        'child_department_ids': fields.function(_get_child_ids, type='many2many' , relation="hr.department", string= "子部门集合" ),<br />        'parent_department_ids': fields.function(_get_parent_ids, type='many2many' , relation="hr.department", string= "父部门集合" ),<br />    }<br />res_users()<br />[/code]<br />做完这些工作后,继续对规则进行定义,现在有这样一个场景。<br />公司部门结构为上下三层,自己可以看到自己,经理可以看到部门内其他员工但普通员工之间不可互相看到,上级部门的员工可以看到所有下级部门的员工。<br />开动,在"设置-技术-安全设定-记录规则"中新建一个全局规则,名字随便取,对象选择为hr.employee,在规则定义( Domain 过滤器)文本框内写入规则:<br />[code]<br />['|', '|', ('users_id', '=', user.id), ('department_id.manager_id.users_id', '=', user.id), ('department_id.id', 'in', [depart.id[0] for depart in user.child_department_ids])]<br />[/code]<br />我们来解读一下<br />('users_id', '=', user.id),这个是自己能看到自己<br />('department_id.manager_id.users_id', '=', user.id),这个是部门经理可以看到部门的所有<br />('department_id.id', 'in', [depart.id[0] for depart in user.child_department_ids]),这个是员工可以看到所属部门的所有下级部门<br />两个'|'表示这3个条件都是或者的关系。<br />这样,用户再次登录后,规则生效。<br />



  • HR模块主要包含了hr.employee(员工), hr.department(部门), hr.job(岗位), hr.employee.category(员工分类)对象,以及扩展继承了res.users(用户)对象。<br />其中hr.employee和res.users对象之间的关系是,hr.employee -> resource.resource -> res.users。但是,在HR模块里,res.users扩展了一个属性,employee_ids用来记录用户关联了哪些员工。<br />现在我们做些扩展,需要知道用户属于哪些部门,他的上级有哪些部门,下级有哪些部门。<br />对res_users类进行扩展,_get_self_department_ids函数是用来获取用户关联部门的,_get_parent_ids函数是用来获取用户关联部门的所有父节点(所有的上级部门),_get_child_ids函数是用来获取用户关联部门的所有子节点(所有的下级部门)。<br /><br />写完这三个函数后,我们在columns中扩展出对应的属性即可。<br />[code]<br />        'department_ids' : fields.function(_get_self_department_ids, type='many2many' , relation= "hr.department", string= "部门" ),<br />        'child_department_ids' : fields.function(_get_child_ids, type='many2many' , relation= "hr.department", string= "子部门集合" ),<br />        'parent_department_ids' : fields.function(_get_parent_ids, type='many2many' , relation= "hr.department", string= "父部门集合" ),<br />[/code]<br /><br />完整代码如下<br />[code]<br />class res_users(osv.osv):<br />    _name = 'res.users'<br />    _inherit = 'res.users'<br />    def create(self, cr, uid, data, context= None):<br />        user_id = super(res_users, self).create(cr, uid, data, context=context)<br />        # add shortcut unless 'noshortcut' is True in context<br />        if not(context and context.get('noshortcut', False)):<br />            data_obj = self.pool.get('ir.model.data')<br />            try:<br />                data_id = data_obj._get_id(cr, uid, 'hr ', 'ir_ui_view_sc_employee' )<br />                view_id  = data_obj.browse(cr, uid, data_id, context=context).res_id<br />                self.pool.get('ir.ui.view_sc').copy(cr, uid, view_id, default = {<br />                                            'user_id': user_id}, context=context)<br />            except:<br />                # Tolerate a missing shortcut. See product/product.py for similar code.<br />                _logger.debug( 'Skipped meetings shortcut for user "%s".', data.get('name', '<new'))<br />        return user_id<br />   <br />    # 获取用户关联的部门<br />    def _get_self_department_ids(self, cr, uid, ids, field_name, arg, context=None):<br />        result = {}<br />        for user in self.browse(cr, uid, ids, context=context):<br />            if user.employee_ids:<br />                departs = []<br />                for emp in user.employee_ids:<br />                    departs.append(emp.department_id)<br />                result[user.id] = departs<br />        return result<br />   <br />    # 向下递归,寻找所有子节点<br />    def _get_child_ids(self, cr, uid, ids, field_name, arg, context=None):<br />        result = {}<br />        for user in self.browse(cr, uid, ids, context=context):<br />            if user.employee_ids:<br />                departs = []<br />                for emp in user.employee_ids:<br />                    sql = '''<br />WITH RECURSIVE r AS (<br />SELECT * FROM hr_department WHERE id = %d<br />union   ALL<br />SELECT hr_department.* FROM hr_department, r WHERE hr_department.parent_id = r.id<br />)<br />SELECT * FROM r where r.id <> %d<br />ORDER BY id;''' % (emp.department_id.id, emp.department_id.id)<br />                    cr.execute(sql)<br />                    for depart in cr.fetchall():<br />                        departs.append(depart)<br />                result[user.id] = departs<br />        return result<br />   <br />    # 向上递归,寻找所有父节点<br />    def _get_parent_ids(self, cr, uid, ids, field_name, arg, context=None):<br />        result = {}<br />        for user in self.browse(cr, uid, ids, context=context):<br />            if user.employee_ids:<br />                departs = []<br />                for emp in user.employee_ids:<br />                    sql = '''<br />WITH RECURSIVE r AS (<br />SELECT parent_id FROM hr_department WHERE id = %d<br />union   ALL<br />SELECT hr_department.parent_id FROM hr_department, r WHERE hr_department.id = r.parent_id<br />)<br />SELECT * FROM hr_department where id in (select parent_id from r)''' % (emp.department_id.id, )<br />                    cr.execute(sql)<br />                    for depart in cr.fetchall():<br />                        departs.append(depart)<br />                result[user.id] = departs<br />        return result<br />    _columns = {<br />        'employee_ids': fields.one2many('hr.employee', 'user_id', 'Related employees' ),<br />        'department_ids': fields.function(_get_self_department_ids, type='many2many' , relation="hr.department", string= "部门"),<br />        'child_department_ids': fields.function(_get_child_ids, type='many2many' , relation="hr.department", string= "子部门集合" ),<br />        'parent_department_ids': fields.function(_get_parent_ids, type='many2many' , relation="hr.department", string= "父部门集合" ),<br />    }<br />res_users()<br />[/code]<br />做完这些工作后,继续对规则进行定义,现在有这样一个场景。<br />公司部门结构为上下三层,自己可以看到自己,经理可以看到部门内其他员工但普通员工之间不可互相看到,上级部门的员工可以看到所有下级部门的员工。<br />开动,在"设置-技术-安全设定-记录规则"中新建一个全局规则,名字随便取,对象选择为hr.employee,在规则定义( Domain 过滤器)文本框内写入规则:<br />[code]<br />['|', '|', ('users_id', '=', user.id), ('department_id.manager_id.users_id', '=', user.id), ('department_id.id', 'in', [depart.id[0] for depart in user.child_department_ids])]<br />[/code]<br />我们来解读一下<br />('users_id', '=', user.id),这个是自己能看到自己<br />('department_id.manager_id.users_id', '=', user.id),这个是部门经理可以看到部门的所有<br />('department_id.id', 'in', [depart.id[0] for depart in user.child_department_ids]),这个是员工可以看到所属部门的所有下级部门<br />两个'|'表示这3个条件都是或者的关系。<br />这样,用户再次登录后,规则生效。<br />



  • 这个是谁啊?新手上路就写这么猛的代码...



  • 这 domain写得猛,学习了



  • 各位过奖了,呵呵,我就是在群里潜水,还经常问你们问题的。<br /><br />这个只是总结了下。


  • 管理员

    谢谢分享。看了下代码,res.users继承create方法是用来自动添加shortcut吗?<br />对于求所有的子部门,可以直接用[b]child_of[/b]<br />[code]child_ids = self.pool.get('hr.department').search(cr, uid, [('id', 'child_of', emps)])[/code]



  • 谢谢Joshua。child_of我也研究过,但是一直没思路,所以我就自己递归出来的。<br /><br />您的这个代码里,emps是一个数组吗,员工本身部门的ID集合?<br /><br />res.users里的这个create方法是原来就有的,我只是一起copy出来了。


  • 管理员

    [quote author=bingsun8208 link=topic=8095.msg18860#msg18860 date=1375081535]<br />您的这个代码里,emps是一个数组吗,员工本身部门的ID集合?<br />[/quote]<br />是的<br /><br />



  • Domain规则是Lisp语法吗?



  • Mark,还没研究到HR这块



  • [quote author=xvweirong link=topic=8095.msg18867#msg18867 date=1375150804]<br />Domain规则是Lisp语法吗?<br />[/quote]<br /><br />前缀表达式



  • 学习了,非常好的实践教学啊


登录后回复
 

与 Odoo 中文社区 的连接断开,我们正在尝试重连,请耐心等待