[IMP] hr: allow users to manage plan activities
When starting an onboarding/offboarding plan on an employee, activities were only created for the users that were part of the HR Officer group. Regular users can't access the `hr.employee` model and it's not possible to have activities on `hr.employee.public`. A new model has been created to manage those activities and is only accessible to the user and their manager. task-3151758 closes odoo/odoo#111505 Signed-off-by: Kevin Baptiste <kba@odoo.com>
This commit is contained in:
@@ -37,6 +37,7 @@
|
||||
'views/mail_channel_views.xml',
|
||||
'views/res_users.xml',
|
||||
'views/res_partner_views.xml',
|
||||
'views/hr_templates.xml',
|
||||
'data/hr_data.xml',
|
||||
],
|
||||
'demo': [
|
||||
|
||||
@@ -11,6 +11,7 @@ from . import hr_departure_reason
|
||||
from . import hr_job
|
||||
from . import hr_plan
|
||||
from . import hr_plan_activity_type
|
||||
from . import hr_plan_employee_activity
|
||||
from . import hr_work_location
|
||||
from . import mail_alias
|
||||
from . import mail_channel
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class HrPlanEmployeeActivity(models.Model):
|
||||
_name = 'hr.plan.employee.activity'
|
||||
_description = 'Plan'
|
||||
_inherit = ['mail.thread', 'mail.activity.mixin']
|
||||
_mail_post_access = 'read'
|
||||
_rec_name = 'employee_id'
|
||||
|
||||
employee_id = fields.Many2one('hr.employee', required=True, ondelete='cascade')
|
||||
department_id = fields.Many2one(related='employee_id.department_id')
|
||||
image_128 = fields.Image(related='employee_id.image_128')
|
||||
company_id = fields.Many2one(related='employee_id.company_id')
|
||||
user_id = fields.Many2one(related='employee_id.user_id')
|
||||
summary = fields.Html(compute='_compute_summary')
|
||||
|
||||
@api.depends('activity_ids.summary')
|
||||
def _compute_summary(self):
|
||||
for plan in self:
|
||||
plan.summary = self.env['ir.ui.view']._render_template('hr.hr_employee_plan_activity_summary', {
|
||||
'activity_ids': plan.activity_ids,
|
||||
})
|
||||
|
||||
@api.autovacuum
|
||||
def _gc_employee_plan_activity(self):
|
||||
no_activities = self.env['hr.plan.employee.activity'].search(
|
||||
[('activity_ids', '=', False)]
|
||||
)
|
||||
no_activities.unlink()
|
||||
@@ -60,5 +60,17 @@
|
||||
<field name="model_id" ref="model_hr_plan_activity_type"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_plan_employee_activity_company_rule" model="ir.rule">
|
||||
<field name="name">Plan Employee Activity: multi-company rule</field>
|
||||
<field name="model_id" ref="model_hr_plan_employee_activity"/>
|
||||
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'in', company_ids)]</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_plan_employee_activity_own_user" model="ir.rule">
|
||||
<field name="name">Plan Employee Activity: own employee or subordinates</field>
|
||||
<field name="model_id" ref="model_hr_plan_employee_activity"/>
|
||||
<field name="domain_force">['|', ('user_id', '=', user.id), ('activity_ids.user_id', '=', user.id)]</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -18,3 +18,4 @@ access_hr_work_location_user,access_hr_work_location_user,model_hr_work_location
|
||||
access_hr_work_location_manager,access_hr_work_location_manager,model_hr_work_location,group_hr_manager,1,1,1,1
|
||||
access_hr_departure_reason,access_hr_departure_reason_user,model_hr_departure_reason,group_hr_user,1,1,1,1
|
||||
access_hr_contract_type_manager,hr.contract.type.manager,model_hr_contract_type,hr.group_hr_user,1,1,1,1
|
||||
access_hr_plan_employee_activity,hr.plan.employee.activity,model_hr_plan_employee_activity,base.group_user,1,0,0,0
|
||||
|
||||
|
@@ -121,5 +121,63 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_plan_employee_activity_kanban" model="ir.ui.view">
|
||||
<field name="model">hr.plan.employee.activity</field>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="d-flex flex-row">
|
||||
<div class="flex-grow-1">
|
||||
<h3 class="h3 mb-0"><field name="employee_id"/></h3>
|
||||
<span class="fst-italic"><field name="department_id"/></span>
|
||||
</div>
|
||||
<div style="max-width: 64px; max-height: 64px;">
|
||||
<field name="image_128" widget="image" class="oe_avatar"/>
|
||||
</div>
|
||||
</div>
|
||||
<field name="summary"/>
|
||||
<div class="mt-auto d-flex flex-row-reverse">
|
||||
<span>
|
||||
Next Activity: <field name="activity_ids" widget="kanban_activity"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_plan_employee_activity_list" model="ir.ui.view">
|
||||
<field name="model">hr.plan.employee.activity</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree>
|
||||
<field name="employee_id" widget="many2one_avatar_employee"/>
|
||||
<field name="department_id"/>
|
||||
<field name="activity_ids" widget="list_activity"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="hr_plan_employee_activity_form" model="ir.ui.view">
|
||||
<field name="model">hr.plan.employee.activity</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<sheet>
|
||||
<group>
|
||||
<field name="employee_id" widget="many2one_avatar_employee"/>
|
||||
<field name="department_id"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="activity_ids"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="hr_employee_plan_activity_summary">
|
||||
<div class="d-flex flex-column flex-grow">
|
||||
<t t-foreach="activity_ids" t-as="activity">
|
||||
<span><i t-attf-class="fa #{activity.icon}"/> <t t-esc="activity.summary"/> (<t t-esc="activity.user_id.name"/>)</span>
|
||||
<span><i class="fa fa-clock-o"/> <span t-field="activity.date_deadline"/></span>
|
||||
</t>
|
||||
</div>
|
||||
</template>
|
||||
</odoo>
|
||||
@@ -74,17 +74,24 @@ class HrPlanWizard(models.TransientModel):
|
||||
activities = set()
|
||||
for activity_type in self._get_activities_to_schedule():
|
||||
responsible = activity_type.get_responsible_id(employee)['responsible']
|
||||
if self.env['hr.employee'].with_user(responsible).check_access_rights('read', raise_exception=False):
|
||||
date_deadline = self.env['mail.activity']._calculate_date_deadline(activity_type.activity_type_id)
|
||||
employee.activity_schedule(
|
||||
activity_type_id=activity_type.activity_type_id.id,
|
||||
summary=activity_type.summary,
|
||||
note=activity_type.note,
|
||||
user_id=responsible.id,
|
||||
date_deadline=date_deadline
|
||||
)
|
||||
activity = _('%(activity)s, assigned to %(name)s, due on the %(deadline)s', activity=activity_type.summary, name=responsible.name, deadline=date_deadline)
|
||||
activities.add(activity)
|
||||
record = employee
|
||||
if not self.env['hr.employee'].with_user(responsible).check_access_rights('read', raise_exception=False):
|
||||
record = self.env['hr.plan.employee.activity'].sudo().search([('employee_id', '=', employee.id)], limit=1)
|
||||
if not record:
|
||||
record = self.env['hr.plan.employee.activity'].sudo().create({
|
||||
'employee_id': employee.id,
|
||||
})
|
||||
|
||||
date_deadline = self.env['mail.activity']._calculate_date_deadline(activity_type.activity_type_id)
|
||||
record.activity_schedule(
|
||||
activity_type_id=activity_type.activity_type_id.id,
|
||||
summary=activity_type.summary,
|
||||
note=activity_type.note,
|
||||
user_id=responsible.id,
|
||||
date_deadline=date_deadline
|
||||
)
|
||||
activity = _('%(activity)s, assigned to %(name)s, due on the %(deadline)s', activity=activity_type.summary, name=responsible.name, deadline=date_deadline)
|
||||
activities.add(activity)
|
||||
|
||||
if activities:
|
||||
body += '<ul>'
|
||||
|
||||
Reference in New Issue
Block a user