[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:
Kevin Baptiste
2023-02-14 15:52:03 +01:00
parent c3ee7c8780
commit 901e3814fc
8 changed files with 134 additions and 11 deletions
+1
View File
@@ -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': [
+1
View File
@@ -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()
+12
View File
@@ -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>
+1
View File
@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
18 access_hr_work_location_manager access_hr_work_location_manager model_hr_work_location group_hr_manager 1 1 1 1
19 access_hr_departure_reason access_hr_departure_reason_user model_hr_departure_reason group_hr_user 1 1 1 1
20 access_hr_contract_type_manager hr.contract.type.manager model_hr_contract_type hr.group_hr_user 1 1 1 1
21 access_hr_plan_employee_activity hr.plan.employee.activity model_hr_plan_employee_activity base.group_user 1 0 0 0
+58
View File
@@ -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>
+11
View File
@@ -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>
+18 -11
View File
@@ -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>'