diff --git a/hr_holidays_accrual/README.rst b/hr_holidays_accrual/README.rst
new file mode 100644
index 00000000..bd4d2af7
--- /dev/null
+++ b/hr_holidays_accrual/README.rst
@@ -0,0 +1,30 @@
+***************************
+Hibou - HR Holidays Accrual
+***************************
+
+Use Employee Tags to grant Leave Allocations.
+
+For more information and add-ons, visit `Hibou.io `_.
+
+=============
+Main Features
+=============
+
+* 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.
+
+.. image:: https://user-images.githubusercontent.com/15882954/42062226-cf3ce23e-7ae1-11e8-96dc-43268c7b904c.png
+ :alt: 'Equipment Detail'
+ :width: 988
+ :align: left
+
+
+
+
+=======
+License
+=======
+
+Please see `LICENSE `_.
+
+Copyright Hibou Corp. 2018
\ No newline at end of file
diff --git a/hr_holidays_accrual/__init__.py b/hr_holidays_accrual/__init__.py
new file mode 100755
index 00000000..0650744f
--- /dev/null
+++ b/hr_holidays_accrual/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/hr_holidays_accrual/__manifest__.py b/hr_holidays_accrual/__manifest__.py
new file mode 100755
index 00000000..022546ee
--- /dev/null
+++ b/hr_holidays_accrual/__manifest__.py
@@ -0,0 +1,18 @@
+{
+ 'name': 'HR Holidays Accrual',
+ 'author': 'Hibou Corp. ',
+ 'version': '11.0.0.0.0',
+ 'category': 'Human Resources',
+ 'sequence': 95,
+ 'summary': 'Grant leave allocations with tags',
+ 'description': """
+Create leave allocations by tag, then use tags to grant leaves to employees.
+ """,
+ 'website': 'https://hibou.io/',
+ 'depends': ['hr_holidays'],
+ 'data': [
+ 'views/hr_holidays_views.xml',
+ ],
+ 'installable': True,
+ 'application': False,
+}
diff --git a/hr_holidays_accrual/models/__init__.py b/hr_holidays_accrual/models/__init__.py
new file mode 100644
index 00000000..070ade81
--- /dev/null
+++ b/hr_holidays_accrual/models/__init__.py
@@ -0,0 +1 @@
+from . import hr_holidays
diff --git a/hr_holidays_accrual/models/hr_holidays.py b/hr_holidays_accrual/models/hr_holidays.py
new file mode 100644
index 00000000..cbb7e3ac
--- /dev/null
+++ b/hr_holidays_accrual/models/hr_holidays.py
@@ -0,0 +1,54 @@
+from odoo import api, fields, models
+
+
+class HRHolidays(models.Model):
+ _inherit = 'hr.holidays'
+
+ grant_by_tag = fields.Boolean(string="Grant by Tag")
+
+ def _accrue_for_employee_values(self, employee):
+ return {
+ 'holiday_status_id': self.holiday_status_id.id,
+ 'number_of_days_temp': self.number_of_days_temp,
+ 'holiday_type': 'employee',
+ 'employee_id': employee.id,
+ 'type': 'add',
+ 'state': 'confirm',
+ 'double_validation': self.double_validation,
+ 'grant_by_tag': self.grant_by_tag,
+ }
+
+ def accrue_for_employee(self, employee):
+ holidays = self.env['hr.holidays'].sudo()
+ for leave_to_create in self:
+ values = leave_to_create._accrue_for_employee_values(employee)
+ if values:
+ leave = holidays.create(values)
+ leave.action_approve()
+
+
+class HREmployee(models.Model):
+ _inherit = 'hr.employee'
+
+ @api.multi
+ def write(self, values):
+ holidays = self.env['hr.holidays'].sudo()
+ for emp in self:
+ if values.get('category_ids'):
+ categ_ids_command_list = values.get('category_ids')
+ for categ_ids_command in categ_ids_command_list:
+ ids = None
+ if categ_ids_command[0] == 6:
+ ids = set(categ_ids_command[2])
+ ids -= set(emp.category_ids.ids)
+ if categ_ids_command[0] == 4:
+ id = categ_ids_command[1]
+ if id not in emp.category_ids.ids:
+ ids = [id]
+ if ids:
+ # new category ids
+ leaves = holidays.search([('category_id', 'in', list(ids)),
+ ('grant_by_tag', '=', True)])
+ leaves.accrue_for_employee(emp)
+
+ return super(HREmployee, self).write(values)
diff --git a/hr_holidays_accrual/tests/__init__.py b/hr_holidays_accrual/tests/__init__.py
new file mode 100755
index 00000000..76829b5b
--- /dev/null
+++ b/hr_holidays_accrual/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_leaves
diff --git a/hr_holidays_accrual/tests/test_leaves.py b/hr_holidays_accrual/tests/test_leaves.py
new file mode 100644
index 00000000..1fc9de93
--- /dev/null
+++ b/hr_holidays_accrual/tests/test_leaves.py
@@ -0,0 +1,43 @@
+from odoo.addons.hr_holidays.tests.common import TestHrHolidaysBase
+
+
+class TestLeaves(TestHrHolidaysBase):
+
+ def setUp(self):
+ super(TestLeaves, self).setUp()
+
+ 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({
+ 'name': 'Test Status',
+ 'color_name': 'red',
+ })
+ self.test_leave = self.env['hr.holidays'].create({
+ 'holiday_status_id': self.leave_type.id,
+ 'number_of_days_temp': 5,
+ 'holiday_type': 'category',
+ 'category_id': self.categ.id,
+ 'type': 'add',
+ 'state': 'draft',
+ 'grant_by_tag': True,
+ })
+
+ def test_tag_assignment(self):
+ self.test_leave.action_confirm()
+ self.test_leave.action_approve()
+ self.assertEqual(self.employee.leaves_count, 0.0)
+ self.employee.write({'category_ids': [(6, False, [self.categ.id])]})
+ self.assertEqual(self.employee.leaves_count, 5.0)
+ leave = self.env['hr.holidays'].search([('employee_id', '=', self.employee.id)])
+ self.assertEqual(leave.holiday_status_id.id, self.leave_type.id)
+
+ def test_double_validation(self):
+ self.test_leave.write({'double_validation': True})
+ self.test_leave.action_confirm()
+ self.test_leave.action_approve()
+ self.test_leave.action_validate()
+ self.employee.write({'category_ids': [(6, False, [self.categ.id])]})
+ leave = self.env['hr.holidays'].search([('employee_id', '=', self.employee.id)])
+ self.assertEqual(leave.state, 'validate1')
+ self.assertEqual(leave.first_approver_id.id, self.env.uid)
diff --git a/hr_holidays_accrual/views/hr_holidays_views.xml b/hr_holidays_accrual/views/hr_holidays_views.xml
new file mode 100644
index 00000000..7ca7bad6
--- /dev/null
+++ b/hr_holidays_accrual/views/hr_holidays_views.xml
@@ -0,0 +1,13 @@
+
+
+
+ hr.holidays.edit.holiday.new.inherit
+ hr.holidays
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/hr_holidays_accrual_payroll/README.rst b/hr_holidays_accrual_payroll/README.rst
new file mode 100644
index 00000000..2873ee26
--- /dev/null
+++ b/hr_holidays_accrual_payroll/README.rst
@@ -0,0 +1,30 @@
+*************************************
+Hibou - HR Holidays Accrual - Payroll
+*************************************
+
+Accrue employee leave allocations every pay period.
+
+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.
+
+
+.. image:: https://user-images.githubusercontent.com/15882954/42062853-f4175416-7ae3-11e8-8432-f54e26fe6094.png
+ :alt: 'Equipment Detail'
+ :width: 988
+ :align: left
+
+
+
+=======
+License
+=======
+
+Please see `LICENSE `_.
+
+Copyright Hibou Corp. 2018
\ No newline at end of file
diff --git a/hr_holidays_accrual_payroll/__init__.py b/hr_holidays_accrual_payroll/__init__.py
new file mode 100755
index 00000000..0650744f
--- /dev/null
+++ b/hr_holidays_accrual_payroll/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/hr_holidays_accrual_payroll/__manifest__.py b/hr_holidays_accrual_payroll/__manifest__.py
new file mode 100755
index 00000000..061f4429
--- /dev/null
+++ b/hr_holidays_accrual_payroll/__manifest__.py
@@ -0,0 +1,21 @@
+{
+ 'name': 'HR Holidays Accrual - Payroll',
+ 'author': 'Hibou Corp. ',
+ 'version': '11.0.0.0.0',
+ 'category': 'Human Resources',
+ 'sequence': 95,
+ 'summary': 'Grant leave allocations per payperiod',
+ 'description': """
+Automates leave allocations.
+ """,
+ 'website': 'https://hibou.io/',
+ 'depends': [
+ 'hr_holidays_accrual',
+ 'hr_payroll'
+ ],
+ 'data': [
+ 'views/hr_holidays_views.xml',
+ ],
+ 'installable': True,
+ 'application': False,
+}
diff --git a/hr_holidays_accrual_payroll/models/__init__.py b/hr_holidays_accrual_payroll/models/__init__.py
new file mode 100644
index 00000000..5d988fa2
--- /dev/null
+++ b/hr_holidays_accrual_payroll/models/__init__.py
@@ -0,0 +1 @@
+from . import hr_payslip
diff --git a/hr_holidays_accrual_payroll/models/hr_payslip.py b/hr_holidays_accrual_payroll/models/hr_payslip.py
new file mode 100644
index 00000000..893be350
--- /dev/null
+++ b/hr_holidays_accrual_payroll/models/hr_payslip.py
@@ -0,0 +1,32 @@
+from odoo import api, fields, models
+
+
+class HRPayslip(models.Model):
+ _inherit = 'hr.payslip'
+
+ @api.multi
+ 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
+ leave_to_update.write({'number_of_days_temp': new_allocation})
+
+ 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))
+
+ 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
+ return values
diff --git a/hr_holidays_accrual_payroll/tests/__init__.py b/hr_holidays_accrual_payroll/tests/__init__.py
new file mode 100755
index 00000000..6e022122
--- /dev/null
+++ b/hr_holidays_accrual_payroll/tests/__init__.py
@@ -0,0 +1 @@
+from . import test_accrual
diff --git a/hr_holidays_accrual_payroll/tests/test_accrual.py b/hr_holidays_accrual_payroll/tests/test_accrual.py
new file mode 100644
index 00000000..43f325de
--- /dev/null
+++ b/hr_holidays_accrual_payroll/tests/test_accrual.py
@@ -0,0 +1,43 @@
+from odoo.addons.hr_holidays.tests.common import TestHrHolidaysBase
+
+
+class TestLeaves(TestHrHolidaysBase):
+
+ def setUp(self):
+ super(TestLeaves, self).setUp()
+
+ 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({
+ 'name': 'Test Status',
+ 'color_name': 'red',
+ })
+ self.test_leave = self.env['hr.holidays'].create({
+ '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,
+ })
+
+ 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)
diff --git a/hr_holidays_accrual_payroll/views/hr_holidays_views.xml b/hr_holidays_accrual_payroll/views/hr_holidays_views.xml
new file mode 100644
index 00000000..8c15f42c
--- /dev/null
+++ b/hr_holidays_accrual_payroll/views/hr_holidays_views.xml
@@ -0,0 +1,14 @@
+
+
+
+ hr.holidays.edit.holiday.new.inherit.pay
+ hr.holidays
+
+
+
+
+
+
+
+
+
\ No newline at end of file