Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[17.0][MIG] hr_attendance_missing_days: Migration to 17.0 #198

Open
wants to merge 9 commits into
base: 17.0
Choose a base branch
from
Open
84 changes: 84 additions & 0 deletions hr_attendance_missing_days/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
======================================
Attendance generation for missing days
======================================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:14140f914d671ae2a6dcb45632700b88906ccec2abe52643c512ac5de601207d
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fhr--attendance-lightgray.png?logo=github
:target: https://github.com/OCA/hr-attendance/tree/17.0/hr_attendance_missing_days
:alt: OCA/hr-attendance
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/hr-attendance-17-0/hr-attendance-17-0-hr_attendance_missing_days
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/hr-attendance&target_branch=17.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This modules generates attendances for employee with 0 minutes for
working days with missing attendances. The configured reason is set to
make it easier for filtering. This can be used to generate pseudo
attendances for working days otherwise Odoo wouldn't reduce the overtime
of the employee.

1. Go to *Attendances > Configuration > Missing Days*
2. Select a reason to set for the created attendances

**Table of contents**

.. contents::
:local:

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/hr-attendance/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/hr-attendance/issues/new?body=module:%20hr_attendance_missing_days%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* initOS GmbH

Contributors
------------

- initOS GmbH (initOS.com)
- `Heliconia Solutions Pvt. Ltd. <https://www.heliconia.io>`__

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/hr-attendance <https://github.com/OCA/hr-attendance/tree/17.0/hr_attendance_missing_days>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
4 changes: 4 additions & 0 deletions hr_attendance_missing_days/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import models
21 changes: 21 additions & 0 deletions hr_attendance_missing_days/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

{
"name": "Attendance generation for missing days",
"version": "17.0.1.0.0",
"category": "Hidden",
"author": "initOS GmbH, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/hr-attendance",
"license": "AGPL-3",
"summary": "This modules generates attendances for working days without attendance",
"depends": [
"hr_attendance_reason",
],
"data": [
"data/hr_attendance_reason.xml",
"data/ir_cron.xml",
"views/res_config_settings_views.xml",
],
"installable": True,
}
7 changes: 7 additions & 0 deletions hr_attendance_missing_days/data/hr_attendance_reason.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo noupdate="1">
<record id="attendance_reason_missing_days" model="hr.attendance.reason">
<field name="name">System generated attendances for missing days</field>
<field name="code">S-GMD</field>
</record>
</odoo>
20 changes: 20 additions & 0 deletions hr_attendance_missing_days/data/ir_cron.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo noupdate="1">
<record id="missing_attendance_cron" model="ir.cron">
<field name="name">Missing Attendance</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field
name="nextcall"
eval="(DateTime.now() + timedelta(minutes=60)).strftime('%Y-%m-%d 04:00:00')"
/>
<field name="doall" eval="True" />
<field name="model_id" ref="hr.model_hr_employee" />
<field name="active" eval="False" />
<field name="state">code</field>
<field name="code">
model.create_missing_attendances(datetime.date.today() - datetime.timedelta(days=31))
</field>
</record>
</odoo>
4 changes: 4 additions & 0 deletions hr_attendance_missing_days/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from . import hr_employee, res_company, res_config_settings
105 changes: 105 additions & 0 deletions hr_attendance_missing_days/models/hr_employee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

import logging
from datetime import date, datetime, time, timedelta

import pytz

from odoo import models

_logger = logging.getLogger(__name__)


def ensure_tz(dt, tz=None):
if not dt.tzinfo:
dt = pytz.utc.localize(dt)
return dt.astimezone(tz) if tz else dt


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 _get_work_intervals_batch(self, dt_from, dt_to):
self.ensure_one()
return self.resource_calendar_id._work_intervals_batch(dt_from, dt_to)[False]

def create_missing_attendances(self, date_from=None, date_to=None):
for emp in self.search([]):
emp._create_missing_attendances(date_from, date_to)

Check warning on line 38 in hr_attendance_missing_days/models/hr_employee.py

View check run for this annotation

Codecov / codecov/patch

hr_attendance_missing_days/models/hr_employee.py#L38

Added line #L38 was not covered by tests

def _create_missing_attendances(self, date_from=None, date_to=None):
self.ensure_one()

reason = self.env.company.sudo().attendance_missing_days_reason
if not reason:
return

if not date_from:
date_from = self.env.company.sudo().overtime_start_date

if not date_to:
date_to = date.today()

# Ensure date_from and date_to are datetime objects, not just date objects
if isinstance(
date_from, date
): # If date_from is a date object, convert it to datetime
date_from = datetime.combine(date_from, time.min)
if isinstance(
date_to, date
): # If date_to is a date object, convert it to datetime
date_to = datetime.combine(date_to, time.max)

tz = pytz.timezone(self.tz or "UTC")

# Now they are datetime objects, we can safely localize them
dt_from, dt_to = map(tz.localize, (date_from, date_to))

# Ensure the time zone is set to UTC
dt_from, dt_to = ensure_tz(dt_from, pytz.utc), ensure_tz(dt_to, pytz.utc)

# 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._get_work_intervals_batch(dt_from, dt_to)
work_dates = {}
for start, _stop, _attendance in sorted(intervals):
start_date = start.date()
if start_date not in work_dates:
work_dates[start_date] = ensure_tz(start, pytz.utc).replace(tzinfo=None)

domain = [
("check_in", ">=", dt_from.replace(tzinfo=None)),
("check_in", "<=", dt_to.replace(tzinfo=None)),
]
attendance_records = self.attendance_ids.filtered_domain(domain)

attendances = set()
for attendance_date in attendance_records.mapped("check_in"):
if attendance_date:
attendances.add(ensure_tz(attendance_date, tz).date())
for attendance_date in attendance_records.mapped("check_out"):
if attendance_date: # Handle empty check_out field
attendances.add(ensure_tz(attendance_date, tz).date())

vals = []
for missing in set(work_dates) - attendances:
vals.append(
self._prepare_missing_attendance_values(work_dates[missing], reason)
)

self.env["hr.attendance"].create(vals)
16 changes: 16 additions & 0 deletions hr_attendance_missing_days/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResCompany(models.Model):
_inherit = "res.company"

attendance_missing_days_reason = fields.Many2one(
"hr.attendance.reason",
default=lambda self: self.env.ref(
"hr_attendance_missing_days.attendance_reason_missing_days",
raise_if_not_found=False,
),
)
13 changes: 13 additions & 0 deletions hr_attendance_missing_days/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# © 2023 initOS GmbH
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = "res.config.settings"

attendance_missing_days_reason = fields.Many2one(
related="company_id.attendance_missing_days_reason",
readonly=False,
)
3 changes: 3 additions & 0 deletions hr_attendance_missing_days/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"
2 changes: 2 additions & 0 deletions hr_attendance_missing_days/readme/CONTRIBUTORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- initOS GmbH (initOS.com)
- [Heliconia Solutions Pvt. Ltd.](https://www.heliconia.io)
8 changes: 8 additions & 0 deletions hr_attendance_missing_days/readme/DESCRIPTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
This modules generates attendances for employee with 0 minutes for
working days with missing attendances. The configured reason is set to
make it easier for filtering. This can be used to generate pseudo
attendances for working days otherwise Odoo wouldn't reduce the overtime
of the employee.

1. Go to *Attendances \> Configuration \> Missing Days*
2. Select a reason to set for the created attendances
Loading