diff --git a/hr_attendance_missing_days/data/ir_cron.xml b/hr_attendance_missing_days/data/ir_cron.xml
index ff304a4e..c616cf97 100644
--- a/hr_attendance_missing_days/data/ir_cron.xml
+++ b/hr_attendance_missing_days/data/ir_cron.xml
@@ -14,7 +14,7 @@
code
- model.create_missing_attendances(datetime.datetime.now() - datetime.timedelta(days=31))
+ model.create_missing_attendances(datetime.date.today() - datetime.timedelta(days=31))
diff --git a/hr_attendance_missing_days/models/hr_employee.py b/hr_attendance_missing_days/models/hr_employee.py
index 658b6bad..4a91fad5 100644
--- a/hr_attendance_missing_days/models/hr_employee.py
+++ b/hr_attendance_missing_days/models/hr_employee.py
@@ -2,7 +2,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
-from datetime import datetime, time
+from datetime import date, datetime, time, timedelta
import pytz
@@ -20,6 +20,15 @@ def ensure_tz(dt, tz=None):
class Employee(models.Model):
_inherit = "hr.employee"
+ def _prepare_missing_attendance_values(self, dt, reasons):
+ self.ensure_one()
+ return {
+ "employee_id": self.id,
+ "check_in": dt,
+ "check_out": dt,
+ "attendance_reason_ids": [(6, 0, reasons.ids)],
+ }
+
def create_missing_attendances(self, date_from=None, date_to=None):
for emp in self.search([]):
emp._create_missing_attendances(date_from, date_to)
@@ -32,36 +41,37 @@ def _create_missing_attendances(self, date_from=None, date_to=None):
return
if not date_from:
- date_from = datetime.combine(
- self.env.company.sudo().overtime_start_date, time.min
- )
+ date_from = self.env.company.sudo().overtime_start_date
if not date_to:
- date_to = datetime.now()
+ date_to = date.today()
+
+ # Determine the start and end of the day and convert to UTC
+ dt_from = datetime.combine(date_from, time.min)
+ dt_to = datetime.combine(date_to, time.max)
- date_from, date_to = map(ensure_tz, (date_from, date_to))
+ tz = pytz.timezone(self.tz or "UTC")
+ dt_from, dt_to = map(tz.localize, (dt_from, dt_to))
+ dt_from, dt_to = ensure_tz(dt_from, pytz.utc), ensure_tz(dt_to, pytz.utc)
- intervals = self.resource_calendar_id._work_intervals_batch(date_from, date_to)
+ # Skip the active day
+ if dt_to.replace(tzinfo=None) > datetime.now():
+ dt_to -= timedelta(days=1)
+
+ if dt_from > dt_to:
+ return
+
+ intervals = self.resource_calendar_id._work_intervals_batch(dt_from, dt_to)
work_dates = {}
for start, _stop, _attendance in sorted(intervals[False]):
start_date = start.date()
-
- # Check that the end of the day for the employee is before date_to to
- # avoid a run mid working day
- tz = pytz.timezone(self.tz or "UTC")
- end_of_day = datetime.combine(start_date, time.max)
- end_of_day = tz.localize(end_of_day).astimezone(pytz.utc)
- if end_of_day >= date_to:
- continue
-
if start_date not in work_dates:
work_dates[start_date] = ensure_tz(start, pytz.utc).replace(tzinfo=None)
domain = [
- ("check_in", ">=", date_from.replace(tzinfo=None)),
- ("check_in", "<=", date_to.replace(tzinfo=None)),
+ ("check_in", ">=", dt_from.replace(tzinfo=None)),
+ ("check_in", "<=", dt_to.replace(tzinfo=None)),
]
- tz = pytz.timezone(self.tz)
attendances = {
ensure_tz(attendance.check_in, tz).date()
for attendance in self.attendance_ids.filtered_domain(domain)
@@ -70,12 +80,7 @@ def _create_missing_attendances(self, date_from=None, date_to=None):
vals = []
for missing in set(work_dates) - attendances:
vals.append(
- {
- "employee_id": self.id,
- "check_in": work_dates[missing],
- "check_out": work_dates[missing],
- "attendance_reason_ids": [(4, reason.id)],
- }
+ self._prepare_missing_attendance_values(work_dates[missing], reason)
)
self.env["hr.attendance"].create(vals)
diff --git a/hr_attendance_missing_days/tests/test_attendance.py b/hr_attendance_missing_days/tests/test_attendance.py
index 169691c5..2d1ae91d 100644
--- a/hr_attendance_missing_days/tests/test_attendance.py
+++ b/hr_attendance_missing_days/tests/test_attendance.py
@@ -79,9 +79,7 @@ def test_attendance_creation(self):
)
# Cover a huge time span
- employee._create_missing_attendances(
- datetime(2023, 6, 1, 0, 0), datetime(2023, 8, 1, 0, 0)
- )
+ employee._create_missing_attendances(date(2023, 6, 1), date(2023, 8, 1))
domain = [
("employee_id", "=", employee.id),
@@ -96,20 +94,17 @@ def test_attendance_creation(self):
def test_attendance_creation_during_day(self):
self.env.company.attendance_missing_days_reason = self.reason
- start = datetime(2023, 7, 3, 12, 30)
+ now = datetime.now()
self.env["hr.attendance"].create(
{
"employee_id": self.employee.id,
- "check_in": start,
- "check_out": start + timedelta(minutes=30),
+ "check_in": now - timedelta(minutes=30),
+ "check_out": now + timedelta(minutes=30),
}
)
attendances_before = self.employee.attendance_ids
- self.employee._create_missing_attendances(
- start - timedelta(hours=12),
- start - timedelta(minutes=30),
- )
+ self.employee._create_missing_attendances(now, now)
attendances_after = self.employee.attendance_ids
attendances_new = attendances_after - attendances_before