Skip to content
Permalink
Browse files

[IMP] hr_payroll: rename hr.benefit into hr.work.entry

TaskID: 1941598
  • Loading branch information...
RomainLibert authored and tivisse committed Feb 28, 2019
1 parent 67fb11e commit 1e017a54497e6c5e5af37f4bfe9f8d707acbdab4
@@ -29,10 +29,10 @@
'views/res_config_settings_views.xml',
'views/report_contributionregister_templates.xml',
'views/report_payslip_templates.xml',
'views/hr_benefit_views.xml',
'views/hr_work_entry_views.xml',
'views/hr_leave_views.xml',
'views/resource_views.xml',
'views/hr_benefit_template.xml',
'views/hr_work_entry_template.xml',
'views/hr_payroll_menu.xml',
],
'demo': ['data/hr_payroll_demo.xml'],
@@ -65,15 +65,15 @@
<field name="digits">4</field>
</record>

<!-- Benefits Type -->
<!-- Work entries Type -->

<record id="benefit_type_attendance" model="hr.benefit.type">
<record id="work_entry_type_attendance" model="hr.work.entry.type">
<field name="name">Attendance</field>
<field name="color">0</field>
<field name="code">WORK100</field>
</record>

<record id="benefit_type_leave" model="hr.benefit.type">
<record id="work_entry_type_leave" model="hr.work.entry.type">
<field name="name">Generic Time Off</field>
<field name="code">LEAVE100</field>
<field name="color">3</field>
@@ -141,59 +141,59 @@
<field name="state">open</field>
</record>

<!-- Benefits -->
<record id="benefit_type_home_working" model="hr.benefit.type">
<!-- Work entries -->
<record id="work_entry_type_home_working" model="hr.work.entry.type">
<field name="name">Home Working</field>
<field name="code">WORK200</field>
<field name="color">2</field>
</record>

<record id="benefit_type_extra_hours" model="hr.benefit.type">
<record id="work_entry_type_extra_hours" model="hr.work.entry.type">
<field name="name">Extra hours</field>
<field name="code">WORK300</field>
<field name="color">2</field>
</record>

<record id="benefit_type_long_leave" model="hr.benefit.type">
<record id="work_entry_type_long_leave" model="hr.work.entry.type">
<field name="name">Long Term Time Off</field>
<field name="code">LEAVE200</field>
<field name="is_leave">True</field>
<field name="color">4</field>
</record>

<record id="benefit_type_unpaid_leave" model="hr.benefit.type">
<record id="work_entry_type_unpaid_leave" model="hr.work.entry.type">
<field name="name">Unpaid Time Off</field>
<field name="code">LEAVE300</field>
<field name="is_leave">True</field>
<field name="color">5</field>
</record>

<record id="benefit_type_sick_leave" model="hr.benefit.type">
<record id="work_entry_type_sick_leave" model="hr.work.entry.type">
<field name="name">Sick Time Off</field>
<field name="code">LEAVE400</field>
<field name="is_leave">True</field>
<field name="color">5</field>
</record>

<!-- add benefit type to leave type -->
<!-- add work_entry type to leave type -->
<record id="hr_holidays.holiday_status_sl" model="hr.leave.type">
<field name="benefit_type_id" ref="benefit_type_sick_leave"></field>
<field name="work_entry_type_id" ref="work_entry_type_sick_leave"></field>
</record>

<record id="hr_holidays.holiday_status_unpaid" model="hr.leave.type">
<field name="benefit_type_id" ref="benefit_type_unpaid_leave"></field>
<field name="work_entry_type_id" ref="work_entry_type_unpaid_leave"></field>
</record>

<record id="hr_holidays.holiday_status_hw" model="hr.leave.type">
<field name="benefit_type_id" ref="benefit_type_home_working"></field>
<field name="work_entry_type_id" ref="work_entry_type_home_working"></field>
</record>

<record id="hr_holidays.holiday_status_cl" model="hr.leave.type">
<field name="benefit_type_id" ref="benefit_type_leave"></field>
<field name="work_entry_type_id" ref="work_entry_type_leave"></field>
</record>

<record id="hr_holidays.holiday_status_comp" model="hr.leave.type">
<field name="benefit_type_id" ref="benefit_type_leave"></field>
<field name="work_entry_type_id" ref="work_entry_type_leave"></field>
</record>

</odoo>
@@ -7,6 +7,6 @@
from . import res_config_settings
from . import hr_salary_rule
from . import hr_payslip
from . import hr_benefit
from . import hr_work_entry
from . import hr_leave
from . import resource
@@ -23,8 +23,8 @@ def _compute_payslip_count(self):
for employee in self:
employee.payslip_count = len(employee.slip_ids)

def has_non_validated_benefits(self, date_from, date_to):
return bool(self.env['hr.benefit'].search_count([
def has_non_validated_work_entries(self, date_from, date_to):
return bool(self.env['hr.work.entry'].search_count([
('employee_id', 'in', self.ids),
('date_start', '<=', date_to),
('date_stop', '>=', date_from),
@@ -40,13 +40,13 @@ def write(self, vals):
return res

@api.model
def generate_benefit(self, date_start, date_stop):
def generate_work_entry(self, date_start, date_stop):
def _format_datetime(date):
fmt = '%Y-%m-%d %H:%M:%S'
date = datetime.strptime(date, fmt) if isinstance(date, str) else date
return date.replace(tzinfo=pytz.utc) if not date.tzinfo else date

attendance_type = self.env.ref('hr_payroll.benefit_type_attendance')
attendance_type = self.env.ref('hr_payroll.work_entry_type_attendance')
vals_list = []

date_start = _format_datetime(date_start)
@@ -71,28 +71,28 @@ def _format_datetime(date):
global_leaves = employee.resource_calendar_id.global_leave_ids

employee_leaves = (emp_leaves | global_leaves).mapped('holiday_id')
vals_list.extend(employee_leaves._get_benefits_values())
vals_list.extend(employee_leaves._get_work_entries_values())

for contract in contracts:

date_start_benefits = max(date_start, datetime.combine(contract.date_start, datetime.min.time()).replace(tzinfo=pytz.utc))
date_stop_benefits = min(date_stop, datetime.combine(contract.date_end or datetime.max.date(), datetime.max.time()).replace(tzinfo=pytz.utc))
date_start_work_entries = max(date_start, datetime.combine(contract.date_start, datetime.min.time()).replace(tzinfo=pytz.utc))
date_stop_work_entries = min(date_stop, datetime.combine(contract.date_end or datetime.max.date(), datetime.max.time()).replace(tzinfo=pytz.utc))

calendar = contract.resource_calendar_id
resource = employee.resource_id
attendances = calendar._work_intervals(date_start_benefits, date_stop_benefits, resource=resource)
attendances = calendar._work_intervals(date_start_work_entries, date_stop_work_entries, resource=resource)
# Attendances
for interval in attendances:
benefit_type_id = interval[2].mapped('benefit_type_id')[:1] or attendance_type
work_entry_type_id = interval[2].mapped('work_entry_type_id')[:1] or attendance_type
vals_list += [{
'name': "%s: %s" % (benefit_type_id.name, employee.name),
'name': "%s: %s" % (work_entry_type_id.name, employee.name),
'date_start': interval[0].astimezone(pytz.utc),
'date_stop': interval[1].astimezone(pytz.utc),
'benefit_type_id': benefit_type_id.id,
'work_entry_type_id': work_entry_type_id.id,
'employee_id': employee.id,
'contract_id': contract.id,
'state': 'confirmed',
}]

new_benefits = self.env['hr.benefit']._safe_duplicate_create(vals_list, date_start, date_stop)
new_benefits._compute_conflicts_leaves_to_approve()
new_work_entries = self.env['hr.work.entry']._safe_duplicate_create(vals_list, date_start, date_stop)
new_work_entries._compute_conflicts_leaves_to_approve()
@@ -11,26 +11,26 @@
class HrLeaveType(models.Model):
_inherit = 'hr.leave.type'

benefit_type_id = fields.Many2one('hr.benefit.type', string='Benefit Type')
work_entry_type_id = fields.Many2one('hr.work.entry.type', string='Work Entry Type')


class HrLeave(models.Model):
_inherit = 'hr.leave'

@api.multi
def _get_benefits_values(self):
def _get_work_entries_values(self):
vals_list = []
for leave in self:
contract = leave.employee_id._get_contracts(leave.date_from, leave.date_to, states=['open', 'pending', 'close'])
start = max(leave.date_from, datetime.combine(contract.date_start, datetime.min.time()))
end = min(leave.date_to, datetime.combine(contract.date_end or date.max, datetime.max.time()))
benefit_type = leave.holiday_status_id.benefit_type_id
work_entry_type = leave.holiday_status_id.work_entry_type_id
vals_list += [{
'name': "%s%s" % (benefit_type.name + ": " if benefit_type else "", leave.employee_id.name),
'name': "%s%s" % (work_entry_type.name + ": " if work_entry_type else "", leave.employee_id.name),
'date_start': start,
'date_stop': end,
'benefit_type_id': benefit_type.id,
'display_warning': not bool(benefit_type),
'work_entry_type_id': work_entry_type.id,
'display_warning': not bool(work_entry_type),
'employee_id': leave.employee_id.id,
'leave_id': leave.id,
'state': 'confirmed',
@@ -47,7 +47,7 @@ def _create_resource_leave(self):
"""
resource_leaves = super(HrLeave, self)._create_resource_leave()
for resource_leave in resource_leaves:
resource_leave.benefit_type_id = resource_leave.holiday_id.holiday_status_id.benefit_type_id.id
resource_leave.work_entry_type_id = resource_leave.holiday_id.holiday_status_id.work_entry_type_id.id

resource_leave_values = []

@@ -59,7 +59,7 @@ def _create_resource_leave(self):
'name': leave.name,
'holiday_id': leave.id,
'resource_id': leave.employee_id.resource_id.id,
'benefit_type_id': leave.holiday_status_id.benefit_type_id.id,
'work_entry_type_id': leave.holiday_status_id.work_entry_type_id.id,
'time_type': leave.holiday_status_id.time_type,
'date_from': max(leave.date_from, datetime.combine(contract.date_start, datetime.min.time())),
'date_to': min(leave.date_to, datetime.combine(contract.date_end or date.max, datetime.max.time())),
@@ -90,64 +90,64 @@ def _check_contracts(self):
raise ValidationError(_('A leave cannot be set across multiple contracts.'))

@api.multi
def _cancel_benefit_conflict(self):
def _cancel_work_entry_conflict(self):
"""
Unlink any benefit linked to a leave in self.
Re-create new benefits where the leaves do not cover the full range of the deleted benefits.
Create a leave benefit for each leave in self.
Return True if one or more benefits are unlinked.
Unlink any work_entry linked to a leave in self.
Re-create new work_entries where the leaves do not cover the full range of the deleted work_entries.
Create a leave work_entry for each leave in self.
Return True if one or more work_entries are unlinked.
e.g.:
|---------------- benefit ----------------|
|---------------- work_entry ----------------|
|------ leave ------|
||
vv
|-benef-|---benefit leave---|----benefit---|
|-benef-|---work_entry leave---|----work_entry---|
"""
benefits = self.env['hr.benefit'].search([('leave_id', 'in', self.ids)])
if benefits:
vals_list = self._get_benefits_values()
# create new benefits where the leave does not cover the full benefit
benefits_intervals = Intervals(intervals=[(b.date_start, b.date_stop, b) for b in benefits])
work_entries = self.env['hr.work.entry'].search([('leave_id', 'in', self.ids)])
if work_entries:
vals_list = self._get_work_entries_values()
# create new work_entries where the leave does not cover the full work_entry
work_entries_intervals = Intervals(intervals=[(b.date_start, b.date_stop, b) for b in work_entries])
leave_intervals = Intervals(intervals=[(l.date_from, l.date_to, l) for l in self])
remaining_benefits = benefits_intervals - leave_intervals
remaining_work_entries = work_entries_intervals - leave_intervals

for interval in remaining_benefits:
benefit = interval[2]
leave = benefit.leave_id
benefit_type = benefit.benefit_type_id
employee = benefit.employee_id
for interval in remaining_work_entries:
work_entry = interval[2]
leave = work_entry.leave_id
work_entry_type = work_entry.work_entry_type_id
employee = work_entry.employee_id

benefit_start = interval[0] + relativedelta(seconds=1) if leave.date_to == interval[0] else interval[0]
benefit_stop = interval[1] - relativedelta(seconds=1) if leave.date_from == interval[1] else interval[1]
work_entry_start = interval[0] + relativedelta(seconds=1) if leave.date_to == interval[0] else interval[0]
work_entry_stop = interval[1] - relativedelta(seconds=1) if leave.date_from == interval[1] else interval[1]

vals_list += [{
'name': "%s: %s" % (benefit_type.name, employee.name),
'date_start': benefit_start,
'date_stop': benefit_stop,
'benefit_type_id': benefit_type.id,
'contract_id': benefit.contract_id.id,
'name': "%s: %s" % (work_entry_type.name, employee.name),
'date_start': work_entry_start,
'date_stop': work_entry_stop,
'work_entry_type_id': work_entry_type.id,
'contract_id': work_entry.contract_id.id,
'employee_id': employee.id,
'state': 'confirmed',
}]

date_start = min(benefits.mapped('date_start'))
date_stop = max(benefits.mapped('date_stop'))
self.env['hr.benefit']._safe_duplicate_create(vals_list, date_start, date_stop)
benefits.unlink()
date_start = min(work_entries.mapped('date_start'))
date_stop = max(work_entries.mapped('date_stop'))
self.env['hr.work.entry']._safe_duplicate_create(vals_list, date_start, date_stop)
work_entries.unlink()
return True
return False

@api.multi
def action_validate(self):
super(HrLeave, self).action_validate()
self.sudo()._cancel_benefit_conflict() # delete preexisting conflicting benefits
self.sudo()._cancel_work_entry_conflict() # delete preexisting conflicting work_entries
return True

@api.multi
def action_refuse(self):
super(HrLeave, self).action_refuse()
benefits = self.env['hr.benefit'].sudo().search([('leave_id', 'in', self.ids)])
benefits.write({'display_warning': False, 'active': False})
work_entries = self.env['hr.work.entry'].sudo().search([('leave_id', 'in', self.ids)])
work_entries.write({'display_warning': False, 'active': False})
return True

def _get_number_of_days(self, date_from, date_to, employee_id):
@@ -161,15 +161,15 @@ def get_worked_day_lines(self, contract, date_from, date_to):

calendar = contract.resource_calendar_id

benefit_types = self.env['hr.benefit.type'].search([('code', '!=', False)])
for benefit_type in benefit_types:
hours = contract.employee_id._get_benefit_days_data(benefit_type, day_from, day_to, calendar=calendar)['hours']
work_entry_types = self.env['hr.work.entry.type'].search([('code', '!=', False)])
for work_entry_type in work_entry_types:
hours = contract.employee_id._get_work_entry_days_data(work_entry_type, day_from, day_to, calendar=calendar)['hours']
if hours:
line = {
'name': benefit_type.name,
'sequence': benefit_type.sequence,
'code': benefit_type.code,
'number_of_days': hours / calendar.hours_per_day, # n_days returned by benefit_days_data doesn't make sense for extra work
'name': work_entry_type.name,
'sequence': work_entry_type.sequence,
'code': work_entry_type.code,
'number_of_days': hours / calendar.hours_per_day, # n_days returned by work_entry_days_data doesn't make sense for extra work
'number_of_hours': hours,
}
res.append(line)
Oops, something went wrong.

0 comments on commit 1e017a5

Please sign in to comment.
You can’t perform that action at this time.