Initial commit: Hr packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:50 +02:00
commit 62531cd146
2820 changed files with 1432848 additions and 0 deletions

View file

@ -0,0 +1,105 @@
/* @odoo-module */
import { useService } from '@web/core/utils/hooks';
import { registry } from '@web/core/registry'
import { formatDate } from "@web/core/l10n/dates";
const { Component, useState, onWillStart, onWillUpdateProps } = owl;
const { DateTime } = luxon;
export class LeaveStatsComponent extends Component {
setup() {
this.orm = useService('orm');
this.state = useState({
leaves: [],
departmentLeaves: [],
});
this.date = this.props.record.data.date_from || DateTime.now();
this.department = this.props.record.data.department_id;
this.employee = this.props.record.data.employee_id;
onWillStart(async () => {
await this.loadLeaves(this.date, this.employee);
await this.loadDepartmentLeaves(this.date, this.department, this.employee);
});
onWillUpdateProps(async (nextProps) => {
const dateFrom = nextProps.record.data.date_from || DateTime.now();
const dateChanged = this.date !== dateFrom;
const employee = nextProps.record.data.employee_id;
const department = nextProps.record.data.department_id;
if (dateChanged || employee && (this.employee && this.employee[0]) !== employee[0]) {
await this.loadLeaves(dateFrom, employee);
}
if (dateChanged || department && (this.department && this.department[0]) !== department[0]) {
await this.loadDepartmentLeaves(dateFrom, department, employee);
}
this.date = dateFrom;
this.employee = employee;
this.department = department;
})
}
get thisYear() {
return this.date.toFormat('yyyy');
}
async loadDepartmentLeaves(date, department, employee) {
if (!(department && employee && date)) {
this.state.departmentLeaves = [];
return;
}
const dateFrom = date.startOf('month');
const dateTo = date.endOf('month');
const departmentLeaves = await this.orm.searchRead(
'hr.leave',
[
['department_id', '=', department[0]],
['state', '=', 'validate'],
['holiday_type', '=', 'employee'],
['date_from', '<=', dateTo],
['date_to', '>=', dateFrom],
],
['employee_id', 'date_from', 'date_to', 'number_of_days'],
);
this.state.departmentLeaves = departmentLeaves.map((leave) => {
return Object.assign({}, leave, {
dateFrom: formatDate(DateTime.fromSQL(leave.date_from, { zone: 'utc' }).toLocal()),
dateTo: formatDate(DateTime.fromSQL(leave.date_to, { zone: 'utc' }).toLocal()),
sameEmployee: leave.employee_id[0] === employee[0],
});
});
}
async loadLeaves(date, employee) {
if (!(employee && date)) {
this.state.leaves = [];
return;
}
const dateFrom = date.startOf('year');
const dateTo = date.endOf('year');
this.state.leaves = await this.orm.readGroup(
'hr.leave',
[
['employee_id', '=', employee[0]],
['state', '=', 'validate'],
['date_from', '<=', dateTo],
['date_to', '>=', dateFrom]
],
['holiday_status_id', 'number_of_days:sum'],
['holiday_status_id'],
);
}
}
LeaveStatsComponent.template = 'hr_holidays.LeaveStatsComponent';
registry.category('view_widgets').add('hr_leave_stats', LeaveStatsComponent);

View file

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<div t-name="hr_holidays.LeaveStatsComponent" owl="1" class="o_leave_stats">
<div t-if="employee" id="o_leave_stats_employee">
<div class="o_hr_leave_subtitle">
<t t-esc="employee[1]"/> in <t t-esc="thisYear"/>
</div>
<div t-if="state.leaves.length === 0">
None
</div>
<div t-foreach="state.leaves" t-as="leave" t-key="leave_index" class="d-flex flex-row justify-content-between">
<span t-esc="leave.holiday_status_id[1]"/>
<span><t t-esc="leave.number_of_days"/> day(s)</span>
</div>
</div>
<div t-if="department" id="o_leave_stats_department">
<div class="o_horizontal_separator o_hr_leave_subtitle">
<t t-esc="department[1]"/>
</div>
<div t-if="state.departmentLeaves.length === 0">
None
</div>
<div t-foreach="state.departmentLeaves" t-as="leave" t-key="leave_index" t-attf-class="d-flex flex-row justify-content-between {{leave.sameEmployee ? 'fw-bold': ''}}">
<span><t t-esc="leave.employee_id[1]"/>: <t t-esc="leave.number_of_days"/> day(s)</span>
<span><t t-esc="leave.dateFrom"/> - <t t-esc="leave.dateTo"/></span>
</div>
</div>
</div>
</templates>