[IMP] hr_holidays: allow allocation and request per company

Purpose of this commit is to add an option when allocation or requesting
leaves in mass. New option is to do it by company.

Company field used for mass allocation or request is called mode_company_id
to avoid confusion with possible company_id field used for multi company.

This commit is linked to task ID 1876795 and PR #26571.
This commit is contained in:
Thibault Delavallée
2018-09-10 13:09:04 +02:00
parent 744de4ee1c
commit 04250cff1b
4 changed files with 111 additions and 41 deletions
+42 -18
View File
@@ -148,16 +148,20 @@ class HolidaysRequest(models.Model):
meeting_id = fields.Many2one('calendar.event', string='Meeting')
parent_id = fields.Many2one('hr.leave', string='Parent', copy=False)
linked_request_ids = fields.One2many('hr.leave', 'parent_id', string='Linked Requests')
category_id = fields.Many2one(
'hr.employee.category', string='Employee Tag', readonly=True,
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
holiday_type = fields.Selection([
('employee', 'By Employee'),
('company', 'By Company'),
('department', 'By Department'),
('category', 'By Employee Tag')],
string='Allocation Mode', readonly=True, required=True, default='employee',
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
help='By Employee: Allocation/Request for individual Employee, By Employee Tag: Allocation/Request for group of employees in category')
category_id = fields.Many2one(
'hr.employee.category', string='Employee Tag', readonly=True,
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
mode_company_id = fields.Many2one(
'res.company', string='Company', readonly=True,
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
first_approver_id = fields.Many2one(
'hr.employee', string='First Approval', readonly=True, copy=False,
help='This area is automatically filled by the user who validate the leave', oldname='manager_id')
@@ -233,8 +237,12 @@ class HolidaysRequest(models.Model):
request_unit_custom = fields.Boolean('Days-long custom hours')
_sql_constraints = [
('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )",
"The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
('type_value',
"CHECK((holiday_type='employee' AND employee_id IS NOT NULL) or "
"(holiday_type='company' AND mode_company_id IS NOT NULL) or "
"(holiday_type='category' AND category_id IS NOT NULL) or "
"(holiday_type='department' AND department_id IS NOT NULL) )",
"The employee, department, company or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
('date_check2', "CHECK ((date_from <= date_to))", "The start date must be anterior to the end date."),
('duration_check', "CHECK ( number_of_days >= 0 )", "If you want to change the number of days you should use the 'period' mode"),
]
@@ -307,20 +315,28 @@ class HolidaysRequest(models.Model):
@api.onchange('holiday_type')
def _onchange_type(self):
if self.holiday_type == 'employee' and not self.employee_id:
if self.env.user.employee_ids:
self.employee_id = self.env.user.employee_ids[0]
elif self.holiday_type == 'department':
if self.env.user.employee_ids:
self.department_id = self.department_id or self.env.user.employee_ids[0].department_id
self.employee_id = None
self.employee_id = self.env.user.employee_ids[0].id
self.mode_company_id = False
self.category_id = False
elif self.holiday_type == 'company' and not self.mode_company_id:
self.employee_id = False
self.mode_company_id = self.env.user.company_id.id
self.category_id = False
elif self.holiday_type == 'department' and not self.department_id:
self.employee_id = False
self.mode_company_id = False
self.department_id = self.env.user.employee_ids[0].department_id.id
self.category_id = False
elif self.holiday_type == 'category':
self.employee_id = None
self.department_id = None
self.employee_id = False
self.mode_company_id = False
self.department_id = False
@api.onchange('employee_id')
def _onchange_employee_id(self):
self.manager_id = self.employee_id and self.employee_id.parent_id
self.department_id = self.employee_id.department_id
self.manager_id = self.employee_id.parent_id.id
if self.employee_id:
self.department_id = self.employee_id.department_id
@api.onchange('date_from', 'date_to')
def _onchange_leave_dates(self):
@@ -614,12 +630,20 @@ class HolidaysRequest(models.Model):
holiday.write({'first_approver_id': current_employee.id})
if holiday.holiday_type == 'employee':
holiday._validate_leave_request()
elif holiday.holiday_type in ['category', 'department']:
elif holiday.holiday_type in ['company', 'category', 'department']:
leaves = self.env['hr.leave']
employees = holiday.category_id.employee_ids if holiday.holiday_type == 'category' else holiday.department_id.member_ids
if holiday.holiday_type == 'category':
employees = holiday.category_id.employee_ids
elif holiday.holiday_type == 'company':
employees = self.env['hr.employee'].search([('company_id', '=', self.mode_company_id.id)])
else:
holiday.department_id.member_ids
for employee in employees:
values = holiday._prepare_holiday_values(employee)
leaves += self.with_context(mail_notify_force_send=False).create(values)
leaves += self.with_context(
mail_notify_force_send=False,
mail_activity_automation_skip=True
).create(values)
# TODO is it necessary to interleave the calls?
leaves.action_approve()
if leaves and leaves[0].validation_type == 'both':
@@ -87,15 +87,24 @@ class HolidaysAllocation(models.Model):
# mode
holiday_type = fields.Selection([
('employee', 'By Employee'),
('company', 'By Company'),
('department', 'By Department'),
('category', 'By Employee Tag')],
string='Allocation Mode', readonly=True, required=True, default='employee',
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]},
help='By Employee: Allocation for individual Employee, By Employee Tag: Allocation for group of employees in category')
department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
help="Allow to create requests in batchs:\n- By Employee: for a specific employee"
"\n- By Company: all employees of the specified company"
"\n- By Department: all employees of the specified department"
"\n- By Employee Tag: all employees of the specific employee group category")
mode_company_id = fields.Many2one(
'res.company', string='Company', readonly=True,
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
department_id = fields.Many2one(
'hr.department', string='Department', readonly=True,
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
category_id = fields.Many2one(
'hr.employee.category', string='Employee Tag', readonly=True,
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee')
states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]})
# accrual configuration
accrual = fields.Boolean(
"Accrual", readonly=True,
@@ -115,8 +124,12 @@ class HolidaysAllocation(models.Model):
nextcall = fields.Date("Date of the next accrual allocation", default=False, readonly=True)
_sql_constraints = [
('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )",
"The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
('type_value',
"CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or "
"(holiday_type='category' AND category_id IS NOT NULL) or "
"(holiday_type='department' AND department_id IS NOT NULL) or "
"(holiday_type='company' AND mode_company_id IS NOT NULL))",
"The employee, department, company or employee category of this request is missing. Please make sure that your user login is linked to an employee."),
('duration_check', "CHECK ( number_of_days >= 0 )", "The number of days must be greater than 0."),
('number_per_interval_check', "CHECK(number_per_interval > 0)", "The number per interval should be greater than 0"),
('interval_number_check', "CHECK(interval_number > 0)", "The interval number should be greater than 0"),
@@ -399,19 +412,32 @@ class HolidaysAllocation(models.Model):
holiday.write({'second_approver_id': current_employee.id})
else:
holiday.write({'first_approver_id': current_employee.id})
if holiday.holiday_type in ['category', 'department']:
leaves = self.env['hr.leave.allocation']
employees = holiday.category_id.employee_ids if holiday.holiday_type == 'category' else holiday.department_id.member_ids
for employee in employees:
values = holiday._prepare_holiday_values(employee)
leaves += self.with_context(mail_notify_force_send=False).create(values)
# TODO is it necessary to interleave the calls?
leaves.action_approve()
if leaves and leaves[0].validation_type == 'both':
leaves.action_validate()
holiday._action_validate_create_childs()
self.activity_update()
return True
def _action_validate_create_childs(self):
childs = self.env['hr.leave.allocation']
if self.state == 'validate' and self.holiday_type in ['category', 'department', 'company']:
if self.holiday_type == 'category':
employees = self.category_id.employee_ids
elif self.holiday_type == 'department':
employees = self.department_id.member_ids
else:
employees = self.env['hr.employee'].search([('company_id', '=', self.mode_company_id.id)])
for employee in employees:
childs += self.with_context(
mail_notify_force_send=False,
mail_activity_automation_skip=True
).create(self._prepare_holiday_values(employee))
# TODO is it necessary to interleave the calls?
childs.action_approve()
if childs and self.holiday_status_id.validation_type == 'both':
childs.action_validate()
return childs
@api.multi
def action_refuse(self):
current_employee = self.env['hr.employee'].search([('user_id', '=', self.env.uid)], limit=1)
@@ -122,14 +122,20 @@
<field name="holiday_type" string="Mode" groups="hr_holidays.group_hr_holidays_user" context="{'employee_id':employee_id}" />
</xpath>
<xpath expr="//field[@name='employee_id']" position="replace">
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')],'invisible':[('holiday_type','!=','employee')]}"
groups="hr_holidays.group_hr_holidays_user"/>
<field name="employee_id" groups="hr_holidays.group_hr_holidays_user"
attrs="{'required': [('holiday_type', '=', 'employee')], 'invisible': [('holiday_type', '!=', 'employee')]}"/>
</xpath>
<xpath expr="//field[@name='employee_id']" position="after">
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'invisible':[('holiday_type','!=','category')]}"/>
<field name="category_id"
attrs="{'required': [('holiday_type', '=', 'category')], 'invisible': [('holiday_type', '!=', 'category')]}"/>
</xpath>
<xpath expr="//field[@name='department_id']" position="replace">
<field name="department_id" groups="hr_holidays.group_hr_holidays_user" attrs="{'invisible':[('holiday_type','=','category')]}"/>
<field name="department_id" groups="hr_holidays.group_hr_holidays_user"
attrs="{'required': [('holiday_type', '=', 'department')], 'invisible': [('holiday_type', 'not in', ('department', 'category'))]}"/>
</xpath>
<xpath expr="//field[@name='department_id']" position="after">
<field name="mode_company_id" groups="hr_holidays.group_hr_holidays_user"
attrs="{'required': [('holiday_type', '=', 'company')], 'invisible': [('holiday_type', '!=', 'company')]}"/>
</xpath>
<xpath expr="//field[@name='accrual']" position="attributes">
<attribute name="invisible">0</attribute>
+18 -4
View File
@@ -197,10 +197,24 @@
<field name="arch" type="xml">
<xpath expr="//group[@name='col_right']" position="replace">
<group>
<field name="holiday_type" attrs="{'readonly':[('state','!=','draft')]}" string="Mode" groups="hr_holidays.group_hr_holidays_user" context="{'employee_id':employee_id}" />
<field name="employee_id" attrs="{'required':[('holiday_type','=','employee')],'invisible':[('holiday_type','!=','employee')]}" groups="hr_holidays.group_hr_holidays_user"/>
<field name="category_id" attrs="{'required':[('holiday_type','=','category')], 'readonly': [('state','!=','draft'), ('state','!=','confirm')], 'invisible':[('holiday_type','!=','category')]}"/>
<field name="department_id" groups="hr_holidays.group_hr_holidays_user" attrs="{'readonly':['|',('state','=', 'validate'),('holiday_type','!=','department')],'invisible':[('holiday_type','=','category')]}"/>
<field name="holiday_type" string="Mode"
groups="hr_holidays.group_hr_holidays_user"/>
<field name="employee_id" groups="hr_holidays.group_hr_holidays_user" attrs="{
'required': [('holiday_type', '=', 'employee')],
'invisible': [('holiday_type', '!=', 'employee')]
}"/>
<field name="mode_company_id" groups="hr_holidays.group_hr_holidays_user" attrs="{
'required': [('holiday_type', '=', 'company')],
'invisible': [('holiday_type', '!=', 'company')]
}"/>
<field name="category_id" groups="hr_holidays.group_hr_holidays_user" attrs="{
'required': [('holiday_type', '=', 'category')],
'invisible': [('holiday_type', '!=','category')]
}"/>
<field name="department_id" groups="hr_holidays.group_hr_holidays_user" attrs="{
'required': [('holiday_type', '=', 'department')],
'invisible': [('holiday_type', 'not in', ('employee', 'department'))]
}"/>
<field name="payslip_status" groups="hr_holidays.group_hr_holidays_manager" widget="toggle_button"/>
</group>
<div groups="hr_holidays.group_hr_holidays_manager">