diff --git a/hr_payroll_overtime/models/hr_payslip.py b/hr_payroll_overtime/models/hr_payslip.py
index 9031b3a4..538d9b9f 100644
--- a/hr_payroll_overtime/models/hr_payslip.py
+++ b/hr_payroll_overtime/models/hr_payslip.py
@@ -91,6 +91,19 @@ class HRPayslip(models.Model):
:param week_hours: hours worked on iso week already processed
:return:
"""
+ override = work_type.override_for_iso_date(iso_date)
+ if override:
+ new_work_type = override.work_type_id
+ multiplier = override.multiplier
+ if work_type == new_work_type:
+ # trivial infinite recursion from override
+ raise UserError('Work type "%s" (id %s) must not have itself as its override work type. '
+ 'This occurred due to an override line "%s".' % (
+ work_type.name, work_type.id, override.name))
+ # update the work_type on this step.
+ work_type = new_work_type
+ working_aggregation[work_type][2] = multiplier
+
week = iso_date[1]
if work_type.overtime_work_type_id and work_type.overtime_type_id:
ot_h_w = work_type.overtime_type_id.hours_per_week
diff --git a/hr_payroll_overtime/models/hr_work_entry.py b/hr_payroll_overtime/models/hr_work_entry.py
index 3225da5b..f607fd32 100644
--- a/hr_payroll_overtime/models/hr_work_entry.py
+++ b/hr_payroll_overtime/models/hr_work_entry.py
@@ -4,11 +4,51 @@ from odoo.exceptions import ValidationError
from .resource_calendar import WEEKDAY_SELECTION
+class WorkEntryOverride(models.AbstractModel):
+ _name = 'hr.work.entry.type.override.abstract'
+ _order = 'date desc, day_of_week'
+
+ name = fields.Char(string='Description')
+ work_type_id = fields.Many2one('hr.work.entry.type', string='Override Work Type', required=True,
+ help='Distinct Work Type for when this applies.')
+ multiplier = fields.Float(string='Multiplier',
+ help='Rate for override. E.g. maybe you have "Sunday Pay" at 2.0x')
+ day_of_week = fields.Selection(WEEKDAY_SELECTION, string='Day of Week')
+ date = fields.Date(string='Date')
+
+ @api.constrains('day_of_week', 'date')
+ def _constrain_days(self):
+ for override in self:
+ if override.day_of_week and override.date:
+ raise ValidationError('An override should only have a Date OR Day of Week.')
+
+ def iso_date_applies(self, iso_date):
+ for override in self:
+ if override.date and override.date.isocalendar() == iso_date:
+ return override
+ if int(override.day_of_week) == iso_date[2]:
+ return override
+
+
class HRWorkEntryType(models.Model):
_inherit = 'hr.work.entry.type'
overtime_work_type_id = fields.Many2one('hr.work.entry.type', string='Overtime Work Type')
overtime_type_id = fields.Many2one('hr.work.entry.overtime.type', string='Overtime Rules')
+ override_ids = fields.One2many('hr.work.entry.type.override', 'original_type_id', string='Overrides',
+ help='Override work entry type on payslip.')
+
+ def override_for_iso_date(self, iso_date):
+ return self.override_ids.iso_date_applies(iso_date)
+
+
+class HRWorkEntryTypeOverride(models.Model):
+ _name = 'hr.work.entry.type.override'
+ _inherit = 'hr.work.entry.type.override.abstract'
+ _description = 'Work Type Override'
+
+ original_type_id = fields.Many2one('hr.work.entry.type',
+ string='Work Entry Type')
class HRWorkEntryOvertime(models.Model):
@@ -32,30 +72,8 @@ class HRWorkEntryOvertime(models.Model):
class HRWorkEntryOvertimeOverride(models.Model):
_name = 'hr.work.entry.overtime.type.override'
+ _inherit = 'hr.work.entry.type.override.abstract'
_description = 'Overtime Rule Override'
- _order = 'date desc, day_of_week'
- name = fields.Char(string='Description')
overtime_type_id = fields.Many2one('hr.work.entry.overtime.type',
string='Overtime Rules')
- work_type_id = fields.Many2one('hr.work.entry.type', string='Overtime Work Type', required=True,
- help='Distinct Work Type for this. Given the different rate, it should '
- ' be different from other Overtime Work Types (because payslips '
- 'should only have one line/rate per work type).')
- multiplier = fields.Float(string='Multiplier',
- help='Rate for when overtime is reached.')
- day_of_week = fields.Selection(WEEKDAY_SELECTION, string='Day of Week')
- date = fields.Date(string='Date')
-
- @api.constrains('day_of_week', 'date')
- def _constrain_days(self):
- for override in self:
- if override.day_of_week and override.date:
- raise ValidationError('An override should only have a Date OR Day of Week.')
-
- def iso_date_applies(self, iso_date):
- for override in self:
- if override.date and override.date.isocalendar() == iso_date:
- return override
- if int(override.day_of_week) == iso_date[2]:
- return override
diff --git a/hr_payroll_overtime/security/ir.model.access.csv b/hr_payroll_overtime/security/ir.model.access.csv
index 03aadd5f..0b0223eb 100644
--- a/hr_payroll_overtime/security/ir.model.access.csv
+++ b/hr_payroll_overtime/security/ir.model.access.csv
@@ -2,4 +2,6 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_work_entry_overtime_type,access_hr_work_entry_overtime_type,model_hr_work_entry_overtime_type,base.group_user,1,0,0,0
manage_hr_work_entry_overtime_type,manage_hr_work_entry_overtime_type,model_hr_work_entry_overtime_type,hr_payroll.group_hr_payroll_manager,1,1,1,1
access_hr_work_entry_overtime_type_override,access_hr_work_entry_overtime_type_override,model_hr_work_entry_overtime_type_override,base.group_user,1,0,0,0
-manage_hr_work_entry_overtime_type_override,manage_hr_work_entry_overtime_type_override,model_hr_work_entry_overtime_type_override,hr_payroll.group_hr_payroll_manager,1,1,1,1
\ No newline at end of file
+manage_hr_work_entry_overtime_type_override,manage_hr_work_entry_overtime_type_override,model_hr_work_entry_overtime_type_override,hr_payroll.group_hr_payroll_manager,1,1,1,1
+access_hr_work_entry_type_override,access_hr_work_entry_type_override,model_hr_work_entry_type_override,base.group_user,1,0,0,0
+manage_hr_work_entry_type_override,manage_hr_work_entry_type_override,model_hr_work_entry_type_override,hr_payroll.group_hr_payroll_manager,1,1,1,1
diff --git a/hr_payroll_overtime/tests/test_overtime.py b/hr_payroll_overtime/tests/test_overtime.py
index 1c4023e0..fc7e7eaf 100644
--- a/hr_payroll_overtime/tests/test_overtime.py
+++ b/hr_payroll_overtime/tests/test_overtime.py
@@ -453,3 +453,40 @@ class TestOvertime(common.TransactionCase):
'work_type_id': self.work_type_overtime.id, # Note that this wouldn't be good in practice
})]
})
+
+ def test_18_override_day_of_week_on_work_type(self):
+ iso_date = (2020, 24, 1)
+ iso_date2 = (2020, 24, 2)
+
+ work_data = [
+ (iso_date, [
+ (self.work_type, 4.0, None),
+ ]),
+ (iso_date2, [
+ (self.work_type, 4.0, None),
+ ]),
+ ]
+
+ result_data = self.payslip.aggregate_overtime(work_data)
+ self.assertTrue(self.work_type in result_data)
+ self.assertEqual(result_data[self.work_type][0], 2)
+ self.assertEqual(result_data[self.work_type][1], 8.0)
+
+ # Now lets make an override line
+ test_multiplier = 3.0
+ self.work_type.write({
+ 'override_ids': [(0, 0, {
+ 'name': 'Day 2 Override',
+ 'multiplier': test_multiplier,
+ 'day_of_week': str(iso_date[2]),
+ 'work_type_id': self.work_type_overtime.id, # Note that this wouldn't be good in practice
+ })]
+ })
+ result_data = self.payslip.aggregate_overtime(work_data)
+ self.assertTrue(self.work_type in result_data)
+ self.assertEqual(result_data[self.work_type][0], 1)
+ self.assertEqual(result_data[self.work_type][1], 4.0)
+ self.assertTrue(self.work_type_overtime in result_data)
+ self.assertEqual(result_data[self.work_type_overtime][0], 1)
+ self.assertEqual(result_data[self.work_type_overtime][1], 4.0)
+ self.assertEqual(result_data[self.work_type_overtime][2], test_multiplier)
diff --git a/hr_payroll_overtime/views/hr_work_entry_views.xml b/hr_payroll_overtime/views/hr_work_entry_views.xml
index c60f693a..774d61ed 100644
--- a/hr_payroll_overtime/views/hr_work_entry_views.xml
+++ b/hr_payroll_overtime/views/hr_work_entry_views.xml
@@ -15,6 +15,16 @@
+
+
+
+
+
+
+
+
+
+