[FIX] hr_holidays: calculate the number of days left for the report
Steps to reproduce:
-------------------
- create a time off type;
- create two 5 days allocations for an employee;
- validate them;
- create a leave of 8 days for the same employee;
- be in debug mode;
- go to employee form view;
- in action menu, click on "Time off Analysis by Employee and Time Off Type".
Issue:
------
The number of days remaining ("left") for the employee and leave type is -6 instead of 2.
Cause:
------
The query that generates the report is in two parts
```
Find the number of remaining leaves by subtracting leave taken from allocations
(model: hr_leave_allocation and hr_leave) ==> will generate the "left" column
UNION ALL
Find the number of leaves already taken
(model: hr_leave) ==> will generate the "taken" and "planned" columns
```
In the part that generates the "left" column, we relate leaves to allocations.
As there is no "unique" link between allocations and leaves,
we can only link them via employee and type.
We are therefore obliged to use aggregation methods.
The measure that returns negative numbers is:
```sql
CASE
WHEN request.number_of_days > 0 THEN allocation.number_of_days - request.number_of_days
ELSE allocation.number_of_days
END as number_of_days
```
It should be read as follows:
If there are validated or planned leaves, the number of days remaining
for an allocation is the number of days of this allocation minus
the SUM of the days of leaves (validated or planned) for this allocations
(same employee and type).
For example:
2 allocations of 5 days and a leave of 8 days,
we will have (5 - 8) + (5 - 8) = (-3) + (-3) = -6 days remaining ==> this is wrong
In this example, we want: (5 + 5) - 8 = 2 days remaining
Solution:
---------
As it is not possible to link a leave to a specific allocation,
we have to make difference between sums like this:
days left = [SUM(days of allocations) - SUM(days of leaves)]_(for one employee AND one type)
The frontend will sum these days left.
This difference must therefore be calculated only once.
By default, we use allocation with the smallest id.
The result is:
days left frontend = [day left_(for min id) + 0 * (nbr allocation - 1)]_(for one employee AND one type)
opw-3366530
closes odoo/odoo#130781
X-original-commit: a273148cf931f220cc4252c638ae14890f889c9e
Signed-off-by: Sofie Gvaladze (sgv) <sgv@odoo.com>
Signed-off-by: Thomas Lefebvre (thle) <thle@odoo.com>
This commit is contained in:
@@ -51,9 +51,10 @@ class LeaveReport(models.Model):
|
||||
FROM (SELECT
|
||||
allocation.employee_id as employee_id,
|
||||
employee.active as active_employee,
|
||||
CASE
|
||||
WHEN request.number_of_days > 0 THEN allocation.number_of_days - request.number_of_days
|
||||
ELSE allocation.number_of_days
|
||||
CASE
|
||||
WHEN allocation.id = min_allocation_id.min_id
|
||||
THEN aggregate_allocation.number_of_days - aggregate_leave.number_of_days
|
||||
ELSE 0
|
||||
END as number_of_days,
|
||||
allocation.department_id as department_id,
|
||||
allocation.holiday_status_id as leave_type,
|
||||
@@ -64,10 +65,25 @@ class LeaveReport(models.Model):
|
||||
allocation.employee_company_id as company_id
|
||||
FROM hr_leave_allocation as allocation
|
||||
INNER JOIN hr_employee as employee ON (allocation.employee_id = employee.id)
|
||||
LEFT JOIN
|
||||
(SELECT holiday_status_id, employee_id, sum(number_of_days) as number_of_days
|
||||
FROM hr_leave GROUP BY holiday_status_id, employee_id) request
|
||||
on (allocation.employee_id=request.employee_id and allocation.holiday_status_id = request.holiday_status_id)
|
||||
|
||||
/* Obtain the minimum id for a given employee and type of leave */
|
||||
LEFT JOIN
|
||||
(SELECT employee_id, holiday_status_id, min(id) as min_id
|
||||
FROM hr_leave_allocation GROUP BY employee_id, holiday_status_id) min_allocation_id
|
||||
on (allocation.employee_id=min_allocation_id.employee_id and allocation.holiday_status_id=min_allocation_id.holiday_status_id)
|
||||
|
||||
/* Obtain the sum of allocations */
|
||||
LEFT JOIN
|
||||
(SELECT employee_id, holiday_status_id, sum(number_of_days) as number_of_days
|
||||
FROM hr_leave_allocation GROUP BY employee_id, holiday_status_id) aggregate_allocation
|
||||
on (allocation.employee_id=aggregate_allocation.employee_id and allocation.holiday_status_id=aggregate_allocation.holiday_status_id)
|
||||
|
||||
/* Obtain the sum of requested leaves (validated and confirmed) */
|
||||
LEFT JOIN
|
||||
(SELECT employee_id, holiday_status_id, sum(number_of_days) as number_of_days
|
||||
FROM hr_leave GROUP BY employee_id, holiday_status_id) aggregate_leave
|
||||
on (allocation.employee_id=aggregate_leave.employee_id and allocation.holiday_status_id = aggregate_leave.holiday_status_id)
|
||||
|
||||
UNION ALL SELECT
|
||||
request.employee_id as employee_id,
|
||||
employee.active as active_employee,
|
||||
|
||||
Reference in New Issue
Block a user