6 Commits

5 changed files with 47 additions and 74 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "hr_employee_stats_sheet", "name": "hr_employee_stats_sheet",
"version": "16.0.3.0.0", "version": "16.0.3.1.3",
"description": "Add global sheet for employee stats", "description": "Add global sheet for employee stats",
"summary": "Add global sheet for employee stats", "summary": "Add global sheet for employee stats",
"author": "Nicolas JEUDY", "author": "Nicolas JEUDY",
@@ -17,7 +17,6 @@
"resource", "resource",
"hr_employee_calendar_planning", "hr_employee_calendar_planning",
"hr_timesheet_sheet_usability_misc", "hr_timesheet_sheet_usability_misc",
"hr_timesheet_sheet_usability_akretion",
], ],
"data": [ "data": [
"security/ir.model.access.csv", "security/ir.model.access.csv",

View File

@@ -18,11 +18,10 @@ class HrEmployeeStats(models.Model):
is_public_holiday = fields.Boolean("Public Holiday", compute="_compute_dayofweek") is_public_holiday = fields.Boolean("Public Holiday", compute="_compute_dayofweek")
employee_id = fields.Many2one("hr.employee", "Employee", required=True) employee_id = fields.Many2one("hr.employee", "Employee", required=True)
department_id = fields.Many2one("hr.department", "Department") department_id = fields.Many2one("hr.department", "Department")
timesheet_line_ids = fields.One2many( timesheet_line_ids = fields.Many2many(
"account.analytic.line", "account.analytic.line",
"employee_id",
"Timesheet lines",
compute="_compute_timesheet_line_ids", compute="_compute_timesheet_line_ids",
string="Timesheet lines",
) )
date = fields.Date("Date", required=True) date = fields.Date("Date", required=True)
company_id = fields.Many2one( company_id = fields.Many2one(
@@ -114,23 +113,23 @@ class HrEmployeeStats(models.Model):
recovery = self.env["hr.leave"] recovery = self.env["hr.leave"]
total_recovery_hours = 0 total_recovery_hours = 0
if self.date and self.employee_id and self._get_holiday_status_id(): if self.date and self.employee_id and self._get_holiday_status_id():
recovery_id = recovery.search( recovery_ids = recovery.search(
[ [
("employee_id", "=", self.employee_id.id), ("employee_id", "=", self.employee_id.id),
("holiday_status_id", "=", self._get_holiday_status_id()), ("holiday_status_id", "=", self._get_holiday_status_id()),
("request_date_from", "<=", self.date), ("request_date_from", "<=", self.date),
("request_date_to", ">=", self.date), ("request_date_to", ">=", self.date),
], ],
limit=1
) )
if recovery_id: if recovery_ids:
if recovery_id.request_unit_hours: for recovery_id in recovery_ids:
recovery_hours = recovery_id.number_of_hours_display if recovery_id.request_unit_hours:
total_recovery_hours = min(recovery_hours,self._get_total_planned_hours()) recovery_hours = recovery_id.number_of_hours_display
elif recovery_id.request_unit_half: total_recovery_hours += min(recovery_hours,self._get_total_planned_hours())
total_recovery_hours = self._get_total_planned_hours() / 2 elif recovery_id.request_unit_half:
else : total_recovery_hours += self._get_total_planned_hours() / 2
total_recovery_hours = self._get_total_planned_hours() else :
total_recovery_hours += self._get_total_planned_hours()
return total_recovery_hours return total_recovery_hours
def _get_total_leave_hours(self): def _get_total_leave_hours(self):
@@ -138,23 +137,23 @@ class HrEmployeeStats(models.Model):
leave = self.env["hr.leave"] leave = self.env["hr.leave"]
total_leave_hours = 0 total_leave_hours = 0
if self.date and self.employee_id: if self.date and self.employee_id:
leave_id = leave.search( leave_ids = leave.search(
[ [
("employee_id", "=", self.employee_id.id), ("employee_id", "=", self.employee_id.id),
("holiday_status_id", "!=", self._get_holiday_status_id()), ("holiday_status_id", "!=", self._get_holiday_status_id()),
("request_date_from", "<=", self.date), ("request_date_from", "<=", self.date),
("request_date_to", ">=", self.date), ("request_date_to", ">=", self.date),
], ],
limit=1
) )
if leave_id: if leave_ids:
if leave_id.request_unit_hours: for leave_id in leave_ids:
leave_hours = leave_id.number_of_hours_display if leave_id.request_unit_hours:
total_leave_hours = min(leave_hours,self._get_total_planned_hours()) leave_hours = leave_id.number_of_hours_display
elif leave_id.request_unit_half: total_leave_hours += min(leave_hours,self._get_total_planned_hours())
total_leave_hours = self._get_total_planned_hours() / 2 elif leave_id.request_unit_half:
else : total_leave_hours += self._get_total_planned_hours() / 2
total_leave_hours = self._get_total_planned_hours() else :
total_leave_hours += self._get_total_planned_hours()
return total_leave_hours return total_leave_hours
@api.depends("employee_id", "date") @api.depends("employee_id", "date")

View File

@@ -100,28 +100,6 @@ class HrTimesheetSheet(models.Model):
sheet.recovery_allocation_ids.write({"state": "refuse"}) sheet.recovery_allocation_ids.write({"state": "refuse"})
return res return res
def _get_working_hours_per_week(self):
"""
Get the weekly working hours for the employee, which is defined by:
- the employee's work contract,
- or their resource calendar,
- or the company's resource calendar,
- or the default value of 40 hours per week.
:return: limit recovery hours
"""
# get ressource calendar id used during the timesheet sheet time period
ressource_calendar_id = self.employee_id._get_calendar_in_progress_during_a_time_period(self.date_start,self.date_end)
if ressource_calendar_id:
resource_calendar_attendance_ids = self.env[
"resource.calendar.attendance"
].search([("calendar_id", "=", ressource_calendar_id.id)])
# calculate working hours per week according to the employee's resource calendar
weekly_working_hours = 0
for day in resource_calendar_attendance_ids:
weekly_working_hours += day.hour_to - day.hour_from
return weekly_working_hours
return HOURS_PER_DAY * 5
def _get_working_hours_per_day(self): def _get_working_hours_per_day(self):
""" """
Get the hours per day for the employee according to: Get the hours per day for the employee according to:
@@ -137,12 +115,6 @@ class HrTimesheetSheet(models.Model):
return ressource_calendar_id.hours_per_day return ressource_calendar_id.hours_per_day
return HOURS_PER_DAY return HOURS_PER_DAY
def _get_max_allowed_recovery_hours(self):
"""
Get the maximum number of hours beyond which new recovery allowances cannot be created
"""
return self._get_working_hours_per_week()
def action_generate_recovery_allocation(self): def action_generate_recovery_allocation(self):
# check if the user has the right to review the timesheet sheet # check if the user has the right to review the timesheet sheet
self.ensure_one() self.ensure_one()
@@ -175,25 +147,6 @@ class HrTimesheetSheet(models.Model):
# get recovery hours from total gap hours of the timesheet sheet # get recovery hours from total gap hours of the timesheet sheet
recovery_hours = self._get_timesheet_sheet_recovery_hours() recovery_hours = self._get_timesheet_sheet_recovery_hours()
# get recovery hours cap
max_allowed_recovery_hours = self._get_max_allowed_recovery_hours()
if max_allowed_recovery_hours:
# find recovery remaining leaves for the employee
recovery_type_id = self.env.company.recovery_type_id
# get virtual remaining leaves for the employee and the recovery leaves type
data_days = recovery_type_id.get_employees_days([employee_id.id])[employee_id.id]
total_recovery_type_leaves = data_days.get(recovery_type_id.id,{})
total_virtual_remaining_recovery_type_leaves = total_recovery_type_leaves.get('virtual_remaining_leaves', 0)
# add the recovery hours to the total remaining leaves recovery type, and check if the limit of recovery hours is exceeded
exceeded_hours = total_virtual_remaining_recovery_type_leaves + recovery_hours - max_allowed_recovery_hours
# if limit recovery hours is exceeded, don't create a new allocation
if exceeded_hours > 0:
raise UserError(
_(
"The number of recovery hours exceeds the authorized limit (%s h) by %s hours"
)
% (max_allowed_recovery_hours, exceeded_hours)
)
# convert recovery hours into days # convert recovery hours into days
recovery_days = recovery_hours / self._get_working_hours_per_day() recovery_days = recovery_hours / self._get_working_hours_per_day()
@@ -206,6 +159,7 @@ class HrTimesheetSheet(models.Model):
"number_of_days": recovery_days, "number_of_days": recovery_days,
"timesheet_sheet_id": self.id, "timesheet_sheet_id": self.id,
"allocation_type": 'accrual', "allocation_type": 'accrual',
"date_from": self.date_start,
} }
) )

View File

@@ -3,7 +3,7 @@
{ {
"name": "France - Time Off", "name": "France - Time Off",
"version": "16.0.1.0.0", "version": "16.0.1.0.1",
"category": "Human Resources/Time Off", "category": "Human Resources/Time Off",
"countries": ["fr"], "countries": ["fr"],
"summary": "Management of leaves for part-time workers in France", "summary": "Management of leaves for part-time workers in France",

View File

@@ -2,7 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details. # Part of Odoo. See LICENSE file for full copyright and licensing details.
from dateutil.relativedelta import relativedelta from dateutil.relativedelta import relativedelta
from odoo import fields, models, _ from odoo import fields, models, _, api
from odoo.exceptions import UserError from odoo.exceptions import UserError
class HrLeave(models.Model): class HrLeave(models.Model):
@@ -11,6 +11,13 @@ class HrLeave(models.Model):
resource_calendar_id = fields.Many2one('resource.calendar', compute='_compute_resource_calendar_id', store=True, readonly=False, copy=False) resource_calendar_id = fields.Many2one('resource.calendar', compute='_compute_resource_calendar_id', store=True, readonly=False, copy=False)
l10n_fr_date_to_changed = fields.Boolean() l10n_fr_date_to_changed = fields.Boolean()
@api.depends(
'holiday_type',
'employee_id',
'employee_id.resource_calendar_id',
'request_date_from',
'request_date_to',
)
def _compute_resource_calendar_id(self): def _compute_resource_calendar_id(self):
for leave in self: for leave in self:
calendar = False calendar = False
@@ -36,6 +43,20 @@ class HrLeave(models.Model):
# If there are more than one contract they should all have the # If there are more than one contract they should all have the
# same calendar, otherwise a constraint is violated. # same calendar, otherwise a constraint is violated.
calendar = contracts[:1].resource_calendar_id calendar = contracts[:1].resource_calendar_id
# Crappy hack again : if hr_employee_calendar_planning is installed
# use planning calendar instead of contract calendar
if 'hr.employee.calendar' in self.env:
calendar_planning = self.env["hr.employee.calendar"].search(
[
("employee_id", "=", leave.employee_id.id),
("date_start", "<=", leave.request_date_to),
"|", ("date_end", "=", False), # pas de date de fin OU
("date_end", ">=", leave.request_date_from), # date de fin après le début
],
limit=1,
)
if calendar_planning:
calendar = calendar_planning.calendar_id
elif leave.holiday_type == 'department': elif leave.holiday_type == 'department':
calendar = leave.department_id.company_id.resource_calendar_id calendar = leave.department_id.company_id.resource_calendar_id
elif leave.holiday_type == 'company': elif leave.holiday_type == 'company':