diff --git a/hr_holidays_accrual/README.rst b/hr_holidays_accrual/README.rst
index bd4d2af7..9077cef1 100644
--- a/hr_holidays_accrual/README.rst
+++ b/hr_holidays_accrual/README.rst
@@ -2,13 +2,12 @@
Hibou - HR Holidays Accrual
***************************
-Use Employee Tags to grant Leave Allocations.
+**This Module is now Deprecated in 12.0**
-For more information and add-ons, visit `Hibou.io `_.
+If it comes back, it would be a new module.
-=============
-Main Features
-=============
+
+**Old**
* Adds new boolean field `grant_by_tag` to Leave Allocations.
* Allows user to create a Leave Allocation by employee tag, then use that tag to grant the newly created leave to as many employees as desired.
@@ -27,4 +26,4 @@ License
Please see `LICENSE `_.
-Copyright Hibou Corp. 2018
\ No newline at end of file
+Copyright Hibou Corp. 2019
\ No newline at end of file
diff --git a/hr_holidays_accrual/__manifest__.py b/hr_holidays_accrual/__manifest__.py
index 022546ee..bac2ab3c 100755
--- a/hr_holidays_accrual/__manifest__.py
+++ b/hr_holidays_accrual/__manifest__.py
@@ -1,7 +1,7 @@
{
'name': 'HR Holidays Accrual',
'author': 'Hibou Corp. ',
- 'version': '11.0.0.0.0',
+ 'version': '12.0.1.0.0',
'category': 'Human Resources',
'sequence': 95,
'summary': 'Grant leave allocations with tags',
@@ -13,6 +13,6 @@ Create leave allocations by tag, then use tags to grant leaves to employees.
'data': [
'views/hr_holidays_views.xml',
],
- 'installable': True,
+ 'installable': False,
'application': False,
}
diff --git a/hr_holidays_accrual_payroll/README.rst b/hr_holidays_accrual_payroll/README.rst
index 2873ee26..29cd57c4 100644
--- a/hr_holidays_accrual_payroll/README.rst
+++ b/hr_holidays_accrual_payroll/README.rst
@@ -10,14 +10,13 @@ For more information and add-ons, visit `Hibou.io `_.
Main Features
=============
-* New Fields `accrue_by_pay_period` and `allocation_per_pay_period` on Leave allocations.
-* Can set up an accrual by individual employee, or make an Allocation by Employee Tag for multiple employees.
+*New in 12.0*
+Odoo implemented their own accruals, which we now extend. The old base module `hr_holidays_accrual` is now deprecated.
-.. image:: https://user-images.githubusercontent.com/15882954/42062853-f4175416-7ae3-11e8-8432-f54e26fe6094.png
- :alt: 'Equipment Detail'
- :width: 988
- :align: left
+* Adds 'Payslip' to the interval dropdown
+* When Payslip for employee is confirmed, the accrual will be made.
+* Additionally exposes the `accrual_limit` field "Balance limit" (Why Odoo doesn't...)
@@ -27,4 +26,4 @@ License
Please see `LICENSE `_.
-Copyright Hibou Corp. 2018
\ No newline at end of file
+Copyright Hibou Corp. 2019
diff --git a/hr_holidays_accrual_payroll/__manifest__.py b/hr_holidays_accrual_payroll/__manifest__.py
index 96893f7f..c434a958 100755
--- a/hr_holidays_accrual_payroll/__manifest__.py
+++ b/hr_holidays_accrual_payroll/__manifest__.py
@@ -1,7 +1,7 @@
{
'name': 'HR Holidays Accrual - Payroll',
'author': 'Hibou Corp. ',
- 'version': '11.0.1.0.0',
+ 'version': '12.0.1.0.0',
'category': 'Human Resources',
'sequence': 95,
'summary': 'Grant leave allocations per payperiod',
@@ -10,7 +10,7 @@ Automates leave allocations.
""",
'website': 'https://hibou.io/',
'depends': [
- 'hr_holidays_accrual',
+ 'hr_holidays',
'hr_payroll'
],
'data': [
diff --git a/hr_holidays_accrual_payroll/models/__init__.py b/hr_holidays_accrual_payroll/models/__init__.py
index 5d988fa2..8b3405a2 100644
--- a/hr_holidays_accrual_payroll/models/__init__.py
+++ b/hr_holidays_accrual_payroll/models/__init__.py
@@ -1 +1,2 @@
+from . import hr_leave_allocation
from . import hr_payslip
diff --git a/hr_holidays_accrual_payroll/models/hr_leave_allocation.py b/hr_holidays_accrual_payroll/models/hr_leave_allocation.py
new file mode 100644
index 00000000..e05c10c8
--- /dev/null
+++ b/hr_holidays_accrual_payroll/models/hr_leave_allocation.py
@@ -0,0 +1,98 @@
+from datetime import datetime, time
+from dateutil.relativedelta import relativedelta
+
+from odoo import api, fields, models
+from odoo.addons.resource.models.resource import HOURS_PER_DAY
+
+
+class HRLeaveAllocation(models.Model):
+ _inherit = 'hr.leave.allocation'
+
+ interval_unit = fields.Selection(selection_add=[('payslip', 'Payslip')])
+
+ @api.model
+ def payslip_update_accrual(self, payslips):
+ employees = payslips.mapped('employee_id')
+ holidays = self.env['hr.leave.allocation'].search([
+ ('employee_id', 'in', employees.ids),
+ ('accrual', '=', True),
+ ('state', '=', 'validate'),
+ ('holiday_type', '=', 'employee'),
+ '|', ('date_to', '=', False),
+ ('date_to', '>', fields.Datetime.now()),
+ ])
+ for holiday in holidays:
+ days_to_give = holiday.number_per_interval
+ if holiday.unit_per_interval == 'hours':
+ # As we encode everything in days in the database we need to convert
+ # the number of hours into days for this we use the
+ # mean number of hours set on the employee's calendar
+ days_to_give = days_to_give / (holiday.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY)
+
+ new_number_of_days = holiday.number_of_days + days_to_give
+ if holiday.accrual_limit > 0:
+ new_number_of_days = min(new_number_of_days, holiday.accrual_limit)
+ holiday.number_of_days = new_number_of_days
+
+
+
+
+ # This is a 'patch' because I cannot influence the domain/search here to filter out the ones by payslip.
+ @api.model
+ def _update_accrual(self):
+ """
+ Method called by the cron task in order to increment the number_of_days when
+ necessary.
+ """
+ today = fields.Date.from_string(fields.Date.today())
+
+ holidays = self.search([('interval_unit', '!=', 'payslip'), # new domain filter
+ ('accrual', '=', True), ('state', '=', 'validate'), ('holiday_type', '=', 'employee'),
+ '|', ('date_to', '=', False), ('date_to', '>', fields.Datetime.now()),
+ '|', ('nextcall', '=', False), ('nextcall', '<=', today)])
+
+ for holiday in holidays:
+ values = {}
+
+ delta = relativedelta(days=0)
+
+ if holiday.interval_unit == 'weeks':
+ delta = relativedelta(weeks=holiday.interval_number)
+ if holiday.interval_unit == 'months':
+ delta = relativedelta(months=holiday.interval_number)
+ if holiday.interval_unit == 'years':
+ delta = relativedelta(years=holiday.interval_number)
+
+ values['nextcall'] = (holiday.nextcall if holiday.nextcall else today) + delta
+
+ period_start = datetime.combine(today, time(0, 0, 0)) - delta
+ period_end = datetime.combine(today, time(0, 0, 0))
+
+ # We have to check when the employee has been created
+ # in order to not allocate him/her too much leaves
+ start_date = holiday.employee_id._get_date_start_work()
+ # If employee is created after the period, we cancel the computation
+ if period_end <= start_date:
+ holiday.write(values)
+ continue
+
+ # If employee created during the period, taking the date at which he has been created
+ if period_start <= start_date:
+ period_start = start_date
+
+ worked = holiday.employee_id.get_work_days_data(period_start, period_end, domain=[('holiday_id.holiday_status_id.unpaid', '=', True), ('time_type', '=', 'leave')])['days']
+ left = holiday.employee_id.get_leave_days_data(period_start, period_end, domain=[('holiday_id.holiday_status_id.unpaid', '=', True), ('time_type', '=', 'leave')])['days']
+ prorata = worked / (left + worked) if worked else 0
+
+ days_to_give = holiday.number_per_interval
+ if holiday.unit_per_interval == 'hours':
+ # As we encode everything in days in the database we need to convert
+ # the number of hours into days for this we use the
+ # mean number of hours set on the employee's calendar
+ days_to_give = days_to_give / (holiday.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY)
+
+ values['number_of_days'] = holiday.number_of_days + days_to_give * prorata
+ if holiday.accrual_limit > 0:
+ values['number_of_days'] = min(values['number_of_days'], holiday.accrual_limit)
+
+ holiday.write(values)
diff --git a/hr_holidays_accrual_payroll/models/hr_payslip.py b/hr_holidays_accrual_payroll/models/hr_payslip.py
index 1c47b6a4..c046cf9f 100644
--- a/hr_holidays_accrual_payroll/models/hr_payslip.py
+++ b/hr_holidays_accrual_payroll/models/hr_payslip.py
@@ -8,40 +8,5 @@ class HRPayslip(models.Model):
def action_payslip_done(self):
res = super(HRPayslip, self).action_payslip_done()
if res and isinstance(res, (int, bool)):
- holidays = self.env['hr.holidays'].sudo()
- leaves_to_update = holidays.search([('employee_id', '=', self.employee_id.id),
- ('accrue_by_pay_period', '=', True)])
- for leave_to_update in leaves_to_update:
- new_allocation = leave_to_update.number_of_days_temp + leave_to_update.allocation_per_period
- q = """SELECT SUM(number_of_days)
- FROM hr_holidays
- WHERE employee_id = %d AND holiday_status_id = %d;""" % (leave_to_update.employee_id.id, leave_to_update.holiday_status_id.id)
- self.env.cr.execute(q)
- total_days = self.env.cr.fetchall()
- total_days = total_days[0][0]
- new_total_days = total_days + leave_to_update.allocation_per_period
- if leave_to_update.accrue_max and total_days > leave_to_update.accrue_max:
- new_allocation = leave_to_update.number_of_days_temp
- elif leave_to_update.accrue_max and new_total_days > leave_to_update.accrue_max:
- difference = leave_to_update.accrue_max - total_days
- new_allocation = leave_to_update.number_of_days_temp + difference
- if leave_to_update.number_of_days_temp != new_allocation:
- leave_to_update.write({'number_of_days_temp': new_allocation})
-
+ self.env['hr.leave.allocation'].payslip_update_accrual(self)
return res
-
-
-class HRHolidays(models.Model):
- _inherit = 'hr.holidays'
-
- accrue_by_pay_period = fields.Boolean(string="Accrue by Pay Period")
- allocation_per_period = fields.Float(string="Allocation Per Pay Period", digits=(12, 4))
- accrue_max = fields.Float(string="Maximum Accrual")
-
- def _accrue_for_employee_values(self, employee):
- values = super(HRHolidays, self)._accrue_for_employee_values(employee)
- if values:
- values['accrue_by_pay_period'] = self.accrue_by_pay_period
- values['allocation_per_period'] = self.allocation_per_period
- values['accrue_max'] = self.accrue_max
- return values
diff --git a/hr_holidays_accrual_payroll/tests/test_accrual.py b/hr_holidays_accrual_payroll/tests/test_accrual.py
index 43f325de..2a329ae6 100644
--- a/hr_holidays_accrual_payroll/tests/test_accrual.py
+++ b/hr_holidays_accrual_payroll/tests/test_accrual.py
@@ -9,35 +9,37 @@ class TestLeaves(TestHrHolidaysBase):
self.categ = self.env['hr.employee.category'].create({'name': 'Test Category'})
department = self.env['hr.department'].create({'name': 'Test Department'})
self.employee = self.env['hr.employee'].create({'name': 'Mark', 'department_id': department.id})
- self.leave_type = self.env['hr.holidays.status'].create({
+ self.leave_type = self.env['hr.leave.type'].create({
'name': 'Test Status',
'color_name': 'red',
})
- self.test_leave = self.env['hr.holidays'].create({
+ self.allocation = self.env['hr.leave.allocation'].create({
+ 'employee_id': self.employee.id,
'holiday_status_id': self.leave_type.id,
- 'number_of_days_temp': 0,
- 'holiday_type': 'category',
- 'category_id': self.categ.id,
- 'type': 'add',
- 'state': 'draft',
- 'grant_by_tag': True,
+ 'number_of_days': 0.0,
+ 'state': 'validate',
+ 'accrual': True,
+ 'holiday_type': 'employee',
+ 'number_per_interval': 0.75,
+ 'unit_per_interval': 'days',
+ 'interval_unit': 'payslip',
+ 'accrual_limit': 1,
})
def test_payslip_accrual(self):
- self.test_leave.write({
- 'accrue_by_pay_period': True,
- 'allocation_per_period': 1
- })
- self.test_leave.action_confirm()
- self.test_leave.action_approve()
-
- self.employee.write({'category_ids': [(6, False, [self.categ.id])]})
- self.assertEqual(self.employee.leaves_count, 0.0)
-
payslip = self.env['hr.payslip'].create({
'employee_id': self.employee.id,
'date_from': '2018-01-01',
'date_to': '2018-01-31'
})
payslip.action_payslip_done()
- self.assertEqual(self.employee.leaves_count, 1.0)
+ self.assertEqual(self.allocation.number_of_days, 0.75)
+
+ # Should be capped at 1 day
+ payslip = self.env['hr.payslip'].create({
+ 'employee_id': self.employee.id,
+ 'date_from': '2018-02-01',
+ 'date_to': '2018-02-28'
+ })
+ payslip.action_payslip_done()
+ self.assertEqual(self.allocation.number_of_days, 1.0)
diff --git a/hr_holidays_accrual_payroll/views/hr_holidays_views.xml b/hr_holidays_accrual_payroll/views/hr_holidays_views.xml
index a10a06fe..045d1e99 100644
--- a/hr_holidays_accrual_payroll/views/hr_holidays_views.xml
+++ b/hr_holidays_accrual_payroll/views/hr_holidays_views.xml
@@ -1,15 +1,22 @@
-
- hr.holidays.edit.holiday.new.inherit.pay
- hr.holidays
-
+
+
+ hr.leave.allocation.view.form.manager.payslip
+ hr.leave.allocation
+
-
-
-
-
+
+ {'required': [('accrual', '=', True)], 'invisible': [('interval_unit', '=', 'payslip')]}
+
+
+
+
+
+ Days
+
+
\ No newline at end of file