[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:
@@ -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>
|
||||
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user