[FIX] hr_payroll: handle timezones coherently in hr.benefit
This commit simplifies the way the timezones are handled in hr_benefit. Creating a benefit now uses naive datetimes obtained by converting from the employee's timezone into UTC and then stripping timezone information. closes odoo/odoo#31968 Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This commit is contained in:
@@ -139,7 +139,9 @@ class HrBenefit(models.Model):
|
||||
r['employee_id'][0],
|
||||
r['benefit_type_id'][0] if r['benefit_type_id'] else False,
|
||||
) for r in month_recs}
|
||||
new_vals = [v for v in vals_list if (v['date_start'].replace(tzinfo=None), v['date_stop'].replace(tzinfo=None), v['employee_id'], v['benefit_type_id']) not in existing_entries]
|
||||
assert all(v['date_start'].tzinfo is None for v in vals_list)
|
||||
assert all(v['date_stop'].tzinfo is None for v in vals_list)
|
||||
new_vals = [v for v in vals_list if (v['date_start'], v['date_stop'], v['employee_id'], v['benefit_type_id']) not in existing_entries]
|
||||
# Remove duplicates from vals_list, shouldn't be necessary from saas-12.2
|
||||
unique_new_vals = set()
|
||||
for values in new_vals:
|
||||
@@ -184,8 +186,6 @@ class HrBenefit(models.Model):
|
||||
if benefit.date_start.date() == benefit.date_stop.date():
|
||||
new_benefits |= benefit
|
||||
else:
|
||||
tz = pytz.timezone(benefit.employee_id.tz)
|
||||
benefit_start, benefit_stop = tz.localize(benefit.date_start), tz.localize(benefit.date_stop)
|
||||
values = {
|
||||
'name': benefit.name,
|
||||
'employee_id': benefit.employee_id.id,
|
||||
@@ -193,9 +193,9 @@ class HrBenefit(models.Model):
|
||||
}
|
||||
benefit_state = benefit.state
|
||||
benefits_to_unlink |= benefit
|
||||
for start, stop in _split_range_by_day(benefit_start, benefit_stop):
|
||||
values['date_start'] = start.astimezone(pytz.utc)
|
||||
values['date_stop'] = stop.astimezone(pytz.utc)
|
||||
for start, stop in _split_range_by_day(benefit.date_start, benefit.date_stop):
|
||||
values['date_start'] = start
|
||||
values['date_stop'] = stop
|
||||
new_benefit = self.create(values)
|
||||
# Write the state after the creation due to the ir.rule on benefit state
|
||||
new_benefit.state = benefit_state
|
||||
@@ -244,8 +244,8 @@ class HrBenefit(models.Model):
|
||||
def _duplicate_to_calendar_attendance(self):
|
||||
mapped_data = {
|
||||
benefit: [
|
||||
pytz.utc.localize(benefit.date_start).astimezone(pytz.timezone(benefit.employee_id.tz)), # Start date
|
||||
pytz.utc.localize(benefit.date_stop).astimezone(pytz.timezone(benefit.employee_id.tz)) # End date
|
||||
benefit.date_start,
|
||||
benefit.date_stop,
|
||||
] for benefit in self
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# -*- coding:utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.addons.resource.models.resource import Intervals
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime
|
||||
import pytz
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class HrEmployee(models.Model):
|
||||
_inherit = 'hr.employee'
|
||||
@@ -22,20 +22,18 @@ class HrEmployee(models.Model):
|
||||
|
||||
@api.multi
|
||||
def generate_benefit(self, date_start, date_stop):
|
||||
date_start = date_start.replace(tzinfo=pytz.utc)
|
||||
date_stop = date_stop.replace(tzinfo=pytz.utc)
|
||||
date_start = fields.Datetime.to_datetime(date_start)
|
||||
date_stop = fields.Datetime.to_datetime(date_stop)
|
||||
attendance_type = self.env.ref('hr_payroll.benefit_type_attendance')
|
||||
vals_list = []
|
||||
leaves = self.env['hr.leave']
|
||||
|
||||
for employee in self:
|
||||
|
||||
# Approved leaves
|
||||
emp_leaves = employee.resource_calendar_id.leave_ids.filtered(
|
||||
lambda r:
|
||||
r.resource_id == employee.resource_id and
|
||||
r.date_from.replace(tzinfo=pytz.utc) <= date_stop and
|
||||
r.date_to.replace(tzinfo=pytz.utc) >= date_start
|
||||
r.date_from <= date_stop and
|
||||
r.date_to >= date_start
|
||||
)
|
||||
global_leaves = employee.resource_calendar_id.global_leave_ids
|
||||
|
||||
@@ -43,9 +41,8 @@ class HrEmployee(models.Model):
|
||||
vals_list.extend(employee_leaves._get_benefits_values())
|
||||
|
||||
for contract in employee._get_contracts(date_start, date_stop):
|
||||
|
||||
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_benefits = max(date_start, fields.Datetime.to_datetime(contract.date_start)).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)
|
||||
|
||||
calendar = contract.resource_calendar_id
|
||||
resource = employee.resource_id
|
||||
@@ -53,10 +50,11 @@ class HrEmployee(models.Model):
|
||||
# Attendances
|
||||
for interval in attendances:
|
||||
benefit_type_id = interval[2].mapped('benefit_type_id')[:1] or attendance_type
|
||||
# All benefits generated here are using datetimes converted from the employee's timezone
|
||||
vals_list += [{
|
||||
'name': "%s: %s" % (benefit_type_id.name, employee.name),
|
||||
'date_start': interval[0].astimezone(pytz.utc),
|
||||
'date_stop': interval[1].astimezone(pytz.utc),
|
||||
'date_start': interval[0].astimezone(pytz.utc).replace(tzinfo=None),
|
||||
'date_stop': interval[1].astimezone(pytz.utc).replace(tzinfo=None),
|
||||
'benefit_type_id': benefit_type_id.id,
|
||||
'employee_id': employee.id,
|
||||
'state': 'confirmed',
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from datetime import datetime
|
||||
import pytz
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from odoo import exceptions
|
||||
import pytz
|
||||
|
||||
from odoo.fields import Datetime, Date
|
||||
from odoo.tests.common import tagged
|
||||
from odoo.addons.hr_payroll.tests.common import TestPayslipBase
|
||||
@@ -12,15 +12,14 @@ from odoo.addons.hr_payroll.tests.common import TestPayslipBase
|
||||
|
||||
@tagged('benefit')
|
||||
class TestBenefit(TestPayslipBase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBenefit, self).setUp()
|
||||
self.tz = pytz.timezone(self.richard_emp.tz)
|
||||
self.start = self.to_datetime_tz('2015-11-01 01:00:00')
|
||||
self.end = self.to_datetime_tz('2015-11-30 23:59:59')
|
||||
self.start = datetime(2015, 11, 1, 1, 0, 0)
|
||||
self.end = datetime(2015, 11, 30, 23, 59, 59)
|
||||
self.resource_calendar_id = self.env['resource.calendar'].create({'name': 'Zboub'})
|
||||
self.env['hr.contract'].create({
|
||||
'date_start': self.start - relativedelta(days=5),
|
||||
'date_start': self.start.date() - relativedelta(days=5),
|
||||
'name': 'dodo',
|
||||
'resource_calendar_id': self.resource_calendar_id.id,
|
||||
'wage': 1000,
|
||||
@@ -47,24 +46,6 @@ class TestBenefit(TestPayslipBase):
|
||||
'code': 'WORK200'
|
||||
})
|
||||
|
||||
def to_datetime_tz(self, datetime_str, tz=None):
|
||||
tz = tz or self.tz
|
||||
return tz.localize(Datetime.to_datetime(datetime_str))
|
||||
|
||||
def assertDatetimeTzEqual(self, value, target, tz=None):
|
||||
"""
|
||||
Assert equality between two dates.
|
||||
:param value: timezone naive datetime
|
||||
:param target: datetime string
|
||||
:param tz: timezone to interpret the tartget string
|
||||
:raises AssertionError: raises exception if the two dates are not equal
|
||||
"""
|
||||
tz = tz or self.tz
|
||||
self.assertEqual(
|
||||
pytz.utc.localize(value).astimezone(tz),
|
||||
self.to_datetime_tz(target, tz=tz)
|
||||
)
|
||||
|
||||
def test_no_duplicate(self):
|
||||
self.richard_emp.generate_benefit(self.start, self.end)
|
||||
pou1 = self.env['hr.benefit'].search_count([])
|
||||
@@ -73,16 +54,14 @@ class TestBenefit(TestPayslipBase):
|
||||
self.assertEqual(pou1, pou2, "Benefits should not be duplicated")
|
||||
|
||||
def test_benefit(self):
|
||||
|
||||
self.richard_emp.generate_benefit(self.start, self.end)
|
||||
|
||||
attendance_nb = len(self.resource_calendar_id._attendance_intervals(self.start, self.end))
|
||||
attendance_nb = len(self.resource_calendar_id._attendance_intervals(self.start.replace(tzinfo=pytz.utc), self.end.replace(tzinfo=pytz.utc)))
|
||||
benefit_nb = self.env['hr.benefit'].search_count([('employee_id', '=', self.richard_emp.id)])
|
||||
self.assertEqual(attendance_nb, benefit_nb, "One benefit should be generated for each calendar attendance")
|
||||
|
||||
def test_split_benefit_by_day(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 18:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 18, 0, 0)
|
||||
|
||||
# Benefit of type attendance should be split in three
|
||||
benefit = self.env['hr.benefit'].create({
|
||||
@@ -95,18 +74,18 @@ class TestBenefit(TestPayslipBase):
|
||||
benefits = benefit._split_by_day()
|
||||
self.assertEqual(len(benefits), 3, "Benefit should be split in three")
|
||||
|
||||
self.assertDatetimeTzEqual(benefits[0].date_start, '2015-11-01 09:00:00')
|
||||
self.assertDatetimeTzEqual(benefits[0].date_stop, '2015-11-01 23:59:59')
|
||||
self.assertEqual(benefits[0].date_start, datetime(2015, 11, 1, 9, 0, 0))
|
||||
self.assertEqual(benefits[0].date_stop, datetime(2015, 11, 1, 23, 59, 59))
|
||||
|
||||
self.assertDatetimeTzEqual(benefits[1].date_start, '2015-11-02 00:00:00')
|
||||
self.assertDatetimeTzEqual(benefits[1].date_stop, '2015-11-02 23:59:59')
|
||||
self.assertEqual(benefits[1].date_start, datetime(2015, 11, 2, 0, 0, 0))
|
||||
self.assertEqual(benefits[1].date_stop, datetime(2015, 11, 2, 23, 59, 59))
|
||||
|
||||
self.assertDatetimeTzEqual(benefits[2].date_start, '2015-11-03 00:00:00')
|
||||
self.assertDatetimeTzEqual(benefits[2].date_stop, '2015-11-03 18:00:00')
|
||||
self.assertEqual(benefits[2].date_start, datetime(2015, 11, 3, 0, 0, 0))
|
||||
self.assertEqual(benefits[2].date_stop, datetime(2015, 11, 3, 18, 0, 0))
|
||||
|
||||
# Test with end at mid-night -> should not create benefit starting and ending at the same time (at 00:00)
|
||||
start = self.to_datetime_tz('2013-11-01 00:00:00')
|
||||
end = self.to_datetime_tz('2013-11-04 00:00:00')
|
||||
start = datetime(2013, 11, 1, 0, 0, 0)
|
||||
end = datetime(2013, 11, 4, 0, 0, 0)
|
||||
|
||||
benefit = self.env['hr.benefit'].create({
|
||||
'name': '1',
|
||||
@@ -116,19 +95,18 @@ class TestBenefit(TestPayslipBase):
|
||||
})
|
||||
benefits = benefit._split_by_day()
|
||||
self.assertEqual(len(benefits), 3, "Benefit should be split in three")
|
||||
self.assertDatetimeTzEqual(benefits[0].date_start, '2013-11-01 00:00:00')
|
||||
self.assertDatetimeTzEqual(benefits[0].date_stop, '2013-11-01 23:59:59')
|
||||
self.assertEqual(benefits[0].date_start, datetime(2013, 11, 1, 0, 0, 0))
|
||||
self.assertEqual(benefits[0].date_stop, datetime(2013, 11, 1, 23, 59, 59))
|
||||
|
||||
self.assertDatetimeTzEqual(benefits[1].date_start, '2013-11-02 00:00:00')
|
||||
self.assertDatetimeTzEqual(benefits[1].date_stop, '2013-11-02 23:59:59')
|
||||
self.assertEqual(benefits[1].date_start, datetime(2013, 11, 2, 0, 0, 0))
|
||||
self.assertEqual(benefits[1].date_stop, datetime(2013, 11, 2, 23, 59, 59))
|
||||
|
||||
self.assertDatetimeTzEqual(benefits[2].date_start, '2013-11-03 00:00:00')
|
||||
self.assertDatetimeTzEqual(benefits[2].date_stop, '2013-11-03 23:59:59')
|
||||
self.assertEqual(benefits[2].date_start, datetime(2013, 11, 3, 0, 0, 0))
|
||||
self.assertEqual(benefits[2].date_stop, datetime(2013, 11, 3, 23, 59, 59))
|
||||
|
||||
def test_approve_multiple_day_benefit(self):
|
||||
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 18:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 18, 0, 0)
|
||||
|
||||
# Benefit of type attendance should be split in three
|
||||
benefit = self.env['hr.benefit'].create({
|
||||
@@ -144,8 +122,8 @@ class TestBenefit(TestPayslipBase):
|
||||
self.assertEqual(len(benefits), 3, "Benefit should be split in three")
|
||||
|
||||
def test_duplicate_global_benefit_to_attendance(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 18:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 18, 0, 0)
|
||||
|
||||
benef = self.env['hr.benefit'].create({
|
||||
'name': '1',
|
||||
@@ -162,8 +140,8 @@ class TestBenefit(TestPayslipBase):
|
||||
self.assertEqual(attendance_nb, 0, "It should not duplicate the 'normal/global' benefit type")
|
||||
|
||||
def test_duplicate_benefit_to_attendance(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 18:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 18, 0, 0)
|
||||
|
||||
# Benefit (not leave) should be split in three attendance
|
||||
benef = self.env['hr.benefit'].create({
|
||||
@@ -199,8 +177,8 @@ class TestBenefit(TestPayslipBase):
|
||||
]))
|
||||
|
||||
def test_create_benefit_leave(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 18:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 18, 0, 0)
|
||||
|
||||
benef = self.env['hr.benefit'].create({
|
||||
'name': 'Richard leave from benef',
|
||||
@@ -215,8 +193,8 @@ class TestBenefit(TestPayslipBase):
|
||||
self.assertEqual(calendar_leave.benefit_type_id, benef.benefit_type_id, "It should have the same benefit type")
|
||||
|
||||
def test_validate_conflict_benefit(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-01 13:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 1, 13, 0, 0)
|
||||
benef1 = self.env['hr.benefit'].create({
|
||||
'name': '1',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -224,7 +202,7 @@ class TestBenefit(TestPayslipBase):
|
||||
'date_start': start,
|
||||
'date_stop': end + relativedelta(hours=5),
|
||||
})
|
||||
benef2 = self.env['hr.benefit'].create({
|
||||
self.env['hr.benefit'].create({
|
||||
'name': '2',
|
||||
'employee_id': self.richard_emp.id,
|
||||
'benefit_type_id': self.env.ref('hr_payroll.benefit_type_attendance').id,
|
||||
@@ -243,7 +221,7 @@ class TestBenefit(TestPayslipBase):
|
||||
'date_start': self.start,
|
||||
'date_stop': self.end,
|
||||
})
|
||||
leave_1 = self.env['hr.leave'].create({
|
||||
self.env['hr.leave'].create({
|
||||
'name': 'Doctor Appointment',
|
||||
'employee_id': self.richard_emp.id,
|
||||
'holiday_status_id': self.leave_type.id,
|
||||
@@ -251,7 +229,7 @@ class TestBenefit(TestPayslipBase):
|
||||
'date_to': self.start + relativedelta(days=1),
|
||||
'number_of_days': 2,
|
||||
})
|
||||
self.assertFalse(benef1.action_validate(benef1.ids),"It should not validate benefits conflicting with non approved leaves")
|
||||
self.assertFalse(benef1.action_validate(benef1.ids), "It should not validate benefits conflicting with non approved leaves")
|
||||
self.assertTrue(benef1.display_warning)
|
||||
|
||||
def test_validate_undefined_benefit(self):
|
||||
@@ -261,11 +239,11 @@ class TestBenefit(TestPayslipBase):
|
||||
'date_start': self.start,
|
||||
'date_stop': self.end,
|
||||
})
|
||||
self.assertFalse(benef1.action_validate(benef1.ids),"It should not validate benefits without a type")
|
||||
self.assertFalse(benef1.action_validate(benef1.ids), "It should not validate benefits without a type")
|
||||
|
||||
def test_approve_leave_benefit(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 13:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 13, 0, 0)
|
||||
leave = self.env['hr.leave'].create({
|
||||
'name': 'Doctor Appointment',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -285,13 +263,13 @@ class TestBenefit(TestPayslipBase):
|
||||
leave.action_approve()
|
||||
|
||||
new_leave_benef = self.env['hr.benefit'].search([
|
||||
('date_start', '=', Datetime.to_datetime('2015-11-01 09:00:00')),
|
||||
('date_stop', '=', Datetime.to_datetime('2015-11-02 09:00:00')),
|
||||
('date_start', '=', Datetime.to_datetime(datetime(2015, 11, 1, 9, 0, 0))),
|
||||
('date_stop', '=', Datetime.to_datetime(datetime(2015, 11, 2, 9, 0, 0))),
|
||||
('benefit_type_id.is_leave', '=', True)
|
||||
])
|
||||
|
||||
new_benef = self.env['hr.benefit'].search([
|
||||
('date_start', '=', Datetime.to_datetime('2015-11-02 09:00:01')),
|
||||
('date_start', '=', Datetime.to_datetime(datetime(2015, 11, 2, 9, 0, 1))),
|
||||
('date_stop', '=', end),
|
||||
('benefit_type_id.is_leave', '=', False)
|
||||
])
|
||||
@@ -302,8 +280,8 @@ class TestBenefit(TestPayslipBase):
|
||||
self.assertTrue(benef.action_validate((new_benef | new_leave_benef).ids), "It should be able to validate the benefits")
|
||||
|
||||
def test_refuse_leave_benefit(self):
|
||||
start = self.to_datetime_tz('2015-11-01 09:00:00')
|
||||
end = self.to_datetime_tz('2015-11-03 13:00:00')
|
||||
start = datetime(2015, 11, 1, 9, 0, 0)
|
||||
end = datetime(2015, 11, 3, 13, 0, 0)
|
||||
leave = self.env['hr.leave'].create({
|
||||
'name': 'Doctor Appointment',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -331,8 +309,8 @@ class TestBenefit(TestPayslipBase):
|
||||
self.assertEqual(data['hours'], 168.0)
|
||||
|
||||
def test_time_extra_benefit(self):
|
||||
start = self.to_datetime_tz('2015-11-01 10:00:00')
|
||||
end = self.to_datetime_tz('2015-11-01 17:00:00')
|
||||
start = datetime(2015, 11, 1, 10, 0, 0)
|
||||
end = datetime(2015, 11, 1, 17, 0, 0)
|
||||
benef = self.env['hr.benefit'].create({
|
||||
'name': '1',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -346,8 +324,8 @@ class TestBenefit(TestPayslipBase):
|
||||
|
||||
def test_time_week_leave_benefit(self):
|
||||
# /!\ this is a week day => it exists an calendar attendance at this time
|
||||
start = self.to_datetime_tz('2015-11-02 10:00:00', tz=pytz.utc)
|
||||
end = self.to_datetime_tz('2015-11-02 17:00:00', tz=pytz.utc)
|
||||
start = datetime(2015, 11, 2, 10, 0, 0)
|
||||
end = datetime(2015, 11, 2, 17, 0, 0)
|
||||
leave_benef = self.env['hr.benefit'].create({
|
||||
'name': '1leave',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -361,8 +339,8 @@ class TestBenefit(TestPayslipBase):
|
||||
|
||||
def test_time_weekend_leave_benefit(self):
|
||||
# /!\ this is in the weekend => no calendar attendance at this time
|
||||
start = self.to_datetime_tz('2015-11-01 10:00:00', tz=pytz.utc)
|
||||
end = self.to_datetime_tz('2015-11-01 17:00:00', tz=pytz.utc)
|
||||
start = datetime(2015, 11, 1, 10, 0, 0)
|
||||
end = datetime(2015, 11, 1, 17, 0, 0)
|
||||
leave_benef = self.env['hr.benefit'].create({
|
||||
'name': '1leave',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -376,8 +354,8 @@ class TestBenefit(TestPayslipBase):
|
||||
|
||||
def test_payslip_generation_with_leave(self):
|
||||
# /!\ this is a week day => it exists an calendar attendance at this time
|
||||
start = self.to_datetime_tz('2015-11-02 10:00:00', tz=pytz.utc)
|
||||
end = self.to_datetime_tz('2015-11-02 17:00:00', tz=pytz.utc)
|
||||
start = datetime(2015, 11, 2, 10, 0, 0)
|
||||
end = datetime(2015, 11, 2, 17, 0, 0)
|
||||
leave_benef = self.env['hr.benefit'].create({
|
||||
'name': '1leave',
|
||||
'employee_id': self.richard_emp.id,
|
||||
@@ -399,8 +377,8 @@ class TestBenefit(TestPayslipBase):
|
||||
|
||||
def test_payslip_generation_with_extra_work(self):
|
||||
# /!\ this is in the weekend (Sunday) => no calendar attendance at this time
|
||||
start = self.to_datetime_tz('2015-11-01 10:00:00', tz=pytz.utc)
|
||||
end = self.to_datetime_tz('2015-11-01 17:00:00', tz=pytz.utc)
|
||||
start = datetime(2015, 11, 1, 10, 0, 0)
|
||||
end = datetime(2015, 11, 1, 17, 0, 0)
|
||||
benef = self.env['hr.benefit'].create({
|
||||
'name': 'Extra',
|
||||
'employee_id': self.richard_emp.id,
|
||||
|
||||
Reference in New Issue
Block a user