[IMP] hr: add Department org chart

Add an organisation chart on the Department form view.

task-3071039

closes odoo/odoo#106005

Related: odoo/enterprise#34184
Signed-off-by: Kevin Baptiste <kba@odoo.com>
This commit is contained in:
Kevin Baptiste
2022-12-12 15:17:09 +01:00
parent dea1e8b68a
commit d20940cfd8
5 changed files with 145 additions and 5 deletions
+26
View File
@@ -134,3 +134,29 @@ class Department(models.Model):
def get_children_department_ids(self):
return self.env['hr.department'].search([('id', 'child_of', self.ids)])
def get_department_hierarchy(self):
if not self:
return {}
hierarchy = {
'parent': {
'id': self.parent_id.id,
'name': self.parent_id.name,
'employees': self.parent_id.total_employee,
} if self.parent_id else False,
'self': {
'id': self.id,
'name': self.name,
'employees': self.total_employee,
},
'children': [
{
'id': child.id,
'name': child.name,
'employees': child.total_employee
} for child in self.child_ids
]
}
return hierarchy
@@ -0,0 +1,43 @@
/** @odoo-module */
import { registry } from '@web/core/registry';
import { useService } from "@web/core/utils/hooks";
import { standardWidgetProps } from "@web/views/widgets/standard_widget_props";
const { onWillStart, useState, onWillUpdateProps, Component } = owl;
export class DepartmentChart extends Component {
setup() {
super.setup();
this.action = useService('action');
this.orm = useService('orm');
this.state = useState({
hierarchy: {}
});
onWillStart(async () => await this.fetchHierarchy(this.props.record.data.id));
onWillUpdateProps(async (nextProps) => {
await this.fetchHierarchy(nextProps.record.data.id);
});
}
async fetchHierarchy(departmentId) {
this.state.hierarchy = await this.orm.call('hr.department', 'get_department_hierarchy', [departmentId]);
}
openDepartmentEmployees(departmentId) {
this.action.doAction('hr.act_employee_from_department', {
additionalContext: {
'active_id': departmentId,
}
});
}
}
DepartmentChart.template = 'hr.DepartmentChart';
DepartmentChart.props = {
...standardWidgetProps,
};
registry.category("view_widgets").add("hr_department_chart", DepartmentChart);
@@ -0,0 +1,19 @@
.o_widget_hr_department_chart {
display: flex;
justify-content: flex-end;
.o_hr_department_chart {
.o_hr_department_chart_self {
.department_name {
font-weight: bold;
}
}
@include media-breakpoint-up(sm) {
width: 50%;
}
@include media-breakpoint-down(md) {
flex-grow: 1;
}
}
}
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="hr.DepartmentChart" owl="1">
<div class="o_hr_department_chart">
<div class="o_horizontal_separator mb-3 text-uppercase fw-bolder small">Department Organization</div>
<t t-if="state.hierarchy.self">
<div class="o_hr_department_chart_parent">
<t t-set="dept" t-value="state.hierarchy.parent"/>
<t t-set="hideTree" t-value="true"/>
<t t-call="hr.DepartmentChart.Department"/>
</div>
<div t-att-class="state.hierarchy.parent?'ms-4':''">
<div class="o_hr_department_chart_self">
<t t-set="dept" t-value="state.hierarchy.self"/>
<t t-set="hideTree" t-value="!state.hierarchy.parent"/>
<t t-call="hr.DepartmentChart.Department"/>
</div>
<t t-set="hideTree" t-value="false"/>
<div class="o_hr_department_chart_children ms-4">
<t t-foreach="state.hierarchy.children" t-as="dept" t-key="dept.name">
<t t-call="hr.DepartmentChart.Department"/>
</t>
</div>
</div>
</div>
</t>
</t>
<t t-name="hr.DepartmentChart.Department" owl="1">
<t t-if="dept">
<div t-attf-class="#{hideTree?'':'o_treeEntry'} mb-0 ps-4">
<div class="d-flex justify-content-between">
<span class="department_name ms-2">
<t t-esc="dept.name"/>
</span>
<a class="badge rounded-pill bg-white border" role="button"
title="Show employees"
t-on-click.prevent="() => this.openDepartmentEmployees(dept.id)">
<t t-esc="dept.employees"/>
</a>
</div>
</div>
</t>
</t>
</templates>
+10 -5
View File
@@ -18,11 +18,16 @@
</div>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<field name="active" invisible="1"/>
<group col="4">
<field name="name"/>
<field name="manager_id"/>
<field name="parent_id"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<group>
<group>
<field name="name"/>
<field name="manager_id"/>
<field name="parent_id"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
<div>
<widget name="hr_department_chart"/>
</div>
</group>
</sheet>
<div class="oe_chatter">